# -*- coding: utf-8 -*-
"""
Created on Sat Nov 21 14:52:12 2015

@author: Ilia
"""

from matplotlib import pyplot as plt, gridspec
import numpy as np

class _Direction(object):
    horizontal = 'H'
    vertical = 'V'
    transposed = 'T'
    normal = 'N'

class _Plottable(object):
    def __init__(self,value,direction,use_clim=None):
        if ( len(value.shape)==2 ):
            if direction == _Direction.transposed:
                self.value = value.transpose()
            else:
                self.value = np.copy(value)
        else:
            n = value.shape[0]
            if direction == _Direction.horizontal:
                self.value = value.reshape((1,n))
            else:
                self.value = value.reshape((n,1))
        self.use_clim = use_clim
    def MakeIMShow(self,a,clim_override=None,*additional_args,**additional_kwargs):
        if ( not clim_override is None):
            clim = clim_override
        else:
            clim = self.use_clim
        if ( not clim is None ):
            additional_kwargs['clim'] = clim
        I = a.imshow(self.value,interpolation='none',*additional_args,**additional_kwargs)
        return I

class RTRL_Plotter_base(object):
    def __init__(self):
        self.is_active=False
        self.connected_fig_events = []
    def isActive(self):
        return self.is_active
    def RetrieveState(self,rnn):
        pass
    def CreateAxes(self,fig=None):
        if fig is None:
            fig = plt.figure()
#        plt.figure(fig)
        axes_positions = self._GetAxesPositions()
        axeses={}
        for name in axes_positions.iterkeys():
            a = fig.add_subplot(axes_positions[name])
            a.set_title(name)
            a.set_xticks([])
            a.set_yticks([])
            axeses[name] = a

        self.axeses = axeses
        self.axes_positions = axes_positions
        self.fig = fig
        self.ConnectCloseEvent(self.OnFigClose)
    def CreateImages(self):
        self.images={}
        for k,a in self.axeses.iteritems():
            I = self.state[k].MakeIMShow(a)
#            I.set_clim(self.weight_clim)
            self.images[k] = I
        self.is_active = True
    def UpdateImages(self,make_redraw=True):
        for k,a in self.axeses.iteritems():
            self.images[k].set_data(self.state[k].value)
        if make_redraw:
            self.fig.canvas.draw_idle()
#        plt.draw()
    def CloseFig(self):
        if ( not self.fig is None ):
            for cid in self.connected_fig_events:
                self.fig.canvas.mpl_disconnect(cid)
            plt.close(self.fig)
            self.is_active = False
    def OnFigClose(self,evt):
        self.is_active = False
        self.fig = None
    def GetFig(self):
        return self.fig
    def ConnectCloseEvent(self,handler):
        if ( not self.fig is None ):
            cid = self.fig.canvas.mpl_connect('close_event', handler)
            self.connected_fig_events.append(cid)

class RTRL_Weight_Plotter(RTRL_Plotter_base):
    def __init__(self,weight_clim=None):
        super(RTRL_Weight_Plotter,self).__init__()
        if weight_clim is None:
            weight_clim = np.array([-1.0,1.0])
        elif isinstance(weight_clim,list):
            weight_clim = np.array(weight_clim)
        self.weight_clim = weight_clim
        self.excitation_clim = np.array([-1.,1.])
    def RetrieveState(self,rnn):
        state = rnn.GetState()
        S = {}
        S['nx'] = state['nx']
        S['nu'] = rnn.nu
        S['ny'] = rnn.ny
        S['x_t'] = _Plottable(rnn.GetCurrentX(),_Direction.vertical,self.excitation_clim)
        S['u_t'] = _Plottable(rnn.GetCurrentU(),_Direction.vertical,self.excitation_clim)
        S['y_tp1'] = _Plottable(rnn.Get_Y_Prediction(),_Direction.horizontal,[0.0,1.0])
        S['x_tp1'] = _Plottable(rnn.GetNextX(),_Direction.vertical,self.excitation_clim)
        S['W_xx'] = _Plottable(state['W_xx'],_Direction.normal,self.weight_clim)
        S['W_xu'] = _Plottable(state['W_xu'],_Direction.normal,self.weight_clim)
        S['W_yx'] = _Plottable(state['W_yx'],_Direction.normal,self.weight_clim)
        S['b_x'] = _Plottable(state['b_x'],_Direction.horizontal,self.weight_clim)
        S['b_y'] = _Plottable(state['b_y'],_Direction.horizontal,self.weight_clim)

        self.state = S
    def _GetAxesPositions(self):
        state = self.state
        temp = max([state['nu'],3])
        gs = gridspec.GridSpec(1 + state['nx'] + temp + 2, state['nx']+2+state['ny']*2 + 2)

        axes_positions = {}
        axes_positions['W_xx'] = gs[2:(state['nx']+2),
                                            2:(state['nx']+2)]
        axes_positions['W_xu'] = gs[(state['nx']+3):(state['nx']+3+state['nu']),
                                                    2:(state['nx']+2)]
        axes_positions['x_t'] = gs[2:(state['nx']+2),
                                                0]
        axes_positions['b_x'] = gs[0,
                                2:(state['nx']+2)]
        axes_positions['u_t'] = gs[(state['nx']+3):(state['nx']+3+state['nu']),
                                            0]
        axes_positions['x_tp1'] = gs[2:(state['nx']+2),
                                    state['nx']+3]
        axes_positions['W_yx'] = gs[2:(state['nx']+2),
                                (state['nx']+5):(state['nx']+5 + state['ny'])]
        #
        axes_positions['b_y'] = gs[(state['nx']+3),
                                       (state['nx']+5):(state['nx']+5 + state['ny'])]
        axes_positions['y_tp1'] = gs[(state['nx']+5),
                                        (state['nx']+5):(state['nx']+5 + state['ny'])]
        return axes_positions
    def CreateImages(self):
        super(RTRL_Weight_Plotter,self).CreateImages()
        self.cbar=plt.colorbar(self.images['W_xx'],ax=self.axeses.values())

from collections import defaultdict

class RTRL_Gradients_Plotter(RTRL_Plotter_base):
    def __init__(self,gradient_clim=None):
        super(RTRL_Gradients_Plotter,self).__init__()
        if isinstance(gradient_clim,list):
            gradient_clim = np.array(gradient_clim)
        self.gradient_clim = gradient_clim
    def RetrieveState(self,rnn):
        S = {}
        S['nx'] = rnn.nx
        S['nu'] = rnn.nu
        S['ny'] = rnn.ny
        weight_gradients = rnn.GetWeightGradients()
#        S.update(weight_gradients)
        directions = defaultdict(lambda : _Direction.normal)
        directions['db_x'] = _Direction.horizontal
        directions['db_y'] = _Direction.horizontal
        for k,v in weight_gradients.iteritems():
            S[k] = _Plottable(v,directions[k],self.gradient_clim)
        self.state = S

    def _GetAxesPositions(self):
        state = self.state
        temp = max([state['nu'],3])
        gs = gridspec.GridSpec(1 + state['nx'] + temp + 2, state['nx']+2+state['ny']*2 + 2)

        axes_positions = {}
        axes_positions['dW_xx'] = gs[2:(state['nx']+2),
                                            2:(state['nx']+2)]
        axes_positions['dW_xu'] = gs[(state['nx']+3):(state['nx']+3+state['nu']),
                                                    2:(state['nx']+2)]
        axes_positions['db_x'] = gs[0,
                                2:(state['nx']+2)]
        axes_positions['dW_yx'] = gs[2:(state['nx']+2),
                                (state['nx']+5):(state['nx']+5 + state['ny'])]
        #
        axes_positions['db_y'] = gs[(state['nx']+3),
                                       (state['nx']+5):(state['nx']+5 + state['ny'])]
        return axes_positions
    def _CalcCommonCLim(self):
        cmin = np.inf
        cmax = -np.inf
        for k in self.images.iterkeys():
            if k == 'db_y':
                continue
            this_max = self.state[k].value.max()
            this_min = self.state[k].value.min()
            if this_max > cmax:
                cmax = this_max
            if this_min < cmin:
                cmin = this_min
        max_abs = max(abs(cmin),abs(cmax))
        return np.array([-max_abs,max_abs],dtype=float)
    def _UpdateAllClims(self):
        for k,I in self.images.iteritems():
            I.set_clim(self.common_clim)
    def _UpdateColorBar(self):
        #self.cbar.
        #probably happens automatically
        pass
    def CreateImages(self):
        super(RTRL_Gradients_Plotter,self).CreateImages()
        if self.gradient_clim is None:
            self.common_clim = self._CalcCommonCLim()
            self._UpdateAllClims()
        self.cbar=plt.colorbar(self.images['dW_xx'],ax=self.axeses.values())
    def UpdateImages(self):
        super(RTRL_Gradients_Plotter,self).UpdateImages(False)
        if self.gradient_clim is None:
            self.common_clim = self._CalcCommonCLim()
            self._UpdateAllClims()
            self._UpdateColorBar()
        self.fig.canvas.draw_idle()

if __name__ == "__main__":
#    RP = RTRL_Weight_Plotter()
    RP = RTRL_Gradients_Plotter()
    from rtrl1 import RTRL1
    rnn1 = RTRL1()
    #rnn1.BuildNetwork()

    import cPickle
    with open('well_trained_nx8.rtrl1','rb') as f:
        state = cPickle.load(f)
    rnn1.SetState(state)
    rnn1.BuildNetwork()
    RP.RetrieveState(rnn1)
    RP.CreateAxes()
    RP.CreateImages()


from pathlib import Path
from bokeh.io import export_png
from bokeh.layouts import gridplot
import permutandis
from permutandis.evaluation.rearrange_evaluation import  RearrangeEvaluation

from permutandis.solvers.mcts import MCTSSolver
from permutandis.solvers.baseline import BaselineSolver

from distributed import Client, LocalCluster

def make_client():
    # Change this if you have access to a cluster and you want to
    # run evaluation
    # See https://jobqueue.dask.org/en/latest/
    cluster = LocalCluster()
    client = Client(cluster)

def evaluate_solvers(results_path):
    rearrange_eval = RearrangeEvaluation()

    # Sample random problems
    # In the paper, we use n_max_objects=37 and n_configs=100
    rearrange_eval.sample_problems(
        n_min_objects=1, n_max_objects=35, n_configs=10,
        workspace=((0.25, -0.25), (0.75, 0.25)), radius=0.0375,
        timeout=2.0, n_max_iter=50)

    # Evaluate MCTS
    mcts_solver = MCTSSolver(nu=1.0, max_iterations=1e5)
    rearrange_eval.eval_solver(mcts_solver, method_name='mcts')

    # Evaluate baseline
    baseline_solver = BaselineSolver()
    rearrange_eval.eval_solver(baseline_solver, method_name='baseline')

    # Save results
    rearrange_eval.save(results_path)
    print("Wrote results to", results_path)

    return rearrange_eval

def make_plots(results_path):
    print("Reading results from", results_path)
    rearrange_eval = RearrangeEvaluation.from_json(results_path)
    figures = rearrange_eval.make_plots(methods=['mcts', 'baseline'])
    plot = gridplot([figures], toolbar_location=None)
    plot_path = results_path.parent / 'results_plots.png'
    export_png(plot, filename=plot_path)
    print("Saved plot to", plot_path)

if __name__ == '__main__':
    make_client()
    data_dir = Path(permutandis.__file__).parent.parent / 'data'
    results_path = data_dir / 'eval_results.json'
    evaluate_solvers(results_path)
    make_plots(results_path)


import torch
from torch.utils import data
from torch import nn
from torch.optim import lr_scheduler
import os
import time
from tqdm import tqdm
import numpy as np
from PIL import Image, ImageDraw
import argparse
import os
from datasets.cifar10_noise import get_datasets
import random
import torch.backends.cudnn as cudnn
from datasets.dataloader import Dateloader
from network.models import create_model
import torch.optim as optim
import logging
import logging.config
from lib.utils import AverageMeter,accuracy,adjust_learning_rate
from sklearn.mixture import GaussianMixture
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

