import pygame as pg
import numpy as np
from math import sqrt

class Node:
    def __init__(self, data, level, f_score, parent, direct):
        self.data = data
        self.n = sqrt(len(data))
        if parent == None:
            self.level = 1
        else:
            self.level = level * 2
        self.f_score = f_score
        self.parent = parent
        self.thisdirect = direct
    def find_index(self, num):
        index = self.data.index(num)
        i = index // self.n
        j = index - (i * self.n)
        return i, j
    def possible_moves(self):
        i, j = self.find_index("2")
        directions = [(-1,0), (1,0), (0,-1), (0,1)]
        directions_name = ["Up", "Down", "Left", "Right"]
        all_directions = {directions[i]:directions_name[i] for i in range(4)}

        possible_moves = []
        for k in directions:
            if not ((i+k[0]<0) or (i+k[0]>self.n-1) or (j+k[1]<0) or (j+k[1]>self.n-1)):
                possible_moves.append((all_directions[k]))
        left =  int(((i*self.n)+j)-1)
        right = int(((i*self.n)+j)+1)
        top = int(((i-1)*self.n)+j)
        bottom = int(((i+1)*self.n)+j)
        for i in possible_moves:
            if i=="Up":
                if top<0 or self.data[top]=="1":
                    possible_moves.remove("Up")
            elif i=="Down":
                if (bottom>=self.n**2) or (self.data[bottom]=="1"):
                    possible_moves.remove("Down")
            elif i=="Left":
                if left<0 or self.data[left]=="1":
                    possible_moves.remove("Left")
            else:
                if (right>=self.n**2) or (self.data[right]=="1"):
                    possible_moves.remove("Right")
        index = self.data.find("2")
        if "Left" in possible_moves and index%self.n==0:
            possible_moves.remove("Left")
        elif "Right" in possible_moves and (index+1)%self.n==0:
            possible_moves.remove("Right")

        return possible_moves
    def generate_children(self):
        directions = [(-1,0), (1,0), (0,-1), (0,1)]
        directions_name = ["Up", "Down", "Left", "Right"]
        all_directions = {directions_name[i]:directions[i] for i in range(4)}

        possible_directions = self.possible_moves()

        i,j = self.find_index("2")

        left =  int(((i*self.n)+j)-1)
        right = int(((i*self.n)+j)+1)
        top = int(((i-1)*self.n)+j)
        bottom = int(((i+1)*self.n)+j)

        children = []
        for p in possible_directions:
            puzzle_list = list(self.data)
            zero_index = puzzle_list.index("2")
            if p == "Up":
                if puzzle_list[top]!="4":
                    puzzle_list[zero_index], puzzle_list[top]= "1", "2"
                    di = "Up"
                else:
                    continue
            elif p=="Down":
                if puzzle_list[bottom]!="4":
                    puzzle_list[zero_index], puzzle_list[bottom]= "1", "2"
                    di = "Down"
                else:
                    continue
            elif p=="Right":
                if puzzle_list[right]!="4":
                    puzzle_list[zero_index], puzzle_list[right]= "1", "2"
                    di = "Right"
                else:
                    continue
            elif p=="Left":
                if puzzle_list[left]!="4":
                    puzzle_list[zero_index], puzzle_list[left]= "1", "2"
                    di = "Left"
                else:
                    continue
            children.append(("".join(puzzle_list),di))

        children_obj = []
        for i in children:
            children_obj.append(Node(i[0],self.level+1,0,self,i[1]))
        return children_obj

class Puzzle:
    def __init__(self, current, goal):
        self.puzzle = current
        self.open = []
        self.closed = []
        self.visited = {}
        self.goal = goal

    def find_index(self, cur, num):
        index = cur.find(num)
        i = index // (sqrt(len(cur)))
        j = index - (i * (sqrt(len(cur))))
        return i, j
    def f_score(self, current, goal):
        return self.h_score(current.data, goal) + current.level
    def h_score(self, current, goal):
        total = 0
        i,j= self.find_index(current, str(2))
        x,y= self.find_index(goal, str(2))
        total+= abs(i-x) + abs(j-y)
        return total
    def process(self):
        start = Node(self.puzzle, 0, 0, None,None)

        self.open.append(start)

        while True:
            cur = self.open[0]
            if (cur.data[self.goal.find("2")]=="2"):
                _list = []
                _list.append(cur)
                while cur.parent != None:
                    _list.append(cur.parent)
                    cur = cur.parent
                else:
                    _list.append(cur.parent)
                _list = _list[::-1]
                """t = 0
                for i in _list:
                    if i!=None:
                        length_list = int(sqrt(len(i.data)))
                        for q in range(0,len(i.data),length_list):
                            for w in range(length_list):
                                print(i.data[q+w],end=" ")
                            print()
                        print(i.thisdirect)
                        print("********************")
                    t+=1
                print("Total-steps:",t-2)"""
                return _list
                break
            for i in cur.generate_children():
                i.fval = self.f_score(i,self.goal)
                if i.data not in self.visited or self.visited[i.data]>i.fval:
                    self.open.append(i)
                    self.visited[i.data]=i.fval
            self.closed.append(cur)
            self.visited[cur.data]=self.h_score(cur.data,self.goal)
            del self.open[0]

            self.open.sort(key = lambda x:x.fval, reverse=False)

import pygame as pg
pg.init()

print("Hello, and welcome to Maze solver!")
n = 20

white = (255, 255, 255)
black = (0, 0, 0)
green = (0, 166, 147)
red = (122, 0, 0)

width = n * 10 - 10
height = n * 10 + 50

gameDisplay = pg.display.set_mode((width, height))
pg.display.set_caption("Maze")

x = 0
y = 0
for i in range((n*n)):
    exec(f"""sq{i} = pg.draw.rect(gameDisplay,white,({x},{y},10,10),1)""")
    exec(f"sq{i}_x, sq{i}_y = {x},{y}")
    x+=10
    if x>=n*10:
        x=0
        y+=10

start_key = pg.draw.rect(gameDisplay,white,(30,n*10+10,60,30),2)

