from tkinter import *
import json
from tkinter.ttk import *
import tkinter.filedialog as filedialog
import pathlib
import sys, inspect
from os import walk, mkdir
from os import path as osPath
from src.properties import renderProperties
from src.protocols import close
from src.codeGenerator import GenerateCode
from src.menuHandler import *
from src.keyBindings import *

class program(Tk):
    def __init__(self,*args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
        import tkinter.ttk
        iOut = inspect.getmembers(sys.modules[tkinter.ttk.__name__])
        self.widgets = [e for e in iOut if inspect.isclass(e[1])]
        self.tkFile = ""
        self.geometry("500x500")
        self.tabParent = Notebook(self)
        self.fileFrame = Frame(self)
        self.fileFrame.pack(side=LEFT, anchor=NE)
        self.tabParent.pack(side=LEFT, fill=BOTH, expand=1)
        self.tabs = {}
        self.fileDict = {}
        self.cacheDict = {}
        self.tabEntities = {}
        self.tabEntities['canvas'] = {}
        self.tabEntities['canvas']['entities'] = {}
        self.widgetContainer = Frame(self)
        self.widgetContainer.pack(side=RIGHT)
        self.widgetParent = Frame(self.widgetContainer)
        self.widgetParent.pack(side=TOP)
        self.propertiesParent = Frame(self.widgetContainer)
        self.propertiesParent.pack(side=BOTTOM)
        self.renderDirectoryFiles()
        self.canvasEntities = list()
        self.menu = Menu(self)
        self.bind()
        createMenu(self, self.menu)
        close(self, self._quit)
    def _quit(self):
        try:
            with open(self.dirPath + '/tk_project/.cache/components.json', 'w') as f:

                json.dump(self.cacheDict, f)
                f.close()
        except:
            try:
                with open(self.dirPath + '/.cache/components.json') as f:
                    json.dump(self.cacheDict, f)
                    f.close()
            except:
                self.quit()
                return
        GenerateCode(self.cacheDict)
        self.quit()
    def renderDirectoryFiles(self, dirPath=''):
        self.tabParent.destroy()
        self.fileFrame.destroy()

        self.tabParent = Notebook(self)
        self.fileFrame = Frame(self)
        self.fileFrame.pack(side=LEFT, anchor=NE)
        self.tabParent.pack(side=LEFT, fill=BOTH, expand=1)
        if len(dirPath) != 0:
            self.dirPath = dirPath
        else:
            self.dirPath = self.openFileDialog()
        folderTabData = self.breakPaths(self.dirPath)
        self.fileDict = folderTabData
        self.fileFrameEntities = self.renderBlock(self.fileFrame, self.fileDict)
        self.fileDict = {}
        self.cacheDict = {}
        self.tabEntities = {}
        self.tabEntities['canvas'] = {}
        self.tabEntities['canvas']['entities'] = {}
        try:
            self.openTkCanvas()
        except:
            pass
    def renderBlock(self, parent, fileDict):
        index = 0
        output = {}
        keys = list(fileDict.keys())
        for key in keys:
            if key == 'files':
                output[key] = list()
                for file in fileDict['files']:
                    tempButton = Button(parent, text= file, command=lambda path=fileDict['dir'], f=file: self.addTab(path, f))
                    output[key].append(tempButton)
                    index+=1
                    tempButton.grid(row=index+1, sticky=W, padx=(10,))
            elif key == 'dir':
                pass
            else:
                temp =  {}
                temp['frameParent'] = Frame(parent)
                temp['self'] = Button(parent, text=key, command=lambda frame=temp['frameParent'], i=index: self.activate(frame, i))
                if parent != self.fileFrame:
                    temp['self'].grid(row=index, sticky=W, padx=(10,))
                else:
                    temp['self'].grid(row=index, sticky=W)

                index+=2
                temp.update(self.renderBlock(temp['frameParent'], fileDict[key]))

                output = temp

        return output
    def activate(self, frame, index):
        if frame.winfo_ismapped() == 0:
            frame.grid(row=index+1)
        else:
            frame.grid_forget()

    def breakPaths(self, path):
        output = {}
        for (p, dirs, files) in walk(path):
            for e in dirs:
                output[e] = self.breakPaths(str(path) + '/' + e)
            output['dir'] = p
            output['files'] = files
            break
        return output
    def addTab(self,path, name):
        filePath = osPath.join(path, name)
        self.tabEntities[filePath] = {}
        tabFrame = Frame(self.tabParent)
        self.tabEntities[filePath]['self'] = tabFrame
        self.tabParent.add(tabFrame, text=name)
        self.tabEntities[filePath]['text'] = Text(tabFrame, tabs=('8m',))
        self.tabEntities[filePath]['text'].pack(fill=BOTH, expand=1)
        self.tabEntities[filePath]['save'] = Button(tabFrame, text="save", command=lambda p=filePath: self.saveFile(p))
        self.tabEntities[filePath]['save'].pack()
        with open(filePath, "r") as func:
            try:
                text = func.readlines()
                for line in text:
                    self.tabEntities[filePath]['text'].insert(END, line)
            except UnicodeDecodeError:
                self.tabEntities[name]['text'].insert(END, "can't open this file")
    def saveFile(self, filePath):
        #wText is the text widget
        text = self.tabEntities[filePath]['text'].get('1.0', END)
        with open(filePath, "w+") as f:
            f.write(text)
            f.close()
    def createTkinterProject(self, filePath):
        templateText = list()
        with open("templates/empty_window.py", "r") as f:
            templateText = f.readlines()
            f.close()
        mkdir(filePath + '/tk_project')
        mkdir(filePath + '/tk_project/.cache')
        with open(filePath + "/tk_project" + "/main.py", "w+") as f:
            f.writelines(templateText)
            f.close()

        with open(filePath + "/tk_project/.cache/components.json", "w+") as f:
            f.close()
        self.renderDirectoryFiles()
        self.tkFile = filePath + "/tk_project/main.py"
        self.tkFileCache = filePath + "/tk_project/.cache/components.json"
        self.createTkCanvas(self.tkFile)

    def openFileDialog(self):
        folderPath = filedialog.askdirectory(title="open folder")
        return folderPath
    def openTkCanvas(self):
        try:
            tkFileCache = self.dirPath+ "/.cache/components.json"
            with open(tkFileCache, 'r') as f:
                try:
                    cacheDict = json.load(f)
                except json.decoder.JSONDecodeError:
                    cachDict = {}
                self.cacheDict = cacheDict
                for key in list(cacheDict.keys()):
                    if key != '':
                        self.createTkCanvas(key)
                f.close()
        except:
            tkFileCache = self.dirPath+ "/tk_project/.cache/components.json"
            with open(tkFileCache, 'r') as f:
                try:
                    cacheDict = json.load(f)
                except json.decoder.JSONDecodeError:
                    cachDict = {}
                self.cacheDict = cacheDict
                for key in list(cacheDict.keys()):
                    if key != '':
                        self.createTkCanvas(key)
                f.close()

    def createTkCanvas(self, filePath):
        tkCanvas = Frame(self.tabParent)
        CanvasName = filePath.split('/')[len(filePath.split('/'))-1]
        if CanvasName in list(self.tabEntities['canvas']['entities'].keys()):
            CanvasName = "{}/{}~design".format(filePath.split('/')[len(filePath.split())-2],filePath.split('/')[len(filePath.split())-1])
        else:
            CanvasName +='~design'
        self.tabParent.add(tkCanvas, text=CanvasName)
        self.tabEntities['canvas'][filePath] = {}
        self.tabEntities['canvas'][filePath]['self'] = tkCanvas
        self.tabEntities['canvas'][filePath]['children'] = []
        self.tabEntities['canvas']['entities'][CanvasName] = filePath
        try:
            fileComponents = self.cacheDict[filePath]
            self.renderTkWidgets(fileComponents)
            self.renderWidgetGallery()
            self.cacheDict[filePath]['parent']['self'] = {'type': 'Frame', "text": CanvasName}
        except KeyError:
            self.cacheDict[filePath] = {}
            self.renderWidgetGallery()
            self.cacheDict[filePath]['parent'] = {}
            self.cacheDict[filePath]['parent']['self'] = {'type': 'Frame', 'text': CanvasName}
    def renderTkWidgets(self, fileComponents):
        filePath = [e for e in list(self.cacheDict.keys()) if self.cacheDict[e] == fileComponents][0]

        canvas = self.tabEntities['canvas'][filePath]['self']
        for key in list(fileComponents.keys()):
            if key != "parent":
                widget = [e[1] for e in self.widgets if fileComponents[key]['type'] == e[0]][0]
                w = widget(canvas, text= fileComponents[key]['self']['text'])
                w.bind('<B1-Motion>', lambda e, index=key: self.moveWidgetWithCursor(e, index))
                w.place(x= fileComponents[key]['placeProps']['x'], y=fileComponents[key]['placeProps']['y'])
                w.bind('<Button-1>', lambda e, widget=w,k=key ,parent=self: renderProperties(widget,k, parent))
                self.tabEntities['canvas'][filePath]['children'].append((int(key), w))

    def renderWidgetGallery(self):
        objWidgets = list(map(lambda e: Button(self.widgetParent, text=e[0], command= lambda a=e[0]: self.addWidgetToCanvas(a)), self.widgets))
        for widget in objWidgets:
            widget.pack(side=TOP)
    def moveWidgetWithCursor(self, event, index):

        activeTabName = self.tabParent.tab(self.tabParent.select(), "text")
        filePath = self.tabEntities['canvas']['entities'][activeTabName]
        widget = event.widget
        parent = Widget._nametowidget(self, widget.winfo_parent())
        parent = Widget._nametowidget(self, parent.winfo_parent())
        xpos, ypos = self.winfo_pointerx()- self.winfo_x()-8-parent.winfo_x(), self.winfo_pointery()- self.winfo_y()-50-parent.winfo_y()-23
        widget.place_forget()
        widget.place(x=xpos, y=ypos)
        self.cacheDict[filePath][str(index)]['placeProps'].pop('relx', None)
        self.cacheDict[filePath][str(index)]['placeProps'].pop('rely', None)
        self.cacheDict[filePath][str(index)]['placeProps']['x'], self.cacheDict[filePath][str(index)]['placeProps']['y'] = xpos, ypos

    def addWidgetToCanvas(self, widgetName):
        activeTabName = self.tabParent.tab(self.tabParent.select(), "text")
        try:
            filePath = self.tabEntities['canvas']['entities'][activeTabName]
        except KeyError:
            return
        indexes = [b[0] for b in self.tabEntities['canvas'][filePath]['children']]
        try:
            index = max(indexes) + 1
        except ValueError:
            index = 0
        widget = [e[1] for e in self.widgets if e[0] == widgetName][0]
        w = widget(self.tabEntities['canvas'][filePath]['self'], text="text here")
        w.bind('<B1-Motion>', lambda event, e=index: self.moveWidgetWithCursor(event, e))
        w.bind('<Button-1>', lambda e, widget=w, parent=self: renderProperties(widget, parent))
        w.place(relx=0.5, rely=0.5, anchor='center')
        widgetDict = {
            'type': widgetName,
            'self': {
                'text': "text here"
            },
            'placeProps': {'relx': 0.5, 'rely': 0.5, 'anchor': NW}
        }
        self.tabEntities['canvas'][filePath]['children'].append((index, widgetDict))
        self.cacheDict[filePath][str(index)] = widgetDict

test = program()

test.mainloop()


import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import torch.optim as optim

import torchvision.models as models

# Transforms for Augmentation. The exact same augmentation techniques have been used in the BREEDS paper (Santurkar et al.)

IMAGENET_PCA = {
    'eigval':torch.Tensor([0.2175, 0.0188, 0.0045]),
    'eigvec':torch.Tensor([
        [-0.5675,  0.7192,  0.4009],
        [-0.5808, -0.0045, -0.8140],
        [-0.5836, -0.6948,  0.4203],
    ])
}
class Lighting(object):
    """
    Lighting noise (see https://git.io/fhBOc)
    """
    def __init__(self, alphastd, eigval, eigvec):
        self.alphastd = alphastd
        self.eigval = eigval
        self.eigvec = eigvec

    def __call__(self, img):
        if self.alphastd == 0:
            return img

        alpha = img.new().resize_(3).normal_(0, self.alphastd)
        rgb = self.eigvec.type_as(img).clone()\
            .mul(alpha.view(1, 3).expand(3, 3))\
            .mul(self.eigval.view(1, 3).expand(3, 3))\
            .sum(1).squeeze()

        return img.add(rgb.view(3, 1, 1).expand_as(img))

transform_train = transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ColorJitter(
            brightness=0.1,
            contrast=0.1,
            saturation=0.1
        ),
        transforms.ToTensor(),
        Lighting(0.05, IMAGENET_PCA['eigval'],
                      IMAGENET_PCA['eigvec']),
        transforms.Normalize(mean=[0.4717, 0.4499, 0.3837],std=[0.2600, 0.2516, 0.2575])
    ])