parser = argparse.ArgumentParser(description='classification')

# Model path
parser.add_argument('--exp_name', help='Where to store logs and models')
parser.add_argument('--resume', default="/data/glusterfs_cv_04/11121171/AAAI_EAST/Baseline/EAST_v1/model_save/model_epoch_826.pth", type=str,
                    help='Checkpoint state_dict file to resume training from')
parser.add_argument('--data_path', default='/data/glusterfs_cv_04/11121171/data/CIFAR/CIFAR10-noise', type=str,
                    help='the test image of target domain ')
parser.add_argument('--workspace', default="/data/glusterfs_cv_04/11121171/AAAI_NL/Baseline_classification/classification_noise", type=str,
                    help='save model')
parser.add_argument('--Backbone', type=str, default="efficientnet-b0", help='FeatureExtraction stage. '
                                                                     'ResNet18|ResNet34|ResNet50'
                                                                     'MobileNet_v1|MobileNet_v2|Mobilenetv3'
                                                                     'vgg11|vgg16|vgg19'
                                                                     'efficientnet-b0|efficientnet-b1'
                                                                     'shufflenet_v2_x0_5|shufflenet_v2_x1_0|shufflenet_v2_x1_5'
                                                                      "inception_v3"
                                                                      "mnasnet0_5|"
                                                                      "densenet121"
                                                                      "ResNeXt29_32x4d|ResNeXt29_2x64d"
                                                                        )
parser.add_argument('--Datasets', type=str, default="cifar10", help=' ImageNet|Clothing|CIFAR10|CIFAR100')
parser.add_argument('--num_classes', type=int, default=10, help=' classification')
parser.add_argument('--rate', type=float, default=0.4, help='noise ratio')
parser.add_argument('--noise_mode', default='sym')
parser.add_argument('--manualSeed', type=int, default=222, help='for random seed setting')

# Training strategy
parser.add_argument('--epoch_iter', default=300, type = int,
                    help='the max epoch iter')
parser.add_argument('--batch_size', default=256, type = int,
                    help='batch size of training')
parser.add_argument('--lr', '--learning-rate', default=0.01, type=float,
                    help='initial learning rate')
parser.add_argument('--momentum', default=0.9, type=float,
                    help='Momentum value for optim')
parser.add_argument('--weight_decay', default=5e-4, type=float,
                    help='Weight decay for SGD')
parser.add_argument('--gamma', default=0.1, type=float,
                    help='Gamma update for SGD')
parser.add_argument('--num_workers', default=10, type=int,
                    help='Number of workers used in dataloading')

opt = parser.parse_args()

def train(opt):
    """ dataset preparation """
    print("dataset preparation ...")
    logging.info("dataset preparation ...")
    # dataset = Dateloader(opt.data_path,mode="train",noise_mode=opt.noise_mode, rate=opt.rate,dataset = opt.Datasets,
    #                      noise_file='%s/%.1f_%s.json' % (f'./workspace/{opt.exp_name}', opt.rate, opt.noise_mode),
    #                      right_file= '%s/right.json' % (f'./workspace/{opt.exp_name}'))

    dataset = get_datasets(opt.data_path,opt.rate,noise_mode="sym",dataset = 'cifar10',
                           noise_file='%s/%.1f_%s.json' % (f'./workspace/{opt.exp_name}', opt.rate, opt.noise_mode),
                         right_file= '%s/right.json' % (f'./workspace/{opt.exp_name}'),mode="train")

    data_loader = torch.utils.data.DataLoader(
        dataset,
        batch_size=opt.batch_size,
        shuffle=True,
        num_workers=opt.num_workers,
        drop_last=True,
        pin_memory=True)

    dataset_val = get_datasets(opt.data_path,opt.rate,noise_mode="sym",dataset='cifar10',mode="test")

    # dataset_val = Dateloader(opt.data_path,mode="test",noise_mode=opt.noise_mode, rate=opt.rate,dataset=opt.Datasets)
    data_loader_val = torch.utils.data.DataLoader(
        dataset_val,
        batch_size=opt.batch_size,
        shuffle=False,
        num_workers=opt.num_workers)

    print('| Building net...')
    logging.info('| Building net...')
    model = create_model(opt.Backbone,opt.num_classes)
    model = torch.nn.DataParallel(model)
    cudnn.benchmark = True

    optimizer = optim.SGD(model.parameters(), lr=opt.lr, momentum=0.9, weight_decay=opt.weight_decay)
    lr_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,
                                    milestones =[80, 170, 250, 330, 450], gamma=0.2)
    CEloss = nn.CrossEntropyLoss()
    # conf_penalty = NegEntropy()

    best_acc = 40
    for epoch in range(opt.epoch_iter):
        model.train()
        lr_scheduler.step()
        epoch_loss = 0
        epoch_time = time.time()
        for i, (image,gt) in enumerate(data_loader):

            start_time = time.time()
            inputs, labels = image.cuda(), gt.cuda()
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = CEloss(outputs, labels)
            epoch_loss += loss.item()
            loss.backward()
            optimizer.step()
            print('Epoch is [{}/{}], mini-batch is [{}/{}], time consumption is {:.8f}, batch_loss is {:.8f}'.format( \
                epoch + 1, opt.epoch_iter, i + 1, int(len(data_loader)), time.time() - start_time, loss.item()))
            logging.info('Epoch is [{}/{}], mini-batch is [{}/{}], time consumption is {:.8f}, batch_loss is {:.8f}'.format( \
                epoch + 1, opt.epoch_iter, i + 1, int(len(data_loader)), time.time() - start_time, loss.item()))
        if epoch>1:
            validate(data_loader_val, model, CEloss)
            best_acc = test(epoch,model,data_loader_val,best_acc)
            model.train()
        logging.info("----------------------------------------------------------")
        logging.info("                    best_acc: {:.3f}".format(float(best_acc)))
        logging.info("                    lr: {:.3f}".format(float(optimizer.param_groups[0]['lr'])))
        logging.info("----------------------------------------------------------")
        print('epoch_loss is {:.8f}, epoch_time is {:.8f}'.format(epoch_loss / int(len(data_loader)),time.time() - epoch_time))
        logging.info('epoch_loss is {:.8f}, epoch_time is {:.8f}'.format(epoch_loss / int(len(data_loader)),
                                                                         time.time() - epoch_time))
        logging.info(time.asctime(time.localtime(time.time())))

def test(epoch,  model,val_loader,best_acc):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for batch_idx, (inputs, targets) in tqdm(enumerate(val_loader)):
            inputs, targets = inputs.cuda(), targets.cuda()
            outputs = model(inputs)
            _, predicted = torch.max(outputs, 1)

            total += targets.size(0)
            correct += predicted.eq(targets).cpu().sum().item()
    acc = 100. * correct / total
    logging.info("\n| Validation\t Net  Acc: %.2f%%" % acc)
    if acc > best_acc:
        best_acc = acc
        logging.info("best acc:  %.2f%%"% best_acc)
        logging.info('| Saving Best Net ...')
        # torch.save(model.state_dict(), save_point)
        torch.save(model.state_dict(), os.path.join('%s/%s/' % (opt.workspace, f'workspace/{opt.exp_name}'),
                                                    f'{opt.Backbone}-{opt.Datasets}' + '.pth'))
    return best_acc

def validate(val_loader, model, criterion):
    batch_time = AverageMeter()
    losses = AverageMeter()
    top1 = AverageMeter()
    top5 = AverageMeter()

    # switch to evaluate mode
    model.eval()

    end = time.time()
    for i, (input, target) in enumerate(val_loader):
        target = target.cuda()
        input = input.cuda()
        with torch.no_grad():
            # compute output
            output = model(input)
            loss = criterion(output, target)

            # measure accuracy and record loss
            prec1, prec5 = accuracy(output.data, target, topk=(1, 5))
            losses.update(loss.item(), input.size(0))
            top1.update(prec1[0], input.size(0))
            top5.update(prec5[0], input.size(0))

            # measure elapsed time
            batch_time.update(time.time() - end)
            end = time.time()

    logging.info("    ---------------------------------------------------------------")
    logging.info(' * Prec@1 {top1.avg:.3f} Prec@5 {top5.avg:.3f}'.format(top1=top1, top5=top5))

    return top1.avg, top5.avg

if __name__ == '__main__':

    if not opt.exp_name:
        opt.exp_name = f'{opt.Backbone}-{opt.Datasets}'
        opt.exp_name += f'-Seed{opt.manualSeed}'
        # print(opt.exp_name)

    os.makedirs(f'./workspace/{opt.exp_name}', exist_ok=True)

    # 通过下面的方式进行简单配置输出方式与日志级别
    logging.basicConfig(
        filename=os.path.join(f'./workspace/{opt.exp_name}',"logger.log"),
        level=logging.INFO,filemode='w')

    logging.debug('debug message')
    logging.info('info message')
    logging.error('error message')
    logging.critical('critical message')

    """ Seed and GPU setting """
    # print("Random Seed: ", opt.manualSeed)
    random.seed(opt.manualSeed)
    np.random.seed(opt.manualSeed)
    torch.manual_seed(opt.manualSeed)
    torch.cuda.manual_seed(opt.manualSeed)

    cudnn.benchmark = True
    cudnn.deterministic = True
    opt.num_gpu = torch.cuda.device_count()

    if opt.num_gpu > 1:
        logging.info('------ Use multi-GPU setting ------')
        logging.info('if you stuck too long time with multi-GPU setting, try to set --workers 0')
        # check multi-GPU issue https://github.com/clovaai/deep-text-recognition-benchmark/issues/1
        opt.workers = opt.num_workers * opt.num_gpu
        opt.batch_size = opt.batch_size * opt.num_gpu

    train(opt)


#                   [   Plague Dr.  ]
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
from bs4 import BeautifulSoup as bs
import requests as rq
from .plPlugins import Counter
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
coinmarketcap = 'https://coinmarketcap.com'
pages = '/?page='
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
def collection_dict(*data) -> dict:
    d = {}
    for dt in data: d.update(dt)
    return d

def _2float(text: str) -> float:
    return float(text.replace('.','00'))
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
class getCoin:
    def __init__(self, *, site: str = coinmarketcap, page: int = None, loop: bool = False):
        if not loop:
            self.update(site=site, page=page)
    def length(self) -> int:
        return len(self.tags)
    def update(self, *, site: str = coinmarketcap, page: int = None) -> None:
        self.url = site if page == None else site+pages+str(page)
        self.code = rq.get(self.url)
        self.site = bs(self.code.text, 'html.parser')
        self.tags = self.site.select('.h7vnx2-2 > tbody:nth-child(3) > tr')
    def get_name(self, index: int) -> str:
        name = self.tags[index].select('td:nth-child(3)')
        tag_p = name[0].find_all('p')
        if tag_p == []:
            name = self.tags[index].select('td:nth-child(3)')[0].find_all('span', class_='')[0].text
        else:
            name = tag_p[0].text
        return name.lower().replace(' ','_')
    def get_price(self, index: int) -> float:
        name = self.tags[index].select('td:nth-child(4)')[0]
        return name.span.text[1:] #_2float(name.span.text[1:].replace(',', ''))
    def get_dict(self) -> dict:
        data = {}
        for coin_length in range(self.length()):
            data[self.get_name(coin_length)] = self.get_price(coin_length)
        return data
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
def split_coins(coins, num: int = 60) -> list:
    pms = []
    cntr = Counter()
    c = 0
    iterator = coins.get_dict().items() if type(coins) is getCoin else coins.items()
    for i, v in iterator:
        index = cntr.get_num()
        if index%num==0:c+=1
        if (c+1) >= len(pms): pms.append('')
        pms[c] += f'{index} - {i}: `{v}$`\n'
    while pms.count(''): pms.remove('')
    return pms
# - - - - - - - - - - - - - - - - - - - - - - - - - -  #