def clicker(x,y,logic_board,point):
    pg.draw.line(gameDisplay, (255,0,0),(x,y),(x + 10,y + 10),1)
    pg.draw.line(gameDisplay, (255,0,0),(x,y + 10),(x + 10, y),1)
    logic_board[point//n][point%n]="4"
    return logic_board

game_logic_board = []
for i in range(0,n*n,n):
    row = []
    for j in range(n):
        row.append("0")
    game_logic_board.append(row)
game = True
while game:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            game = False
        if event.type == pg.MOUSEBUTTONUP:
            click_pos = pg.mouse.get_pos()
            if start_key.collidepoint(click_pos):
                game = False
            for i in range(0,n*n):
                exec(f"""if sq{i}.collidepoint(click_pos):
   game_logic_board = clicker(sq{i}_x,sq{i}_y,game_logic_board,{i})""")
            x = ""
            for t in range(len(game_logic_board)):
                for y in range(len(game_logic_board)):
                    x+=str(game_logic_board[t][y])
    pg.display.update()
pg.quit()

import pygame as pg
pg.init()
goal = ["0" for i in range(n*n)]
goal[(n*n)-1]="2"
goal = "".join(goal)
x = list(x)
x[0]="2"
x = "".join(x)
x = Puzzle(x,goal)
solution = x.process()

width = n * 10
height = n * 10

gameDisplay = pg.display.set_mode((width, height))
pg.display.set_caption("solution")

x = 0
y = 0
for row in game_logic_board:
    x=0
    for cell in row:
        if cell=="0":
            pg.draw.rect(gameDisplay,black,(x,y,10,10),1)
        elif cell=="1":
            pg.draw.rect(gameDisplay,green,(x,y,10,10),0)
        elif cell=="2":
            pg.draw.rect(gameDisplay,red,(x,y,10,10),0)
        elif cell=="4":
            pg.draw.rect(gameDisplay,white,(x,y,10,10),1)
        x+=10
    y+=10

game = True
while game:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            game = False
    pg.display.update()
pg.quit()


import numpy as np   # to handle matrix and data operation
import pandas as pd  # to read csv and handle dataframe
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator, FormatStrFormatter, AutoMinorLocator
from tqdm import tqdm
import copy
from mpl_toolkits.mplot3d import Axes3D
import random

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data
from torch.utils.data import DataLoader
from torch.autograd import Variable

import pytorch_lightning as pl
from pytorch_lightning.core.decorators import auto_move_data

import torchvision.transforms as transforms
import torchvision.datasets

# from sklearn.model_selection import train_test_split
# from sklearn.cluster import KMeans
# from sklearn.decomposition import PCA
# import scipy.stats as sps
# import scipy.signal as spy_sig
# import scipy.ndimage as ndimage
# import scipy.optimize as spy_opt
# import random
# import os
# import pickle

random_seed = 1
torch.backends.cudnn.enabled = False

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# device = xm.xla_device()

# torch_xla.core.xla_model.set_rng_state(1, device=device)
np.random.seed(0)
torch.manual_seed(0)

class Model(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.model = torchvision.models.resnet18(num_classes=10)

        self.model.conv1 = nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
        # self.model.conv1.conv = nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)  ## googlenet
        # self.model.features[0] = nn.Conv2d(1, 64, kernel_size=(3, 3), stride=(2, 2))

        self.loss = nn.CrossEntropyLoss()

    @auto_move_data
    def forward(self, x):
        return self.model(x)

    def training_step(self, batch, batch_no):
        x, y = batch
        logits = self(x)
        loss = self.loss(logits, y)
        return loss

    def configure_optimizers(self):
        return torch.optim.Adam(self.model.parameters(), lr=0.001)

def load_dataset(download=False, dataset='cifar'):
    global train_dataset_
    dataset = dataset.lower()
    batch_size = 100

    trans_og = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
    # trans_og = transforms.Compose([transforms.Resize(96),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    AlexTransform = transforms.Compose([
        transforms.Resize((227, 227)),
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))])

    imagenet_trans = transforms.Compose([
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    # trans =  transforms.Compose(
    #   [transforms.ToTensor(),
    #    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    # trans = AlexTransform

    if dataset == 'cifar':
        trans = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
        print("CIFAR10")
        train_dataset_ = torchvision.datasets.CIFAR10(root=r"Dataset/CIFAR10", train=True,
                                                      transform=trans, download=download)
        test_dataset_ = torchvision.datasets.CIFAR10(root=r"Dataset/CIFAR10", train=False, transform=trans)

    elif dataset == 'mnist':
        trans_og = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
        print("MNIST")
        train_dataset_ = torchvision.datasets.MNIST(root=r"Dataset/", train=True,
                                                    transform=trans_og, download=download)
        test_dataset_ = torchvision.datasets.MNIST(root=r"Dataset/", train=False, transform=trans_og)

    elif dataset == 'imagenet':
        print("ImageNet")
        trans = imagenet_trans
        train_dataset = torchvision.datasets.ImageNet(root=r"Dataset/", split='train')
        test_dataset_ = torchvision.datasets.ImageNet(root=r"Dataset/", split='test', target_transform=trans)

    else:
        trans = transforms.Compose([transforms.Resize(96),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
        train_dataset_ = torchvision.datasets.CIFAR10(root=r"Dataset/CIFAR10",
                                                      transform=trans, download=download)
        test_dataset_ = torchvision.datasets.CIFAR10(root=r"Dataset/CIFAR10", train=False, transform=trans)

    train_loader_ = DataLoader(dataset=train_dataset_, num_workers=2, batch_size=batch_size, shuffle=True)
    test_loader_ = DataLoader(dataset=test_dataset_, batch_size=100, shuffle=True)

    return train_loader_, test_loader_

def model_tester(model_, test_set):
    # Testing Accuracy
    model_.model.eval()
    model_.model.to(device)
    criterion = nn.CrossEntropyLoss()

    correct, total, running_loss = 0, 0, 0
    with torch.no_grad():
        for data in test_set:
            images, labels = data[0].to(device), data[1].to(device)
            outputs = model_.model(images)

            test_loss = criterion(outputs, labels).to(device)

            _, predicted = torch.max(outputs.data, 1)

            total += labels.size(0)
            correct += (predicted == labels).sum().item()
            running_loss += test_loss.item() * images.size(0)

    accuracy = correct / total
    epoch_loss = running_loss / len(test_set)

    return accuracy, epoch_loss

def get_test_names(ex_model_og):
    ex_model = copy.deepcopy(ex_model_og)
    # params, names = count_parameters(ex_model.model)

    model_obj = copy.deepcopy(ex_model.model.state_dict())
    new_names = []

    for p_name, module in list(ex_model.model.named_modules())[1:]:
        nn_ = p_name + ".weight"
        if isinstance(module, nn.Conv2d):
            new_names.append(nn_)
        elif isinstance(module, nn.Linear):
            new_names.append(nn_)

    return new_names, model_obj

def test_harness(model_, test_set):
    mod_names, mod_obj = get_test_names(model_)
    res_dict = {}
    acc, loss = model_tester(model_, test_set)
    res_dict['OG'] = (acc, loss)
    print("OG", (acc, loss))
    print("\n")

    for name in tqdm(mod_names):
        model_clone = copy.deepcopy(model_)
        new_obj = copy.deepcopy(mod_obj)

        weight = copy.deepcopy(mod_obj[name])
        filtered_weight = torch.ones_like(weight)
        new_obj[name] = filtered_weight
        model_clone.model.load_state_dict(new_obj)
        acc, loss = model_tester(model_clone, test_set)
        res_dict[name] = (acc, loss)

        print(name, (acc, loss))
        print("\n")

        del filtered_weight

    return res_dict

train_loader, test_loader = load_dataset(download=False, dataset='mnist')
# WRAPPED_MODEL = xmp.MpModelWrapper(Model())
dataset_name = "MNIST"
e_no = 10
path = 'Saved_models/'
file_name = 'Init_3/ResNet18_' + dataset_name + "_" + str(e_no) + 'epochs.ckpt'
checkpoint = torch.load(path+file_name, map_location=torch.device("cpu"))

model = Model()
model.load_state_dict(checkpoint)
# red_data = test_harness(model, test_loader)
weight = model.model.layer4[1].conv1.weight.detach()

print(weight[0][0])
weight = weight/weight
print(weight[0][0])


import pygame as pg, random as rd
from pygame.locals import *
#defines the objects in game. like the snake and the apple (could be more than one)
class Stuff:
    def __init__(self, position, body, color, points = None, record = None, direction = None):
        self.position = position
        self.body = body
        self.color = color
        self.points = points
        self.record = record
        self.direction = direction
#defines the apple coordinates
def on_grid_random():
    x, y = rd.randint(0, 690), rd.randint(0, 690)
    return (x//10 * 10, y//10 * 10)
#keeps snake moving
def move(wich_snake):
    for i in range(len(wich_snake.position) - 1, 0, -1):
        wich_snake.position[i] = (wich_snake.position[i-1][0], wich_snake.position[i-1][1])
    if wich_snake.direction == up:
        wich_snake.position[0] = (wich_snake.position[0][0], wich_snake.position[0][1] - 10)
    if wich_snake.direction == down:
        wich_snake.position[0] = (wich_snake.position[0][0], wich_snake.position[0][1] + 10)
    if wich_snake.direction == left:
        wich_snake.position[0] = (wich_snake.position[0][0] - 10, wich_snake.position[0][1])
    if wich_snake.direction == right:
        wich_snake.position[0] = (wich_snake.position[0][0] + 10, wich_snake.position[0][1])
#changes snake direction
def key_verify(wich_snake):
    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()
        if event.type == KEYDOWN:
            if event.key == K_UP:
                if wich_snake.direction != down:
                    wich_snake.direction = up
            if event.key == K_DOWN:
                if wich_snake.direction != up:
                    wich_snake.direction = down
            if event.key == K_LEFT:
                if wich_snake.direction != right:
                    wich_snake.direction = left
            if event.key == K_RIGHT:
                if wich_snake.direction != left:
                    wich_snake.direction = right
#verify colissions and defines the pontuation
def colission(wich_snake):
    if wich_snake.points > wich_snake.record: wich_snake.record += 1

    if wich_snake.position[0] == apple.position:
        wich_snake.position.append([700, 700])
        apple.position = on_grid_random()
        wich_snake.points += 1

    if wich_snake.position[0][0] in wall or wich_snake.position[0][1] in wall:
        wich_snake.direction = right
        snake.position = [(200, 200), (210, 200), (220, 200)]
        apple.position = on_grid_random()
        wich_snake.points = 0
        wich_snake.direction = hit_wall

    if cnt > 2:
        if wich_snake.position[0] in wich_snake.position[1:-2]:
            wich_snake.position = [(200, 200), (210, 200), (220, 200)]
            apple.position = on_grid_random()
            wich_snake.points = 0
            wich_snake.direction = ate_itself
#variables used in game
up, down, left, right, ate_itself, hit_wall = 0, 1, 2, 3, 4, 5
snake = Stuff(([(200, 200), (210, 200), (220, 200)]), pg.Surface((10, 10)), (255, 215, 0), 0, 0, right)
apple = Stuff(on_grid_random(), pg.Surface((10, 10)), (50, 205, 50))
wall = [700, -10]
clock = pg.time.Clock()
cnt = 0
pg.init()
screen = pg.display.set_mode((700, 700))
#game running
while True:
    caption = 'Snake size ' + str(snake.points) + ' | record: ' + str(snake.record)
    if snake.direction == ate_itself:
        caption = 'Ate itself! Choose a new direction'
    if snake.direction == hit_wall:
        caption = 'It hit the wall! choose a new direction'
    cnt += 1
    clock.tick(35)
    screen.fill((255, 255, 250))
    apple.body.fill(apple.color)
    snake.body.fill(snake.color)
    screen.blit(apple.body, apple.position)

    pg.display.set_caption(caption)

    key_verify(snake)
    move(snake)
    colission(snake)

    for pos in snake.position:
        screen.blit(snake.body, pos)
    pg.display.update()


# coding:utf8
from config import api_id, api_key, api_pwd
from aip import AipOcr

""" 如果有可选参数 """

class bns:
    def __init__(self):
        self.options = self._init_options()
        self.client = AipOcr(api_id, api_key, api_pwd)

    def _init_options(self):
        options = {}
        options["language_type"] = "CHN_ENG"
        options["detect_direction"] = "true"
        options["detect_language"] = "true"
        options["probability"] = "true"
        return options

    def ana(self, img_file):
        return self.client.general(img_file, self.options)

if __name__ == '__main__':
    from pic_deal import load_image

    img, _, _, _ = load_image("../data/se_pic/chi_IMG_1884.JPG")
    print(img)
    b = bns()
    res = b.ana(img)
    print(res)


# coding: utf-8
#

import time
import threading
import pytest
from uiautomator2 import utils

def test_list2cmdline():
    testdata = [
        [("echo", "hello"), "echo hello"],
        [("echo", "hello&world"), "echo 'hello&world'"],
        [("What's", "your", "name?"), """'What'"'"'s' your 'name?'"""]
    ]
    for args, expect in testdata:
        cmdline = utils.list2cmdline(args)
        assert cmdline == expect, "Args: %s, Expect: %s, Got: %s" % (args, expect, cmdline)

def test_inject_call():
    def foo(a, b, c=2):
        return a*100+b*10+c

    ret = utils.inject_call(foo, a=2, b=4)
    assert ret == 242

    with pytest.raises(TypeError):
        utils.inject_call(foo, 2)

def test_threadsafe_wrapper():
    class A:
        n = 0

        @utils.thread_safe_wrapper
        def call(self):
            v = self.n
            time.sleep(.5)
            self.n = v + 1

    a = A()
    th1 = threading.Thread(name="th1", target=a.call)
    th2 = threading.Thread(name="th2", target=a.call)
    th1.start()
    th2.start()
    th1.join()
    th2.join()

    assert 2 == a.n


import sys
import os
import numpy as np
from pandas import DataFrame
from scipy import stats

words = ["hicha", "hishu", "hisa", "hivu"]
distractors = ["hichu", "hisha", "hisu", "hiva"]

timecourse_types = ["dw_dd", "w1_d1", "w2_d2"]

time_lbls = ["220_495","285_295", "300-360"]
time_periods = [[220, 495], [285, 295], [300, 360]]

behav_parameters = ["learning_criterion", "false_alarms"]

stc_table_path = "/data/programs/razoral/insula_timecourses/target_timecourses/corr_tables_insula/corr_table_insula_{}_{}.tsv"
behavioral_table_path = "/data/programs/razoral/insula_timecourses/examples/active1_{}_per_subject.tsv"

def calc_corr(beh_table_path, stc_table_path, timecourse_types, behav_parameter, time_period, time_lbl, words):

	corr_table = np.zeros(shape = (len(timecourse_types) , len(words), 2))

	for timecourse_type_id, timecourse_type in enumerate(timecourse_types):

		beh_df = DataFrame.from_csv(beh_table_path.format(behav_parameter), sep = "\t")
		stc_df = DataFrame.from_csv(stc_table_path.format(timecourse_type, time_lbl), sep = "\t")

		# exclude subjects
		sub_list = beh_df.index
		actual_sub_list = stc_df.index
		sub_to_del = sub_list.difference(actual_sub_list)
		beh_df = beh_df.drop(sub_to_del)

		# calc correlation
		for word_id, word in enumerate(words):
			corr_cur = stats.pearsonr(beh_df[word],stc_df[word])
			corr_table[timecourse_type_id, word_id, :] = corr_cur

		# form corr table

	os.makedirs("/data/programs/razoral/insula_timecourses/target_timecourses/behave_correlations_insula", exist_ok=True)
	f = open("/data/programs/razoral/insula_timecourses/target_timecourses/behave_correlations_insula/pearson_corr_insula_{}_{}.tsv".format(behav_parameter, time_lbl), "w")
	f.write("timecourse_type")
	for word in words:
		f.write("\t{}_corr\t{}_p-val".format(word, word))
	f.write("\n")
	for timecourse_type_id, timecourse_type in enumerate(timecourse_types):
		f.write("{}".format(timecourse_type))
		for word_id, word in enumerate(words):
			f.write("\t{:e}\t{:e}".format(corr_table[timecourse_type_id, word_id, 0], corr_table[timecourse_type_id, word_id, 1]))
		f.write("\n")
	f.close()

for t, time_period in enumerate(time_periods):
	for behav_parameter in behav_parameters:
		calc_corr(behavioral_table_path, stc_table_path, timecourse_types, behav_parameter, time_period, time_lbls[t], words)


import re
from collections import defaultdict
from collections import deque

filename = '2020/day7/day7.txt'
puzzle_input = open(filename).readlines()

def get_containers():
    """ returns a dictionary that maps a string to a set of strings
    with all bags that can contain that string """
    containers = defaultdict(set)
    for rule in puzzle_input:
        outer_bag = re.match('([A-Za-z ]+) bags', rule)[1]
        inner_bags = re.findall(r'(\d+) ([A-Za-z ]+?) bags?', rule)
        for bag in inner_bags:
            containers[bag[1]].add(outer_bag)
    return containers

def get_num_containing():
    """ returns a dictionary that maps a string to a set of tuples (n, b)
    such that the key must contain n bags of type b """
    containing = {}
    for rule in puzzle_input:
        outer_bag = re.match(r'([A-Za-z ]+) bags', rule)[1].split(" bags contain no other")[0]
        inner_bags = re.findall(r'(\d+) ([A-Za-z ]+?) bags?', rule)
        containing[outer_bag] = {(int(t[0]), t[1]) for t in inner_bags}
    return containing

def get_all_possible_containers(color):
    containers = get_containers()
    possible = set()
    seen = set()
    queue = deque()
    queue.append(color)
    while queue:
        c = queue.pop()
        for container in containers[c]:
            if container not in seen: # prevents cycles
                possible.add(container)
                seen.add(container)
                queue.append(container)
    return possible

def get_total_num_containing(color, containing):
    num_containing = 0
    for t in containing[color]:
        num_containing += t[0]*(1 + get_total_num_containing(t[1], containing))
    return num_containing

def part_1():
    return len(get_all_possible_containers('shiny gold'))

def part_2():
    return get_total_num_containing('shiny gold', get_num_containing())

print("Part 1: {}".format(part_1()))
print("Part 2: {}".format(part_2()))


import openai
import pickle
import os

def cut_message(message,turns):
    return message[max(0,len(message)-turns*2+1):]

def add_assistant_message_latest(message):
    if message[0]["role"] == "assistant":
        message_assistant = message.pop(0)
        message.insert(len(message)-1,message_assistant)
    return message

def preprocess(message,turns,support):
    if support:
        message = add_assistant_message_latest(message)
    message = cut_message(message,turns)
    return message

print("タイトルを入力してください")
title = input()
print("保存する対話ターン数を指定してください。指定しない場合は5です。")
turns = input()
if turns == "":
    turns = 5
else:
    turns = int(turns)
if os.path.isfile("history/pic/{}.pic".format(title)):
    with open("history/pic/{}.pic".format(title), 'rb') as f:
        dialogue_message = pickle.load(f)
    print("前回の対話です。")
    for line in dialogue_message:
        print("role:{} context:{}".format(line["role"],line["content"]))
else:
    dialogue_message = []
    print("ChatGPTに設定を入力してください。不要の場合はenterを押してください")
    system_setting = input()
    if system_setting != "":
        dialogue_message.append({"role": "system","content": system_setting})
    print("エージェントへの支持を直前に持っていきますか？(yes/no)、指定しない場合はnoです。")
    support = input()
    if support == "yes":
        support = True
    else:
        support = False

flag=True

while flag:
    print("モデルを選択してください。3.5を入力するとGPT-3.5,4を入力するとGPT-4を使用します。")
    input_model = input()
    if input_model == "3.5":
        model = "gpt-3.5-turbo"
        flag=False
    elif input_model == "4":
        model = "gpt-4"
        flag=False

flag=True
print("質問を入力してください")
while flag:
    text = input()
    if text == "exit":
        exit()
    else:
        dialogue_message.append({"role": "user","content": text})

    send_text_data = preprocess(dialogue_message,turns,support)
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=send_text_data
        )
    print(response["choices"][0]["message"]["content"])
    dialogue_message.append({"role": "assistant","content": response["choices"][0]["message"]["content"]})
    # オブジェクト保存
    with open("history/pic/{}.pic".format(title),"wb") as f:
        pickle.dump(dialogue_message,f)
    # textファイル用
    text_data = ""
    for line in dialogue_message:
        text_data += "role:{}\ncontext:{}\n".format(line["role"],line["content"])
    with open("history/text/{}.txt".format(title),"w",encoding="utf-8") as f:
        f.write(text_data)


import datetime as dt
import pandas as pd
# pricing libraries
import py_vollib_vectorized
from py_vollib.black_scholes.implied_volatility import implied_volatility
from py_vollib.black_scholes.greeks.analytical import delta

import api

# Output
# option_data.info()
# Data columns (total 23 columns):
# #   Column            Non-Null Count  Dtype
# ---  ------            --------------  -----
#  0   volume_option     63 non-null     float64
#  1   ticks             63 non-null     int64
#  2   status_option     63 non-null     object
#  3   open_option       63 non-null     float64
#  4   low_option        63 non-null     float64
#  5   high_option       63 non-null     float64
#  6   cost_option       63 non-null     float64
#  7   close_option      63 non-null     float64
#  8   volume_spot       63 non-null     float64
#  9   status_spot       63 non-null     object
#  10  open_spot         63 non-null     float64
#  11  low_spot          63 non-null     float64
#  12  high_spot         63 non-null     float64
#  13  cost_spot         63 non-null     float64
#  14  close_spot        63 non-null     float64
#  15  timestamp         63 non-null     datetime64[ns]
#  16  time_to_expiry    63 non-null     timedelta64[ns]
#  17  days_to_expiry    63 non-null     int64
#  18  ivol_mid          63 non-null     float64
#  19  delta_mid         63 non-null     float64
#  20  daily_pnl_option  62 non-null     float64
#  21  daily_pnl_spot    62 non-null     float64
#  22  pnl               62 non-null     float64

def get_historical_data(instrument_dict, time_period="1D",day_past=None):
    ts_creation = instrument_dict["creation_timestamp"]
    ts_expiration = instrument_dict["expiration_timestamp"]

    if day_past:
        ts_start = int((dt.datetime.now() +
                        dt.timedelta(days=-day_past)).timestamp() * 1000)
    else:
        ts_start=ts_creation

    option_data = api.get_historical_data(ts_start,
                                          ts_expiration,
                                          instrument_dict["instrument_name"],
                                          time_period)

    if instrument_dict["quote_currency"] == "BTC":
        spot_name = "BTC-PERPETUAL"
    elif instrument_dict["quote_currency"] == "ETH":
        spot_name = "ETH-PERPETUAL"
    else:
        raise(NotImplementedError("The currency has not been implemented yet"))

    spot_data = api.get_historical_data(ts_creation,
                                        ts_expiration,
                                        spot_name,
                                        time_period)
    data = pd.merge(option_data, spot_data, how="left",
                    on="ticks", suffixes=("_option", "_spot"))
    unwanted = data.columns[data.columns.str.startswith('Unnamed')]
    data.drop(unwanted, axis=1, inplace=True)
    data.drop(["timestamp_option", "timestamp_spot"], axis=1, inplace=True)
    data['timestamp'] = data.ticks.apply(
        lambda x: dt.datetime.fromtimestamp(x/1000))

    # we express the price of the option in USD
    data['close_option_usd'] = data.apply(lambda row: (
        row['close_option'] * row['close_spot']), axis=1)

    expiry = dt.datetime.fromtimestamp(ts_expiration/1000)
    data["time_to_expiry"] = data.timestamp.apply(lambda x: expiry-x)
    data["days_to_expiry"] = data["time_to_expiry"].apply(lambda x: x.days)
    data['strike'] = instrument_dict["strike"]
    return data

def compute_pnl(instrument_dict, data, qty=1, mult=1, is_delta_hedged=True):
    strike = instrument_dict['strike']

    if instrument_dict['option_type'] == 'call':
        option_type = 'c'
    else:
        option_type = 'p'

    r = 0.01  # This is the risk-free interest rate. For short-dated options it doesn't matter much

    data['ivol_mid'] = implied_volatility(price=data['close_option_usd'],
                                          S=data['close_spot'],
                                          K=strike,
                                          t=data['days_to_expiry']/365,
                                          r=r,
                                          flag=option_type,
                                          return_as="series")
    data['delta_mid'] = py_vollib_vectorized.greeks.delta(option_type, data['close_spot'],
                                                          strike, data['days_to_expiry']/365, r, data['ivol_mid'])

    data['daily_pnl_option'] = data['close_option_usd'].diff() * qty * mult

    data["daily_pnl_spot"] = data['close_spot'].diff(
    ) * data['delta_mid'].shift() * qty * mult

    ts = data['daily_pnl_option'] - data["daily_pnl_spot"] * is_delta_hedged

    data['pnl'] = ts.cumsum()

    return data


import os
from PIL import Image
import numpy as np
import sys
import pandas as pd
import pickle
import random
import matplotlib.pyplot as plt
import math
import requests
from io import BytesIO
from urllib.request import urlopen

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder

from keras.utils import to_categorical

import keras

class ezdata:
    def __init__(self,parameters=None,load=None):

        self.params      = None

        if parameters is None:
            if load is None:
                #print("[Fail] ezdata() : Please provide a parameter list to instantiate ezdata object !")
                #raise Exception("[Fail] ezdata() : Please provide a parameter list to instantiate ezdata object !")
                pass
                return
            else:
                self.load(load)
                return
        else:
            self.params = parameters

        if "name" not in self.params:
            self.params["name"] = "Noname"

        if "path" not in self.params:
            raise Exception("[Fail] ezdata(): Please provide a path !")
        else:
            #Images classification from directory
            if (os.path.isdir(self.params["path"])) and ("path_mask" not in self.params):
                self.import_classification_images(parameters)
                #self.type = "classification"
                return
            #Images segmentation from directory
            if (os.path.isdir(self.params["path"])) and (os.path.isdir(self.params["path_mask"])):
                self.import_segmentation_images(parameters)
                #self.type = "segmentation"
                return

            if (os.path.isfile(self.params["path"])):

                extension = os.path.splitext(self.params["path"])[1]
                if extension == ".csv":
                    #Table Classification or regression
                    self.import_table(parameters)
                    return
                if extension == ".npz":
                    self.from_npz(self.params)
                    return
                raise Exception('File extension/type not recognized ! Should be "csv" or "npz" !')
                return

            #Image classification from directory and csv index file
            if (os.path.isdir(self.params["path"])) and (os.path.isfile(self.params["path_index"])):
                self.import_classification_images_from_indexes()
                #self.type="classification"

        # if (self.params["type"].lower() == "classification") and (self.params["format"].lower()=="images"):
        #     self.import_classification_images(parameters)
        #     return
        #
        # if (self.params["type"].lower() == "classification") and (self.params["format"].lower()=="table"):
        #     self.import_classification_table(parameters)
        #     return

    def import_classification_images_from_index(self,parameters):
        print('TODO: import_classification_images_from_index()')
        return

    #SEGMENTATION IMAGES from DIRECTORY
    def import_segmentation_images(self,parameters):

        images =[]
        image_paths=[]
        masks =[]
        mask_paths=[]

        if not os.path.isdir(parameters["path"]):
            raise Exception("[Fail] ezdata.import_classification_images() : Path in parameters is not a directory !")

        if not os.path.isdir(parameters["path_mask"]):
            raise Exception("[Fail] ezdata.import_classification_images() : Path Mask in parameters is not a directory !")

        #Images
        print ('[X] Loading Images:', parameters["path"])
        i=0
        for filename in os.listdir(parameters["path"]):
            curimg = os.path.join(parameters["path"], filename)
            img = Image.open(curimg)
            images.append(img)
            image_paths.append(curimg)
            i=i+1
        tot=i
        print ('--- Total images :', str(tot))
        self.images = images
        self.image_paths = image_paths

        #Masks
        print ('[X] Loading Masks:', parameters["path_mask"])
        i=0
        for filename in os.listdir(parameters["path_mask"]):
            curimg = os.path.join(parameters["path_mask"], filename)
            img = Image.open(curimg)
            masks.append(img)
            mask_paths.append(curimg)
            i=i+1
        tot=i
        print ('--- Total images :', str(tot))
        self.masks = masks
        self.mask_paths = mask_paths

        print("\n")

        if "resize" in self.params:
          self.images_masks_to_keras(self.params["resize"])
        else:
          self.images_masks_to_keras()

    #CLASSIFICATION IMAGES from CSVTABLE annuaire

    #CLASSIFICATION - TABLES
    def import_table(self,parameters):

        table =[]
        table_path = []

        if not os.path.isfile(parameters["path"]):
            raise Exception("[Fail] ezdata.import_classification_table(): Path file in parameters doesn't exist !")

        print ('[X] Loading :', parameters["path"])

        #Delimiter
        if "table.delimiter" in parameters:
            table = pd.read_csv(parameters["path"],delimiter=parameters["table.delimiter"])
        else:
            found = False
            for delim in [",",";"," ","\t"]:
                table = pd.read_csv(parameters["path"],delimiter=delim)
                if table.columns.shape[0] != 1:
                    print("[Notice] Found a delimiter !")
                    found = True
                    break
            if not found:
                raise Exception("[Fail] ezdata.import_table() : No delimiter suitable for your table have been automatically found. Please provide one using 'table.delim' parameter.")

        if "table.target.column" in parameters:

            Y = table[parameters["table.target.column"]]
            table = table.drop(columns=parameters["table.target.column"])
        else:
            raise Exception("[Fail] ezdata.import_classification_table(): You didn't provide any Target columns into parameters. \n Please assign: 'table.target.column' into parameters list")

        if "table.drop.column" in parameters:
            table = table.drop(columns=parameters["table.drop.column"])

        X = table.values

        self.table      = table
        self.table_path = parameters["path"]
        self.X = X

        #Check the dtype of Y (to know whether it's number or string)
        print ("[X] Table conversion to Keras format: Done")
        print ("--- 'X' and 'y' tensors have been created into current ezdata object.")

        if "table.target.type" in parameters:
            if parameters["table.target.type"]=="string":
                encoder = LabelEncoder()
                Y = encoder.fit_transform(np.squeeze(Y))
                self.synsets = encoder.classes_
                print("--- 'synsets' have been create into current ezdata object.")
        else:
            if Y.dtype == "object":
                encoder = LabelEncoder()
                Y = encoder.fit_transform(np.squeeze(Y))
                self.synsets = encoder.classes_
                print("--- 'synsets' have been create into current ezdata object.")

        # if "table.target.type" in parameters:
        #     if parameters["table.target.type"]=="string":
        #         encoder = LabelEncoder()
        #         Y = encoder.fit_transform(np.squeeze(Y))
        #         self.synsets = encoder.classes_

        self.y = Y

        print("\n")

    # CLASSIFICATION - IMAGES
    def import_classification_images(self,parameters):
        images =[]
        labels =[]
        image_paths=[]
        synsets=[]

        if not os.path.isdir(parameters["path"]):
            raise Exception("[Fail] ezdata.import_classification_images() : Path in parameters is not a directory !")

        print ('[X] Loading :', parameters["path"])

        k=0
        tot=0
        for subdir in os.listdir(parameters["path"]):
            curdir = os.path.join(parameters["path"],subdir)
            i=0
            for filename in os.listdir(curdir):
                curimg = os.path.join(curdir, filename)
                img = Image.open(curimg)
                images.append(img)
                labels.append(k)
                image_paths.append(curimg)
                i=i+1
            synsets.append(subdir)
            k=k+1
            tot=tot+i
            print ('--- dir: ', subdir, '(',str(i),' images )')
        print ('--- Total images :', str(tot))
        self.images = images
        self.labels = labels
        self.image_paths = image_paths
        self.synsets = synsets
        print('--- Synsets have been generated')
        print("\n")

        if "resize" in self.params:
          self.images_to_keras(self.params["resize"])
        else:
          self.images_to_keras()

    def images_masks_to_keras(self,resize=None):

        #Images
        im=[]
        for image in self.images:
            r = image
            if resize is not None:
                r = image.resize((resize[0],resize[1]), Image.NEAREST)
            im.append(r)
        imgarray=list();
        for i in range(len(im)):
            tmp = np.array(im[i])
            imgarray.append(tmp)
        imgarray = np.asarray(imgarray)

        if len(imgarray.shape)==1:
            raise Exception("[Fail] images_to_keras() : Image size heterogeneity !  Size of images into the dataset are not the same. You should try to use 'resize' parameters to make them homogenous.")
        if len(imgarray.shape)==3:
            imgarray = np.expand_dims(imgarray,axis=3)
        self.X = imgarray.astype('float32')

        #Masks
        im=[]
        for image in self.masks:
            r = image
            if resize is not None:
                r = image.resize((resize[0],resize[1]), Image.NEAREST)
            im.append(r)
        imgarray=list();
        for i in range(len(im)):
            tmp = np.array(im[i])
            imgarray.append(tmp)
        imgarray = np.asarray(imgarray)

        if len(imgarray.shape)==1:
            raise Exception("[Fail] images_to_keras() : Masks size heterogeneity !  Size of Masks into the dataset are not the same. You should try to use 'resize' parameters to make them homogenous.")
        if len(imgarray.shape)==3:
            imgarray = np.expand_dims(imgarray,axis=3)
        self.y = imgarray.astype('float32')

        print ("[X] Images & Masks conversion to Keras format: Done")
        print ("--- 'X' and 'y' tensors have been created into current ezdata object.")
        print("\n")

    def images_to_keras(self,resize=None):

        im=[]
        for image in self.images:
            r = image
            if resize is not None:
                r = image.resize((resize[0],resize[1]), Image.NEAREST)
            im.append(r)
        imgarray=list();
        for i in range(len(im)):
            tmp = np.array(im[i])
            imgarray.append(tmp)
        imgarray = np.asarray(imgarray)

        if len(imgarray.shape)==1:
            raise Exception("[Fail] images_to_keras() : Image size heterogeneity !  Size of images into the dataset are not the same. You should try to use 'resize' parameters to make them homogenous.")

        if len(imgarray.shape)==3:
            imgarray = np.expand_dims(imgarray,axis=3)

        self.X = imgarray.astype('float32')
        self.y = np.asarray(self.labels)

        print ("[X] Images conversion to Keras format: Done")
        print ("--- 'X' and 'y' tensors have been created into current ezdata object.")
        print("\n")

    def gen_test(self,size=0.2,random_state=42):

        X_train,X_test,y_train,y_test = train_test_split(self.X,self.y,test_size=size,random_state=42)

        self.X = X_train
        self.y = y_train
        self.X_test = X_test
        self.y_test = y_test

        print ("[X] Test set generation (size = ,",str(size),",): Done")
        print ("--- Test set : ", self.X_test.shape[0], "images")
        print ("--- 'X_test' and 'y_test' tensors have been created into current ezdata object.")
        print("\n")

    #def preprocess(data,type=None,scaler=None):
    def preprocess(self,X=None,y=None):

        if X.lower() not in ["minmax","standard","mobilenet","vgg16","vgg19"]:
            raise Exception('[Fail] preprocess() : Only "minmax","standard","mobilenet","vgg16","vgg19" are accepted as preprocessing for X')

        if y is None:
            y="none"

        if y.lower() not in ["minmax","standard","categorical","none"]:
            raise Exception('[Fail] preprocess() : Only "minmax","standard","categorical" or "None" are accepted as preprocessing for Y')

        #X
        if X.lower() == "minmax":
            self.X = self.X.astype("float32")
            self.X,self.scalerX = self.minmax_scaling(self.X)

        if X.lower() == "standard":
            self.X = self.X.astype("float32")
            self.X,self.scalerX = self.standard_scaling(self.X)

        if X.lower() == "mobilenet":
            self.X = self.X.astype("float32")
            self.X = keras.applications.mobilenet.preprocess_input(self.X)
            self.scalerX = "mobilenet"

        if X.lower() == "vgg16":
            self.X = self.X.astype("float32")
            self.X = keras.applications.vgg16.preprocess_input(self.X)
            self.scalerX = "vgg16"

        if X.lower() == "vgg19":
            self.X = self.X.astype("float32")
            self.X = keras.applications.vgg19.preprocess_input(self.X)
            self.scalerX = "vgg19"

        if hasattr(self,"X_test"):
            self.X_test = self.X_test.astype("float32")
            if self.scalerX == "mobilenet":
                self.X_test = keras.applications.mobilenet.preprocess_input(self.X_test)
            elif self.scalerX == "vgg16":
                self.X_test = keras.applications.vgg16.preprocess_input(self.X_test)
            elif self.scalerX == "vgg19":
                self.X_test = keras.applications.vgg19.preprocess_input(self.X_test)

            else:
                self.X_test,_= self.scaler_scaling(self.X_test,self.scalerX)

        #Y
        if y.lower() == "minmax":
            self.y = self.y.astype("float32")
            self.y,self.scalerY = self.minmax_scaling(self.y)
            if hasattr(self,"y_test"):
                self.y_test = self.y_test.astype("float32")
                self.y_test,_= self.scaler_scaling(self.y_test,self.scalerY)

        if y.lower() == "standard":
            self.y = self.y.astype("float32")
            self.y,self.scalerY = self.standard_scaling(self.y)
            if hasattr(self,"y_test"):
                self.y_test = self.y_test.astype("float32")
                self.y_test,_= self.scaler_scaling(self.y_test,self.scalerY)

        if y.lower() == "categorical":
            self.y,self.scalerY = self.categorical_transform(self.y)
            if hasattr(self,"y_test"):
                self.y_test,_       = self.categorical_transform(self.y_test)

        if y.lower() == "none":
            self.scalerY = "none"

        print ("[X] Preprocessing using '",X,"' for X, and '",y,"' for Y.")
        print("\n")

    def minmax_scaling(self,data):
        scalers=[]

        if len(data.shape)==4:
            for i in range(data.shape[3]):
                scaler = MinMaxScaler()
                shape_before = data[:,:,:,i].shape
                a = data[:,:,:,i].reshape(-1,1)
                scalers.append(scaler.fit(a))
                b = scalers[i].transform(a)
                data[:,:,:,i] = b.reshape(shape_before)
                return data,scalers

        if len(data.shape)==2:
            scaler = MinMaxScaler()
            a = data
            scalers.append(scaler.fit(a))
            b = scaler.transform(a)
            data=b
            return data,[scaler]

    def standard_scaling(self,data):

        scalers=[]

        if len(data.shape)==4:
            for i in range(data.shape[3]):
                scaler = StandardScaler()
                shape_before = data[:,:,:,i].shape
                a = data[:,:,:,i].reshape(-1,1)
                scalers.append(scaler.fit(a))
                b = scalers[i].transform(a)
                data[:,:,:,i] = b.reshape(shape_before)
            return data,scalers

        if len(data.shape)==2:
            scaler = StandardScaler()
            a = data
            scalers.append(scaler.fit(a))
            b = scaler.transform(a)
            data=b
            return data,[scaler]

    def categorical_transform(self,data):
        #print ("[X] Preprocessing : Categorical")
        #print("\n")
        return to_categorical(data),"categorical"

    def scaler_scaling(self,data,scaler):

        self.X = self.X.astype("float32")

        for i in range(len(scaler)):
            if len(data.shape)==4:
                shape_before = data[:,:,:,i].shape
                a = data[:,:,:,i].reshape(-1,1)
                b = scaler[i].transform(a)
                data[:,:,:,i] = b.reshape(shape_before)
            if len(data.shape)==2:
                a = data
                b = scaler[i].transform(a)
                data = b
        return data,scaler

    def save(self,filename):
        filehandler = open(filename.strip()+".pkl","wb")
        pickle.dump(self,filehandler)
        filehandler.close()
        print("--- EZ data has been saved in     :",filename,".pkl")
        print("\n")

    def load(self,filename):
        filehandler = open(filename+".pkl", 'rb')
        tmp = pickle.load(filehandler)
        filehandler.close()
        self.__dict__.update(tmp.__dict__)

    def is_kernel(self):
        if 'IPython' not in sys.modules:
            # IPython hasn't been imported, definitely not
            return False
        from IPython import get_ipython
        # check for `kernel` attribute on the IPython instance
        return getattr(get_ipython(), 'kernel', None) is not None

    def show_images(self,n=16):
        #if not isinstance(int(math.sqrt(n)),int):
        #    raise Exception("[Fail] ezdata.show_images(): Please provide n as power of 2 ! (2, 4, 8, 16 ...)")

        if not math.sqrt(n).is_integer():
            raise Exception("[Fail] ezdata.show_images(): Please provide n as a perfect quare ! (2, 4, 9, 16, 25, 36, 49, 64 ...)")
        population = list(range(self.X.shape[0]))
        r = random.sample(population,n)
        fig,axes = plt.subplots(nrows = int(math.sqrt(n)),ncols = int(math.sqrt(n)))
        fig.tight_layout()
        for i in range(n):
            plt.subplot(math.sqrt(n),math.sqrt(n),i+1)

            if (self.X[r[i]].shape[2])==1:
                plt.imshow(np.squeeze(self.X[r[i]]),cmap="gray")
            else:
                plt.imshow(self.X[r[i]])
            #plt.title(self.y[r[i]])
            if hasattr(self,"scalerY"):
                if self.scalerY == "categorical":
                    plt.title(self.synsets[np.argmax(self.y[r[i]])])
                if self.scalerY == "none":
                    plt.title(self.y[r[i]])

            plt.axis("off")

        plt.show()

    def show_table(self,filename=None,head=None):
        from IPython.display import display
        if hasattr(self,"table"):
            if head==None:
                if not self.is_kernel():
                    print(self.table)
                else:
                    display(self.table)
            else:
                if not self.is_kernel():
                    print(self.table.head(head))
                else:
                    display(self.table.head(head))
        else:
            if filename is None:
                raise Exception('[Fail] ezdata.show_table() : Please provide a filename !')
            else:
                #d = pd.read_csv(filename)
                found = False
                for delim in [",",";"," ","\t"]:
                    d = pd.read_csv(filename,delimiter=delim)
                    if d.columns.shape[0] != 1:
                        #print("[Notice] Found a delimiter !")
                        found = True
                        break

                if head==None:
                    if not self.is_kernel():
                        print(d)
                    else:
                        display(d)
                else:
                    if not self.is_kernel():
                        print(d.head(head))
                    else:
                        display(d.head(head))

    def to_npz(self,filename):
        if hasattr(self,"synsets"):
            np.savez(filename+".npz",X=self.X,y=self.y,synsets=self.synsets)
        else:
            np.savez(filename+".npz",X=self.X,y=self.y)

    def from_npz(self,parameters):
        data = np.load(parameters["path"])
        if "X.key" in parameters:
            self.X = data[parameters["X.key"]]
        else:
            self.X = data["X"]

        if "y.key" in parameters:
            self.y = data[parameters["y.key"]]
        else:
            self.y = data["y"]
        if "synsets.key" in parameters:
            self.synsets = data[parameters["synsets.key"]]
        else:
            if "synsets" in data:
                self.synsets = data["synsets"]

        if "name" in parameters:
            self.name = parameters["name"]
        else:
            self.name = "NoName"
        print("[X] Loading from : " + parameters["path"])
        print("\n")

    #Download one image from url
    def image_from_url(self,url,img_size=(128,128)):

        #Get image from url
        response = requests.get(url)
        img = Image.open(BytesIO(response.content))

        #Resize the image
        resize = img.resize(img_size, Image.NEAREST)
        resize = np.asarray(resize)
        resize = resize.astype('float32')
        resize = np.expand_dims(resize,axis=0)
        return resize

    def make(self,test=None):

        if hasattr(self,"synsets"):
            if test is not None:
                self.gen_test(test)
                np.savez(self.params["name"]+"_test.npz",X=self.X_test,y=self.y_test,synsets=self.synsets)
                print("[X] Test set has been save into: " + self.params["name"]+"_test.npz")
            np.savez(self.params["name"]+"_train.npz",X=self.X,y=self.y,synsets=self.synsets)
            print("[X] Training set has been save into: " + self.params["name"]+"_train.npz")
        else:
            if test is not None:
                self.gen_test(test)
                np.savez(self.params["name"]+"_test.npz",X=self.X_test,y=self.y_test,synsets=self.synsets)
                print("[X] Test set has been save into: " + self.params["name"]+"_test.npz")
            np.savez(self.params["name"]+"_train.npz",X=self.X,y=self.y)
            print("[X] Training set has been save into: " + self.params["name"]+"_train.npz")

        print("\n")


import numpy as np
import torch
from torch import nn

class FastSpeechLoss(nn.Module):
    def __init__(self):
        super().__init__()
        self.mse_loss = nn.MSELoss()
        self.l1_loss = nn.L1Loss()

    def forward(self, mel_output, duration_predictor_output, mel_target, duration, **kwargs):
        mel_loss = self.mse_loss(mel_output, mel_target)

        duration_loss = self.l1_loss(duration_predictor_output,
                                               duration.float())

        loss = mel_loss + duration_loss
        return {
            "loss": loss,
            "mel_loss": mel_loss,
            "duration_loss": duration_loss,
        }


bl_info = {
    "name": "GHD Camera",
    "author": "Gholamreza Dar",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D > Add > Mesh > GHD Camera",
    "description": "Adds a new Camera From View and Locked to View",
    "warning": "",
    "doc_url": "",
    "category": "Add Mesh",
}

import bpy
from bpy.types import Operator
from bpy.props import FloatVectorProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector

class OBJECT_OT_add_object(Operator, AddObjectHelper):
    """Create a new Camera From View and Locked to View"""
    bl_idname = "mesh.add_ghd_camera"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):

        bpy.ops.object.camera_add(enter_editmode=False, align='VIEW', location=(0, 0, 0), rotation=(0.0, 0.0, 0.0))
        bpy.ops.view3d.camera_to_view()
        context.space_data.lock_camera = True

        return {'FINISHED'}

# Registration

def add_object_button(self, context):
    self.layout.operator(
        OBJECT_OT_add_object.bl_idname,
        text="GHD Camera",
        icon='PLUGIN')

def register():
    bpy.utils.register_class(OBJECT_OT_add_object)
    bpy.types.VIEW3D_MT_mesh_add.append(add_object_button)

def unregister():
    bpy.utils.unregister_class(OBJECT_OT_add_object)
    bpy.types.VIEW3D_MT_mesh_add.remove(add_object_button)

if __name__ == "__main__":
    register()


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np

from sklearn.metrics import accuracy_score, \
    f1_score, \
    precision_score, \
    recall_score

def print_config(config):

    print(" |   MODEL:          | %s |" % config.__class__.__name__)

    keys = [x for x in dir(config) if not x.startswith('__')]

    for x in keys:
        print(" | %-*s | %-*s |" % (16, x, 8, str(getattr(config, x))[:6]))

def evaluate(p, y, print_it=True):

    precision = precision_score(y, p, average="samples")
    recall = recall_score(y, p, average="weighted")
    f1 = f1_score(y, p, average="weighted")
    accuracy = accuracy_score(y, p)

    if print_it:
        print("F1 Score: ", f1)
        print("Recall: ", recall)
        print("Precision: ", precision)
        print("Accuracy: ", accuracy)

    return [f1, recall, precision, accuracy]

def evaluate_multilabel(predictions, y_data, threshold, print_it = True):
    for pred in predictions:
        pred[pred > threshold] = 1
        pred[pred < threshold] = 0

    p = np.array([x.astype(int).tolist() for x in predictions])
    y = np.array([x.astype(int).tolist() for x in y_data])

    if print_it:
        print("Threshold: %.6f" % threshold)

    return evaluate(p, y, print_it)

def evaluate_multiclass(predictions, y_data, print_it=True):

    y = np.array([x.astype(int).tolist() for x in y_data])
    pred = [[0 for x in range(len(y[0]))] for z in range(len(y))]
    print(predictions.shape)
    print(len(pred))
    for index in range(0, predictions.shape[0]):
        pred[index][predictions[index].argmax()] = 1

    p = np.array([x for x in pred])

    return evaluate(p, y, print_it)

def make_loss_graph(CONST):
    from util.utils import load_pickle as load
    gru = load(CONST.DATA_DIR + 'GRU')
    lstm = load(CONST.DATA_DIR + 'LSTM')
    birnn = load(CONST.DATA_DIR + 'BiRNN')

    cutoff = 105

    gru = gru[:cutoff]
    lstm = lstm[:cutoff]
    birnn= birnn[:cutoff]

    import matplotlib.pyplot as plt
    x = [i for i in range(cutoff)]
    plt.plot(np.array(x), np.array(gru))
    plt.plot(np.array(x), np.array(lstm))
    plt.plot(np.array(x), np.array(birnn))
    plt.legend(['GRU', 'LSTM', 'BiRNN LSTM'], loc='upper right')
    plt.savefig("losses_all.png")
    print("all losses plot saved")

def re_evalute_slot3(CONST):

    from util.utils import load_pickle as load
    birnn = load(CONST.DATA_DIR + "BiRNNslot3" + "_predictions")
    evaluate_multiclass(birnn["predictions"], birnn["y"], True)

def re_evalute(CONST):
    threshold = float(CONST.THRESHOLD)

    from util.utils import load_pickle as load
    gru = load(CONST.DATA_DIR + "GRU" + "predictions")
    lstm = load(CONST.DATA_DIR + "LSTM" + "predictions")
    biRNN = load(CONST.DATA_DIR + "BiRNN" + "predictions")

    print("###########  GRU ###############")
    find_best_slot1("gru", gru["predictions"], gru["y"])
    print("########### LSTM ##############")
    find_best_slot1("lstm", lstm["predictions"], lstm["y"])
    print("########### BiRNN LSTM ##############")
    find_best_slot1("birnn", biRNN["predictions"], biRNN["y"])

def find_best_slot1(name, pred, y):

    max_threshhold_result = 0
    score = 0
    results = {}
    f1 = []
    recall = []
    precision = []
    thresholds = np.arange(0.04001, 0.20000, 0.001)
    for t in thresholds:
        pred_copy = np.copy(pred)
        t_result = evaluate_multilabel(pred_copy, y, t, print_it=False)

        if t_result[0] > score:
            score = t_result[0]
            max_threshhold_result = t
            results = t_result

        f1.append(t_result[0])
        recall.append(t_result[1])
        precision.append(t_result[2])

    print("Threshold: %.6f" % max_threshhold_result)
    print("F1 Score: ", results[0])
    print("Recall: ", results[1])
    print("Precision: ", results[2])

    import matplotlib.pyplot as plt
    plt.plot(np.array(thresholds), np.array(f1), '--')
    plt.plot(np.array(thresholds), np.array(recall))
    plt.plot(np.array(thresholds), np.array(precision), ':')
    plt.legend(['F1', 'Recall', 'Precision'], loc='upper right')
    plt.savefig("score_" + name + ".png")
    try:
        plt.close()
    except AttributeError as e:
        pass
    print("Saved BiRNN F1, Recall, and Precision")

if __name__ == "__main__":

    import argparse
    from read.config_reader import CONST
    CONST.parse_argument(argparse.ArgumentParser())

    #make_loss_graph(CONST)

    re_evalute(CONST)

    # slot 3
    re_evalute_slot3(CONST)


import numpy as np
import sympy
from pytest import approx

from analysis import Analysis
from fexc import WeightCalculator, WeightedDensity, WD
from test_weighted_density_analytic import calculate_analytic

def test_weighted_densities_simple() -> None:
    dr = 2 ** -3
    n = 32
    ana = Analysis(dr, n)
    wc = WeightCalculator()

    # expect this to take a while
    wd = WeightedDensity(ana, wc)
    rho_bulk = 0.1
    rho = rho_bulk * np.ones(n)

    n3 = wd.calc_density(WD.N3, rho)
    # the edge is tricky, need to extrapolate
    assert n3 == approx(rho_bulk * np.ones(n) * np.pi / 6)

    n2 = wd.calc_density(WD.N2, rho)
    assert n2 == approx(rho_bulk * np.ones(n) * np.pi)

    n2v = wd.calc_density(WD.N2V, rho)
    assert n2v == approx(np.zeros(n), abs=1e-13)

    n11 = wd.calc_density(WD.N11, rho)
    assert n11 == approx(np.zeros(n), abs=1e-13)

    psi2 = wd.calc_density(WD.PSI2, rho)
    assert psi2 == approx(rho_bulk * np.ones(n) * np.pi)

    psi3 = wd.calc_density(WD.PSI3, rho)
    assert psi3 == approx(rho_bulk * np.ones(n) * np.pi / 6)

    r = np.arange(n) * dr
    r[0] = 1  # it's not, but it avoids the division warning
    R = 0.5
    psi2v_ana = np.pi * (-(R - r) ** 2 * abs(R - r) + (R + r) ** 3 + 3 * (R + r) * (R ** 2 - r ** 2) - 3 * (
                R ** 2 - r ** 2) * abs(R - r)) / (3 * r)
    psi2v_ana[0] = np.pi
    psi2v = wd.calc_density(WD.PSI2V, rho)
    assert psi2v[:-8] == approx(rho_bulk * psi2v_ana[:-8])

def test_weighted_densities() -> None:
    R = sympy.Rational(1, 2)
    r, rp = sympy.symbols('r rp', real=True)

    rho = sympy.Rational(2, 10) + sympy.sin(sympy.pi*rp)/1000
    rho_eval = sympy.lambdify([rp], rho)

    n11, n2, n2v, n3, psi11, psi2v = calculate_analytic(R, r, rp, rho)

    dr = 2 ** -6
    n = 256
    r = np.array(np.arange(n)*dr, dtype=np.longdouble)
    ana = Analysis(dr, n)
    wc = WeightCalculator()
    wd = WeightedDensity(ana, wc)

    rho_discrete = np.array([rho_eval(i * dr) for i in range(n)])

    n3_discrete, n2_discrete, n2v_discrete, n11_discrete, \
        psi3_discrete, psi2_discrete, psi2v_discrete, psi11_discrete \
        = wd.calc_densities([WD.N3, WD.N2, WD.N2V, WD.N11, WD.PSI3, WD.PSI2, WD.PSI2V, WD.PSI11], rho_discrete)

    n3_ana = n3(r)
    n2_ana = n2(r)
    n2v_ana = n2v(r)
    n11_ana = n11(r)
    psi2_ana = n2_ana
    psi3_ana = n3_ana
    psi2v_ana = psi2v(r)
    psi11_ana = psi11(r)

    mask = int(0.5/dr)
    np.savetxt("n3.dat", np.hstack((r.reshape(-1, 1), n3_discrete.reshape(-1, 1), n3_ana.reshape(-1, 1))))
    np.savetxt("n2.dat", np.hstack((r.reshape(-1, 1), n2_discrete.reshape(-1, 1), n2_ana.reshape(-1, 1))))
    np.savetxt("n2v.dat", np.hstack((r.reshape(-1, 1), n2v_discrete.reshape(-1, 1), n2v_ana.reshape(-1, 1))))
    np.savetxt("n11.dat", np.hstack((r.reshape(-1, 1), n11_discrete.reshape(-1, 1), n11_ana.reshape(-1, 1))))
    np.savetxt("psi3.dat", np.hstack((r.reshape(-1, 1), psi3_discrete.reshape(-1, 1), psi3_ana.reshape(-1, 1))))
    np.savetxt("psi2.dat", np.hstack((r.reshape(-1, 1), psi2_discrete.reshape(-1, 1), psi2_ana.reshape(-1, 1))))
    np.savetxt("psi2v.dat", np.hstack((r.reshape(-1, 1), psi2v_discrete.reshape(-1, 1), psi2v_ana.reshape(-1, 1))))
    np.savetxt("psi11.dat", np.hstack((r.reshape(-1, 1), psi11_discrete.reshape(-1, 1), psi11_ana.reshape(-1, 1))))

    assert n3_discrete[:-mask] == approx(n3_ana[:-mask], rel=1e-5)
    assert n2_discrete[:-mask] == approx(n2_ana[:-mask], rel=1e-5)
    assert n2v_discrete[mask // 2:-mask] == approx(n2v_ana[mask // 2:-mask], rel=2e-3)
    assert n11_discrete[mask // 2:-mask] == approx(n11_ana[mask // 2:-mask], rel=2e-3)
    assert psi3_discrete[:-mask] == approx(psi3_ana[:-mask], rel=1e-5)
    assert psi2_discrete[:-mask] == approx(psi2_ana[:-mask], rel=1e-5)
    assert psi2v_discrete[mask // 2:-mask] == approx(psi2v_ana[mask // 2:-mask], rel=2e-3)
    assert psi11_discrete[mask // 2:-mask] == approx(psi11_ana[mask // 2:-mask], rel=2e-3)


from flask import Blueprint, render_template, request, current_app as app, redirect, url_for, flash
from flask_login import login_required, current_user
from werkzeug.utils import secure_filename
from Productos.converter import convert_Inputs, convert_Objects
import os, json
from models import db, Producto, Proveedor, Ingrediente, InventarioIngredientes, InventarioProductos, Gramaje, Log
from datetime import datetime
from my_decorator import role_required

Productos = Blueprint('Productos', __name__)

#----------------------RUTAS-------------------------------------------------------------------------------------------------------------------------------------#

#PRODUCTOS-------------------------------------------------------
#Obtiene y muestra los productos
@Productos.route('/Admin/productos', methods=['GET'])
@login_required
@role_required('admin', 'visor')
def get_Productos():
    producst = Producto.query.all()
    return render_template('products.html', name = 'Productos', type = 'lateral', products = producst)

#Obtiene y muestra un solo producto
@Productos.route('/Producto/<int:id>', methods=['GET'])
@login_required
@role_required('admin', 'visor')
def get_Producto(id):
    error = False
    product = Producto.query.filter_by(id=id).first()
    receta = convert_Objects(product.receta)
    jreceta = json.dumps(receta)
    ingredientes = Ingrediente.query.all()

    for r in receta:
        if r['id'] == 'ERROR':
            error = True

    if error:
        flash('Algunos ingredientes han sido eliminados, se recomienda revisar la receta y corregir')
    return render_template('product_data.html', name = 'Producto', type = 'lateral', product = product, receta = receta, jreceta = jreceta, ingredientes = ingredientes, ing = len(receta), delete_route = ('/DeleteProducto/' + str(product.id)))

#Vista que permite agregar productos
@Productos.route('/Admin/add_productos', methods=['GET', 'POST'])
@login_required
@role_required('admin')
def show_new_Producto():
    ingredientes = 0
    ingredients = []
    if request.method == 'POST':
        ingredientes = int(request.form.get('ingre'))
        ingredients = Ingrediente.query.all()
    return render_template('new_product.html', name = 'Agregar Producto', type = 'lateral', ing = ingredientes, ingredients = ingredients)

#Agrega productos
@Productos.route('/Admin/add_producto', methods=['POST'])
@login_required
@role_required('admin')
def add_producto():
    try:
        nombre = request.form.get('name')
        descripcion_corta = request.form.get('descripcion_corta')
        descripcion_larga = request.form.get('descripcion_larga')
        precio_menudeo = request.form.get('precio_menudeo')
        precio_mayoreo = request.form.get('precio_mayoreo')
        file = request.files['file']
        receta = convert_Inputs(request.form)

        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

        prod = Producto(
            nombre=nombre,
            descripcion_corta=descripcion_corta,
            descripcion_larga=descripcion_larga,
            precio_menudeo=precio_menudeo,
            precio_mayoreo=precio_mayoreo,
            url_photo=('../static/img/upload/' + filename),
            receta=receta
        )

        inventario = InventarioProductos(stock=0.0, producto=prod)
        prod.inventario = [inventario]

        ahora = datetime.now()
        fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
        log = Log(
            log = (current_user.name + ' ha agregado el producto: ' + prod.nombre +  ' - ' + fecha_hora),
            usuario_id = current_user.id
        )

        db.session.add(log)

        db.session.add(prod)
        db.session.commit()

        return redirect(url_for('Productos.get_Productos'))
    except Exception as e:
        db.session.rollback()
        flash('Hubo un error al agregar el producto: verifique que los datos que ingresó son correctos o que no dejó ningún campo vacío')
        return redirect(url_for('Productos.get_Productos'))

#Edita info general de productos
@Productos.route('/Editproduct/<int:id>', methods=['POST'])
@login_required
@role_required('admin', 'visor')
def edit_product(id):
    try:
        producto = Producto.query.get(id)

        producto.descripcion_corta = request.form.get('descripcion_corta')
        producto.descripcion_larga = request.form.get('descripcion_larga')
        producto.nombre = request.form.get('name')
        producto.precio_menudeo = request.form.get('precio_menudeo')

        if request.files['file'].filename:
            file = request.files['file']
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            producto.url_photo = ('../static/img/upload/' + filename)

        ahora = datetime.now()
        fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
        log = Log(
            log = (current_user.name + ' ha editado la información del producto: ' + producto.nombre +  ' - ' + fecha_hora),
            usuario_id = current_user.id
        )

        db.session.add(log)

        db.session.commit()
        flash('Se han guardado con éxito los cambios!')

    except TypeError:
        flash('Se ha producido un error')
    return redirect(url_for('Productos.get_Productos'))

#Edita la receta
@Productos.route('/Editrecipe/<int:id>', methods=['POST'])
@login_required
@role_required('admin')
def edit_recipe(id):
    producto = Producto.query.get(id)
    new_receta = convert_Inputs(request.form)
    if producto.receta == new_receta:
        flash ('No se han ralizado cambios en la receta')
    else:
        try:
            producto.receta = new_receta

            ahora = datetime.now()
            fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
            log = Log(
                log = (current_user.name + ' ha editado la receta del producto: ' + producto.nombre +  ' - ' + fecha_hora),
                usuario_id = current_user.id
            )

            db.session.add(log)

            db.session.commit()
            flash ('La receta ha sido cambiada con exito')
        except:
            flash('Ha ocurrido un error')

    return redirect(url_for('Productos.get_Productos'))

#Elimina productos
@Productos.route('/DeleteProducto/<int:id>', methods=['POST'])
@login_required
@role_required('admin')
def deleteProducto(id):
    try:
        producto = Producto.query.get(id)

        # Eliminar primero de la tabla inventario_ingredientes
        inventario = InventarioProductos.query.filter_by(producto_id=id).first()
        if inventario:
            db.session.delete(inventario)

        ahora = datetime.now()
        fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
        log = Log(
            log = (current_user.name + ' ha eliminado: ' + producto.nombre +  ' - ' + fecha_hora),
            usuario_id = current_user.id
        )

        db.session.add(log)

        db.session.delete(producto)
        db.session.commit()

        flash('Se ha eliminado el elemento, asegurese de cancelar los pedidos que puedan contener este elemento')
    except:
        flash('Ha ocurrido un error')

    return redirect(url_for('Productos.get_Productos'))

#INGREDIENTES-------------------------------------------------------
#Muestra todos los ingredientes
@Productos.route('/Admin/ingredientes', methods=['GET'])
@login_required
@role_required('admin', 'visor')
def get_Ingredientes():
    ingredients = Ingrediente.query.all()
    error = False
    r_i = []
    for ingredient in ingredients:
        inventario = ingredient.inventario[0]
        prov = Proveedor.query.filter_by(id=ingredient.proveedor_id).first()
        if not prov:
            error = True
        r_i.append({
            "id" : ingredient.id,
            "nombre" : ingredient.nombre,
            "stock" : inventario.stock,
            "proveedor" : prov,
            "precio" : ingredient.precio,
            "gramaje" : ingredient.gramaje.uni_larga,
        })

    if error:
        flash('Hay elementos con valores erroneos, favor de corregirlos')

    return render_template('ingredients.html', name = 'Ingredientes', type = 'lateral', ingredients = r_i)

#Muestra la vista de agregar ingredientes
@Productos.route('/Admin/add_ingrediente', methods=['GET'])
@login_required
@role_required('admin')
def get_show_new_ingrediente():
    providers = Proveedor.query.all()
    gramaje = Gramaje.query.all()
    return render_template('new_ingrediente.html', name = 'Agregar Ingrediente', type = 'lateral', providers = providers, gramaje = gramaje)

#Agrega ingredientes
@Productos.route('/Admin/add_ingrediente', methods=['POST'])
@login_required
@role_required('admin')
def add_ingrediente():
    nombre = request.form.get('nombre')
    prov = request.form.get('provider')
    precio = request.form.get('precio')
    gramaje = request.form.get('gramaje')

    ingr = Ingrediente(
        nombre = nombre,
        proveedor_id = prov,
        precio = precio,
        gramaje_id = gramaje
        )

    inventario = InventarioIngredientes(stock=0.0, ingrediente=ingr)
    ingr.inventario = [inventario]

    try:
        db.session.add(ingr)
        ahora = datetime.now()
        fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
        log = Log(
            log = (current_user.name + ' ha agregado el ingrediente: ' + ingr.nombre +  ' - ' + fecha_hora),
            usuario_id = current_user.id
        )

        db.session.add(log)

        db.session.commit()
    except:
        flash('Error al insertar en la base de datos. Por favor, revise que los datos sean correctos y vuelva a intentar.')
        return redirect(url_for('Productos.get_Ingredientes'))

    return redirect(url_for('Productos.get_Ingredientes'))

#Agrega al stock ingredientes
@Productos.route('/Admin/add_ingrediente_stock', methods=['POST'])
@login_required
@role_required('admin', 'visor')
def add_ingrediente_stock():
    ingr = Ingrediente.query.get(int(request.form.get('id')))
    stock = request.form.get('ammount')

    ingr.inventario[0].stock += (float(stock) * 1000)

    ahora = datetime.now()
    fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
    log = Log(
        log = (current_user.name + ' ha agregado stock al ingrediente: ' + ingr.nombre + ' una cantidad de ' + str(float(stock) * 1000) +  ' - ' + fecha_hora),
        usuario_id = current_user.id
    )

    db.session.add(log)

    db.session.commit()
    return redirect(url_for('Productos.get_Ingredientes'))

#Muestra la vista de editar ingredientes
@Productos.route('/Ingrediente/<id>', methods=['GET'])
@login_required
@role_required('admin')
def get_show_ingrediente(id):
    ingrediente = Ingrediente.query.get(id)
    providers = Proveedor.query.all()
    return render_template('edit_ingredient.html', name = 'Editar Ingrediente', type = 'lateral', providers = providers, ingrediente = ingrediente, delete_route = ('/DeleteIngrediente/' + str(ingrediente.id)))

#Edita ingredientes
@Productos.route('/Ingrediente/<id>', methods=['POST'])
@login_required
@role_required('admin')
def edit_ingrediente(id):
    ingrediente = Ingrediente.query.get(id)
    if not ingrediente:
        flash('No se encontró el ingrediente especificado')
        return redirect(url_for('Productos.get_Ingredientes'))

    nombre = request.form.get('nombre')
    prov = request.form.get('provider')
    precio = request.form.get('precio')

    # Validar que los campos no estén vacíos
    if not nombre or not prov or not precio:
        flash('Todos los campos son requeridos')
        return redirect(url_for('Productos.get_Ingredientes'))

    # Convertir los tipos de datos necesarios
    prov = int(prov)
    precio = float(precio)

    # Actualizar los datos del ingrediente
    ingrediente.nombre = nombre
    ingrediente.proveedor_id = prov
    ingrediente.precio = precio

    ahora = datetime.now()
    fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
    log = Log(
        log = (current_user.name + ' ha agregado actualizado el ingrediente: ' + ingrediente.nombre + ' - ' + fecha_hora),
        usuario_id = current_user.id
    )

    db.session.add(log)

    db.session.commit()

    return redirect(url_for('Productos.get_Ingredientes'))

# Elimina los ingredientes
@Productos.route('/DeleteIngrediente/<int:id>', methods=['POST'])
@login_required
@role_required('admin')
def delete_ingrediente(id):
    try:
        ingrediente = Ingrediente.query.get(id)

        # Eliminar primero de la tabla inventario_ingredientes
        inventario = InventarioIngredientes.query.filter_by(ingrediente_id=id).first()
        if inventario:
            db.session.delete(inventario)

        db.session.delete(ingrediente)
        ahora = datetime.now()
        fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
        log = Log(
            log = (current_user.name + ' ha eliminado al ingrediente: ' + ingrediente.nombre + ' - ' + fecha_hora),
            usuario_id = current_user.id
        )

        db.session.add(log)

        db.session.commit()

        flash('Se ha eliminado el elemento, asegurese de editar las recetas que puedan contener este elemento')
    except:
        flash('Ha ocurrido un error')

    return redirect(url_for('Productos.get_Ingredientes'))

#GRAMAJE---------------------------------------------------------------
@Productos.route('/Admin/gramaje', methods=['GET'])
@login_required
@role_required('admin')
def gramaje():
    gramajes = Gramaje.query.all()
    return render_template('gramaje.html', name = 'Gramaje', type = 'lateral', gramajes = gramajes)

@Productos.route('/Admin/addgramaje', methods=['POST'])
@login_required
@role_required('admin')
def gramaje_add():
    umi = request.form.get('uni_mini')
    ula = request.form.get('uni_larga')

    if not umi or not ula:
        flash('Por favor ingrese los campos requeridos')
        return redirect(url_for('Productos.gramaje'))

    gramaje = Gramaje(
        uni_mini = umi,
        uni_larga = ula
    )

    ahora = datetime.now()
    fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
    log = Log(
        log = (current_user.name + ' ha agregado el gramaje: ' + gramaje.uni_larga + ' - ' + fecha_hora),
        usuario_id = current_user.id
    )

    db.session.add(log)

    db.session.add(gramaje)
    db.session.commit()

    return redirect(url_for('Productos.gramaje'))

#INVENTARIO----------------------------------------------------------------
#Agrega productos, descuenta del inventario (Esta funcion sera larga, ya no quiero martha)
@Productos.route('/Producto_stock/<int:id>', methods=['POST'])
@login_required
@role_required('admin', 'visor')
def add_producto_stock(id):
    try:
        prod = Producto.query.get(id)
        stock = float(request.form.get('added'))
        rec = request.form.get('receta')
        receta = json.loads(rec)

        for ingrediente in receta:
            total_add = ingrediente['cantidad'] * stock
            if (ingrediente['disponible'] - total_add) < 0:
                flash('Demasiado stock, poco inventario, intenta de nuevo')
                return redirect('/Producto/'+str(id))
            ingr = Ingrediente.query.get(ingrediente['id'])
            ingr.inventario[0].stock -= total_add

        prod.inventario[0].stock += stock

        ahora = datetime.now()
        fecha_hora = ahora.strftime('%d/%m/%Y %H:%M:%S')
        log = Log(
            log = (current_user.name + ' ha agregado stock al producto: ' + prod.nombre + ' una cantidad de: ' + str(stock) + ' - ' + fecha_hora),
            usuario_id = current_user.id
        )

        db.session.add(log)

        db.session.commit()
    except:
        flash('Ha ocurrido un error, verifica la receta que no contenga elementos eliminados')
    return redirect(url_for('Productos.get_Productos'))


import csv
import json
import logging
import math
import os
import sys
from io import StringIO

from nltk.corpus import stopwords

from .cosine import cosine_distance
from .reduce import pca_reduce

sys.path.append('../text_mining')

from text_mining.annotation import annotate_text

def rle_encode(data_str):
    current_seq = ""
    prev_seq = ""
    encoding = ""
    count = 1
    data = data_str[(str(data_str).find(',')):] + ","
    if not data:
        return ''
    for char in data:
        if char == ',':
            if current_seq == prev_seq:
                count += 1
            else:
                if prev_seq:
                    if count > 1:
                        encoding += str(count) + "_" + prev_seq + ","
                    else:
                        encoding += prev_seq + ","
                count = 1
            prev_seq = current_seq
            current_seq = ""
            continue
        current_seq += char
    if count > 1:
        encoding += str(count) + "_" + prev_seq + ","
    else:
        encoding += prev_seq + ","
    return data_str[:(str(data_str).find(',') + 1)] + encoding[:-1]

def rle_decode(text):
    freq_str = text[(text.find(',') + 1):]
    expanded_text_list = []
    for fr_info in freq_str.split(','):
        if "_" in fr_info:
            amount = int(fr_info.split("_")[0])
            fr = fr_info.split("_")[1]
            for i in range(0, amount):
                expanded_text_list.append(int(fr))
        else:
            expanded_text_list.append(int(fr_info))
    return expanded_text_list

def get_file_lines_number(file):
    file = open(file, "r")
    line_count = 0
    for line in file:
        if line != "\n":
            line_count += 1
    file.close()
    return line_count

def matrix_header_csv_string_to_list(text):
    comm_index = text.find(',') + 1
    line = StringIO(text[comm_index:-1])
    reader = csv.reader(line, delimiter=',')
    split_list = []
    for parts in reader:
        split_list.append(parts)
    return split_list[0]

def get_tokens_list_with_token_tags_from_document_annotation(document_path):
    tokens = []
    with open(document_path, "r") as f:
        line = f.readline()
        while line:
            if line:
                token = line.split("\t")[0]
                if token != '\n':
                    tokens.append((token, line.split("\t")[3][:-1]))
            line = f.readline()
    f.close()
    return tokens

def build_frequency_dict_and_term_doc_matrix(annotation_documents_dir_path, min_fr, dict_file, matrix_file):
    tokens_dict = {}
    eng_stopwords = stopwords.words("english")
    file_counter = 1
    docs_list = []
    for subdir, dirs, files in os.walk(annotation_documents_dir_path):
        for file in files:
            doc_tokens_list = get_tokens_list_with_token_tags_from_document_annotation(os.path.join(subdir, file))
            doc_name = file
            docs_list.append(doc_name)
            logging.info(file_counter)
            file_counter += 1
            for token_info in doc_tokens_list:
                if (token_info[0].lower() not in eng_stopwords) and (token_info[1] != "punctuation sign") \
                        and (token_info[1] != "quotation"):
                    token = str(token_info[0].lower())
                    if not (token in tokens_dict):
                        tokens_dict[token] = {}
                    if doc_name in tokens_dict[token]:
                        tokens_dict[token][doc_name] += 1
                    else:
                        tokens_dict[token][doc_name] = 1
    tokens_dict = {k: v for k, v in tokens_dict.items() if sum(tokens_dict[k].values()) >= min_fr}
    tokens_with_total_frequencies_dict = {}
    for key in tokens_dict:
        tokens_with_total_frequencies_dict[key] = sum(tokens_dict[key].values())
    f1 = open(dict_file, "w")
    json.dump(tokens_with_total_frequencies_dict, f1)
    f1.close()
    f2 = open(matrix_file, "w")
    header_string = ""
    for key in tokens_dict.keys():
        if "," in key:
            header_string += ",\"" + key + "\""
        else:
            header_string += "," + key
    f2.write(header_string)
    f2.write("\n")
    f2.write('total_docs,' + rle_encode(','.join([str(len(tokens_dict[k])) for k in tokens_dict])))
    f2.write("\n")
    processed_lines_counter = 1
    for doc in docs_list:
        freq_string = doc
        for key in tokens_dict:
            if doc in tokens_dict[key]:
                freq_string += "," + str(tokens_dict[key][doc])
            else:
                freq_string += ",0"
        f2.write(rle_encode(freq_string))
        f2.write("\n")
        logging.info(processed_lines_counter)
        processed_lines_counter += 1
    f2.close()

def read_word_dict_to_dict(dict_file):
    f = open(dict_file, "r")
    fr_dict = json.load(f)
    f.close()
    return fr_dict

def tokenize_with_filter(text):
    eng_stopwords = stopwords.words("english")
    tokens_list = [token_info.token.lower() for token_info in annotate_text(text)
                   if (token_info.token_type != "whitespace" and token_info.token_type != "punctuation"
                       and token_info.token_type != "quotation" and token_info.token.lower() not in eng_stopwords)]
    return tokens_list

def vectorize_custom_text(text, matrix_file):
    tokens_list = tokenize_with_filter(text)
    total_documents_amount = get_file_lines_number(matrix_file) - 2  # two first rows are headers
    f = open(matrix_file, "r")
    dictionary_words_list = matrix_header_csv_string_to_list(f.readline())
    dictionary_words_total_docs_num_row = f.readline()
    dictionary_words_total_docs_num_list = \
        rle_decode(dictionary_words_total_docs_num_row[(dictionary_words_total_docs_num_row.find(',')):-1])
    text_vector = []
    for term in dictionary_words_list:
        tf_value = (tokens_list.count(term)) / float(len(tokens_list))
        idf_value = math.log10(total_documents_amount /
                               int(dictionary_words_total_docs_num_list[dictionary_words_list.index(term)]))
        tf_idf_value = tf_value * idf_value
        text_vector.append(tf_idf_value)
    return text_vector

def get_single_word_tf_idf(word, dict_file, matrix_file):
    words_dict = read_word_dict_to_dict(dict_file)
    total_documents_amount = get_file_lines_number(matrix_file) - 2
    f = open(matrix_file, "r")
    dictionary_words_list = matrix_header_csv_string_to_list(f.readline())
    dictionary_words_total_docs_num_row = f.readline()
    dictionary_words_total_docs_num_list = \
        rle_decode(dictionary_words_total_docs_num_row[(dictionary_words_total_docs_num_row.find(',')):-1])
    if word in words_dict and word in dictionary_words_list:
        tf_value = (words_dict[word]) / float(sum(words_dict.values()))
        idf_value = math.log10(total_documents_amount /
                               int(dictionary_words_total_docs_num_list[dictionary_words_list.index(word)]))
        tf_idf_value = tf_value * idf_value
        return tf_idf_value
    else:
        return None

def use_tdidf_model(matrix_file, token_to_test, similar_tokens, same_field_tokens, other_tokens):
    logging.info("Custom tf-idf vectorization")
    all_tokens = []
    all_tokens.append(token_to_test)
    all_tokens = all_tokens + similar_tokens + same_field_tokens + other_tokens
    x = [vectorize_custom_text(token, matrix_file) for token in all_tokens]
    reduced_embeddings = pca_reduce(x, 2)
    logging.info("Cosine distance " + all_tokens[0])
    for i in range(1, len(all_tokens)):
        logging.info(
            "\twith " + all_tokens[i] + ": " + str(cosine_distance(reduced_embeddings[0], reduced_embeddings[i])))
    return reduced_embeddings, all_tokens


from fastapi import APIRouter ,status , File, UploadFile
from pydantic import BaseModel, Field
from fastapi.responses import JSONResponse
from app.service import departments_users
from typing import Union
import json
from app.models import departments_users as department_user_model

router = APIRouter()
departments_users_service = departments_users.DepartmentUsersService()

@router.post("/")
async def CreateDepartmentUser(department_user: department_user_model.CreateDepartmentUserForm):
    return await departments_users_service.CreateDepartmentUser(department_user)

@router.get("/{department_user_id}")
async def GetOneDepartmentUser(department_user_id: int):
    return await departments_users_service.GetOneDepartmentUser(department_user_id)

@router.get("/")
async def GetAllDepartmentsUsersPaginated(page_number: int, page_size: int):
    return await departments_users_service.GetAllDepartmentsUsersPaginated(page_number, page_size)

@router.put("/{department_user_id}")
async def UpdateDepartmentUser(department_user_id: int, department_user: department_user_model.CreateDepartmentUserForm):
    return await departments_users_service.UpdateDepartmentUser(department_user_id, department_user)

@router.delete("/{department_user_id}")
async def DeleteUser(department_user_id: int):
    return await departments_users_service.DeleteDepartmentUser(department_user_id)


from digitalocean import ClientV2
from . import commands
import ConfigParser, os

config = ConfigParser.ConfigParser()
config.read(['dosh.cfg', os.path.expanduser('~/.dosh.cfg')])

token = config.get("digitalocean", "token")

client = ClientV2(token=token)

def isdroplet(droplet_id):
    for i in client.droplets.all()['droplets']:
        if i['id'] == droplet_id:
            return True
    return False


"""
Created on May 2022

@author: Niko Suchowitz
"""
import numpy as np
import pandas as pd
import os
import rpy2.robjects as robjects
from rpy2.robjects.packages import importr

imputeTS = importr('imputeTS')
kalman_StructTs = robjects.r['na_kalman']
kalman_auto_arima = robjects.r['na_kalman']

def kalman_method(origin_api, data_w_nan, country, year, atc, tech, datatype, val_col, header):
    """
    fills the gaps with the kalman filter
    :param origin_api: if data is downloaded by the api
    :type origin_api: boolean
    :param data_w_nan: dataframe containing the gaps
    :type data_w_nan: dataframe
    :param country: code of the country
    :type country: string
    :param year: year of the data
    :type year: string
    :param atc: area type code of the dataframe
    :type atc: string
    :param tech: technology of the dataframe
    :type tech: string
    :param datatype: type of the data
    :type datatype: string
    :param val_col: header of the column which contains the important values
    :type val_col: string
    :param header: whole header of the dataframe
    :type header: list
    :return: filled dataframes from kalman methods
    :rtype: dataframe
    """
    # copy the df so we do not change the original
    df_w_nan_copy = data_w_nan.copy()

    # values need to be a numeric vector
    w_gaps = np.ndarray.tolist(df_w_nan_copy[val_col].values)
    w_gaps = robjects.FloatVector(w_gaps)

    # ----------
    # StructTs-filling
    # ----------
    without_gaps_structts = np.array(kalman_StructTs(w_gaps, model="StructTS", smooth=True))

    # ----------
    # arima-filling
    # ----------
    # stepwise=False, approximation=False recommended in official documentation; code can be faster with deleting both
    # arguments, but then maybe less precise
    without_gaps_arima = np.array(kalman_StructTs(w_gaps, model="auto.arima", smooth=True, stepwise=False,
                                                  approximation=False))

    # combine filled values with date and time again
    df_structts = pd.concat([df_w_nan_copy['DateTime'], pd.Series(without_gaps_structts)], axis=1)
    df_arima = pd.concat([df_w_nan_copy['DateTime'], pd.Series(without_gaps_arima)], axis=1)
    # set header
    df_structts.columns = header
    df_arima.columns = header

    # check were to save
    if origin_api:
        path = 'data/' + datatype + '/api_data/' + str(year) + '/' + country
    else:
        path = 'data/' + datatype + '/' + str(year) + '/' + country

    # first check if folder exists to save data in
    isExist = os.path.exists(path + '/kalman')
    if not isExist:
        os.makedirs(path + '/kalman')
    # save the combined df as csv
    pd.DataFrame(df_structts).to_csv(path + '/kalman/' + atc + '_' + tech + '_filled_structts.csv',
                                     sep='\t', encoding='utf-8', index=False,
                                     header=header)
    pd.DataFrame(df_arima).to_csv(path + '/kalman/' + atc + '_' + tech + '_filled_arima.csv',
                                  sep='\t', encoding='utf-8', index=False, header=header)

    return df_structts, df_arima


import numpy as np
import tensorflow as tf

celsius = np.array([-40,-10, -9,26, 15, 100, 0, 21,30, 36, -5,21,8], dtype=float)
fahrenheit = np.array([-40,14, 15.8,78.8, 59, 212, 32, 69.8, 86,96.8, 23,69.8,46.4], dtype=float)

#keras es un framework que ahorra codigo al crear las capas

#capa = tf.keras.layers.Dense(units=1,input_shape=[1])
#modelo = tf.keras.Sequential([capa])
oculta1 = tf.keras.layers.Dense(units=3, input_shape=[1])
oculta2 = tf.keras.layers.Dense(units=3)
salida = tf.keras.layers.Dense(units=1)
modelo = tf.keras.Sequential([oculta1, oculta2 ,salida])

#crear el modelo de la red neuronal
modelo.compile(
    optimizer = tf.keras.optimizers.Adam(0.1),
    loss = 'mean_squared_error'
)
#compilar el modelo con los parametros del optimizador
print("Hola estoy comenzando el entrenamiento...")
historial = modelo.fit(celsius, fahrenheit, epochs=2000, verbose=False)
print("... ya termine \n----- MODELO TERMINADO -----")

import matplotlib.pyplot as plt
plt.xlabel('# Epoca')
plt.ylabel('Magnitud de perdida')
plt.plot(historial.history['loss']) # grafica para ver como se va aprendiendo
plt.show()

print("hagamos una prediccion")
prediccion = float(input())
resultado = modelo.predict([prediccion])

print("el resultado es " + str(resultado) + "°F")

#ver laestructura de la red

print("ver variables internas del modelo")
print (oculta1.get_weights())
print (oculta2.get_weights())
print (salida.get_weights())


import gensim
import numpy
import pandas as pd
from gensim.models.ldamodel import LdaModel
from gensim.models.coherencemodel import CoherenceModel
import gensim.corpora as corpora

df = pd.read_csv('../data/tweets_cutoff0.01_sorted.csv',sep='\t')

texts = df['text'].values
texts = [x.split(' ') for x in texts]

id2word = corpora.Dictionary(texts)

corpus = [id2word.doc2bow(text) for text in texts]

num_topics=[2,3,4,5,6,7,8,9,10,15,20,25,30,35,40,45,50]
coh_scores = []
for ntop in num_topics:
    lda_model = LdaModel(corpus=corpus,
                           id2word=id2word,
                           num_topics=ntop,
                           random_state=42,
                           update_every=1,
                           chunksize=100,
                           passes=10,
                           alpha='auto',
                           per_word_topics=True)

    coherence_model_lda = CoherenceModel(model=lda_model, texts=texts, dictionary=id2word, coherence='c_uci')

    coherence_lda = coherence_model_lda.get_coherence()

    coh_scores.append(coherence_lda)

df_out = pd.DataFrame.from_dict({'ntop':num_topics,'coh':coh_scores})

df_out.to_csv('lda_coh.csv',index=False)