transform_test = transforms.Compose([
 transforms.Resize(256),
 transforms.CenterCrop(224),
 transforms.ToTensor(),
 transforms.Normalize(mean=[0.4717, 0.4499, 0.3837],std=[0.2600, 0.2516, 0.2575])
])

# These are the hardcoded system paths for the data. Download and store the data as per given by the robustness packagae and then proceed with the correct data path.
# Path for Training Data

train_path = "/local/a/mukher44/Work/Datasets/BREEDS_datasets/Living_17/Regular_unbalanced/Source/"

train_imageNet = torchvision.datasets.ImageFolder(train_path,transform_train)

train_loader = torch.utils.data.DataLoader(train_imageNet, batch_size=128, shuffle=True, num_workers=8)

# Path for validation on the seen to seen distrubtion. The models are saved using the performance of the seen validation set. During training only this test path is used.
test_path = "/local/a/mukher44/Work/Datasets/BREEDS_datasets/Living_17/Regular_unbalanced/Source_Val/"

val_imageNet = torchvision.datasets.ImageFolder(test_path,transform_test)

val_loader = torch.utils.data.DataLoader(val_imageNet, batch_size=128, shuffle=True, num_workers=8)

# For ResNet-18
cl = models.resnet18()
# For ResNet-34
#cl = models.resnet34()
cl.fc = nn.Linear(512,17)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

cl.to(device);

# The standard softmax loss is used for training. All hyperparameters are used as described in the BREEDS paper (Santurkar et al.)
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(cl.parameters(), lr = 0.1, momentum=0.9, weight_decay= 1e-4)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size= 150, gamma=0.1)

def save_model(model, filename):
    torch.save(model.state_dict(),filename)

def validate(model, device, set_loader, criterion):
    model.eval()
    corrects = 0
    val_loss = 0.0
    with torch.no_grad():
        for inputs, labels in set_loader:
            inputs, label = inputs.to(device), labels.to(device)
            output = model(inputs)
            val_loss += criterion(output, label).item()
            val_loss = val_loss/len(set_loader)
            preds = output.max(1, keepdim=True)[1]
            corrects += preds.eq(label.view_as(preds)).sum().item()
        acc = corrects / float(len(set_loader.dataset))
    return val_loss, acc

best_acc = 0.0
for epoch in range(450):
    cl.train()
    count = 0
    for inputs, label in train_loader:
        inputs, label = inputs.to(device), label.to(device)
        optimizer.zero_grad()
        output = cl(inputs)
        loss = loss_fn(output, label)
        loss.backward()
        optimizer.step()
        count += len(inputs)

    tr_loss, tr_acc = validate(cl, device, train_loader, loss_fn)
    print('Training-----Epoch {}: Loss={:.4f}, Accuracy={:.3f}'.format(epoch, tr_loss, tr_acc))

    val_loss, val_acc = validate(cl, device, val_loader, loss_fn)
    print('Validation------Epoch {}: Loss={:.4f}, Accuracy={:.3f}'.format(epoch, val_loss, val_acc))

    if val_acc > best_acc:
        checkpoint = {'model': cl.state_dict(),
                      'optimizer':optimizer.state_dict()}
        torch.save(checkpoint, 'trial_5_trained_ResNet_18_baseline_best_model.pth')
        best_acc = val_acc

    scheduler.step()

print('Finished Training')


from decimal import Decimal
from datetime import datetime

from django.db import models
from django.db.models import signals as pos_model_signals, \
    Sum
from django.contrib.auth.models import User
from django.conf import settings
from django.utils.functional import lazy

from jazzpos.helpers import get_customertype_for_choices
from jazzpos.models import CustomerType

#from kecupu.pos.exceptions import NullTotalException

# Create your models here.

ORDER_STATUS_NEW = 0
ORDER_STATUS_CONFIRM = 1
ORDER_STATUS_CANCEL = 2
ORDER_STATUS_COMPLETE = 3

ORDER_STATUS_CHOICES = (
    (ORDER_STATUS_NEW, 'Baru'),
    (ORDER_STATUS_CONFIRM, 'Sah'),
    (ORDER_STATUS_CANCEL, 'Batal'),
    (ORDER_STATUS_COMPLETE, 'Selesai'),
)

PAYMENT_METHOD_CHOICES = (
    ('TUNAI', 'TUNAI'),
    ('CEK', 'CEK'),
    ('KOMISEN', 'KOMISEN'),
)

def get_customertype_for_choices():
    outer = []
    ctypes = CustomerType.objects.all()
    for ctype in ctypes:
        inner = (ctype.name, ctype.description)
        outer.append(inner)
    return outer

Model = models.Model

class Item(Model):
    ITEM_STATUS_ACTIVE = 1
    ITEM_STATUS_INACTIVE = 0
    ITEM_STATUS_CHOICES = (
        (ITEM_STATUS_ACTIVE, 'Aktif'),
        (ITEM_STATUS_INACTIVE, 'Tidak Aktif'),
    )

    name = models.CharField(max_length=255, unique=True)
    price_cost = models.DecimalField(max_digits=7, decimal_places=2)
    price_sale = models.DecimalField(max_digits=7, decimal_places=2)
    komisen = models.DecimalField(max_digits=7, decimal_places=2, default=0)
    komisen_ahli = models.DecimalField(max_digits=7, decimal_places=2, default=0)
    discount = models.DecimalField(max_digits=7,
                                   decimal_places=2,
                                   default='0.00')
    description = models.TextField(blank=True)
    stock_threshold = models.IntegerField(default=10)
    category = models.CharField(max_length=255)
    status = models.IntegerField(default=1, choices=ITEM_STATUS_CHOICES)

    def save(self, *args, **kwargs):
        self.price_cost = str(self.price_cost)
        self.price_sale = str(self.price_sale)
        self.discount = str(self.discount)
        super(Item, self).save(*args, **kwargs)

    def total_stock(self):
        qs = self.stock_set.aggregate(models.Sum('qty'))
        total = qs['qty__sum'] if qs['qty__sum'] is not None else 0

        qs = self.orderitem_set.aggregate(models.Sum('qty'))
        total_ordered = qs['qty__sum'] if qs['qty__sum'] is not None else 0

        stock_in_hand = total - total_ordered
        return stock_in_hand

    def get_price(self, customertype=None):
        # TODO: Optimize - this will run a query for each item
        try:
            itemprice = ItemPrice.objects.get(item=self, customertype=customertype)
            price = itemprice.price
        except ItemPrice.DoesNotExist:
            price = self.price_sale

        return price

    def __getattr__(self, name):
        if name.startswith('itemprice_'):
            customertype = name.replace('itemprice_', '')
            try:
                price = self.itemprice_set.get(customertype__name=customertype).price
                return price
            except Exception:
                return None
        return super(Item, self).__getattr__(self, name)

    def __unicode__(self):
        return self.name

class Stock(Model):
    qty = models.IntegerField(verbose_name='Kuantiti')
    created = models.DateTimeField()
    item = models.ForeignKey(Item)
    notes = models.TextField(blank=True)

class Order(Model):
    STATUS_NEW = 0
    STATUS_CONFIRM = 1
    STATUS_CANCEL = 2
    STATUS_COMPLETE = 3

    STATUS_CHOICES = (
        (STATUS_NEW, 'Baru'),
        (STATUS_CONFIRM, 'Sah'),
        (STATUS_CANCEL, 'Batal'),
        (STATUS_COMPLETE, 'Selesai'),
    )

    transaction_date = models.DateTimeField(verbose_name='Tarikh Transaksi')
    payment_due_date = models.DateTimeField(verbose_name='Tarikh Bayaran')
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    customer = models.ForeignKey(settings.XPOS_CUSTOMER_MODEL)
    items = models.ManyToManyField(Item, through='OrderItem')
    total = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
    total_discount = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
    status = models.IntegerField(default=0, choices=ORDER_STATUS_CHOICES)
    order_type = models.CharField(max_length=20, verbose_name='Kategori')
    store = models.ForeignKey('jazzpos.Store')

    def save(self, *args, **kwargs):
        orderitems = self.orderitem_set.all()
        if len(orderitems) == 0:
            self.total = '0.00'
        else:
            self.total = reduce((lambda x,y: x+y), [orderitem.total for orderitem in orderitems])
            self.total_discount = reduce(
                (lambda x,y: x+y),
                [orderitem.total_discount for orderitem in orderitems]
            )
        super(Order, self).save(*args, **kwargs)

    def total_after_discount(self):
        return self.total - self.total_discount

    def total_payment(self):
        qs = self.payment_set.filter(order=self.id)
        qs = qs.aggregate(total_payment=models.Sum('amount'))
        total = qs['total_payment']
        if not total:
            total = Decimal('0.00')

        return total

    def get_order_type_display(self):
        order_types = get_customertype_for_choices()
        for row in order_types:
            order_type, description = row
            if self.order_type == order_type:
                return description
        return self.order_type

    def is_new(self):
        return self.status == ORDER_STATUS_NEW

    def is_confirm(self):
        return self.status == ORDER_STATUS_CONFIRM

    def is_cancel(self):
        return self.status == ORDER_STATUS_CANCEL

    def is_complete(self):
        return self.status == ORDER_STATUS_COMPLETE

class ItemPrice(Model):
    item = models.ForeignKey('xpos.Item') # has to avoid cyclic import
    customertype = models.ForeignKey(CustomerType)
    price = models.DecimalField(max_digits=7, decimal_places=2)

    class Meta:
        unique_together = ('item', 'customertype')

    def __unicode__(self):
        return '%s-%s' % (self.item.name, self.customertype.description)

class OrderItem(Model):
    item = models.ForeignKey(Item)
    order = models.ForeignKey(Order)
    qty = models.IntegerField()
    price = models.DecimalField(max_digits=7, decimal_places=2)
    discount = models.DecimalField(max_digits=7,
                                   decimal_places=2,
                                   default=Decimal('0.00'))
    total = models.DecimalField(max_digits=7, decimal_places=2)
    total_discount = models.DecimalField(max_digits=7, decimal_places=2)

    class Meta:
        unique_together = ('item', 'order')

    def get_price(self):
        if self.price is not None:
            return self.price

        try:
            itemprice = ItemPrice.objects.get(item=self.item, customertype=self.order.order_type)
            price = itemprice.price
        except ItemPrice.DoesNotExist:
            price = self.item.price_sale

        return price

    def save(self, *args, **kwargs):
        price = self.get_price()
        self.price = price
        self.total = price * int(self.qty)
        self.total_discount = self.discount * int(self.qty)

        if self.total == 0: self.total = Decimal('0.00')
        if self.total_discount == 0: self.total_discount = Decimal('0.00')
        if self.discount == 0: self.discount = Decimal('0.00')
        super(OrderItem, self).save(*args, **kwargs)

    def total_after_discount(self):
        return self.total - self.total_discount

class Payment(Model):
    order = models.ForeignKey(Order)
    created = models.DateTimeField()
    modified = models.DateTimeField()
    method = models.CharField(max_length=50, choices=PAYMENT_METHOD_CHOICES)
    checque_no = models.CharField(max_length=255, blank=True)
    amount = models.DecimalField(max_digits=7, decimal_places=2)
    notes = models.TextField(null=True, blank=True)
    status = models.IntegerField(null=True, blank=True)
    store = models.ForeignKey('jazzpos.Store')

    def save(self, *args, **kwargs):
        if self.created is None:
            self.created = datetime.now()
        if self.modified is None:
            self.modified = datetime.now()
        super(Payment, self).save(*args, **kwargs)

def update_order_total(sender, **kwargs):
    order_item = kwargs['instance']
    order = order_item.order
    order.total = order.orderitem_set.aggregate(Sum('total'))['total__sum']
    order.save()