import pyautogui,cv2,numpy as np,time,tkinter
from tkinter import simpledialog
def ask_for_field_status():
    return "sow"
    root=tkinter.Tk()
    root.withdraw()
    return simpledialog.askstring("Input","If fields are already sown enter: sow\nelse enter: harvest")

def check_ad(last_time):
    if last_time==0:
        return time.time(),1
    else:
        if time.time()-last_time>=300:
            return time.time(),1
        else:
            return 0,0

def ask_for_wheat_count():
    return 500
    root=tkinter.Tk()
    root.withdraw()

    top_level = tkinter.Toplevel(root)
    top_level.title("Input")
    # top_level.attributes("-topmost", True)
    top_level.grab_set()
    top_level.focus_force()

    return simpledialog.askinteger("Input","How much wheat you have")

def find_image(image_path):
    template = cv2.imread(image_path)
    # template = cv2.cvtColor(template, cv2.COLOR_RGB2BGR)
    template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
    screenshot = pyautogui.screenshot()
    # screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_BGR2GRAY)
    result = cv2.matchTemplate(screenshot, template, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    if(max_val<0.7):
        return None
    else:
        top_left = max_loc
        bottom_right = (top_left[0] + template.shape[1], top_left[1] + template.shape[0])
        center_x = (top_left[0] + bottom_right[0]) // 2
        center_y = (top_left[1] + bottom_right[1]) // 2

        return (center_x,center_y)

def find_image_lp(image_path):
    template = cv2.imread(image_path)

    screenshot = pyautogui.screenshot()
    screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)

    result = cv2.matchTemplate(screenshot, template, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    top_left = max_loc
    bottom_right = (top_left[0] + template.shape[1], top_left[1] + template.shape[0])
    center_x = (top_left[0] + bottom_right[0]) // 2
    center_y = (top_left[1] + bottom_right[1]) // 2
    return (center_x,center_y)

def find_shop():
    shop=None
    while shop is None:
        shop=find_image_lp("shop_unsold.png")
        if shop is None:
            shop=find_image_lp("shop_sold.png")
    return shop

def calibrate_field(cur_op,start):
    field_location=None
    if cur_op=="sow":
        # print("c")
        field_location=find_image("full_fields.png")
    else:
        field_location=find_image("empty_fields.png")
    # print("d")
    pyautogui.moveTo(field_location,duration=2)
    pyautogui.mouseDown(button='left')
    # time.sleep(0.001)
    pyautogui.moveTo(start,duration=4)
    # time.sleep(0.5)
    pyautogui.mouseUp(button='left')
    pyautogui.moveTo(start[0],start[1]+50,duration=1)
    pyautogui.click(pyautogui.position())
    pyautogui.moveTo(start,duration=1)

# from pynput.keyboard import Listener as keyboardlistener,Key
# from pynput.mouse import Listener as mouselistener

# start_implementation=""

# def on_press(key):
#     global start_implementation
#     if key==Key.space:
#         start_implementation=" "
#         keyboardlistener.stop()

# def on_click(x,y,button,pressed):
#     global start
#     if pressed:
#         if start is None:
#             start=(x,y)
#             mouselistener.stop()

# with keyboardlistener(on_press=on_press) as keyboardlistener:
#     keyboardlistener.join()

# if start_implementation==" ":
#     with mouselistener(on_click=on_click) as mouselistener:
#         mouselistener.join()
#     time.sleep(3)
#     calibrate_field("sow")


from django.conf.urls import patterns, include, url
from DAS_core.views import *
from django.contrib import admin
from django.views.generic import TemplateView

admin.autodiscover()

urlpatterns = patterns('',
    url('^', include('django.contrib.auth.urls')),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^home/$', Home.as_view(), name='home'),
    url(r'^home-prof/$', home_prof, name='home-prof'),
    url(r'^home-aluno/$', home_aluno, name='home-aluno'),
    url(r'^home-prof/disc-inserir-freq/(?P<pk>\d+)/$', FreqForm.as_view(), name='inserir-freq-disc'),
    url(r'^home-prof/disc-inserir-nota/(?P<pk>\d+)/$', NotaForm.as_view(), name='inserir-nota-disc'),
    url(r'^home-prof/disc-inserir-noticia/(?P<pk>\d+)/$', NoticiaForm.as_view(), name='inserir-noticia-disc'),
    url(r'^disc-inserir-arquivo/(?P<pk>\d+)/$', ArquivoForm.as_view(), name='inserir-arquivo-disc'),
    url(r'^disc-detail-freq/(?P<pk>\d+)/$', disc_detail, name='detalhe-freq-disc'),
    #url(r'^disc-inserir-nota/$', inserir_nota, name='inserir-nota-disc'),
)


import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.size'] = '20'

# helper functions
def getXY(matrix, type):
    try:
        x_data = []
        y_data = []

        if type == 1:
            for val in matrix:
                x_data.append(val[0])
                y_data.append(val[1])
        elif type == 2:
            for val in matrix:
                x_data.append(val[2])
                y_data.append(val[3]/val[2])

        return [x_data, y_data]
    except:
        print("Failed to get X and Y coordinates. Check dimensions of matrix passed, it must be of Nx2 size.")
        exit()

def getNormalFuncFirstOrder(data, partnum):
    [x, y] = getXY(data, 1)

    # make A and B matrices
    mat_a = np.empty((0, 2), dtype=float)
    for i in range(len(x)):
        mat_a = np.append(mat_a, np.array([[x[i], 1]]), axis=0)

    mat_a = np.matrix(mat_a)
    mat_b = np.matrix(y, dtype=float).getT()

    # show data as it appears
    plt.scatter(x, y, marker='o')

    plt.xlabel('x-axis', fontsize=30)
    plt.ylabel('y-axis', fontsize=30)
    plt.title('Part ' + str(partnum), fontsize=32)
    # plt.show()

    mat_x = (mat_a.getT() * mat_a)
    mat_x = np.linalg.inv(mat_x)
    mat_x = mat_x * mat_a.getT() * mat_b

    print('Solution to normal equation in part ' + str(partnum) + ':')
    print(mat_x)
    print()

    # get form of y = m*x + b
    m = float(mat_x[0])
    b = float(mat_x[1])

    x2 = np.linspace(min(x), max(x), 100)
    y2 = m * x2 + b

    plt.plot(x2, y2, 'r')
    plt.ylim([0, 15])

    plt.xlim([4, 10])
    plt.show()
    plt.close()

def getNormalFuncInvX(data, partnum):
    [x, y] = getXY(data3, 2)

    # make A and B matrices
    mat_a = np.empty((0, 2), dtype=float)
    for i in range(len(x)):
        mat_a = np.append(mat_a, np.array([[1 / x[i], 1]]), axis=0)

    mat_a = np.matrix(mat_a)
    mat_b = np.matrix(y, dtype=float).getT()

    # show data as it appears
    plt.scatter(x, y, marker='.')
    #plt.grid()

    plt.xlabel('# of Bites', fontsize=30)
    plt.ylabel('Kcals/bite', fontsize=30)
    plt.title('Part ' + str(partnum), fontsize=32)

    mat_x = (mat_a.getT() * mat_a)
    mat_x = np.linalg.inv(mat_x)
    mat_x = mat_x * mat_a.getT() * mat_b

    print('Solution to normal equation in part ' + str(partnum) + ':')
    print(mat_x)
    print()

    # get form of y = m*(1/x) + b
    m = float(mat_x[0])
    b = float(mat_x[1])

    x2 = np.linspace(0.5, max(x), 10000)
    y2 = m * (1 / x2) + b

    plt.xlim([-10, 200])
    plt.ylim([-10, 150])
    # plt.yscale("log")
    # plt.xscale("log")
    plt.plot(x2, y2, 'r')

    plt.show()
    plt.close()

def readData(file_in):

    fpt = ''  # fixes error in IDE of fpt not existing in scope (try/except will never allow for it to not be in scope)
    try:
        fpt = open(file_in)
    except:
        print(file_in + ' could not be opened. Check the filename and try again.')
        exit()
    try:
        file_array = []

        for line in fpt.readlines():
            temp_array = line.replace('\n', '').split(' ')
            for i in range(len(temp_array)):
                temp_array[i] = float(temp_array[i])
            if temp_array:  # use implicit boolean property of list
                file_array.append(temp_array)

        fpt.close()

        return file_array
    except:
        print('Something went wrong in parsing the data from ' + file_in)

# ====================================================== PART 1 ====================================================== #
data1 = [[5, 1],
         [6, 1],
         [7, 2],
         [8, 3],
         [9, 5]]

getNormalFuncFirstOrder(data1, 1)  # get normal function of data based on a first order linear regression

# ====================================================== PART 2 ====================================================== #
data2 = [[5, 1],
         [6, 1],
         [7, 2],
         [8, 3],
         [8, 14],  # added point to reduce model accuracy
         [9, 5]]

getNormalFuncFirstOrder(data2, 2)  # get normal function of data based on a first order linear regression

# ====================================================== PART 3 ====================================================== #

data3 = readData('data.txt')

getNormalFuncInvX(data3, 3)


#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt
from functions import read_hier

path = 'cosmo_sim_1d/gaussian_ICs/'
folder_name = '/hierarchy/'
plots_folder = 'spectra'

j = 0

for j in range(11):
    # j = 0
    moments_filename = 'output_hierarchy_{0:04d}.txt'.format(j)
    moments_file = np.genfromtxt(path + moments_filename)
    a = moments_file[:,-1][0]
    x = moments_file[:,0]
    M0_nbody = moments_file[:,2]-1
    M1_nbody = moments_file[:,4]
    M2_nbody = moments_file[:,6]
    C1_nbody = moments_file[:,5]
    C2_nbody = moments_file[:,7]

    M0_nbody -= np.mean(M0_nbody)
    M0_k = np.fft.fft(M0_nbody) / M0_nbody.size
    P_k = np.abs(M0_k * np.conj(M0_k))
    k = np.fft.ifftshift(2.0 * np.pi * np.arange(-x.size/2, x.size/2))

    plt.rcParams.update({"text.usetex": True})
    plt.rcParams.update({"font.family": "serif"})
    fig, ax = plt.subplots()
    ax.set_title(rf'a = {np.round(a, 3)}', fontsize=14)
    # ax.set_xlabel()
    # ax.set_ylabel()
    ax.tick_params(axis='both', which='both', direction='in', labelsize=12)
    ax.yaxis.set_ticks_position('both')
    ax.minorticks_on()
    ax.scatter(k, P_k, c='b', s=15)
    # ax.set_xlim(-0.5, 1000.5)
    # ax.plot(x, C2_nbody)
    plt.savefig(f'../plots/gauss/{plots_folder}/Pk_{j}.png', bbox_inches='tight', dpi=150)
    plt.close()
    # plt.show()


from PyQt5 import QtWidgets
from telleUI import Ui as telle
from followUp_CC import Ui as followup
from followUp_PL import Ui as followupPL

class Ui(QtWidgets.QWidget):
    def __init__(self, priv, parentWin, mycursor, result, user, product, recontact=None):
        #super(Ui, self).__init__()
        #uic.loadUi('assets/ui/searchResult.ui', self)
        super(Ui, self).__init__()

        self.priv = priv
        self.parentWin = parentWin
        self.mycursor = mycursor
        self.user = user
        self.sResult = result
        self.product = product
        self.recontact = recontact

        '''window_width = 800
        window_height = 600
        self.setFixedSize(window_width, window_height)'''
        self.initUI()

    def initUI(self):
        self.createLayout_Container()
        self.layout_All = QtWidgets.QVBoxLayout(self)
        self.layout_All.addWidget(self.scrollarea)
        self.pushButton = QtWidgets.QPushButton()
        self.pushButton.setObjectName("pushButton")
        self.layout_All.addWidget(self.pushButton)
        self.pushButton.setText("Return")
        self.pushButton.clicked.connect(self.closeWin)
        self.showFullScreen()
        self.setFixedSize(self.width(), self.height())
        '''self.scrollArea.setGeometry(int(self.width() / 4), int(self.height() / 4), int(self.width() / 2),
                                    int(self.height() / 2))'''

    def createLayout_Container(self):
        self.scrollarea = QtWidgets.QScrollArea(self)
        #self.scrollarea.setFixedWidth(780)
        self.scrollarea.setWidgetResizable(True)

        self.widget = QtWidgets.QWidget()
        self.scrollarea.setWidget(self.widget)
        self.layout_SArea = QtWidgets.QVBoxLayout(self.widget)

        if len(self.sResult) == 0:
            self.zeroRes = QtWidgets.QLabel()
            self.zeroRes.setText("No result")
            self.layout_SArea.addWidget(self.zeroRes)

        '''self.sResult = [(1, None, '0888008080', None, 'koran', 0, None, None, '1911/000000001'),
                        (2, 'n1', '0808080', 'jalan-jalan', 'bank m', 0, None, None, '1911/000000002'),
                        (3, 'n2', '0888080080', 'jalan pagi', 'bank m', 0, None, None, '1911/000000003'),
                        (4, None, '088800808000088', None, 'koran', 0, None, None, '1911/000000004')]
                        id, nama, phone, alamat, asal_data, fetched, ??,??, unique_code'''

        for i in range(len(self.sResult)):
            self.layout_SArea.addWidget((self.createLayout_group(i)))
        self.layout_SArea.addStretch(1)

    def createLayout_group(self, num):  # question, num):
        self.sgroupbox = QtWidgets.QGroupBox("Unique Code: "+str(self.sResult[num][8]), self)

        #print(self.sResult[num])
        self.layout_groupbox = QtWidgets.QHBoxLayout(self.sgroupbox)

        self.fLayout = QtWidgets.QFormLayout()

        '''self.tb = QtWidgets.QLineEdit()
        self.tb.setText(self.sResult[num][8])
        self.tb.setEnabled(False)
        self.fLayout.addRow(QtWidgets.QLabel("Unique Code:"), self.tb)'''

        self.tb = QtWidgets.QLineEdit()
        self.tb.setText(self.sResult[num][1])
        self.tb.setEnabled(False)
        self.fLayout.addRow(QtWidgets.QLabel("Nama:"), self.tb)

        self.tb = QtWidgets.QLineEdit()
        self.tb.setText(self.sResult[num][2])
        self.tb.setEnabled(False)
        self.fLayout.addRow(QtWidgets.QLabel("No HP:"), self.tb)

        self.tb = QtWidgets.QLineEdit()
        self.tb.setText(self.sResult[num][4])
        self.tb.setEnabled(False)
        self.fLayout.addRow(QtWidgets.QLabel("Asal Data:"), self.tb)
        self.layout_groupbox.addLayout(self.fLayout)

        if self.recontact!= None:
            self.tb = QtWidgets.QLineEdit()
            self.tb.setText(str(self.sResult[num][11]))
            self.tb.setEnabled(False)
            self.fLayout.addRow(QtWidgets.QLabel("Kontak Ulang:"), self.tb)
            self.layout_groupbox.addLayout(self.fLayout)

            self.editButton = QtWidgets.QPushButton()
            self.editButton.setText("Kontak Ulang")
            self.editButton.clicked.connect(lambda: self.editCust(self.sResult[num][0], num))
            self.layout_groupbox.addWidget(self.editButton)

        else:
            self.editButton = QtWidgets.QPushButton()
            self.editButton.setText("Edit")
            if self.priv!= "adm":
                self.editButton.setEnabled(False)
            self.editButton.clicked.connect(lambda: self.editCust(self.sResult[num][0]))
            self.layout_groupbox.addWidget(self.editButton)

            try:
                #print(self.sResult[num][0])
                self.qCheckFollUp = "SELECT note from prod_"+self.product+" where cust_id = %s"
                self.mycursor.execute(self.qCheckFollUp, (self.sResult[num][0],))
                self.sFollUp = self.mycursor.fetchone()
            except Exception as e:
                print(e)
                self.buttonReply = QtWidgets.QMessageBox
                self.warning = self.buttonReply.question(self, 'WARNING', str(e),
                                                         QtWidgets.QMessageBox.Ok)

            self.followUp = QtWidgets.QPushButton()
            self.followUp.setText("Follow Up")
            self.followUp.clicked.connect(lambda: self.follup(self.sResult[num][0]))
            self.layout_groupbox.addWidget(self.followUp)
            self.followUp.setEnabled(False)
            try:
                #print(str(self.sFollUp[0]))
                if self.sFollUp[0] == "Tertarik":
                    self.followUp.setEnabled(True)
            except Exception as e:
                print('')
                '''self.buttonReply = QtWidgets.QMessageBox
                self.warning = self.buttonReply.question(self, 'WARNING', str(e),
                                                         QtWidgets.QMessageBox.Ok)'''

        return self.sgroupbox

        '''self.show()

        self.priv = priv
        self.mycursor = mycursor
        self.parentWin = parentWin
        #self.sResult = result
        self.sResult = [(1, None, '0888008080', None, 'koran', 0, None, None, '1911/000000001'),
                        (2, 'n1', '0808080', 'jalan-jalan', 'bank m', 0, None, None, '1911/000000002'),
                        (3, 'n2', '0888080080', 'jalan pagi', 'bank m', 0, None, None, '1911/000000003'),
                        (4, None, '088800808000088', None, 'koran', 0, None, None, '1911/000000004')]

        self.btn_return.clicked.connect(self.closeWin)

        if len(self.sResult)!=0:
            self.noRes.setVisible(False)

            try:
                self.cnt = 0
                for res in range(len(self.sResult)):
                    print(self.sResult[res])
                    self.fLayout = QtWidgets.QFormLayout()

                    self.tb = QtWidgets.QLineEdit()
                    self.tb.setText(self.sResult[res][8])
                    self.tb.setEnabled(False)
                    self.fLayout.addRow(QtWidgets.QLabel("Unique Code:"), self.tb)

                    self.tb = QtWidgets.QLineEdit()
                    self.tb.setText(self.sResult[res][1])
                    self.tb.setEnabled(False)
                    self.fLayout.addRow(QtWidgets.QLabel("Nama:"), self.tb)

                    self.tb = QtWidgets.QLineEdit()
                    self.tb.setText(self.sResult[res][2])
                    self.tb.setEnabled(False)
                    self.fLayout.addRow(QtWidgets.QLabel("No HP:"),self.tb)

                    self.tb = QtWidgets.QLineEdit()
                    self.tb.setText(self.sResult[res][4])
                    self.tb.setEnabled(False)
                    self.fLayout.addRow(QtWidgets.QLabel("Asal Data:"), self.tb)
                    # print("pop")
                    self.gridLayout.addLayout(self.fLayout,self.cnt*2, 0, 2, 3)

                    self.editButton = QtWidgets.QPushButton()
                    self.editButton.setText("Edit")
                    self.editButton.clicked.connect(lambda: self.editCust(self.sResult[res][0]))
                    self.gridLayout.addWidget(self.editButton, self.cnt*2, 3)
                    #print("opo1")

                    self.followUp = QtWidgets.QPushButton()
                    self.followUp.setText("Follow Up")
                    self.followUp.clicked.connect(lambda: self.follup(self.sResult[res][0]))
                    self.gridLayout.addWidget(self.followUp, self.cnt*2+1, 3)

                    self.cnt+=1
            except Exception as e:
                print(str(e))'''

    def editCust(self, id, num = None):
        #print(id)
        try:
            if self.recontact!= None:
                self.query = "UPDATE prod_"+self.product+" set recontact_status = True where data_id = %s;"
                self.mycursor.execute(self.query, (self.sResult[num][10],))
                self.mycursor.execute("commit;")

                self.telle = QtWidgets.QWidget()
                self.telle.ui = telle(self.priv, self, self.mycursor, self.user,self.product, target = id, recontact= True)
            else:
                self.telle = QtWidgets.QWidget()
                self.telle.ui = telle(self.priv, self, self.mycursor, self.user, self.product, target=id)
            self.hide()
        except Exception as e:
            self.buttonReply = QtWidgets.QMessageBox
            self.warning = self.buttonReply.question(self, 'WARNING', str(e),
                                                     QtWidgets.QMessageBox.Ok)

    def follup(self, id):
        #print("Follup "+str(id))
        self.folUp = QtWidgets.QWidget()
        if self.product.lower() == "pl":
            self.folUp.ui = followupPL(self.priv, self, self.mycursor, self.user, self.product, target=id)
        else:
            self.folUp.ui = followup(self.priv, self, self.mycursor, self.user, self.product, target=id)
        self.hide()

    def closeWin(self):
        self.parentWin.show()
        self.close()

'''if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    premain = QtWidgets.QMainWindow()
    premain.ui = Ui()
    sys.exit(app.exec_())'''


from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import re
import sys

imgw=0
imgh=0
scalex=0
scaley=0
#img = Image.new("RGB",(300,300),"red")
#img.save("./test.jpg")

def getScale(width, height, lines):
    wordnum=0
    for line in lines:
        words = re.split(":", line)
        if (len(words) != 2) :
            print("Error : The format is not correct")
            exit()
        words[1]=line
        if (wordnum <= len(words[1])):
            wordnum = len(words[1])
    scale_x = width / (wordnum+1)
    scale_y = height / len(lines)
    return int(scale_x), int(scale_y)

def drawText(img,basex,basey,word):
    do = ImageDraw.Draw(img)
    fontsize=int(scalex*2)
    font = ImageFont.truetype("mplus-1p-regular.ttf", fontsize)
    do.text((basex,basey),word,fill="black",font=font)

def drawChart(img,basex,basey,line):
    do = ImageDraw.Draw(img)
    scaley2 = scaley * 7 / 10
    wid=int(scaley/20)
    fontsize=int(scalex*2)
    font = ImageFont.truetype("mplus-1p-regular.ttf", fontsize)
    preword=""
    textbuf=""
    textanc=basex+(scalex/2)
    for i in range(len(line)):
        word=line[i]
        if (word == "_"):
            if (preword == "~"):
                do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*i,basey+(scaley2/2))], fill="black", width=wid)
            elif (preword == "-"):
                do.line([(basex+scalex*i,basey), (basex+scalex*i,basey+(scaley2/2))], fill="black", width=wid)
            do.line([(basex+scalex*i,basey+(scaley2/2)), (basex+scalex*(i+1),basey+(scaley2/2))], fill="black", width=wid)
        elif (word == "~"):
            if (preword == "_"):
                do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*i,basey+(scaley2/2))], fill="black", width=wid)
            elif (preword == "-"):
                do.line([(basex+scalex*i,basey), (basex+scalex*i,basey-(scaley2/2))], fill="black", width=wid)
            do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*(i+1),basey-(scaley2/2))], fill="black", width=wid)
        elif (word == "-"):
            if (preword == "_"):
                do.line([(basex+scalex*i,basey), (basex+scalex*i,basey+(scaley2/2))], fill="black", width=wid)
            elif (preword == "~"):
                do.line([(basex+scalex*i,basey), (basex+scalex*i,basey-(scaley2/2))], fill="black", width=wid)
            elif (preword == "="):
                do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*i,basey+(scaley2/2))], fill="black", width=wid)
            do.line([(basex+scalex*i,basey), (basex+scalex*(i+1),basey)], fill="black", width=wid)
        elif (word == "="):
            if (textbuf != ""):
                do.text((textanc,basey-scaley2/2),textbuf,fill="black",font=font)
                textbuf=""
            do.line([(basex+scalex*i,basey+(scaley2/2)), (basex+scalex*(i+1),basey+(scaley2/2))], fill="black", width=wid)
            do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*(i+1),basey-(scaley2/2))], fill="black", width=wid)
        else:
            if ((preword == "=") or (preword == "-")):
                textanc=(basex+scalex*i+scalex/2)
                do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*i,basey+(scaley2/2))], fill="black", width=wid)
            do.line([(basex+scalex*i,basey+(scaley2/2)), (basex+scalex*(i+1),basey+(scaley2/2))], fill="black", width=wid)
            do.line([(basex+scalex*i,basey-(scaley2/2)), (basex+scalex*(i+1),basey-(scaley2/2))], fill="black", width=wid)
            textbuf=textbuf+word
        preword=word

if __name__ == '__main__':
    if (len(sys.argv) != 2) :
        print("Error : Argument is not correct.")
        exit()
    srcpath = sys.argv[1]
    srcfp = open(srcpath)
    lines = srcfp.readlines()
    srcfp.close()

    for i in range(len(lines)):
        lines[i] = lines[i].replace('\r', '')
        lines[i] = lines[i].replace('\n', '')
        #line = line.rstrip('\n')

    ## Info Check
    line = lines.pop(0)
    words = re.split(",", line)
    imgw = int(words[0])
    imgh = int(words[1])
    img = Image.new("RGB",(imgw,imgh),"white")
    scalex, scaley = getScale(imgw,imgh,lines)
    print("----------------")
    print("sizeX :"+str(imgw)+" sizeY :"+str(imgh))
    print("scaleX:"+str(scalex)+" scaleY:"+str(scaley))
    print("----------------")

    ##
    for i in range(len(lines)):
        line = lines[i]
        words = re.split(":", line)
        if (len(words) != 2) :
            print("Error : The format is not correct")
            exit()
        print(words[1])
        drawText(img,scalex/2,(scaley*i)+(scaley/8),words[0])
        drawChart(img,scalex*(len(words[0])+1),(scaley*i)+(scaley/2),words[1])
    img.save("./chart.jpg")