pos_model_signals.post_save.connect(update_order_total, sender=OrderItem)

def add_payment(order, data):
    payment = Payment(
        order = order,
        method = 'cash',
        amount = data['amount'],
        notes = data['notes']
    )
    payment.save()

def get_class(django_path):
    from django.utils.importlib import import_module
    app, model_name = django_path.split('.')
    models_module = import_module('%s.models' % (app))
    return getattr(models_module, model_name)

def get_previous_order_total(customer, current_date, store=None):
    qs = Order.objects.filter(customer=customer)
    qs = qs.filter(transaction_date__lt=current_date)
    qs = qs.exclude(status=ORDER_STATUS_CANCEL)
    qs = qs.exclude(status=ORDER_STATUS_NEW)

    if store:
        qs = qs.filter(store=store)

    previous_order_total = qs.aggregate(total=Sum('total'))['total']
    if previous_order_total:
        return previous_order_total
    return Decimal('0.00')

def get_previous_payment_total(customer, current_date, store=None):
    qs = Payment.objects.filter(order__customer=customer)
    qs = qs.filter(created__lt=current_date)

    if store:
        qs = qs.filter(store=store)

    previous_payment_total = qs.aggregate(total=Sum('amount'))['total']
    if previous_payment_total:
        return previous_payment_total
    return Decimal('0.00')

def calculate_total_sale(transactions):
    total = 0
    for transaction in transactions:
        if transaction['type'] == 'debit':
            total += transaction['amount']
    return total

def calculate_total_cash_payment(transactions):
    total = 0
    for transaction in transactions:
        if transaction['type'] == 'credit' and transaction['method'] == 'TUNAI':
            total += transaction['amount']
    return total

def calculate_total_checque_payment(transactions):
    total = 0
    for transaction in transactions:
        if transaction['type'] == 'credit' and transaction['method'] == 'CEK':
            total += transaction['amount']
    return total

def get_all_transactions(store, customer=None, start_date=None, end_date=None):
    qs = Order.objects.filter(store=store)

    if customer:
        qs = qs.filter(customer=customer)
    if start_date and end_date:
        qs = qs.filter(transaction_date__gte=start_date, transaction_date__lte=end_date)

    qs = qs.exclude(status=ORDER_STATUS_CANCEL)
    qs = qs.exclude(status=ORDER_STATUS_NEW)

    transactions = []
    for order in qs:
        txn = {}
        txn['item'] = order
        txn['date'] = order.transaction_date
        item_lists = [order_item.name for order_item in order.items.all()]
        txn['description'] = "Order #%d - %s" % (order.id, " ".join(item_lists))
        txn['amount'] = order.total
        txn['type'] = 'debit'
        transactions.append(txn)

    qs = Payment.objects.filter(order__store=store)
    if customer:
        qs = qs.filter(order__customer=customer)
    if start_date and end_date:
        qs = qs.filter(created__gte=start_date, created__lte=end_date)

    for payment in qs:
        txn = {}
        txn['item'] = payment
        txn['date'] = payment.created
        txn['description'] = "Bayaran untuk Order #%d" % (payment.order.id)
        txn['amount'] = payment.amount
        txn['type'] = 'credit'
        txn['method'] = payment.method
        transactions.append(txn)
    transactions.sort(key=lambda item: item['date'])
    return transactions


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Oct 10 20:15:38 2021