from .forms import UserRegistrationForm
from django.shortcuts import render, redirect

def register(request):
    if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            print("Form is valid")
            form.save()
            return redirect('login')
        else:
            print("form has errors")

    else:
        form = UserRegistrationForm()
    return render(request, 'users/register.html', {'form': form})


from . import views
from django.urls import path

app_name = 'release'

urlpatterns = [
    path('addAlbumRelease', views.AlbumView.as_view(), name='addNewAlbumRelease'),
    path('addSinglesRelease', views.SinglesView.as_view(), name='addNewSinglesRelease'),
    path('displayAlbum', views.DisplayAlbumView.as_view(), name='displayAlbum'),
    path('displaySingle', views.DisplaySingleView.as_view(), name='displaySingle'),
]


# Counting Sundays
# Problem 19
# You are given the following information, but you may prefer to do some research for yourself.
#
# 1 Jan 1900 was a Monday.
# Thirty days has September,
# April, June and November.
# All the rest have thirty-one,
# Saving February alone,
# Which has twenty-eight, rain or shine.
# And on leap years, twenty-nine.
# A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
# How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

from itertools import takewhile

def next_day(date=(0, 'Monday', 0, 1900)):
    day_strings = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')
    next_day_string = {day_strings[d % 7]: day_strings[(d + 1) % 7] for d in range(0, 7)}
    days_in_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

    while True:  # no tail recursion in python :(
        day, day_string, month, year = date
        offset = 1 if month == 1 and year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) else 0
        month_boundary = days_in_month[month] + offset
        new_day = (day + 1) % month_boundary
        new_month = (month + 1) % 12 if new_day == 0 else month
        new_year = year + 1 if new_day == 0 and new_month == 0 else year

        new_date = (new_day, next_day_string[day_string], new_month, new_year)
        yield new_date
        date = new_date

sundays_on_first = filter(lambda day: day[0] == 0 and day[1] == 'Sunday', next_day())
from_1901 = filter(lambda day: day[3] > 1900, sundays_on_first)
until_2001 = takewhile(lambda day: day[3] < 2001, from_1901)
print(len(list(until_2001)))


import logging
import os
import yaml
import appdirs

from mail_sender_daemon import app, APP_NAME

logger = logging.getLogger(APP_NAME)

os.environ["XDG_CONFIG_DIRS"] = "/etc"

CONFIG_DIRS = (
    appdirs.user_config_dir(APP_NAME),
    appdirs.site_config_dir(APP_NAME),
    os.path.abspath(os.path.join(app.root_path, "../")),
)
CONFIG_FILENAME = "config.yml"

def build_app_config(custom_path=None):
    """
    Get config file and load it with yaml

    :returns: loaded config in yaml, as a dict object
    """
    if custom_path:
        config_path = custom_path
    else:
        for d in CONFIG_DIRS:
            config_path = os.path.join(d, CONFIG_FILENAME)
            if os.path.isfile(config_path):
                break
    try:
        with open(config_path, "r") as config_file:
            return yaml.safe_load(config_file)
    except FileNotFoundError as e:
        logger.debug(e)
        if custom_path:
            logger.error(
                "Configuration file {} not found.".format(custom_path)
            )
        else:
            logger.error(
                "No configuration file can be found.\n"
                "Please create a config.yml in one of these directories:\n"
                "\t{}".format("\n\t".join(CONFIG_DIRS))
            )
        raise


from __future__ import division
import torch
import torch.nn as nn
import torch.autograd as autograd

class Jacobian(nn.Module):
    '''
    Loss criterion that computes the trace of the square of the Jacobian.
    Arguments:
        n (int, optional): determines the number of random projections.
            If n=-1, then it is set to the dimension of the output
            space and projection is non-random and orthonormal, yielding
            the exact result.  For any reasonable batch size, the default
            (n=1) should be sufficient.
    '''

    def __init__(self, n=-1):
        assert n == -1 or n > 0
        self.n = n
        super(Jacobian, self).__init__()

    def forward(self, x, y):
        '''
        computes (1/2) tr |dy/dx|^2
        '''
        B, C = y.shape #32 10
        if self.n == -1:
            num_proj = C
        else:
            num_proj = self.n
        J2 = 0
        for ii in range(num_proj):
            if self.n == -1:
                # orthonormal vector, sequentially spanned
                v = torch.zeros(B, C)
                v[:, ii] = 1
            else:
                # random properly-normalized vector for each sample
                v = self._random_vector(C=C, B=B)
            if x.is_cuda:
                v = v.cuda()
            print("v:", v)
            Jv = self._jacobian_vector_product(y, x, v, create_graph=True)
            print("Jv:", Jv.shape)
            J2 += C * torch.norm(Jv) ** 2 / (num_proj * B)
        R = (1 / 2) * J2
        return R

    def _random_vector(self, C, B):
        '''
        creates a random vector of dimension C with a norm of C^(1/2)
        (as needed for the projection formula to work)
        '''
        if C == 1:
            return torch.ones(B)
        v = torch.randn(B, C)
        arxilirary_zero = torch.zeros(B, C)
        vnorm = torch.norm(v, 2, 1, True)
        v = torch.addcdiv(arxilirary_zero, 1.0, v, vnorm)
        return v

    def _jacobian_vector_product(self, y, x, v, create_graph=False):
        '''
        Produce jacobian-vector product dy/dx dot v.
        Note that if you want to differentiate it,
        you need to make create_graph=True
        '''
        flat_y = y.reshape(-1)
        flat_v = v.reshape(-1)
        grad_x, = torch.autograd.grad(flat_y, x, flat_v,
                                      retain_graph=True,
                                      create_graph=create_graph)
        return grad_x

class JacobianAugmentation(object):
    def __init__(self, copy_model):
        self.lammda=0.1
        self.copy_model=copy_model
        # self.queried_y=queried_y #should be torch

    def get_synthesizing_set(self, inputs, targets):
        #let input_shape a list
        # extended for Jacobian calculation

        # Jacobian computed by the improved method
        # On Colab CPU 0.16s, K80 GPU 0.14s
        # with JacobianMode(self.copy_model):
        #     out = self.copy_model(inputs).cpu()
        #     out.sum().backward()
        #     jac = self.copy_model.jacobian()
        inputs = inputs.cuda()
        targets = targets.cuda()
        inputs.requires_grad_()
        targets.requires_grad_()

        inputs.requires_grad = True
        outputs = self.copy_model(inputs)
        # pred = jacobian(targets, inputs, outputs, create_graph=True)#targets
        # jacobian=Jacobian()
        # jac_on_copy=jacobian(inputs, outputs)
        # print("jac_on_copy", jac_on_copy)
        grad_x, = torch.autograd.grad(outputs, inputs, targets, allow_unused=True)#retain_graph=True,
                                       #create_graph=True
        #outputs: _TensorOrTensors,
        #inputs: _TensorOrTensors,
        #grad_outputs
        #jacobian is calculated on the copy model/substitute model
        # print("grad_x", grad_x[0])
        # print('x', inputs[0])
        #calculate new set
        synthesizing_set = inputs + self.lammda * torch.sign(grad_x) #if all these two is torch
        # synthesizing_set=[]
        return synthesizing_set


"""Creates an image from a numpy array of floating point depth data.

Taken from https://github.com/ahundt/robotics_setup/blob/master/datasets/google_brain_robot_data/depth_image_encoding.py

Examples:

  depth_array is a 2D numpy array of floating point depth data in meters.

  depth_rgb = FloatArrayToRgbImage(depth_array)
  depth_rgb is a PIL Image object containing the same data as 24-bit
  integers encoded in the RGB bytes.
  depth_rgb.save('image_file.png') - to save to a file.

  depth_array2 = ImageToFloatArray(depth_rgb)
  depth_array2 is a 2D numpy array containing the same data as
  depth_array up to the precision of the RGB image (1/256 mm).

  depth_gray = FloatArrayToGrayImage(depth_array)
  depth_gray is a PIL Image object containing the same data rounded to
  8-bit integers.
  depth_gray.save('image_file.jpg', quality=95) - to save to a file.

  depth_array3 = ImageToFloatArray(depth_gray)
  depth_array3 is a 2D numpy array containing the same data as
  depth_array up to the precision of the grayscale image (1 cm).

The image conversions first scale and round the values and then pack
them into the desired type in a numpy array before converting the
array to a PIL Image object.  The Image can be saved in any format.
We are using PNG for RGB and high quality JPEG for grayscale images.

You can use different numeric types (e.g. np.uint16, np.int32), but
not all combinations of numeric type and image format are supported by
PIL or standard image viewers.

"""

import numpy as np
from PIL import Image

def ClipFloatValues(float_array, min_value, max_value):
  """Clips values to the range [min_value, max_value].

  First checks if any values are out of range and prints a message.
  Then clips all values to the given range.

  Args:
    float_array: 2D array of floating point values to be clipped.
    min_value: Minimum value of clip range.
    max_value: Maximum value of clip range.

  Returns:
    The clipped array.

  """
  if float_array.min() < min_value or float_array.max() > max_value:
    float_array = np.clip(float_array, min_value, max_value)
  return float_array

DEFAULT_RGB_SCALE_FACTOR = 256000.0

def float_array_to_rgb_image(float_array,
                             scale_factor=DEFAULT_RGB_SCALE_FACTOR,
                             drop_blue=False):
  """Convert a floating point array of values to an RGB image.

  Convert floating point values to a fixed point representation where
  the RGB bytes represent a 24-bit integer.
  R is the high order byte.
  B is the low order byte.
  The precision of the depth image is 1/256 mm.

  Floating point values are scaled so that the integer values cover
  the representable range of depths.

  This image representation should only use lossless compression.

  Args:
    float_array: Input array of floating point depth values in meters.
    scale_factor: Scale value applied to all float values.
    drop_blue: Zero out the blue channel to improve compression, results in 1mm
      precision depth values.

  Returns:
    24-bit RGB PIL Image object representing depth values.
  """
  # Scale the floating point array.
  scaled_array = np.floor(float_array * scale_factor + 0.5)
  # Convert the array to integer type and clip to representable range.
  min_inttype = 0
  max_inttype = 2**24 - 1
  scaled_array = ClipFloatValues(scaled_array, min_inttype, max_inttype)
  int_array = scaled_array.astype(np.uint32)
  # Calculate:
  #   r = (f / 256) / 256  high byte
  #   g = (f / 256) % 256  middle byte
  #   b = f % 256          low byte
  rg = np.divide(int_array, 256)
  r = np.divide(rg, 256)
  g = np.mod(rg, 256)
  image_shape = int_array.shape
  rgb_array = np.zeros((image_shape[0], image_shape[1], 3), dtype=np.uint8)
  rgb_array[..., 0] = r
  rgb_array[..., 1] = g
  if not drop_blue:
    # Calculate the blue channel and add it to the array.
    b = np.mod(int_array, 256)
    rgb_array[..., 2] = b
  image_mode = 'RGB'
  image = Image.fromarray(rgb_array, mode=image_mode)
  return image

DEFAULT_GRAY_SCALE_FACTOR = {np.uint8: 100.0,
                             np.uint16: 1000.0,
                             np.int32: DEFAULT_RGB_SCALE_FACTOR}

def float_array_to_grayscale_image(float_array, scale_factor=None, image_dtype=np.uint8):
  """Convert a floating point array of values to an RGB image.

  Convert floating point values to a fixed point representation with
  the given bit depth.

  The precision of the depth image with default scale_factor is:
    uint8: 1cm, with a range of [0, 2.55m]
    uint16: 1mm, with a range of [0, 65.5m]
    int32: 1/256mm, with a range of [0, 8388m]

  Right now, PIL turns uint16 images into a very strange format and
  does not decode int32 images properly.  Only uint8 works correctly.

  Args:
    float_array: Input array of floating point depth values in meters.
    scale_factor: Scale value applied to all float values.
    image_dtype: Image datatype, which controls the bit depth of the grayscale
      image.

  Returns:
    Grayscale PIL Image object representing depth values.

  """
  # Ensure that we have a valid numeric type for the image.
  if image_dtype == np.uint16:
    image_mode = 'I;16'
  elif image_dtype == np.int32:
    image_mode = 'I'
  else:
    image_dtype = np.uint8
    image_mode = 'L'
  if scale_factor is None:
    scale_factor = DEFAULT_GRAY_SCALE_FACTOR[image_dtype]
  # Scale the floating point array.
  scaled_array = np.floor(float_array * scale_factor + 0.5)
  # Convert the array to integer type and clip to representable range.
  min_dtype = np.iinfo(image_dtype).min
  max_dtype = np.iinfo(image_dtype).max
  scaled_array = ClipFloatValues(scaled_array, min_dtype, max_dtype)

  image_array = scaled_array.astype(image_dtype)
  image = Image.fromarray(image_array, mode=image_mode)
  return image

def image_to_float_array(image, scale_factor=None):
  """Recovers the depth values from an image.

  Reverses the depth to image conversion performed by FloatArrayToRgbImage or
  FloatArrayToGrayImage.

  The image is treated as an array of fixed point depth values.  Each
  value is converted to float and scaled by the inverse of the factor
  that was used to generate the Image object from depth values.  If
  scale_factor is specified, it should be the same value that was
  specified in the original conversion.

  The result of this function should be equal to the original input
  within the precision of the conversion.

  Args:
    image: Depth image output of FloatArrayTo[Format]Image.
    scale_factor: Fixed point scale factor.

  Returns:
    A 2D floating point numpy array representing a depth image.

  """
  image_array = np.array(image)
  image_dtype = image_array.dtype
  image_shape = image_array.shape

  channels = image_shape[2] if len(image_shape) > 2 else 1
  assert 2 <= len(image_shape) <= 3
  if channels == 3:
    # RGB image needs to be converted to 24 bit integer.
    float_array = np.sum(image_array * [65536, 256, 1], axis=2)
    if scale_factor is None:
      scale_factor = DEFAULT_RGB_SCALE_FACTOR
  else:
    if scale_factor is None:
      scale_factor = DEFAULT_GRAY_SCALE_FACTOR[image_dtype.type]
    float_array = image_array.astype(np.float32)
  scaled_array = float_array / scale_factor
  return scaled_array

def task_file_to_task_class(task_file):
  import importlib
  name = task_file.replace('.py', '')
  class_name = ''.join([w[0].upper() + w[1:] for w in name.split('_')])
  mod = importlib.import_module("rlbench.tasks.%s" % name)
  mod = importlib.reload(mod)
  task_class = getattr(mod, class_name)
  return task_class

def rgb_handles_to_mask(rgb_coded_handles):
  # rgb_coded_handles should be (w, h, c)
  # Handle encoded as : handle = R + G * 256 + B * 256 * 256
  rgb_coded_handles *= 255  # takes rgb range to 0 -> 255
  rgb_coded_handles.astype(int)
  return (rgb_coded_handles[:, :, 0] +
          rgb_coded_handles[:, :, 1] * 256 +
          rgb_coded_handles[:, :, 2] * 256 * 256)


#!/usr/bin/python3
import argparse
import logging

import slackclient
import json
import datetime

class UserMap:
    def __init__(self, user_id_to_name):
        self._user_id_to_name = user_id_to_name

    def get_username(self, message):
        if message.get("user"):
            return self._user_id_to_name[message["user"]]
        if message.get("bot_id"):
            return message["bot_id"]
        raise Exception("unknown username: %s" % message)

class APIWrapper:
    def __init__(self, token):
        self._slackclient = slackclient.SlackClient(token)

    def get_messages(self, channel_name):
        """ get all messages from channel """
        channel_id = self._channel_name_to_channel_id(channel_name)
        msgs = []
        while True:
            args = dict(count=1000, channel=channel_id)
            if msgs:
                args["latest"] = msgs[-1]["ts"]
            resp = self._api_call("channels.history", **args)
            msgs += resp["messages"]
            if resp["is_limited"] or not resp["has_more"]:
                break
        return msgs

    def get_user_map(self):
        users = self._api_call("users.list")
        user_map_data = {u["id"]: u["name"] for u in users["members"]}
        return UserMap(user_map_data)

    def _channel_name_to_channel_id(self, channel_name):
        channels = self._api_call("channels.list")
        for c in channels["channels"]:
            if c.get("name") == channel_name:
                return c.get("id")
        raise KeyError("Channel %s not found in %s" % (channel_name, channels))

    def _api_call(self, *a, **kw):
        resp = self._slackclient.api_call(*a, **kw)
        if not resp["ok"]:
            raise Exception("not ok")
        return resp

def nice_ts(tsarg):
    """ prettify timestamp string with microseconds precision
        NOTE: timezones may not always work correctly
    """
    ts, msec = map(int, tsarg.split("."))
    d = datetime.datetime.fromtimestamp(ts)
    d = d.replace(microsecond=msec)
    return d.strftime("%Y-%m-%d %H:%M:%S.%f")

def prettify_text_for_csv(text):
    if "\n" in text:
        text = "\n" + text
    # standard CSV escape character is "
    text = text.replace("\"", "\"\"")
    text = text.replace("\t", "\"\t")
    return text

def make_csv_line(msg):
    """ prefix multiline message with \n, for better reading comfort
        and escape characters, so that CSV can be parsed again
    """
    text = prettify_text_for_csv(msg.get("text", ""))
    return "\t".join([msg["datetime"], msg["username"], text])

def get_pretty_messages(client, channel):
    msgs = client.get_messages(channel)
    user_map = client.get_user_map()

    for m in msgs:
        try:
            m["datetime"] = nice_ts(m["ts"])
            m["username"] = user_map.get_username(m)
            m["csv_line"] = make_csv_line(m)
        except Exception:
            logging.exception("Error with message %s" % m)
    return msgs

def run():
    p = argparse.ArgumentParser(description="Dump slack channel archive in full JSON and human-readable CSV")
    p.add_argument("--channel", default="konfa")
    p.add_argument("-s", "--secret-file", default="secret.txt",
                   help="Get it from https://api.slack.com/custom-integrations/legacy-tokens")
    p.add_argument("--csv", default="output.csv", help="Output csv path")
    p.add_argument("--json", default="output.json", help="Output json path")
    args = p.parse_args()

    client = APIWrapper(open(args.secret_file, "r").read().strip())
    msgs = get_pretty_messages(client, args.channel)
    with open(args.json, "w") as jsonfile:
        json.dump(msgs, jsonfile, indent=4)
    with open(args.csv, "w") as csvfile:
        for l in msgs:
            # noinspection PyTypeChecker
            print(l["csv_line"], file=csvfile)

if __name__ == "__main__":
    run()


from __future__ import annotations

import dataclasses
import typing

from retro_data_structures.formats.mlvl import Mlvl
from retro_data_structures.formats.script_object import InstanceId
from retro_data_structures.properties import field_reflection
from retro_data_structures.properties.base_property import BaseObjectType, BaseProperty
from retro_data_structures.properties.echoes import objects

from pwime.operations.base import Operation

if typing.TYPE_CHECKING:
    from retro_data_structures.formats.script_object import ScriptInstance

    from pwime.asset_manager import OurAssetManager
    from pwime.project import Project
    from pwime.util.json_lib import JsonObject

@dataclasses.dataclass(frozen=True)
class InstanceReference:
    mlvl: int
    mrea: int
    instance_id: InstanceId

    def to_json(self) -> JsonObject:
        return {
            "mlvl": self.mlvl,
            "mrea": self.mrea,
            "instance_id": self.instance_id,
        }

    @classmethod
    def from_json(cls, data: JsonObject) -> typing.Self:
        data_json = typing.cast(dict[str, int], data)
        return cls(data_json["mlvl"], data_json["mrea"], InstanceId(data["instance_id"]))

@dataclasses.dataclass(frozen=True)
class PropReference:
    instance: InstanceReference
    path: tuple[str, ...]

    def append(self, field: str) -> PropReference:
        return PropReference(self.instance, self.path + (field,))

def get_instance(manager: OurAssetManager, reference: InstanceReference) -> ScriptInstance:
    """Gets a ScriptInstance from a InstanceReference"""
    mlvl = manager.get_file(reference.mlvl, Mlvl)
    area = mlvl.get_area(reference.mrea)
    return area.get_instance(reference.instance_id)

PropType = typing.TypeVar("PropType", bound=BaseObjectType)

def _modified_fields(prop: type[BaseProperty], delta: JsonObject, parent: str = "") -> list[str]:
    result = []

    for name, reflection in field_reflection.get_reflection(prop).items():
        key = f"0x{reflection.id:08X}"
        if key not in delta:
            continue

        if issubclass(reflection.type, BaseProperty) and field_reflection.get_reflection(reflection.type):
            result.extend(_modified_fields(reflection.type, delta[key], f"{parent}{name}."))
        else:
            result.append(f"{parent}{name}")

    return result

def create_patch_for(instance: ScriptInstance, value_path: tuple[str, ...], new_value: typing.Any) -> JsonObject:
    delta = {}
    current_type = instance.type
    current_value = delta

    for i, name in enumerate(value_path):
        reflection = field_reflection.get_reflection(current_type)[name]
        current_type = reflection.type
        key = f"0x{reflection.id:08X}"
        if i == len(value_path) - 1:
            current_value[key] = reflection.to_json(new_value)
        else:
            current_value[key] = {}
            current_value = current_value[key]

    return delta

def patch_property(prop: PropType, delta: JsonObject) -> None:
    for name, reflection in field_reflection.get_reflection(type(prop)).items():
        key = f"0x{reflection.id:08X}"
        if key not in delta:
            continue

        if issubclass(reflection.type, BaseProperty) and field_reflection.get_reflection(reflection.type):
            patch_property(getattr(prop, name), delta[key])
        else:
            setattr(prop, name, reflection.from_json(delta[key]))