@author: chenhanchuan
"""

import numpy as np
import matplotlib.pyplot as plt
data = np.genfromtxt("/Users/chenhanchuan/Desktop/DS112/corporateSales.csv", delimiter = ",")

IQ = data[:,0]
Complaint = data[:,1]
Ethical = data[:,2]

#r = np.corrcoef(IQ,Complaint)

#plt.plot(IQ, Complaint, "o")
#plt.xlabel("IQ")
#plt.ylabel("Complaint")
#plt.title("r = {:.3f}".format(r[0,1]))

medianComplaint = np.median(Complaint)
meanIQ = np.mean(IQ)
MADComplaint = np.mean(np.absolute(Complaint-np.mean(Complaint)))
medianIQ = np.median(IQ)
stdEthical = np.std(Ethical)
stdIQ = np.std(IQ)
medianEthical = np.median(Ethical)

#r1 = np.corrcoef(Complaint, Ethical)
#plt.plot(Complaint, Ethical, "o")
#plt.xlabel("Complaint")
#plt.ylabel("Ethical")
#plt.title("r1 = {:.3f}".format(r1[0,1]))

r2 = np.corrcoef(IQ, Ethical)
plt.plot(IQ, Ethical, "o")
plt.xlabel("IQ")
plt.ylabel("Ethical")
plt.title("r2 = {:.3f}".format(r2[0,1]))


import argparse
import os
import platform
import shutil
import time
from pathlib import Path

import cv2
import torch
import torch.backends.cudnn as cudnn
from numpy import random

from models.experimental import attempt_load
from utils.datasets import LoadStreams, LoadImages
from utils.general import (
    check_img_size, non_max_suppression, apply_classifier, scale_coords, xyxy2xywh, plot_one_box, strip_optimizer)
from utils.torch_utils import select_device, load_classifier, time_synchronized

coco_class_name = [
    'person', 'cellphone', 'identification', 'notebook', 'face', 'chest'
]

coco_chinese_name = {
    'person': '人',
    'cellphone': '手机',
    'identification': '证件',
    'notebook': '笔记本',
    'face': '脸',
    'chest': '胸'
}

colors = [(187, 127, 77), (212, 82, 94), (118, 194, 101), (59, 154, 176),
          (255, 215, 0), (255, 250, 250)]

class_colors = {}
for i in range(len(coco_class_name)):
    class_name = coco_class_name[i]
    color = colors[i]
    class_colors[class_name] = color

def a_in_b(a,b):
    #a:xywh b:xyxy
    if a[0]>b[0] and a[0]<b[2] and a[1]>b[1] and a[1]<b[3]:
        return True
    else:
        return False

def filter_items(det, names, gn, keep_height=0.3):
    people = {}
    i = 0
    face_list = []
    chest_list = []
    identification_list = []

    results = []

    if det is not None and len(det):
        for *xyxy, conf, cls in det:

            class_name = names[int(cls)]
            xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) /
                    gn).view(-1).tolist()  #xy center

            center = (xyxy2xywh(torch.tensor(xyxy).view(
                1, 4))).view(-1).tolist()[:2]  #xy center
            if xywh[1] > keep_height:  # y在keep_height 下面
                if class_name == 'person':
                    people[i] = {
                        'xyxy': torch.tensor(xyxy).tolist(),
                        'face': False,
                        'chest': False,
                        'identification': False
                    }
                    i += 1
                elif class_name == 'face':
                    face_list.append(center)
                elif class_name == 'chest':
                    chest_list.append(center)
                elif class_name == 'identification':
                    identification_list.append(center)

    for person_id, person in people.items():
        person_location = person['xyxy']
        #if identification is in person
        if len(identification_list):
            for identification in identification_list:
                if a_in_b(identification,person_location):
                    person['identification']=True
        # tell if this person has the front face
        if len(face_list):
            for face in face_list:
                if a_in_b(face, person_location):
                    person['face']=True
        #tell if one can see the chest
            if len(chest_list):
                for chest in chest_list:
                    if a_in_b(chest, person_location):
                        person['chest']=True

    people_not_wear_id=[]
    for person_id, person in people.items():
        if person['face'] and person['chest'] and not person['identification']:
            person['not_wear_identification']=True
            people_not_wear_id.append(person['xyxy'])

    if det is not None and len(det):
        for *xyxy, conf, cls in det:
            _ = torch.tensor(xyxy).tolist()
            class_name = names[int(cls)]
            if class_name == 'person' and _ in people_not_wear_id:
                CN_class_name = '未佩戴证件'
            else:
                CN_class_name = coco_chinese_name[class_name]
            color = class_colors[class_name]
            _.extend([CN_class_name, conf.item(), color])
            results.append(_)

    return results

def detect(save_img=False):
    out, source, weights, view_img, save_txt, imgsz = \
        opt.output, opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size
    webcam = source == '0' or source.startswith('rtsp') or source.startswith('http') or source.endswith('.txt')

    # Initialize
    device = select_device(opt.device)
    if os.path.exists(out):
        shutil.rmtree(out)  # delete output folder
    os.makedirs(out)  # make new output folder
    half = device.type != 'cpu'  # half precision only supported on CUDA

    x = torch.cuda.FloatTensor(256, 1024, 1000)
    del x

    # Load model
    model = attempt_load(weights, map_location=device)  # load FP32 model
    imgsz = check_img_size(imgsz, s=model.stride.max())  # check img_size
    if half:
        model.half()  # to FP16

    # Second-stage classifier
    classify = False
    if classify:
        modelc = load_classifier(name='resnet101', n=2)  # initialize
        modelc.load_state_dict(torch.load('weights/resnet101.pt', map_location=device)['model'])  # load weights
        modelc.to(device).eval()

    # Set Dataloader
    vid_path, vid_writer = None, None
    if webcam:
        view_img = True
        cudnn.benchmark = True  # set True to speed up constant image size inference
        dataset = LoadStreams(source, img_size=imgsz)
    else:
        save_img = False
        view_img = True
        dataset = LoadImages(source, img_size=imgsz)

    save_vid = True
    if save_vid:
        fourcc = 'MJPG'  # output video codec
        fps = 25
        w = int(1920)
        h = int(1080)
        vid_writer = cv2.VideoWriter('test.avi', cv2.VideoWriter_fourcc(*fourcc), fps, (w, h))

    # Get names and colors
    names = model.module.names if hasattr(model, 'module') else model.names
    colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(names))]

    # Run inference
    t0 = time.time()
    img = torch.zeros((1, 3, imgsz, imgsz), device=device)  # init img
    _ = model(img.half() if half else img) if device.type != 'cpu' else None  # run once

    for path, img, im0s, vid_cap in dataset:

        # imgs, im0s_list = img_split(img, im0s)
        # img = imgs[2]
        # im0s = im0s_list[2]
        # for index_img in range(len(imgs)):
        #     img = imgs[index_img]
        #     im0s = im0s_list[index_img]

        img = torch.from_numpy(img).to(device)
        img = img.half() if half else img.float()  # uint8 to fp16/32
        img /= 255.0  # 0 - 255 to 0.0 - 1.0
        if img.ndimension() == 3:
            img = img.unsqueeze(0)

        # Inference
        t1 = time_synchronized()
        pred = model(img, augment=opt.augment)[0]

        # Apply NMS
        pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
        t2 = time_synchronized()

        # Apply Classifier
        if classify:
            pred = apply_classifier(pred, modelc, img, im0s)

        # Process detections
        for i, det in enumerate(pred):  # detections per image
            if webcam:  # batch_size >= 1
                p, s, im0 = path[i], '%g: ' % i, im0s[i].copy()
            else:
                p, s, im0 = path, '', im0s

            filter_img = im0.copy()

            save_path = str(Path(out) / Path(p).name)
            txt_path = str(Path(out) / Path(p).stem) + ('_%g' % dataset.frame if dataset.mode == 'video' else '')
            s += '%gx%g ' % img.shape[2:]  # print string
            gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
            if det is not None and len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()

                # Print results
                for c in det[:, -1].unique():
                    n = (det[:, -1] == c).sum()  # detections per class
                    s += '%g %ss, ' % (n, names[int(c)])  # add to string

                # Write results
                for *xyxy, conf, cls in det:
                    if save_txt:  # Write to file
                        xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                        with open(txt_path + '.txt', 'a') as f:
                            f.write(('%g ' * 5 + '\n') % (cls, *xywh))  # label format

                    if save_img or view_img:  # Add bbox to image
                        label = '%s %.2f' % (names[int(cls)], conf)
                        plot_one_box(xyxy, im0, label=label, color=colors[int(cls)], line_thickness=3)

            # Print time (inference + NMS)
            print('%sDone. (%.3fs)' % (s, t2 - t1))

            filtered_results = filter_items(det, names, gn)

            for i in filtered_results:
                if i[4] == '未佩戴证件':
                    label='no ID'
                else:
                    label=''
                plot_one_box(i[:4],
                             filter_img,
                             label=label,
                             color=i[-1],
                             line_thickness=3)

            # Stream results
            if view_img:
                cv2.imshow(p, im0)
                cv2.imshow('', filter_img)

            # Save results (image with detections)
            if save_vid:
                vid_writer.write(im0)

            if save_img:
                if dataset.mode == 'images':
                    cv2.imwrite(save_path, im0)

        if cv2.waitKey(1) & 0xFF == ord('q'):

            if save_vid:
                vid_writer.release()
            cv2.destroyAllWindows()
            break

    if save_txt or save_img:
        print('Results saved to %s' % Path(out))
        if platform == 'darwin' and not opt.update:  # MacOS
            os.system('open ' + save_path)

    print('Done. (%.3fs)' % (time.time() - t0))

if __name__ == '__main__':

    ip = "172.23.0.37"
    video_path = 'rtsp://admin:123456789bit@' + ip + '/main/Channels/1'
    # video_path = '/media/yy/DATA/data/vid/monitor/monitor1.mp4'

    parser = argparse.ArgumentParser()
    parser.add_argument('--weights',
                        nargs='+',
                        type=str,
                        default='chest.pt',
                        help='model.pt path(s)')
    parser.add_argument('--source',
                        type=str,
                        default=video_path,
                        help='source')  # file/folder, 0 for webcam
    parser.add_argument('--output', type=str, default='inference/output', help='output folder')  # output folder
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.3, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
    parser.add_argument('--device',
                        default='1',
                        help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    opt = parser.parse_args()
    print(opt)

    with torch.no_grad():
        if opt.update:  # update all models (to fix SourceChangeWarning)
            for opt.weights in ['yolov5s.pt', 'yolov5m.pt', 'yolov5l.pt', 'yolov5x.pt']:
                detect()
                strip_optimizer(opt.weights)
        else:
            detect()


import matplotlib.pyplot as plt
import csv
import numpy as np

n=[]
temp=[]
humi=[]
ave_temp=[]
ave_humi=[]

with open('sensordata.txt','r') as csvfile:
    data=csv.reader(csvfile,delimiter=',')
    for row in data:
        n.append(int(row[0]))
        temp.append(int(row[1]))
        humi.append(int(row[2]))

mean_temp=int(np.mean(temp))
mean_humi=int(np.mean(humi))
ave_temp=[mean_temp]*10
ave_humi=[mean_humi]*10

plt.plot(n,temp,label='temperature')
plt.plot(n,humi,label='humidity')
plt.plot(n,ave_temp,label='mean temperature')
plt.plot(n,ave_humi,label='mean humidity')
plt.xlabel('last 10 samples, 2 sec intervals')
plt.ylabel('temperature in deg C & humidity in %')
plt.legend()
plt.show()


import os

from oslo_config import cfg
from oslo_db import options as db_options
import oslo_messaging as messaging
from paste import deploy

from vnfsvc.api.v2 import attributes
from vnfsvc.common import utils
from vnfsvc.openstack.common import log as logging
from vnfsvc import version
from vnfsvc.common import rpc as n_rpc
from vnfsvc.openstack.common.gettextutils import _

LOG = logging.getLogger(__name__)

core_opts = [
    cfg.StrOpt('bind_host', default='0.0.0.0',
               help=_("The host IP to bind to")),
    cfg.IntOpt('bind_port', default=9010,
               help=_("The port to bind to")),
    cfg.StrOpt('api_paste_config', default="api-paste.ini",
               help=_("The API paste config file to use")),
    cfg.StrOpt('api_extensions_path', default="",
               help=_("The path for API extensions")),
    cfg.StrOpt('policy_file', default="policy.json",
               help=_("The policy file to use")),
    cfg.StrOpt('auth_strategy', default='keystone',
               help=_("The type of authentication to use")),
    cfg.StrOpt('core_plugin',
               help=_("The core plugin Vnfsvc will use")),
    cfg.BoolOpt('allow_bulk', default=True,
                help=_("Allow the usage of the bulk API")),
    cfg.BoolOpt('allow_pagination', default=False,
                help=_("Allow the usage of the pagination")),
    cfg.BoolOpt('allow_sorting', default=False,
                help=_("Allow the usage of the sorting")),
    cfg.StrOpt('pagination_max_limit', default="-1",
               help=_("The maximum number of items returned in a single "
                      "response, value was 'infinite' or negative integer "
                      "means no limit")),
    cfg.StrOpt('host', default=utils.get_hostname(),
               help=_("The hostname Vnfsvc is running on")),
    cfg.StrOpt('nova_url',
               default='http://127.0.0.1:8774/v2',
               help=_('URL for connection to nova')),
    cfg.StrOpt('nova_admin_username',
               help=_('Username for connecting to nova in admin context')),
    cfg.StrOpt('nova_admin_password',
               help=_('Password for connection to nova in admin context'),
               secret=True),
    cfg.StrOpt('nova_admin_tenant_id',
               help=_('The uuid of the admin nova tenant')),
    cfg.StrOpt('nova_admin_auth_url',
               default='http://localhost:5000/v2.0',
               help=_('Authorization URL for connecting to nova in admin '
                      'context')),
    cfg.StrOpt('nova_ca_certificates_file',
               help=_('CA file for novaclient to verify server certificates')),
    cfg.BoolOpt('nova_api_insecure', default=False,
                help=_("If True, ignore any SSL validation issues")),
    cfg.StrOpt('nova_region_name',
               help=_('Name of nova region to use. Useful if keystone manages'
                      ' more than one region.')),
    cfg.IntOpt('send_events_interval', default=2,
               help=_('Number of seconds between sending events to nova if '
                      'there are any events to send.')),
]

core_cli_opts = [
    cfg.StrOpt('state_path',
               default='/var/lib/nfvsvc',
               help=_("Where to store NFV Service state files. "
                      "This directory must be writable by the agent.")),
]

# Register the configuration options
cfg.CONF.register_opts(core_opts)
cfg.CONF.register_cli_opts(core_cli_opts)

# Ensure that the control exchange is set correctly
messaging.set_transport_defaults(control_exchange='vnfsvc')
_SQL_CONNECTION_DEFAULT = 'sqlite://'
# Update the default QueuePool parameters. These can be tweaked by the
# configuration variables - max_pool_size, max_overflow and pool_timeout
db_options.set_defaults(cfg.CONF,
                        connection=_SQL_CONNECTION_DEFAULT,
                        sqlite_db='', max_pool_size=10,
                        max_overflow=20, pool_timeout=10)

def init(args, **kwargs):
    cfg.CONF(args=args, project='vnfsvc',
             version='%%prog %s' % version.version_info.release_string(),
             **kwargs)

    # FIXME(ihrachys): if import is put in global, circular import
    # failure occurs
    from vnfsvc.common import rpc as n_rpc
    n_rpc.init(cfg.CONF)

def setup_logging(conf):
    """Sets up the logging options for a log with supplied name.

    :param conf: a cfg.ConfOpts object
    """
    product_name = "vnfsvc"
    logging.setup(product_name)
    LOG.info(_("Logging enabled!"))

def load_paste_app(app_name):
    """Builds and returns a WSGI app from a paste config file.

    :param app_name: Name of the application to load
    :raises ConfigFilesNotFoundError when config file cannot be located
    :raises RuntimeError when application cannot be loaded from config file
    """

    config_path = cfg.CONF.find_file(cfg.CONF.api_paste_config)
    if not config_path:
        raise cfg.ConfigFilesNotFoundError(
            config_files=[cfg.CONF.api_paste_config])
    config_path = os.path.abspath(config_path)
    LOG.info(_("Config paste file: %s"), config_path)

    try:
        app = deploy.loadapp("config:%s" % config_path, name=app_name)
    except (LookupError, ImportError):
        msg = (_("Unable to load %(app_name)s from "
                 "configuration file %(config_path)s.") %
               {'app_name': app_name,
                'config_path': config_path})
        LOG.exception(msg)
        raise RuntimeError(msg)
    return app


#!/usr/bin/python3
# The python command server is actually located in bukkit/src/main/resources/cmdsvr
# Here we just start it with appropiate environment

import os
import sys
from os.path import abspath, dirname, join
from argparse import ArgumentParser
from subprocess import Popen

parent_dir = dirname(dirname(dirname(abspath(__file__))))
server_dir = join("bukkit", "src", "main", "resources", "cmdsvr")
server_path = join(parent_dir, server_dir, "pycmdsvr.py")
parser = ArgumentParser()
parser.add_argument("--apihost", default="localhost", help="api host")
parser.add_argument("--apiport", default="4711", help="api port")
parser.add_argument("--svrhost", default="localhost", help="server host")
parser.add_argument("--svrport", default="4731", help="server port")
args = parser.parse_args()
env = {"PYTHONHASHSEED": "6666",
       "JRP_API_HOST": args.apihost,
       "JRP_API_PORT": args.apiport,
       "JRP_CMDSVR_HOST": args.svrhost,
       "JRP_CMDSVR_PORT": args.svrport}
if "SYSTEMROOT" in os.environ:
    env['SYSTEMROOT'] = os.environ['SYSTEMROOT']

print("Python:", sys.executable)
print("cmdsvr:", server_path)
Popen([sys.executable, server_path], env=env)


import streamlit as st
import pandas as pd
import time
import plotly.graph_objs as go

#
# ページのセッティング
#
st.set_page_config(
    page_title="Streamlit Examples",
    page_icon="🧊",
    layout="wide",
    initial_sidebar_state="expanded",
    menu_items={
        'Get Help': 'https://www.extremelycoolapp.com/help',
        'Report a bug': "https://www.extremelycoolapp.com/bug",
        'About': "# This is a header. This is an *extremely* cool app!"
    }
)

def mainview():
    st.markdown("# Streamlit Examples Demo")

    # -------------------------------------------------------
    # タイトルとテキストの表示
    # -------------------------------------------------------
    st.markdown("## 文字表示")
    st.markdown("""
    markdownでテキストやヘッダを記述することができます．markdown以外にもタイトルの表示には
    `st.title()`，テキストの表示には`st.write()`を使うことができます．
    `st.write()`はテキスト以外にもデータフレームや数値など様々な形式を汎用的に扱えます．

    markdownでのコードブロックの表示や数式の表示にも対応しています．
    ```python
    print("Hello World")
    ```
    $$
    e^{i \pi} + 1 = 0
    $$

    コードは`st.code()`，数式は`st.latex()`でも表示可能です．また，`st.echo()`を用いると
    コードを実行しつつ表示することが可能です．
    """)

    st.markdown("## メッセージの装飾")
    st.info('This is a purely informational message')
    st.warning('This is a warning')
    st.error('This is an error')
    st.success('This is a success message!')
    e = RuntimeError('This is an exception of type RuntimeError')
    st.exception(e)

    #
    # multipage
    #
    st.markdown("## multipage")

if __name__ == "__main__":
    mainview()


from selenium import webdriver
from selenium.webdriver.common.keys import Keys#导入的键盘
import time
#可能需要手动添加路径
chromedriverAddress = r"C:\Users\lenovo1\AppData\Local\Programs\Python\Python37\Lib\site-packages\selenium\webdriver\chrome\chromedriver.exe"
driver = webdriver.Chrome(executable_path=chromedriverAddress)
#写这一行的时候报错了，可见这里配置：https://blog.csdn.net/weixin_43746433/article/details/95237254

url = "http://www.baidu.com"
driver.get(url)
text1 = driver.find_element_by_id("wrapper").text#得到这个元素的值
print(text1)
print(driver.title)
#得到页面的快照
driver.save_screenshot("index,png")

driver.find_element_by_id("kw").send_keys(u"大熊猫")#向这个id输入“大熊猫”（实际上这里的kw的id就是查找的字段）
driver.find_element_by_id("su").click()#点击操作（实际上就是上一步键入信息，下一步我们进行检索）
time.sleep(5)
driver.save_screenshot("daxiongmao.png")
#获取当前界面的cookie
print(driver.get_cookies())
#模拟输入两个按键ctrl+a
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
#模拟ctrl + x,剪切操作
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')
driver.find_element_by_id("kw").send_keys(u"航空母舰")
driver.save_screenshot("hangmu.png")
driver.find_element_by_id("su").send_keys(Keys.RETURN)
time.sleep(5)
driver.save_screenshot("hangmu2.png")
#清空输入框,clear
driver.find_element_by_id("kw").clear()

#关闭浏览器
driver.quit()


#!/usr/bin/env python3
import itertools

import utils

class Challenge(utils.BaseChallenge):
    def solve(self, _input, debug=False):
        """
        >>> Challenge().default_solve()
        375
        """
        return PathSet.from_paths_text(_input).get_black_count()

class PathSet:
    @classmethod
    def from_paths_text(cls, paths_text):
        """
        >>> PathSet.from_paths_text(
        ...     "sesenw\\n"
        ...     "neeene\\n"
        ...     "seswne\\n"
        ... )
        PathSet([Path(('se', 'se', 'nw')), Path(('ne', 'e', 'e', 'ne')),
            Path(('se', 'sw', 'ne'))])
        """
        non_emtpy_lines = filter(None, paths_text.splitlines())
        return cls(list(map(Path.from_path_text, non_emtpy_lines)))

    def __init__(self, paths):
        self.paths = paths

    def __repr__(self):
        return f"{type(self).__name__}({self.paths})"

    def get_black_count(self, start=(0, 0)):
        """
        >>> PathSet.from_paths_text(
        ...     "sesenwnenenewseeswwswswwnenewsewsw\\n"
        ...     "neeenesenwnwwswnenewnwwsewnenwseswesw\\n"
        ...     "seswneswswsenwwnwse\\n"
        ...     "nwnwneseeswswnenewneswwnewseswneseene\\n"
        ...     "swweswneswnenwsewnwneneseenw\\n"
        ...     "eesenwseswswnenwswnwnwsewwnwsene\\n"
        ...     "sewnenenenesenwsewnenwwwse\\n"
        ...     "wenwwweseeeweswwwnwwe\\n"
        ...     "wsweesenenewnwwnwsenewsenwwsesesenwne\\n"
        ...     "neeswseenwwswnwswswnw\\n"
        ...     "nenwswwsewswnenenewsenwsenwnesesenew\\n"
        ...     "enewnwewneswsewnwswenweswnenwsenwsw\\n"
        ...     "sweneswneswneneenwnewenewwneswswnese\\n"
        ...     "swwesenesewenwneswnwwneseswwne\\n"
        ...     "enesenwswwswneneswsenwnewswseenwsese\\n"
        ...     "wnwnesenesenenwwnenwsewesewsesesew\\n"
        ...     "nenewswnwewswnenesenwnesewesw\\n"
        ...     "eneswnwswnwsenenwnwnwwseeswneewsenese\\n"
        ...     "neswnwewnwnwseenwseesewsenwsweewe\\n"
        ...     "wseweeenwnesenwwwswnew\\n"
        ... ).get_black_count()
        10
        """
        flipped_destinations = self.get_flipped_destinations(start)
        return len(flipped_destinations)

    def get_flipped_destinations(self, start=(0, 0)):
        destinations = self.get_destinations(start)
        flip_counts = {
            destination: len(list(items))
            for destination, items in itertools.groupby(sorted(destinations))
        }
        return [
            destination
            for destination in destinations
            if flip_counts[destination] % 2 == 1
        ]

    def get_destinations(self, start=(0, 0)):
        """
        >>> PathSet.from_paths_text(
        ...     "sesenwnenenewseeswwswswwnenewsewsw\\n"
        ...     "neeenesenwnwwswnenewnwwsewnenwseswesw\\n"
        ...     "seswneswswsenwwnwse\\n"
        ...     "nwnwneseeswswnenewneswwnewseswneseene\\n"
        ...     "swweswneswnenwsewnwneneseenw\\n"
        ...     "eesenwseswswnenwswnwnwsewwnwsene\\n"
        ...     "sewnenenenesenwsewnenwwwse\\n"
        ...     "wenwwweseeeweswwwnwwe\\n"
        ...     "wsweesenenewnwwnwsenewsenwwsesesenwne\\n"
        ...     "neeswseenwwswnwswswnw\\n"
        ...     "nenwswwsewswnenenewsenwsenwnesesenew\\n"
        ...     "enewnwewneswsewnwswenweswnenwsenwsw\\n"
        ...     "sweneswneswneneenwnewenewwneswswnese\\n"
        ...     "swwesenesewenwneswnwwneseswwne\\n"
        ...     "enesenwswwswneneswsenwnewswseenwsese\\n"
        ...     "wnwnesenesenenwwnenwsewesewsesesew\\n"
        ...     "nenewswnwewswnenesenwnesewesw\\n"
        ...     "eneswnwswnwsenenwnwnwwseeswneewsenese\\n"
        ...     "neswnwewnwnwseenwseesewsenwsweewe\\n"
        ...     "wseweeenwnesenwwwswnew\\n"
        ... ).get_destinations()
        [(-2, 2), (-1, -3), (-2, 3), ...]
        """
        return [
            path.get_destination(start)
            for path in self.paths
        ]

class Path:
    DIRECTION_OFFSETS = {
        0: {
            'e': (1, 0),
            'se': (0, 1),
            'ne': (0, -1),
            'w': (-1, 0),
            'nw': (-1, -1),
            'sw': (-1, 1),
        },
        1: {
            'e': (1, 0),
            'se': (1, 1),
            'ne': (1, -1),
            'w': (-1, 0),
            'nw': (0, -1),
            'sw': (0, 1),
        },
    }
    INSTRUCTIONS = sorted(DIRECTION_OFFSETS[0])

    @classmethod
    def from_path_text(cls, path_text):
        """
        >>> Path.from_path_text("esenee")
        Path(('e', 'se', 'ne', 'e'))
        """
        instruction_path = ()
        while path_text:
            instruction = path_text[:2]
            if instruction not in cls.DIRECTION_OFFSETS[0]:
                instruction = path_text[:1]
                if instruction not in cls.DIRECTION_OFFSETS[0]:
                    raise Exception(
                        f"Unknown instruction '{instruction}', expected one "
                        f"of {', '.join(cls.INSTRUCTIONS)}")
            instruction_path += (instruction,)
            path_text = path_text[len(instruction):]

        return cls(instruction_path)

    @classmethod
    def add(cls, lhs, rhs):
        """
        >>> Path.add((0, 0), (0, 0))
        (0, 0)
        >>> Path.add((1, -2), (-3, 4))
        (-2, 2)
        """
        l_x, l_y = lhs
        r_x, r_y = rhs

        return l_x + r_x, l_y + r_y

    def __init__(self, direction_path):
        self.direction_path = direction_path

    def __repr__(self):
        return f"{type(self).__name__}({self.direction_path})"

    def get_destination(self, start=(0, 0)):
        """
        >>> Path.from_path_text("").get_destination()
        (0, 0)
        >>> Path.from_path_text("esenee").get_destination()
        (3, 0)
        >>> Path.from_path_text("esew").get_destination()
        (0, 1)
        >>> Path.from_path_text("nwwswee").get_destination()
        (0, 0)
        """
        position = start
        for instruction in self.direction_path:
            position = self.get_neighbour(position, instruction)

        return position

    @classmethod
    def get_neighbours(cls, position):
        return [
            cls.get_neighbour(position, instruction)
            for instruction in cls.INSTRUCTIONS
        ]

    @classmethod
    def get_neighbour(cls, position, instruction):
        _, y = position
        offset = cls.DIRECTION_OFFSETS[y % 2][instruction]
        position = cls.add(position, offset)

        return position

Challenge.main()
challenge = Challenge()


from logs import init_logs
init_logs.init()
#TODO:
#- Implement more advanced Counting Channels (Track several roles in one channel)
#- Split main.py into several files. probably utils.py, bot.py, commands.py, and maybe one file for every command
#-

from db import db
from events import events
from commands import commands as commands
import discord
from discord.ext import commands as discordCommands
from utils import config
from utils import utils

from logs.log import print
from DiscordOverrides.Bot import Bot

DEFAULT_PREFIX = config.DEFAULT_PREFIX
BOT_TOKEN = config.BOT_TOKEN
intents = discord.Intents.default()
# Intents.members is needed for the bot to be able to see what roles every member has
intents.members = True
# Intents.presences is needed for the bot to be able to see what members are online
intents.presences = True
def get_prefix(bot, message):
    return db.getPrefix(message.guild.id)

bot = Bot(command_prefix=get_prefix, intents=intents)

@bot.event
async def on_ready():
    global bot
    await events.on_ready(bot)

@bot.event
async def on_guild_join(guild):
    await events.on_guild_join(guild)

@bot.event
async def on_guild_leave(guild):
    await events.on_guild_leave(guild)

@bot.listen('on_message')
async def on_message(message):
    global bot
    await events.on_message(bot, message)

@bot.event
async def on_member_update(before, after):
    await events.on_member_update(before, after)

@bot.event
async def on_member_join(member):
    await events.on_member_join(member)

@bot.event
async def on_member_remove(member):
    await events.on_member_remove(member)

@bot.event
async def on_guild_channel_delete(channel):
    await events.on_guild_channel_delete(channel)

@bot.command(name="forceupdate", help="Forces an update to the Counting Channels in your guild")
async def forceUpdate(ctx):
    await commands.forceUpdate(ctx)

@bot.command(name="prefix", brief="Changes the bot's prefix", help=commands.prefixHelpText())
@discordCommands.has_permissions(manage_guild=True)
async def prefix(ctx, prefix):
    await commands.prefix(ctx, prefix)

@prefix.error
async def prefixError(ctx, error):
    await commands.prefixError(ctx, error)

@bot.command(name="create", brief="Creates a Counting Channel", help=commands.createHelpText())
@discordCommands.has_permissions(manage_channels=True)
async def create(ctx, name, role):
    await commands.create(ctx, name, role)

@create.error
async def createError(ctx, error):
    await commands.createError(ctx, error)

@bot.command(name="edit", brief="Changes what role a Counting Channel tracks", help=commands.editHelpText())
async def edit(ctx, name, role, newName):
    await commands.edit(ctx, name, role, newName)

@edit.error
async def editError(ctx, error):
    await commands.editError(ctx, error)

@bot.command(name="notify", brief="Signs your guild up for announcements about the bot's development and upcomming features", help=commands.notifyHelpText())
async def notify(ctx, channel):
    await commands.notify(ctx, channel)

@notify.error
async def notifyError(ctx, error):
    await commands.notifyError(ctx, error)
@bot.command(name="listchannels", help="Lists all the Counting Channels in your guild")
async def listChannels(ctx):
    await commands.listChannels(ctx)

@bot.command(name="listguilds", help="Debugging command - Lists all the guilds the bot is in")
@discordCommands.is_owner()
async def listGuilds(ctx):
    global bot
    await commands.listGuilds(ctx, bot)

@listGuilds.error
async def listGuildsError(ctx, error):
    await commands.listGuildsError(ctx, error)

@bot.command(name="listchannelsinallguilds", help="Debugging command - Lists all the channels in the guilds the bot is apart of")
@discordCommands.is_owner()
async def listChannelsInAllGuilds(ctx):
    global bot
    await commands.listChannelsInAllGuilds(ctx, bot)

@listChannelsInAllGuilds.error
async def listChannelsInAllGuildsError(ctx, error):
    await commands.listChannelsInAllGuildsError(ctx, error)

@bot.command(name="listroles", help="Lists all the roles in your guild, exists mostly for debugging")
async def listRoles(ctx):
    await commands.listRoles(ctx)

@listRoles.error
async def listRolesError(ctx, error):
    await commands.listRolesError(ctx, error)

@bot.command(name="repeat", help="Replies with what you typed")
async def repeat(ctx):
    await utils.printAndSend(ctx, "stat/help")

@repeat.error
async def repeatError(ctx, error):
    await utils.printAndSend(ctx ,error)

bot.run(BOT_TOKEN)


__author__ = 'Richard Lincoln, r.w.lincoln@gmail.com'

""" This script creates the plots published in Learning to Trade Power by
Richard Lincoln. """

import matplotlib
#matplotlib.use('WXAgg')#'TkAgg')

#matplotlib.rc('font', **{'family': 'sans-serif',
#                         'sans-serif': ['Computer Modern Sans serif']})
#matplotlib.rc('font', **{'family': 'serif', 'serif': ['Computer Modern Roman']})
#matplotlib.rc('text', usetex=True)

import random

from pylab import \
    figure, plot, xlabel, ylabel, legend, savefig, rcParams, clf, title, \
    xlim, ylim, show, errorbar, subplot, twinx, subplots_adjust, grid, gca

from matplotlib.ticker import IndexLocator, FixedLocator

from scipy import arange, sqrt, zeros, mean, std, r_
from scipy.io import mmread

from common import \
    get_winter_hourly, get_summer_hourly, get_spring_autumn_hourly, \
    get_weekly, get_daily

tex = False
paper = False

if not paper:
    matplotlib.rcParams['lines.linewidth'] = 0.5
    matplotlib.rcParams['axes.linewidth'] = 0.7

if tex:
    # Set up publication quality graphs.
    matplotlib.rc('font', **{'family': 'serif',
                             'serif': ['Computer Modern Roman']})

    if paper:
        fig_width = 6.15 # width in inches
        fig_height = 8.5 # height in inches
        params = {'backend': 'ps',
                  'axes.titlesize': 12,
                  'axes.labelsize': 10,
                  'text.fontsize': 10,
                  'legend.fontsize': 10,
                  'xtick.labelsize': 10,
                  'ytick.labelsize': 10,
                  'text.usetex': True,
                  'figure.figsize': [fig_width, fig_height]}
        rcParams.update(params)
    else:
        #fig_width_pt = 246.0  # Get this from LaTeX using \showthe\columnwidth
        #inches_per_pt = 1.0 / 72.27               # Convert pt to inch
        golden_mean = (sqrt(5) - 1.0) / 2.0 # Aesthetic ratio
        fig_width = 6.15#fig_width_pt * inches_per_pt  # width in inches
        fig_height = 10.0#fig_width * golden_mean      # height in inches
        fig_size = [fig_width, fig_height]
        params = {'backend': 'ps',
                  'axes.titlesize': 10,
                  'axes.labelsize': 10,
                  'text.fontsize': 10,
                  'legend.fontsize': 8,
                  'xtick.labelsize': 8,
                  'ytick.labelsize': 8,
                  'text.usetex': True,
        #          'markup': 'tex',
        #          'text.latex.unicode': True,
                  'figure.figsize': fig_size}
        rcParams.update(params)
else:
    params = {'axes.titlesize': 10,
              'axes.labelsize': 10,
              'text.fontsize': 8,
              'legend.fontsize': 8,
              'xtick.labelsize': 8,
              'ytick.labelsize': 8,
              'figure.figsize': (8, 10)}
    rcParams.update(params)

clr = ["black", "0.5", "0.8"]
ls = ["-"]#, ":", "--", "-."]
nc, ns = len(clr), len(ls)

def plot_results(results, ai, ylab, xlab="Time (h)"):
    nplot = len(results)

    for i, (result_mean, result_std, epsilon, lab, y2lab, y2max, y2min) in \
    enumerate(results):

        subplot(nplot, 1, i + 1)

        if i == nplot-1:
            xlabel(xlab)

        title(lab)

        x = arange(0.0, result_mean.shape[1], 1.0)
        y = result_mean[ai, :]
        e = result_std[ai, :]
        y2 = epsilon[ai, :]

#        plot(x, result_mean[ai, :],
#             color=clr[ai % nc],
#             linestyle=ls[ai % ns],
#             label=lab)

        errorbar(x, y, yerr=e, fmt='ko', linestyle="None",
                 label=ylab,
                 capsize=0, markersize=3)#, linewidth=0.2)
        ylabel(ylab)

        l = legend(loc="upper right")
        l.get_frame().set_linewidth(0.5)

        # Exploration rate plot.
        twinx()
        plot(x, y2, color="black", label=y2lab)
        ylabel(y2lab)
        if y2max is not None:
            ylim(ymax=y2max)
        if y2min is not None:
            ylim(ymin=y2min)

        l = legend(loc="lower right")
        l.get_frame().set_linewidth(0.5)

#        subplots_adjust(left=0.09, bottom=0.05, right=None,
#                        wspace=None, hspace=None)

def plot5_X(minor):
    re_epsilon = mmread("./out/ex5_%d_rotherev_epsilon.mtx" % minor)
    q_epsilon = mmread("./out/ex5_%d_q_epsilon.mtx" % minor)
    reinforce_epsilon = mmread("./out/ex5_%d_reinforce_epsilon.mtx" % minor)
    enac_epsilon = mmread("./out/ex5_%d_enac_epsilon.mtx" % minor)

    re_action_mean = mmread("./out/ex5_%d_rotherev_action_mean.mtx" % minor)
    re_action_std = mmread("./out/ex5_%d_rotherev_action_std.mtx" % minor)
    q_action_mean = mmread("./out/ex5_%d_q_action_mean.mtx" % minor)
    q_action_std = mmread("./out/ex5_%d_q_action_std.mtx" % minor)
    reinforce_action_mean = \
        mmread("./out/ex5_%d_reinforce_action_mean.mtx" % minor)
    reinforce_action_std = \
        mmread("./out/ex5_%d_reinforce_action_std.mtx" % minor)
    enac_action_mean = mmread("./out/ex5_%d_enac_action_mean.mtx" % minor)
    enac_action_std = mmread("./out/ex5_%d_enac_action_std.mtx" % minor)

    actions = [
        (re_action_mean, re_action_std, re_epsilon,
         "Roth-Erev", "Boltzmann Temperature", None, None),
        (q_action_mean, q_action_std, q_epsilon,
         "Q-Learning", "Epsilon", 1.0, 0.0),
        (reinforce_action_mean, reinforce_action_std, reinforce_epsilon,
         "REINFORCE", "Sigma", None, None),
        (enac_action_mean, enac_action_std, enac_epsilon,
         "ENAC", "Sigma", None, None)
    ]

    for ai in [0, 1]:
        figure(ai)
        plot_results(actions, ai, "Action (\%)", "Market Period")
        if tex:
            savefig('./out/fig5_%d_action_a%d.pdf' % (minor, ai + 1))
#            savefig('./out/fig5_%d_action_a%d.eps' % (minor, ai + 1))
        else:
            savefig('./out/fig5_%d_action_a%d.png' % (minor, ai + 1))

    re_reward_mean = mmread("./out/ex5_%d_rotherev_reward_mean.mtx" % minor)
    re_reward_std = mmread("./out/ex5_%d_rotherev_reward_std.mtx" % minor)
    q_reward_mean = mmread("./out/ex5_%d_q_reward_mean.mtx" % minor)
    q_reward_std = mmread("./out/ex5_%d_q_reward_std.mtx" % minor)
    reinforce_reward_mean = \
        mmread("./out/ex5_%d_reinforce_reward_mean.mtx" % minor)
    reinforce_reward_std = \
        mmread("./out/ex5_%d_reinforce_reward_std.mtx" % minor)
    enac_reward_mean = mmread("./out/ex5_%d_enac_reward_mean.mtx" % minor)
    enac_reward_std = mmread("./out/ex5_%d_enac_reward_std.mtx" % minor)

    rewards = [
        (re_reward_mean, re_reward_std, re_epsilon,
         "Roth-Erev", "Boltzmann Temperature", None, None),
        (q_reward_mean, q_reward_std, q_epsilon,
         "Q-Learning", "Epsilon", 1.0, 0.0),
        (reinforce_reward_mean, reinforce_reward_std, reinforce_epsilon,
         "REINFORCE", "Sigma", None, None),
        (enac_reward_mean, enac_reward_std, enac_epsilon,
         "ENAC", "Sigma", None, None)
    ]

    for ai in [0, 1]:
        figure(ai + 10)
        plot_results(rewards, ai, r"Reward (\verb+$+)", "Market Period")
        if tex:
            savefig('./out/fig5_%d_reward_a%d.pdf' % (minor, (ai + 1)))
#            savefig('./out/fig5_%d_reward_a%d.eps' % (minor, (ai + 1)))
        else:
            savefig('./out/fig5_%d_reward_a%d.png' % (minor, (ai + 1)))

#    if not tex:
#        show()

def plot5_1():
    plot5_X(1)

def plot5_2():
    plot5_X(2)

def plot5_1X(minor):
    params = {'figure.figsize': [6.15, 5.0]}
    rcParams.update(params)

    reinforce_epsilon = mmread("./out/ex5_%d_reinforce_epsilon.mtx" % minor)
    enac_epsilon = mmread("./out/ex5_%d_enac_epsilon.mtx" % minor)

    reinforce_action_mean = \
        mmread("./out/ex5_%d_reinforce_action_mean.mtx" % minor)
    reinforce_action_std = \
        mmread("./out/ex5_%d_reinforce_action_std.mtx" % minor)
    enac_action_mean = mmread("./out/ex5_%d_enac_action_mean.mtx" % minor)
    enac_action_std = mmread("./out/ex5_%d_enac_action_std.mtx" % minor)

    actions = [
        (reinforce_action_mean, reinforce_action_std, reinforce_epsilon,
         "REINFORCE", "Sigma", None, None),
        (enac_action_mean, enac_action_std, enac_epsilon,
         "ENAC", "Sigma", None, None)
    ]

    for ai in [0, 1]:
        figure(ai)
        plot_results(actions, ai, "Action (\%)", "Market Period")
        if tex:
            savefig('./out/fig5_%d_action_a%d.pdf' % (minor, ai + 1))
#            savefig('./out/fig5_%d_action_a%d.eps' % (minor, ai + 1))
        else:
            savefig('./out/fig5_%d_action_a%d.png' % (minor, ai + 1))

def plot5_3():
    plot5_1X(3)

def plot5_4():
    plot5_1X(4)

def plot_episodes(results, ai, ylab, xlab="Hour"):
    maxSteps = 24
    nplot = len(results)

    for i, (result_mean, result_std,
            passive_mean, passive_std, lab) in enumerate(results):

        ax = subplot(nplot, 1, i + 1)

#        title("Agent %d (%s)" % (ai + 1, lab))

        x = arange(0.0, maxSteps, 1.0)
        y = result_mean[ai, :]
        e = result_std[ai, :]
        py = passive_mean[ai, :]
        pe = passive_std[ai, :]
#        y2 = epsilon[ai, :]

#        plot(x, y,
#             color=clr[ai % nc],
#             linestyle=ls[ai % ns],
#             label=lab)

        errorbar(x, y, yerr=e, fmt='kx', linestyle="None",
                 label="Agent %d (%s)" % (ai + 1, lab),
                 capsize=3, markersize=5)#, linewidth=0.2)
        ylabel(ylab)

        errorbar(x, py, yerr=pe, fmt='ko', linestyle="None",
                 label="Marginal Cost",
                 capsize=1, markersize=3)#, linewidth=0.2)

        ax.ticklabel_format(style='sci', scilimits=(0,0), axis='y')

        xlim((0, 23))
        ax.yaxis.grid(True)
        locator = FixedLocator(range(0, 24))
        ax.xaxis.set_major_locator(locator)      #minor x-axis ticks

        l = legend(loc="upper left")
        l.get_frame().set_linewidth(0.5)

    xlabel(xlab)

def plot_agents(rewards, ylab, agents=[0,1,2,3], xlab="Hour",
                fmt=["w^", "wo", "ks", "kv"]):
    maxSteps = 24
    nplots = len(agents)

    for i, ai in enumerate(agents):
        ax = subplot(nplots, 1, i + 1)
        title("Agent %d" % (ai + 1))
        ylabel(ylab)

        x = arange(0.0, maxSteps, 1.0)

        for j, (result_mean, _, _, _, lab) in enumerate(rewards):

            y = result_mean[i, :]

            if paper:
                msize = 3
            else:
                msize = 5
            plot(x, y, fmt[j], linestyle="None",
#                 markerfacecolor='white',
                 markersize=msize,
#                 color=clr[ai % nc],
#                 linestyle=ls[ai % ns],
                 label="%s" % (lab)
#                 label="A%s (%s)" % (ai + 1, lab)
            )

            ax.ticklabel_format(style='sci', scilimits=(0,0), axis='y')

            xlim((0, 23))
#            ax.yaxis.grid(True)
            if paper:
                locator = FixedLocator(range(0, 24, 2))
            else:
                locator = FixedLocator(range(0, 24))
            ax.xaxis.set_major_locator(locator)      #minor x-axis ticks

            l = legend(loc="upper left")
            l.get_frame().set_linewidth(0.5)

    xlabel(xlab)

def plot6_X(minor=1):
#    re_epsilon = mmread("./out/ex6_%d_rotherev_epsilon.mtx" % minor)
#    q_epsilon = mmread("./out/ex6_%d_q_epsilon.mtx" % minor)
#    reinforce_epsilon = mmread("./out/ex6_%d_reinforce_epsilon.mtx" % minor)
#    enac_epsilon = mmread("./out/ex6_%d_enac_epsilon.mtx" % minor)

    passive_reward_mean = mmread("./out/ex6_%d_passive_reward_mean.mtx" % minor)
    passive_reward_std = mmread("./out/ex6_%d_passive_reward_std.mtx" % minor)

#    re_reward_mean = mmread("./out/ex6_%d_rotherev_reward_mean.mtx" % minor)
#    re_reward_std = mmread("./out/ex6_%d_rotherev_reward_std.mtx" % minor)
    re_reward_mean = mmread("./out/ex6_%d_statefulre_reward_mean.mtx" % minor)
    re_reward_std = mmread("./out/ex6_%d_statefulre_reward_std.mtx" % minor)

    q_reward_mean = mmread("./out/ex6_%d_q_reward_mean.mtx" % minor)
    q_reward_std = mmread("./out/ex6_%d_q_reward_std.mtx" % minor)
    reinforce_reward_mean = \
        mmread("./out/ex6_%d_reinforce_reward_mean.mtx" % minor)
    reinforce_reward_std = \
        mmread("./out/ex6_%d_reinforce_reward_std.mtx" % minor)
    enac_reward_mean = mmread("./out/ex6_%d_enac_reward_mean.mtx" % minor)
    enac_reward_std = mmread("./out/ex6_%d_enac_reward_std.mtx" % minor)

    if False:
        def average(reward):
            na = reward.shape[0]
            maxSteps = 24

            reward_mean = zeros((na, maxSteps))
            reward_std = zeros((na, maxSteps))

            roleouts = 8 * 7 # num of final episodes to average
            episodes = 1
            reward = reward[:, -maxSteps * episodes * roleouts:]

            for s in range(maxSteps):
                reward_mean[:, s] = mean(reward[:, s::maxSteps], axis=1)
                reward_std[:, s] = std(reward[:, s::maxSteps], axis=1, ddof=1)

            return reward_mean, reward_std

        re_rewards = mmread("./out/ex6_%d_rotherev_all_rewards.mtx" % minor)
        enac_rewards = mmread("./out/ex6_%d_enac_all_rewards.mtx" % minor)

        re_reward_mean, re_reward_std = average(re_rewards)
        enac_reward_mean, enac_reward_std = average(enac_rewards)

    rewards = [
#        (passive_reward_mean, passive_reward_std, "Passive"),
        (re_reward_mean, re_reward_std,
         passive_reward_mean, passive_reward_std, "Roth-Erev"),
        (q_reward_mean, q_reward_std,
         passive_reward_mean, passive_reward_std, "Q-Learning"),
        (reinforce_reward_mean, reinforce_reward_std,
         passive_reward_mean, passive_reward_std, "REINFORCE"),
        (enac_reward_mean, enac_reward_std,
         passive_reward_mean, passive_reward_std, "ENAC")
    ]

#    for ai in range(4):
#        figure(ai + 10)
#        plot_episodes(rewards, ai, r"Reward (\verb+$+)")
#        if tex:
#            savefig('./out/fig6_%d_reward_a%d.pdf' % (minor, (ai + 1)))
##            savefig('./out/fig6_%d_reward_a%d.eps' % (minor, (ai + 1)))
#        else:
#            savefig('./out/fig6_%d_reward_a%d.png' % (minor, (ai + 1)))

    figure(909)
    plot_agents(rewards, r"Reward (\verb+$+)")
    savefig('./out/fig6_%d_rewards.png' % minor)

#    if not tex:
#        show()

def plot6_0():
    plot6_X(1)

def plot6_1():
    if paper:
        fig_width = 3.0 # width in inches
        fig_height = 4.0 # height in inches
        params = {'axes.titlesize': 8,
                  'axes.labelsize': 6,
                  'text.fontsize': 6,
                  'legend.fontsize': 5,
                  'xtick.labelsize': 6,
                  'ytick.labelsize': 6,
                  'figure.figsize': [fig_width, fig_height]}
        rcParams.update(params)
    else:
        fig_width = 6.15 # width in inches
        fig_height = 5.0 # height in inches
        params = {'figure.figsize': [fig_width, fig_height]}
        rcParams.update(params)

    re_mean = mmread("./out/ex6_1/ex6_1_rotherev_reward_mean.mtx")
    sre_mean = mmread("./out/ex6_1/ex6_1_statefulre_reward_mean.mtx")
    q_mean = mmread("./out/ex6_1/ex6_1_q_reward_mean.mtx")

    rewards = [
        (re_mean, None, None, None, "Roth-Erev"),
        (q_mean, None, None, None, "Q-Learning"),
        (sre_mean, None, None, None, "Stateful RE")
    ]
    figure()
    plot_agents(rewards, r"Reward (\verb+$+)", agents=[0, 3],
                fmt=["w^", "wo", "kp"])

    if tex:
        if paper:
            subplots_adjust(bottom=0.07, top=0.94, hspace=0.25)
        else:
            subplots_adjust(hspace=0.3)
        savefig('./out/ex6_1/fig6_1.pdf')
    else:
        savefig('./out/ex6_1/fig6_1.png')

def plot6_2():
    if paper:
        fig_width = 3.0 # width in inches
        fig_height = 5.5 # height in inches
        params = {'axes.titlesize': 6,
                  'axes.labelsize': 6,
                  'text.fontsize': 6,
                  'legend.fontsize': 5,
                  'xtick.labelsize': 6,
                  'ytick.labelsize': 6,
                  'figure.figsize': [fig_width, fig_height]}
        rcParams.update(params)

    q1 = mmread("./out/ex6_2/ex6_2-1_q_reward_mean.mtx")
    reinforce1 = mmread("./out/ex6_2/ex6_2-1_reinforce_reward_mean.mtx")
    enac1 = mmread("./out/ex6_2/ex6_2-1_enac_reward_mean.mtx")

#    q2 = mmread("./out/ex6_2/ex6_2-2_q_reward_mean.mtx")
    reinforce2 = mmread("./out/ex6_2/ex6_2-2_reinforce_reward_mean.mtx")
    enac2 = mmread("./out/ex6_2/ex6_2-2_enac_reward_mean.mtx")

    maxSteps = 24
    nplots = 4
    fmt = ["wo", "ks", "kv"]

    x = arange(0.0, maxSteps, 1.0)

    def plot62(results, i, n):
        ax = subplot(nplots, 1, n)
        if paper:
            msize = 3
        else:
            msize = 5

        for k, (r, lab) in enumerate(results):
            plot(x, r[i, :], fmt[k], linestyle="None", markersize=msize,
                 label=lab)

        ax.ticklabel_format(style='sci', scilimits=(0,0), axis='y')

        xlim((0, 23))
        if paper:
            locator = FixedLocator(range(0, 24, 2))
        else:
            locator = FixedLocator(range(0, 24))
        ax.xaxis.set_major_locator(locator)      #minor x-axis ticks

        ylabel(r"Reward (\verb+$+)")

        l = legend(loc="upper left")
        l.get_frame().set_linewidth(0.5)

    results1 = [(q1, "Q-learning"), (reinforce1, "REINFORCE"), (enac1, "ENAC")]
    results2 = [(q1, "Q-learning"), (reinforce2, "REINFORCE"), (enac2, "ENAC")]

    figure()
    plot62(results1, i=1, n=1)
    title("Agent 1 (demand forecast only)")
    plot62(results2, i=1, n=2)
    title("Agent 1 (demand and bus voltage)")
#    xlabel("Hour")
#    if tex:
#        savefig('./out/ex6_2/fig6_2_agent1.pdf')

#    figure()
    plot62(results1, i=3, n=3)
    title("Agent 4 (demand forecast only)")
    plot62(results2, i=3, n=4)
    title("Agent 4 (demand and bus voltage)")
    xlabel("Hour")
#    if tex:
#        savefig('./out/ex6_2/fig6_2_agent4.pdf')

    subplots_adjust(hspace=0.3)

    if tex:
        if paper:
            subplots_adjust(bottom=0.05, top=0.96)
        savefig('./out/ex6_2/fig6_2.pdf')
    else:
        savefig('./out/ex6_2/fig6_2.png')

def plot6_3():
    if paper:
        fig_width = 3.0 # width in inches
        fig_height = 4.0 # height in inches
        params = {'axes.titlesize': 8,
                  'axes.labelsize': 6,
                  'text.fontsize': 6,
                  'legend.fontsize': 6,
                  'xtick.labelsize': 6,
                  'ytick.labelsize': 6,
                  'figure.figsize': [fig_width, fig_height]}
        rcParams.update(params)
    else:
        fig_width = 6.15 # width in inches
        fig_height = 5.0 # height in inches
        params = {'figure.figsize': [fig_width, fig_height]}
        rcParams.update(params)

    q_mean = mmread("./out/ex6_3/ex6_3_q_reward_mean.mtx")
    enac_mean = mmread("./out/ex6_3/ex6_3_enac_reward_mean.mtx")

    rewards = [
        (q_mean, None, None, None, "Q-Learning"),
        (enac_mean, None, None, None, "ENAC")
    ]
    figure()
    plot_agents(rewards, r"Reward (\verb+$+)", agents=[0, 3], fmt=["wo", "kv"])

    subplots_adjust(hspace=0.3)

    if tex:
        if paper:
            subplots_adjust(bottom=0.07, top=0.94, hspace=0.25)
        else:
            subplots_adjust(hspace=0.3)
        savefig('./out/ex6_3/fig6_3.pdf')
    else:
        savefig('./out/ex6_3/fig6_3.png')

def plot_profiles():
    figure()
    subplot(3, 1, 1)
#    clf()
    x = arange(0.0, 52.0, 1.0)
    plot(x, get_weekly(), color="black")
    xlabel("Week of the year (starting January 1st)")
    ylabel("\% of annual peak load")
    xlim((0.0, 51.0))
    ylim((0.0, 100.0))
    title("IEEE RTS Weekly Load Profile")
    legend()
    grid()
#    savefig('./out/ieee_rts_weekly.pdf')

    subplot(3, 1, 2)
#    clf()
    x = arange(1.0, 8.0, 1.0)
    plot(x, get_daily(), color="black")
    xlabel("Day of the week (starting on Monday)")
    ylabel("\% of weekly peak load")
    xlim((1.0, 7.0))
    ylim((0.0, 100.0))
    title("IEEE RTS Daily Load Profile")
    legend()
    grid()
#    savefig('./out/ieee_rts_daily.pdf')

    subplot(3, 1, 3)
#    clf()
    hourly_winter_wkdy, hourly_winter_wknd = get_winter_hourly()
    hourly_summer_wkdy, hourly_summer_wknd = get_summer_hourly()
    hourly_spring_autumn_wkdy, hourly_spring_autumn_wknd = \
        get_spring_autumn_hourly()

    x = arange(0.0, 24.0, 0.5)

    plot(x, r_[hourly_winter_wkdy, hourly_winter_wknd],
         label="Winter (Weeks 1-8 \& 44-52)", color="black")
    plot(x, r_[hourly_summer_wkdy, hourly_summer_wknd],
         label="Summer (Weeks 18-30)", color="0.4")
    plot(x, r_[hourly_spring_autumn_wkdy, hourly_spring_autumn_wknd],
         label="Spring \& Autumn (Weeks 9-17 \& 31-43)", color="0.6")

    xlabel("Hour of the day (starting at midnight)")
    ylabel("\% of daily peak load")
    xlim((0.0, 23.0))
    ylim((0.0, 100.0))
    title("IEEE RTS Hourly Load Profiles")
    l = legend(loc="lower right")
#    l.get_frame().set_linewidth(0.7)
    grid()
#    savefig('./out/ieee_rts_hourly.pdf')

    subplots_adjust(hspace=0.35)

#    savefig('./out/ieee_rts_profiles.pdf')
    savefig('/tmp/ieee_rts_profiles.eps')

if __name__ == "__main__":
#    plot5_1()
#    plot5_2()
#    plot5_3()
    plot5_4()
#    plot6_0()
#    plot6_1()
#    plot6_2()
#    plot6_3()
#    plot_profiles()


import torch.nn as nn
import torch.nn.functional as F
import torch
class Model_Mnist(nn.Module):
    def __init__(self, num_class=2):
        super(Model_Mnist, self).__init__()
        self.num_class = num_class
        self.conv1 = nn.Conv2d(1, 6, 5, padding=2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, self.num_class)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, (2, 2))

        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2)

        x = x.view(x.size()[0], -1)

        x = F.relu(self.fc1(x))

        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

class Model_Cifar10(nn.Module):
  def __init__(self, num_class=2):
    super(Model_Cifar10, self).__init__()
    self.num_class = num_class
    self.conv1 = nn.Conv2d(3, 128, 5, padding=2)
    self.conv2 = nn.Conv2d(128, 128, 5, padding=2)
    self.conv3 = nn.Conv2d(128, 256, 3, padding=1)
    self.conv4 = nn.Conv2d(256, 256, 3, padding=1)
    self.pool = nn.MaxPool2d(2, 2)
    self.bn_conv1 = nn.BatchNorm2d(128)
    self.bn_conv2 = nn.BatchNorm2d(128)
    self.bn_conv3 = nn.BatchNorm2d(256)
    self.bn_conv4 = nn.BatchNorm2d(256)
    self.bn_dense1 = nn.BatchNorm1d(1024)
    self.bn_dense2 = nn.BatchNorm1d(512)
    self.dropout_conv = nn.Dropout2d(p=0.25)
    self.dropout = nn.Dropout(p=0.5)
    self.fc1 = nn.Linear(256 * 8 * 8, 1024)
    self.fc2 = nn.Linear(1024, 512)
    self.fc3 = nn.Linear(512, self.num_class)

  def conv_layers(self, x):
    out = F.relu(self.bn_conv1(self.conv1(x)))
    out = F.relu(self.bn_conv2(self.conv2(out)))
    out = self.pool(out)
    out = self.dropout_conv(out)
    out = F.relu(self.bn_conv3(self.conv3(out)))
    out = F.relu(self.bn_conv4(self.conv4(out)))
    out = self.pool(out)
    out = self.dropout_conv(out)
    return out

  def dense_layers(self, x):
    out = F.relu(self.bn_dense1(self.fc1(x)))
    out = self.dropout(out)
    out = F.relu(self.bn_dense2(self.fc2(out)))
    out = self.dropout(out)
    out = self.fc3(out)
    return out

  def forward(self, x):
    out = self.conv_layers(x)
    out = out.view(-1, 256 * 8 * 8)
    out = self.dense_layers(out)
    return out

class Model_Cifar100(nn.Module):
  def __init__(self, num_class=2):
    super(Model_Cifar100, self).__init__()
    self.num_class = num_class
    self.conv1 = nn.Conv2d(3, 128, 5, padding=2)
    self.conv2 = nn.Conv2d(128, 128, 5, padding=2)
    self.conv3 = nn.Conv2d(128, 256, 3, padding=1)
    self.conv4 = nn.Conv2d(256, 256, 3, padding=1)
    self.pool = nn.MaxPool2d(2, 2)
    self.bn_conv1 = nn.BatchNorm2d(128)
    self.bn_conv2 = nn.BatchNorm2d(128)
    self.bn_conv3 = nn.BatchNorm2d(256)
    self.bn_conv4 = nn.BatchNorm2d(256)
    self.bn_dense1 = nn.BatchNorm1d(1024)
    self.bn_dense2 = nn.BatchNorm1d(512)
    self.dropout_conv = nn.Dropout2d(p=0.25)
    self.dropout = nn.Dropout(p=0.5)
    self.fc1 = nn.Linear(256 * 8 * 8, 1024)
    self.fc2 = nn.Linear(1024, 512)
    self.fc3 = nn.Linear(512, self.num_class)

  def conv_layers(self, x):
    out = F.relu(self.bn_conv1(self.conv1(x)))
    out = F.relu(self.bn_conv2(self.conv2(out)))
    out = self.pool(out)
    out = self.dropout_conv(out)
    out = F.relu(self.bn_conv3(self.conv3(out)))
    out = F.relu(self.bn_conv4(self.conv4(out)))
    out = self.pool(out)
    out = self.dropout_conv(out)
    return out

  def dense_layers(self, x):
    out = F.relu(self.bn_dense1(self.fc1(x)))
    out = self.dropout(out)
    out = F.relu(self.bn_dense2(self.fc2(out)))
    out = self.dropout(out)
    out = self.fc3(out)
    return out

  def forward(self, x):
    out = self.conv_layers(x)
    out = out.view(-1, 256 * 8 * 8)
    out = self.dense_layers(out)
    return out

class Model_Caltech101(nn.Module):
    def __init__(self, num_class=101, init_weights=False):
        super(Model_Caltech101, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 48, kernel_size=11),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.BatchNorm2d(48),
            nn.Conv2d(48, 128, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.BatchNorm2d(128),
            nn.Conv2d(128, 192, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 192, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Dropout(0.5),
            nn.Linear(6 * 6 * 128, 2048),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(2048, 2048),
            nn.ReLU(inplace=True),
            nn.Linear(2048, num_class),
        )
        if init_weights:
            self._initialize_weights()

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, start_dim=1)
        x = self.classifier(x)
        return x

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)

class Model_Ttru(nn.Module):
    def __init__(self):
        super(Model_Ttru, self).__init__()
        self.input_dim = 1
        self.filter1 = 64
        self.filter2 = 128
        self.output_dim = 2
        self.conv = nn.Sequential(
            nn.Conv2d(self.input_dim, self.filter1, 2, 2),   # 64 ---> 32
            nn.BatchNorm2d(self.filter1),
            nn.ReLU(),

            nn.Conv2d(self.filter1, self.filter2, 5, 1, 1),  # 32 ---> 30
            nn.BatchNorm2d(self.filter2),
            nn.ReLU(),

            nn.Conv2d(self.filter2, self.filter2, 5, 1, 1),  # 30 ---> 28
            nn.BatchNorm2d(self.filter2),
            nn.ReLU(),

            nn.MaxPool2d(2),

            nn.Conv2d(self.filter2, self.filter2, 5, 1, 1),  # 14 ---> 12
            nn.BatchNorm2d(self.filter2),
            nn.ReLU(),

            nn.MaxPool2d(2),
        )

        self.fc1 = nn.Sequential(
            nn.Linear(self.filter2 * 6 * 6, 1024),  # 128*6*6 ---> 1024
            nn.BatchNorm1d(1024),
            nn.ReLU(),

            nn.Linear(1024, 512),  # 1024 ---> 512
            nn.BatchNorm1d(512),
            nn.ReLU(),

            nn.Linear(512, self.output_dim)  # 512 ---> 2
        )

    def forward(self, input):
        x = self.conv(input)
        x = x.view(-1, self.filter2 * 6 * 6)
        x = self.fc1(x)
        return x


import cv2
import numpy as np
from config import *

def ReadImg(path):
    return np.array(cv2.cvtColor(cv2.imread(path.strip()), code=cv2.COLOR_RGB2BGR))

# http://docs.opencv.org/3.1.0/d5/daf/tutorial_py_histogram_equalization.html
def AdaptiveThresholding(img):
    clahe = cv2.createCLAHE()
    return clahe.apply(img)

def abs_sobel_thresh(img, orient='x', thresh=(0, 255)):
    # Apply the following steps to img
    # 1) Convert to grayscale
    # 2) Take the derivative in x or y given orient = 'x' or 'y'
    # 3) Take the absolute value of the derivative or gradient
    # 4) Scale to 8-bit (0 - 255) then convert to type = np.uint8
    # 5) Create a mask of 1's where the scaled gradient magnitude
            # is > thresh_min and < thresh_max
    # 6) Return this mask as your binary_output image
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    if orient == 'x':
        abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
    else:
        abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))

    scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))
    binary_output = np.zeros_like(scaled_sobel)
    binary_output[(scaled_sobel >= thresh[0]) & (scaled_sobel <= thresh[1])] = 1
    return binary_output

def mag_thresh(img, sobel_kernel=3, mag_thresh=(0, 255)):

    # Apply the following steps to img
    # 1) Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    # 2) Take the gradient in x and y separately
    sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)

    # 3) Calculate the magnitude
    gradmag = np.sqrt(sobelx**2 + sobely**2)

    # Rescale to 8 bit
    gradmag = (255*gradmag/np.max(gradmag)).astype(np.uint8)

    # Create a binary image of ones where threshold is met, zeros otherwise
    binary_output = np.zeros_like(gradmag)
    binary_output[(gradmag >= mag_thresh[0]) & (gradmag <= mag_thresh[1])] = 1
    return binary_output

def dir_threshold(img, sobel_kernel=3, thresh=(0, np.pi/2)):

    # Apply the following steps to img
    # 1) Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    # 2) Take the gradient in x and y separately
    sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)

    # 3) Take the absolute value of the x and y gradients
    abs_sobelx = np.absolute(sobelx)
    abs_sobely = np.absolute(sobely)
    # 4) Use np.arctan2(abs_sobely, abs_sobelx) to calculate the direction of the gradient
    gradir = np.arctan2(abs_sobely, abs_sobelx)
    # 5) Create a binary mask where direction thresholds are met
    binary_output = np.zeros_like(gradir)
    binary_output[(gradir >= thresh[0]) & (gradir <= thresh[1])] = 1
    # 6) Return this mask as your binary_output image
    return binary_output

def color_threshold(img, sthreshold=(100, 255), vthreshold=(50, 255)):
    img = np.copy(img)
    hls = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
    s_channel = hls[:,:,2]

    sbinary = np.zeros_like(s_channel)
    sbinary[(s_channel > sthreshold[0]) & (s_channel <= sthreshold[1])] = 1

    hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
    v_channel = hsv[:, :, 2]
    vbinary = np.zeros_like(v_channel)
    vbinary[(v_channel > vthreshold[0]) & (v_channel <= vthreshold[1])] = 1

    output = np.zeros_like(s_channel)
    output[(sbinary == 1) & (vbinary == 1)] = 1
    return output

class Polyfit():

    def __init__(self):
        self.fit_intercept = []

    def fit(self, X, y):
        self.fit_intercept = np.polyfit(X, y, 2)

    def predict(self, y):
        return np.array(self.fit_intercept[0]*y*y + self.fit_intercept[1]*y + self.fit_intercept[2], np.int32)

def window_mask(width, height, img_ref, center, level):
    output = np.zeros_like(img_ref)
    output[int(img_ref.shape[0]-(level+1)*height):int(img_ref.shape[0]-level*height),max(0,int(center-width/2)):min(int(center+width/2),img_ref.shape[1])] = 1
    return output

"""
Tested src/dst
src = np.float32([[590, 450], [750, 450], [1225, 700], [200, 700]])
src = np.float32([[560, 470], [790, 470], [1150, 700], [260, 700]])
src = np.float32([[590, 470], [790, 470], [1190, 700], [260, 700]])
src = np.float32([[(img_size[0] / 2) - 55, img_size[1] / 2 + 100],[((img_size[0] / 6) - 10), img_size[1]],[(img_size[0] * 5 / 6) + 60, img_size[1]],[(img_size[0] / 2 + 55), img_size[1] / 2 + 100]])
dst = np.float32([[(img_size[0] / 4), 0],[(img_size[0] / 4), img_size[1]],[(img_size[0] * 3 / 4), img_size[1]],[(img_size[0] * 3 / 4), 0]])
"""
def Warp(img, src, dst):
    img_size = (img.shape[1], img.shape[0])
    offset = 260
    src = np.float32([[590, 470], [750, 470], [1190, 700], [260, 700]])
    dst = np.float32([[offset, 0], [img_size[0]-offset, 0], [img_size[0]-offset, img_size[1]], [offset, img_size[1]]])
    M = cv2.getPerspectiveTransform(src, dst)
    Minv = cv2.getPerspectiveTransform(dst, src)
    warpedImage = cv2.warpPerspective(img, M, img_size, flags=cv2.INTER_LINEAR)

    return (warpedImage, M, Minv)

def region_of_interest(img, vertices):
    """
    Applies an image mask.

    Only keeps the region of the image defined by the polygon
    formed from `vertices`. The rest of the image is set to black.
    """
    #defining a blank mask to start with
    mask = np.zeros_like(img)

    #defining a 3 channel or 1 channel color to fill the mask with depending on the input image
    if len(img.shape) > 2:
        channel_count = img.shape[2]  # i.e. 3 or 4 depending on your image
        ignore_mask_color = (255,) * channel_count
    else:
        ignore_mask_color = 255

    #filling pixels inside the polygon defined by "vertices" with the fill color
    cv2.fillPoly(mask, vertices, ignore_mask_color)

    #returning the image only where mask pixels are nonzero
    masked_image = cv2.bitwise_and(img, mask)
    return masked_image