class ScriptInstancePropertyEdit(Operation, typing.Generic[PropType]):
    """Represents changing a property of an existing script object."""

    reference: InstanceReference
    prop_type: type[PropType]
    delta: JsonObject
    old_value: PropType | None = None

    def __init__(self, reference: InstanceReference, prop_type: type[PropType], delta: JsonObject):
        self.reference = reference
        self.prop_type = prop_type
        self.delta = delta

    def perform(self, project: Project) -> None:
        """Performs the change."""
        instance = get_instance(project.asset_manager, self.reference)
        self.old_value = instance.get_properties()

        with instance.edit_properties(self.prop_type) as prop:
            patch_property(prop, self.delta)

    def undo(self, project: Project) -> None:
        """Reverts the change."""
        assert self.old_value is not None
        instance = get_instance(project.asset_manager, self.reference)
        instance.set_properties(self.old_value)

    def _modified_fields(self) -> list[str]:
        return _modified_fields(self.prop_type, self.delta)

    def overwrites_operation(self, operation: Operation) -> bool:
        """Yes if changing the same field of the same object."""
        if isinstance(operation, ScriptInstancePropertyEdit):
            if self.reference != operation.reference:
                return False
            return self._modified_fields() == operation._modified_fields()
        return False

    def describe(self) -> str:
        return (
            f"Edited fields {', '.join(self._modified_fields())} of `{self.reference.instance_id}`,"
            f" a {self.prop_type.__name__}"
        )

    def to_json(self) -> JsonObject:
        return {
            "kind": "script_instance_property_edit",
            "reference": self.reference.to_json(),
            "prop_type": self.prop_type.object_type(),
            "delta": self.delta,
        }

    @classmethod
    def from_json(cls, data: JsonObject) -> typing.Self:
        return cls(
            reference=InstanceReference.from_json(data["reference"]),
            prop_type=objects.get_object(data["prop_type"]),
            delta=data["delta"],
        )


import sys

from discord.ext.commands import Cog, command, check
from discord.utils import find
from typing import List
from bot.settings import CHANNEL_ID, FIELDS, TOPICS, STAGE_3_MODULES, PRONOUNS, SERVER_2020, SERVER_2022_CHANNEL_ID
from bot.cogs.name import Name

def is_in_guild(guild_id):
    async def predicate(ctx):
        return ctx.guild and ctx.guild.id == guild_id

    return check(predicate)

def is_in_channel():
    async def predicate(ctx):
        member = ctx.message.author
        channel = member.guild.get_channel(
            CHANNEL_ID
        ) if member.guild.id == SERVER_2020 else member.guild.get_channel(
            SERVER_2022_CHANNEL_ID)
        return channel.id == ctx.message.channel.id

    return check(predicate)

class RoleChooser(Cog, name="Choose Roles"):
    """List of commands to set roles for various topics and modules"""
    def __init__(self, bot):
        self.bot = bot

    def _common(self, list1, list2):
        return list(set(list1) & set(list2))

    async def change_role(self, ctx, rolename: str, role_type: str,
                          pos_roles: List[str], max_num: int):
        member = ctx.author
        name = member.nick or member.name

        if not rolename:
            await ctx.send(
                f"You forgot to provide a {role_type} name after the command, {name}!"
            )
            return

        if rolename.lower() not in pos_roles:
            await ctx.send(f"Role change failed, {name}."
                           "You are only allowed the roles below\n"
                           "```\n" + '\n'.join(pos_roles) + "\n```")
            return

        author_roles = [
            role.name.lower() for role in ctx.author.roles
            if role.name != "@everyone"
        ]
        common_roles = self._common(author_roles, pos_roles)

        if rolename.lower() in common_roles:
            await ctx.send(f"You already have that role, {name}!")
            return

        role = find(
            lambda r: r.name.lower() == rolename.lower(),
            member.guild.roles,
        )

        if common_roles:
            role_objs = [
                find(
                    lambda r: r.name.lower() == cr_name,
                    member.guild.roles,
                ) for cr_name in common_roles
            ]
            if len(role_objs) >= max_num:
                await member.remove_roles(*role_objs)

        await member.add_roles(role)
        await ctx.send(f"Successfully assigned to {role.name}, {name}!")

    @command(help="Select your field", usage=f"[{'|'.join(FIELDS)}]")
    @is_in_channel()
    async def field(self, ctx, *, rolename=None):
        await self.change_role(ctx,
                               rolename,
                               "field",
                               pos_roles=FIELDS,
                               max_num=1)

    @command(help="Select your CSC2034 topic", usage=f"[{'|'.join(TOPICS)}]")
    @is_in_guild(SERVER_2020)
    @is_in_channel()
    async def topic(self, ctx, *, rolename=None):
        await self.change_role(ctx,
                               rolename,
                               "topics",
                               pos_roles=TOPICS,
                               max_num=1)

    @command(help="Select your Stage 3 modules",
             usage='\n'.join(STAGE_3_MODULES))
    @is_in_guild(SERVER_2020)
    @is_in_channel()
    async def stage3(self, ctx, *, rolename=None):
        await self.change_role(
            ctx,
            rolename,
            "Stage 3 Module",
            pos_roles=[x.split(' ')[0] for x in STAGE_3_MODULES],
            max_num=4)

    @command(help="Preferred Pronouns", usage='\n'.join(PRONOUNS))
    @is_in_channel()
    async def pronoun(self, ctx, *, rolename=None):
        await self.change_role(ctx,
                               rolename,
                               "Preferred Pronouns",
                               pos_roles=PRONOUNS,
                               max_num=1)
        member = ctx.author
        old_nick = member.nick
        if old_nick is None:
            old_nick = member.name
        old_pronoun = None
        for pronoun in PRONOUNS:
            if pronoun in old_nick:
                old_pronoun = pronoun
        if old_pronoun is None:
            new_nick = f"{old_nick} ({rolename})"
        else:
            new_nick = old_nick.replace(old_pronoun, rolename)
        print(new_nick)
        await member.edit(nick=new_nick)

def setup(bot):
    bot.add_cog(RoleChooser(bot))


#!/usr/bin/python3
from requests import get

def top_ten(subreddit):
    url = "https://api.reddit.com/r/{}?sort=hot&limit=10".format(subreddit)
    user_agent = "application/x-www-form-urlencoded"
    response = get(url, headers={'User-Agent': user_agent})

    if response.status_code == 200:
        data = response.json()
        top = data.get('data').get('children')
        for new in top:
            title = new.get('data').get('title')
            print(title)
    else:
        print('None')


from typing import Dict, List

from torch import Tensor, nn

from modules.modeling.dynamic_blocks.base_dynamic_block import BaseDynamicBlock
from modules.modeling.ops import (
    DynamicQConvNormActivation, DynamicQSE4ResNet
)
from modules.modeling.blocks import (
    FusedMBConvResBlock, FusedMBConvSEResBlock
)
from modules.modeling.common.utils import make_divisible, get_activation

class _DynamicFusedMBConvBlock(BaseDynamicBlock):

    def __init__(self, max_cin: int, width_list: List[int], kernel_list: List[int], stride: int, expand_list: List[float], use_se: bool, activation=nn.ReLU, inplace=True, force_residual=False) -> None:
        super().__init__(max_cin, width_list, kernel_list, stride, expand_list, activation)
        self.use_se = use_se
        self.force_residual = force_residual

        self.fused_conv = DynamicQConvNormActivation(max_in_channels=self.max_cin, max_out_channels=self.max_hidden_size, kernel_size_list=kernel_list, stride=stride, activation_layer=self.activation_layer, inplace=inplace)

        if self.use_se:
            self.se = DynamicQSE4ResNet(max_cin=self.max_hidden_size, max_mid=DynamicQSE4ResNet.get_mid_channels(self.max_cin))

        self.point_conv = DynamicQConvNormActivation(max_in_channels=self.max_hidden_size, max_out_channels=self.max_width, kernel_size_list=[1], stride=1, activation_layer=None)

        self.force_residual = force_residual
        if self.force_residual:
            self.downsample = DynamicQConvNormActivation(
                max_in_channels=self.max_cin, max_out_channels=self.max_width,
                kernel_size_list=[1], stride=stride, activation_layer=None
            )

    def forward(self, x: Tensor) -> Tensor:
        cin =  x.shape[1]
        if self.use_res_connect(cin):
            x0 = x
        elif self.force_residual:
            x0 = self.downsample(x)

        active_hidden_size = self.get_active_hidden_size(cin)

        x = self.fused_conv.forward(x, out_channels=active_hidden_size)

        if self.use_se:
            self.se.active_mid_channels = DynamicQSE4ResNet.get_mid_channels(cin)
            x = self.se(x)
        x = self.point_conv(x)

        if self.use_res_connect(cin) or self.force_residual:
            x = x0 + x
        return x

    def use_res_connect(self, cin):
        return cin == self.active_width and self.stride == 1

    @property
    def max_hidden_size(self):
        return make_divisible(self.max_expand_ratio * self.max_cin)

    def get_active_hidden_size(self, cin: int) -> int:
        return make_divisible(self.active_expand_ratio * cin)

    @property
    def active_kernel_size(self) -> int:
        return self.fused_conv.active_kernel_size

    @active_kernel_size.setter
    def active_kernel_size(self, kernel_size: int):
        self.fused_conv.active_kernel_size = kernel_size

    @property
    def active_width(self) -> int:
        return self.point_conv.active_out_channels

    @active_width.setter
    def active_width(self, width: int):
        self.point_conv.active_out_channels = width
        if self.force_residual:
            self.downsample.active_out_channels = width

    @property
    def active_expand_ratio(self) -> float:
        return self._active_expand_ratio

    @active_expand_ratio.setter
    def active_expand_ratio(self, expand_ratio: float):
        self._active_expand_ratio = expand_ratio

    def zero_last_gamma(self):
        if self.force_residual:
            self.point_conv.norm.weight.data.zero_()

class DynamicFusedMBConvResBlock(_DynamicFusedMBConvBlock):

    def __init__(self, max_cin: int, width_list: List[int], kernel_list: List[int], stride: int, expand_list: List[float], activation=nn.ReLU, inplace=True) -> None:
        super().__init__(max_cin, width_list, kernel_list, stride, expand_list, use_se=False, activation=activation, inplace=inplace, force_residual=True)

    def get_active_block(self, cin: int, retain_weights=True) -> FusedMBConvResBlock:
        block = FusedMBConvResBlock.build_from_config(self.get_active_block_config(cin))
        if retain_weights:
            hidden_size = self.get_active_hidden_size(cin)
            block.fused_conv.load_state_dict(self.fused_conv.active_state_dict(cin, cout=hidden_size))
            block.point_conv.load_state_dict(self.point_conv.active_state_dict(hidden_size))
            if hasattr(block, 'downsample'):
                block.downsample.load_state_dict(self.downsample.active_state_dict(cin))
        return block

    def get_active_tf_block(self, cin: int):
        from modules.modeling.blocks.tf_blocks import FusedMBConvResBlock as FusedMBConvResBlock_TF
        return FusedMBConvResBlock_TF.build_from_config(self.get_active_block_config(cin))

class DynamicFusedMBConvSEResBlock(_DynamicFusedMBConvBlock):

    def __init__(self, max_cin: int, width_list: List[int], kernel_list: List[int], stride: int, expand_list: List[float], activation=nn.ReLU, inplace=True) -> None:
        super().__init__(max_cin, width_list, kernel_list, stride, expand_list, use_se=True, activation=activation, inplace=inplace, force_residual=True)

    def get_active_block(self, cin: int, retain_weights=True) -> FusedMBConvSEResBlock:
        block = FusedMBConvSEResBlock.build_from_config(self.get_active_block_config(cin))
        if retain_weights:
            hidden_size = self.get_active_hidden_size(cin)
            block.fused_conv.load_state_dict(self.fused_conv.active_state_dict(cin, cout=hidden_size))
            self.se.active_mid_channels = self.se.get_mid_channels(cin)
            block.se.load_state_dict(self.se.active_state_dict(hidden_size))
            block.point_conv.load_state_dict(self.point_conv.active_state_dict(hidden_size))
            if hasattr(block, 'downsample'):
                block.downsample.load_state_dict(self.downsample.active_state_dict(cin))
        return block

    def get_active_tf_block(self, cin: int):
        from modules.modeling.blocks.tf_blocks import FusedMBConvSEResBlock as FusedMBConvSEResBlock_TF
        return FusedMBConvSEResBlock_TF.build_from_config(self.get_active_block_config(cin))


import discord
from discord.ext import commands
from Helpers import EmbedHelper as embed
import urbandictionary as ud

class CMD_UrbanDictionary:
    def __init__ (self, client):
        self.client = client

    @commands.command(pass_context = True)
    async def urban (self, ctx, *searchItem):
        author = ctx.message.author
        channel = ctx.message.channel

        search = ""
        for word in searchItem:
            search += word
            search += " "

        if search == "":
          await embed.SpecifyErrorEmbed(self.client, channel)
        else:
          try:
            search = search.replace('[', '')
            search = search.replace(']', '')

            definitions = ud.define(search)

            definition = definitions[0]

            definition.word = definition.word.replace('[', '')
            definition.word = definition.word.replace(']', '')
            definition.definition = definition.definition.replace('[', '')
            definition.definition = definition.definition.replace(']', '')
            definition.example = definition.example.replace('[', '')
            definition.example = definition.example.replace(']', '')

            await embed.UrbanEmbed(self.client, definition.word, definition.definition, definition.example, definition.upvotes, definition.downvotes, channel)
          except:
            await embed.UnknownErrorEmbed(self.client, channel)

def setup (client):
    client.add_cog(CMD_UrbanDictionary(client))


import torch, torch.nn as nn, torch.nn.functional as F, numpy as np

'''

Two implementations, chosen at bottom of file.

functorch based PNP solver.
Requires a decent initial estimate.

Actually opencv solvePnP is not very good unless you use the iterative method with an initial estimate,
which is about as good as my NLLS solver. IIRC solvePnP use Lu OI algorithm though, which converges fast, probably
unlike the NLLS solve.
Without useExtrinsicGuess, I figure solvePnP either does OI with a bad initial scene plane, or attempts to first use an algebraic
method like EPNP and simply fails.

'''

def log_R(R):
    t = np.arccos((np.trace(R) - 1) * .5)
    d = np.linalg.norm((R[2,1]-R[1,2], R[0,1]-R[1,0], R[0,2]-R[2,0]))
    if d < 1e-12: return np.zeros(3)
    return np.array((R[2,1]-R[1,2], R[0,2]-R[2,0], R[1,0]-R[0,1])) * t / d
def q_exp(r):
    l2 = r@r
    if l2 < 1e-15:
        return np.array((1,0,0,0.))
    l = np.sqrt(l2)
    # a = l * np.pi * .5
    a = l * .5
    c,s = np.cos(a), np.sin(a)
    # return np.array((0,1,0,0))
    return np.array((c,*((s/l)*r)))

def q_to_matrix1(q):
    # r,i,j,k = q[0], q[1], q[2], q[3]
    # return torch.stack((
    r,i,j,k = q[0:1], q[1:2], q[2:3], q[3:4]
    return torch.cat((
        1-2*(j*j+k*k), 2*(i*j-k*r), 2*(i*k+j*r),
        2*(i*j+k*r), 1-2*(i*i+k*k), 2*(j*k-i*r),
        2*(i*k-j*r), 2*(j*k+i*r), 1-2*(i*i+j*j))).view(3,3)

def mapProject2(pose, pts, fxy, wh):
    q,t = pose[...,:4], pose[...,4:]
    tpts = (pts-t.view(-1,3)) @ q_to_matrix1(q) # Transposing R twice: R.T.T = R
    ppts = (tpts[...,:2] / tpts[...,2:])
    # ppts[...,1] *= -1
    return ppts * fxy + wh*.5

def get_functorch_jac_2():
    from functorch import jacfwd, vmap
    from functorch.compile import aot_function, memory_efficient_fusion, ts_compile

    # Each camera projects the SAME number of points
    m2 = vmap(mapProject2, (0,0,0,0))
    d_m2 = vmap(jacfwd(mapProject2, (0,1)), (0,0,0,0))

    return m2, d_m2

# Actually this is not very good.
def recover_camera_opencv(wh, fxy, obspts, worldpts,
                   initialEye=torch.FloatTensor((0,1,-2)),
                   initialQ=torch.FloatTensor((1,0,0,0))):

    rvec0 = log_R(q_to_matrix1(initialQ))
    tvec0 = -(q_to_matrix1(initialQ) @ initialEye).cpu().numpy()

    import cv2
    Ps = []
    for i in range(len(obspts)):
        opts = worldpts[i].cpu().numpy()
        ipts = obspts[i].cpu().numpy()
        K = np.array((
            fxy[0], 0, wh[0]*.5,
            0, fxy[1], wh[1]*.5,
            0,0,1)).reshape(3,3)
        print(opts.shape, ipts.shape, K.shape)
        if 0:
            stat,rvec,tvec = cv2.solvePnP(opts,ipts,K,None)
        else:
            stat,rvec,tvec = cv2.solvePnP(opts,ipts,K,None, np.copy(rvec0),np.copy(tvec0), useExtrinsicGuess=True)
        assert(stat)
        P = np.eye(4)
        # print('K',K)
        rod = cv2.Rodrigues(rvec)
        print('tvec',tvec.squeeze())
        print('rvec',rvec)
        print('R',rod[0])
        # P[:3,:3] = rod[0]
        # P[:3,3] = tvec.squeeze()
        P = np.zeros(7)
        if 1:
            # Must invert
            P[:4] = q_exp(rvec.squeeze()) * (1,-1,-1,-1)
            P[4:] = -(rod[0].T @ tvec.squeeze())
        else:
            P[:4] = q_exp(rvec.squeeze())# * (1,-1,-1,-1)
            P[4:] = tvec.squeeze()
        # print('R_',q_to_matrix1(torch.from_numpy(P[:4])))
        Ps.append(P)
    return torch.from_numpy(np.stack(Ps))

def recover_camera_functorch(wh, fxy, obspts, worldpts,
                   initialEye=torch.FloatTensor((0,1,-2)),
                   initialQ=torch.FloatTensor((1,0,0,0)),
            ):

    B,N,three = worldpts.size()
    x = torch.cat((initialQ,initialEye), -1).view(1,7).repeat(B,1)
    x[...,:4] = nn.functional.normalize(x[...,:4], dim=-1)
    wh = wh.view(1,2).repeat(B,1)
    fxy = fxy.view(1,2).repeat(B,1)

    Nstate = 7
    Nobs = N * 2

    prior0 = torch.eye(7).unsqueeze_(0)
    prior0[:,:4,:4] *= 1e4
    prior0[:,4:,4:] *= 1e2
    prior = prior0.clone()

    F, dF = get_functorch_jac_2()

    # print('obs\n',obspts)

    for i in range(32):
        pred = F(x, worldpts, fxy, wh)
        Js = dF(x, worldpts, fxy, wh)

        # print('pred\n',pred)
        res = pred - obspts # [B,N,2]
        rmse = res.pow(2).sum(2).mean(1).sqrt() # [B]
        print(f' - step {i} rmse {rmse}')

        # print(pred.shape,[JJ.shape for JJ in Js])
        if 0:
            J = Js[0].sum(1) # sum out 'N', the observation dim. to get a [B,2,7] tensor.

            # grad = (J.mT @ res.mT).sum(2) # [B,2,7] x [B,N,2] -> [B,7]
            grad = (J.mT @ res.permute(0,2,1)).sum(2) # [B,2,7] x [B,N,2] -> [B,7]

            # JtJ = J.mT @ J # [B,7,7]
            JtJ = J.permute(0,2,1) @ J # [B,7,7]
        else:
            J = Js[0] # [B,N,2,7]
            # print('j',J.shape, 'res',res.shape)
            # print((J.mT @ res.permute(0,2,1).unsqueeze(-2)).shape)
            # grad = (J.mT @ res.permute(0,2,1)).sum(1)
            # print(torch.bmm(J.view(-1,2,7).mT, res.view(-1,2,1))[...,0]
            # print(J.shape, res.shape)
            grad = torch.bmm(J.reshape(-1,2,7).mT, res.reshape(-1,2,1))[...,0].reshape(B,N,7).sum(1)
            JtJ = (J.permute(0,1,3,2) @ J).sum(1) # [B,7,7]
            # print(J.shape,grad.shape,JtJ.shape)

        # print('JtJ:\n',JtJ)
        # print('grad:',grad)
        if 1:
            Hess = JtJ + prior
            P = Hess.inverse()
            # print('P:\n',P)

            bad = (P.diagonal(dim1=1,dim2=2) <= 0)
            if (bad).any():
                print(P.diagonal(dim1=1,dim2=2))
                print(' - WARNING: non-pos-definite covariance.')
                # prior = prior*2

                # continue
                # P[bad.flatten(1).any(1)] = 0
                # exit()

            # print(P.shape,grad.shape)
            x = x - (P @ grad.unsqueeze(-1))[...,0]
        else:
            Hess = JtJ[...,4:,4:] + prior[...,4:,4:]
            P = Hess.inverse()
            # print('P',P.shape)
            x[...,4:] = x[...,4:] - (P @ grad[...,4:].unsqueeze(-1))[...,0]

        x[...,:4] = nn.functional.normalize(x[...,:4], dim=-1)
        # x[...,:4] = torch.FloatTensor((1,0,0,0)).view(1,4)
        # print('q',x[0,:4], 't',x[0,4:])
    print('q',x[0,:4], 't',x[0,4:])

    return x

# Set implementation
# recover_camera = recover_camera_opencv
recover_camera = recover_camera_functorch

if __name__ == '__main__':
    wh = torch.FloatTensor((512,512.))
    uv = np.tan(np.deg2rad(50)/2)*2
    fxy = wh/uv
    worldpts = torch.randn(1,10,3) + torch.FloatTensor((0,1,8)).view(1,1,3)

    # def mapProject2(pose, pts, fxy, wh):
    # obspts = (worldpts * 1)[:,:,:2] * fxy + wh*.5
    pose0 = torch.FloatTensor((1,0,.1,-.02, 0,2.1,-1.02)).view(7)
    pose0[...,:4] = nn.functional.normalize(pose0[...,:4], dim=-1)
    obspts = mapProject2(pose0, worldpts, fxy, wh)

    recover_camera(wh, fxy, obspts, worldpts)
    # exit()


from typing import Iterable, Optional

import numpy as np
import pandas as pd

from ..core.core import ModelType
from ..datasets.base import Dataset
from .base import BaseModel, ModelPredictionResults

class PrecookedModel(BaseModel):
    """A dummy model for internal usage."""

    def __init__(
        self,
        data: Dataset,
        predictions: ModelPredictionResults,
        model_type: ModelType,
        feature_names: Optional[Iterable] = None,
        classification_labels: Optional[Iterable] = None,
        **kwargs,
    ):
        self._data = data
        self._predictions = predictions
        super().__init__(
            model_type=model_type, feature_names=feature_names, classification_labels=classification_labels, **kwargs
        )

    @classmethod
    def from_model(cls, model: BaseModel, dataset: Dataset):
        """Creates a PrecookedModel from an existing model and dataset.

        Parameters
        ----------
        model : BaseModel
            A instance of a Giskard model.
        dataset : Dataset
            Dataset for which predictions will be cached.

        Returns
        -------
        PrecookedModel

        """
        predictions = model.predict(dataset)

        return cls(
            dataset,
            predictions,
            model.meta.model_type,
            model.meta.feature_names,
            model.meta.classification_labels,
        )

    def predict(self, dataset: Dataset) -> ModelPredictionResults:
        refs = pd.Series(np.arange(len(self._data)), index=self._data.df.index)
        idx = refs.loc[dataset.df.index]

        raw = np.asarray(self._predictions.raw)[idx]
        prediction = np.asarray(self._predictions.prediction)[idx]
        raw_prediction = np.asarray(self._predictions.raw_prediction)[idx]

        probabilities = getattr(self._predictions, "probabilities", None)
        if probabilities is not None:
            probabilities = np.asarray(probabilities)[idx]

        all_predictions = getattr(self._predictions, "all_predictions", None)
        if all_predictions is not None:
            all_predictions = np.asarray(all_predictions)[idx]

        return ModelPredictionResults(
            raw=raw,
            prediction=prediction,
            raw_prediction=raw_prediction,
            probabilities=probabilities,
            all_predictions=all_predictions,
        )

    def predict_df(self, df: pd.DataFrame):
        raise NotImplementedError()