from astroid import Attribute

from pylint.checkers import BaseChecker
from pylint.interfaces import IAstroidChecker

class FunctionOrderChecker(BaseChecker):
    __implements__ = IAstroidChecker
    name = "function-order"
    priority = -1
    msgs = {
        "R1004": ("Function is out of order", "wrong-function-order",
                  "Function should be defined after its caller"),
        "R1005": ("Method is out of order", "wrong-method-order",
                  "Method should be defined after its caller")
    }

    def __init__(self, linter):
        super().__init__(linter)
        self.function_definitions = {}
        self.function_stack = []

    def visit_functiondef(self, node):
        self.function_stack.append(node.name)
        if len(self.function_stack) <= 1:
            self.function_definitions[node.name] = {'called': False, 'method': node.is_method(), 'node': node}

    def visit_call(self, node):
        callee_name = node.func.attrname if isinstance(node.func, Attribute) else node.func.name
        callee = self.function_definitions.get(callee_name, None)
        if callee and not callee['called']:
            callee['called'] = True
            if callee['method']:
                self.add_message('wrong-method-order', node=callee['node'])
            else:
                self.add_message('wrong-function-order', node=callee['node'])

    def leave_functiondef(self, _):
        self.function_stack.pop()


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os

def save_images_result(exp_path, csv_path):
    if not os.path.exists(exp_path):
        os.makedirs(exp_path)

    accuracies, class_recall, poison_rate = read_csv(csv_path=csv_path, attacker_label=None, poison_label=4)
    draw_results(accuracies, class_recall, poison_rate, exp_path)

def read_csv(csv_path, attacker_label, poison_label):

    accuracies = list()
    class_recall = list()
    poison_rate = list()

    df = pd.read_csv(csv_path, header=None)
    for idx, row in df.iterrows():
        accuracy = 0.0
        for i in range(10):
            if i != poison_label:
                accuracy += row[i + 12]
        accuracies.append(accuracy/9)
        class_recall.append(row[poison_label + 12])
        poison_rate.append(row[22]/1000)

    return accuracies, class_recall, poison_rate

def draw_results(accuracies, class_recall, poison_rate, exp_path):
    round = [i for i in range(200)]

    # Main task and Poison task Accuracy
    plt.figure(figsize=(10, 5))
    plt.plot(round, accuracies, label="Main task")
    plt.plot(round, class_recall, label="Poison task")
    plt.xlabel('Round')
    plt.ylabel('Accuracy')
    plt.legend(loc='best')
    plt.savefig(exp_path + '/class_recall.png')

    # Main task accuracy and Poison success rate
    plt.figure(figsize=(10, 5))
    plt.plot(round, accuracies, label="Main task")
    plt.plot(round, poison_rate, label="Poison task")
    plt.xlabel('Round')
    plt.ylabel('Accuracy')
    plt.legend(loc='best')
    plt.savefig(exp_path + '/poison_success_rate.png')

if __name__ == "__main__":
    save_images_result('experiment/multi_round_attack/exp_1', '3000_results.csv')


import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import torch.nn.functional as F
from sklearn import metrics
import seaborn as sns
from torch_sparse import spspmm
import numpy as np

from src.visualization.visualize import Visualization
from src.features.link_prediction import Link_prediction

class BDRRAA(nn.Module, Link_prediction, Visualization):
    def __init__(self, k, d, sample_size, data, data_type = "sparse", data2 = None, non_sparse_i = None, non_sparse_j = None, sparse_i_rem = None, sparse_j_rem = None):
        super(BDRRAA, self).__init__()
        self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        self.data_type = data_type
        self.sample_size = sample_size
        self.k = k
        self.d = d

        self.sparse_i_idx = data.to(self.device)
        self.sparse_j_idx = data2.to(self.device)
        self.non_sparse_i_idx_removed = non_sparse_i.to(self.device)
        self.non_sparse_j_idx_removed = non_sparse_j.to(self.device)
        self.sparse_i_idx_removed = sparse_i_rem.to(self.device)
        self.sparse_j_idx_removed = sparse_j_rem.to(self.device)
        self.removed_i = torch.cat((self.non_sparse_i_idx_removed, self.sparse_i_idx_removed))
        self.removed_j = torch.cat((self.non_sparse_j_idx_removed, self.sparse_j_idx_removed))

        self.sample_shape = (len(self.sparse_i_idx), len(self.sparse_j_idx))
        self.sampling_i_weights = torch.ones(self.sample_shape[0], device = self.device)
        self.sampling_j_weights = torch.ones(self.sample_shape[1], device = self.device)

        self.sample_i_size = int(self.sample_shape[0] * self.sample_size)
        self.sample_j_size = int(self.sample_shape[1] * self.sample_size)

        self.beta = torch.nn.Parameter(torch.randn(self.sample_shape[0], device = self.device))
        self.gamma = torch.nn.Parameter(torch.randn(self.sample_shape[1], device = self.device))
        self.softplus = nn.Softplus()
        self.A = torch.nn.Parameter(torch.randn(self.d, self.k, device = self.device))

        self.Z_i = torch.nn.Parameter(torch.randn(self.k, self.sample_shape[0], device = self.device))
        self.Z_j = torch.nn.Parameter(torch.randn(self.k, self.sample_shape[1], device = self.device))

        self.Gate = torch.nn.Parameter(torch.randn(self.sample_shape[0] + self.sample_shape[1], self.k, device = self.device))

        self.losses = []
        self.N = self.sample_shape[0] + self.sample_shape[1]

        Link_prediction.__init__(self)
        Visualization.__init__(self)

    def sample_network(self):
        # USE torch_sparse lib i.e. : from torch_sparse import spspmm

        # sample for undirected network
        sample_i_idx = torch.multinomial(self.sampling_i_weights, self.sample_i_size, replacement=False)
        sample_j_idx = torch.multinomial(self.sampling_j_weights, self.sample_j_size, replacement=False)
        # translate sampled indices w.r.t. to the full matrix, it is just a diagonal matrix
        indices_i_translator = torch.cat([sample_i_idx.unsqueeze(0), sample_i_idx.unsqueeze(0)], 0)
        indices_j_translator = torch.cat([sample_j_idx.unsqueeze(0), sample_j_idx.unsqueeze(0)], 0)
        # adjacency matrix in edges format
        edges = torch.cat([self.sparse_i_idx.unsqueeze(0), self.sparse_j_idx.unsqueeze(0)], 0)
        # matrix multiplication B = Adjacency x Indices translator
        # see spspmm function, it give a multiplication between two matrices
        # indexC is the indices where we have non-zero values and valueC the actual values (in this case ones)
        indexC, valueC = spspmm(edges, torch.ones(edges.shape[1]), indices_j_translator,
                                torch.ones(indices_j_translator.shape[1]), self.sample_shape[0], self.sample_shape[1],
                                self.sample_shape[1], coalesced=True)
        # second matrix multiplication C = Indices translator x B, indexC returns where we have edges inside the sample
        indexC, valueC = spspmm(indices_i_translator, torch.ones(indices_i_translator.shape[1]), indexC, valueC,
                                self.sample_shape[0], self.sample_shape[0], self.sample_shape[1], coalesced=True)

        # edge row position
        sparse_i_sample = indexC[0, :]
        # edge column position
        sparse_j_sample = indexC[1, :]

        return sample_i_idx, sample_j_idx, sparse_i_sample, sparse_j_sample

    def log_likelihood(self):
        sample_i_idx, sample_j_idx, sparse_sample_i, sparse_sample_j = self.sample_network()
        Z_i = F.softmax(self.Z_i, dim=0)  # (K x N)
        Z_j = F.softmax(self.Z_j, dim=0)
        Z = torch.cat((Z_i[:,sample_i_idx], Z_j[:,sample_j_idx]),1) #Concatenate partition embeddings
        Gate = torch.cat((self.Gate[sample_i_idx,:], self.Gate[sample_j_idx,:]), 0)
        Gate = torch.sigmoid(Gate)  # Sigmoid activation function
        C = (Z.T * Gate) / (Z.T * Gate).sum(0)  # Gating function
        # For the nodes without links
        bias_matrix = self.beta[sample_i_idx].unsqueeze(1) + self.gamma[sample_j_idx]  # (N x N)
        AZC = torch.mm(self.A, torch.mm(Z, C))
        mat = (torch.exp(bias_matrix -
                         ((torch.mm(AZC,Z_i[:,sample_i_idx]).T.unsqueeze(1) -
                           torch.mm(AZC,Z_j[:,sample_j_idx]).T + 1e-06) ** 2).sum(-1) ** 0.5)).sum()
        mat_links = ((self.beta[sparse_sample_i] + self.gamma[sparse_sample_j]) -
                     (((AZC @ Z_i[:,sparse_sample_i]).T -
                       (AZC @ Z_j[:,sparse_sample_j]).T + 1e-06) ** 2).sum(-1) ** 0.5).sum()
        log_likelihood_sparse = mat_links - mat
        return log_likelihood_sparse

    def train(self, iterations, LR = 0.1, print_loss = False):
        optimizer = torch.optim.Adam(params = self.parameters(), lr=LR)

        for _ in range(iterations):
            loss = - self.log_likelihood() / self.N
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            self.losses.append(loss.item())
            if print_loss:
                print('Loss at the',_,'iteration:',loss.item())

if __name__ == "__main__":
    seed = 42
    torch.random.manual_seed(seed)
    k = 3
    d = 2

    # Data
    dataset = "drug-gene"
    data = torch.from_numpy(np.loadtxt("../data/train_masks/" + dataset + "/sparse_i.txt")).long()
    data2 = torch.from_numpy(np.loadtxt("../data/train_masks/" + dataset + "/sparse_j.txt")).long()
    sparse_i_rem = torch.from_numpy(np.loadtxt("../data/train_masks/" + dataset + "/sparse_i_rem.txt")).long()
    sparse_j_rem = torch.from_numpy(np.loadtxt("../data/train_masks/" + dataset + "/sparse_j_rem.txt")).long()
    non_sparse_i = torch.from_numpy(np.loadtxt("../data/train_masks/" + dataset + "/non_sparse_i.txt")).long()
    non_sparse_j = torch.from_numpy(np.loadtxt("../data/train_masks/" + dataset + "/non_sparse_j.txt")).long()

    model = BDRRAA(k = k, d = d, sample_size = 0.2, data = data, data2 = data2, non_sparse_i=non_sparse_i, non_sparse_j=non_sparse_j, sparse_i_rem=sparse_i_rem, sparse_j_rem=sparse_j_rem)
    iterations = 10000
    model.train(interations = iterations, print_loss = True)
    # Plotting latent space
    Z_i = F.softmax(model.Z_i, dim=0)
    Z_j = F.softmax(model.Z_j, dim=0)
    Z = torch.cat((Z_i,Z_j),1)
    G = torch.sigmoid(model.Gate)
    C = (Z.T * G) / (Z.T * G).sum(0)

    embeddings = torch.matmul(model.A, torch.matmul(torch.matmul(Z, C), Z)).T
    archetypes = torch.matmul(model.A, torch.matmul(Z, C))

    fig, ([ax1, ax2]) = plt.subplots(nrows=1, ncols=2)
    sns.heatmap(Z.detach().numpy(), cmap="YlGnBu", cbar=False, ax=ax1)
    sns.heatmap(C.T.detach().numpy(), cmap="YlGnBu", cbar=False, ax=ax2)
    #sns.heatmap(Z_j.detach().numpy(), cmap="YlGnBu", cbar=False, ax=ax3)
    #sns.heatmap(C_j.T.detach().numpy(), cmap="YlGnBu", cbar=False, ax=ax4)

    if embeddings.shape[1] == 3:
        fig = plt.figure()
        ax = fig.add_subplot(projection='3d')
        ax.scatter(embeddings[:, 0].detach().numpy(), embeddings[:, 1].detach().numpy(),
                   embeddings[:, 2].detach().numpy(), c='red')
        ax.scatter(archetypes[0, :].detach().numpy(), archetypes[1, :].detach().numpy(),
                   archetypes[2, :].detach().numpy(), marker='^', c='black')
        '''ax.scatter(embeddings_j[:, 0].detach().numpy(), embeddings_j[:, 1].detach().numpy(),
                   embeddings_j[:, 2].detach().numpy(), c='blue')
        ax.scatter(archetypes_j[0, :].detach().numpy(), archetypes_j[1, :].detach().numpy(),
                   archetypes_j[2, :].detach().numpy(), marker='^', c='purple')'''
        ax.set_title(f"Latent space after {iterations} iterations")
    else:
        fig, (ax1, ax2) = plt.subplots(1, 2)
        ax1.scatter(embeddings[model.input_size[0]:, 0].detach().numpy(), embeddings[model.input_size[0]:, 1].detach().numpy(), c='red')
        ax1.scatter(embeddings[:model.input_size[0], 0].detach().numpy(), embeddings[:model.input_size[0], 1].detach().numpy(), c='blue')
        ax1.scatter(archetypes[0, :].detach().numpy(), archetypes[1, :].detach().numpy(), marker='^', c='black')
        #ax1.scatter(embeddings_j[:, 0].detach().numpy(), embeddings_j[:, 1].detach().numpy(), c='blue')
        #ax1.scatter(archetypes_j[0, :].detach().numpy(), archetypes_j[1, :].detach().numpy(), marker='^', c='purple')
        ax1.set_title(f"Latent space after {iterations} iterations")
        # Plotting learning curve
        ax2.plot(model.losses)
        ax2.set_yscale("log")
        ax2.set_title("Loss")
    plt.show()

    model.plot_auc()

"""
    def link_prediction(self):
        with torch.no_grad():
            Z_i = F.softmax(self.Z_i, dim=0)  # (K x N)
            Z_j = F.softmax(self.Z_j, dim=0)
            Z = torch.cat((Z_i, Z_j),1) #Concatenate partition embeddings
            #Z = F.softmax(Z, dim=0)
            G = F.sigmoid(self.G)
            C = (Z.T * G) / (Z.T * G).sum(0)  # Gating function

            M_i = torch.matmul(self.A, torch.matmul(torch.matmul(Z, C), Z[:, self.removed_i])).T  # Size of test set e.g. K x N
            M_j = torch.matmul(self.A, torch.matmul(torch.matmul(Z, C), Z[:, self.removed_j])).T
            z_pdist_test = ((M_i - M_j + 1e-06) ** 2).sum(-1) ** 0.5  # N x N
            theta = (self.beta[self.removed_i] + self.gamma[self.removed_j] - z_pdist_test)  # N x N

            # Get the rate -> exp(log_odds)
            rate = torch.exp(theta)  # N

            # TODO Skal lige ha tjekket om det er den rigtige rækkefølge.
            target = torch.cat((torch.zeros(self.non_sparse_i_idx_removed.shape[0]), torch.ones(self.sparse_i_idx_removed.shape[0])))

            fpr, tpr, threshold = metrics.roc_curve(target, rate.numpy())

            # Determining AUC score and precision and recall
            auc_score = metrics.roc_auc_score(target, rate.cpu().data.numpy())

            return auc_score, fpr, tpr

    G = mmread('data/toy_data/divorce/divorce.mtx')

    edge_list = torch.tensor([G.row,G.col]).T
    edge_list = edge_list.long()
    seed = 42
    torch.random.manual_seed(seed)

    # A = mmread("data/raw/soc-karate.mtx")
    # A = A.todense()
    k = 3
    d = 2

    link_pred = True

    if link_pred:
        num_samples = round(0.2 * ((50 * 9)))
        idx_i_test = torch.multinomial(input=torch.arange(0, float(50)), num_samples=num_samples,
                                       replacement=True)
        idx_j_test = torch.multinomial(input=torch.arange(0, float(9)), num_samples=num_samples, replacement=True)

        test = torch.stack((idx_i_test, idx_j_test))

        # TODO: could be a killer.. maybe do it once and save adjacency list ;)
        def if_edge(a, edge_list):
            a = a.tolist()
            edge_list = edge_list.tolist()
            a = list(zip(a[0], a[1]))
            edge_list = list(zip(edge_list[0], edge_list[1]))
            return [a[i] in edge_list for i in range(len(a))]

        target = [] #if_edge(test, edge_list)
        G = G.todense()
        for i in range(len(idx_i_test)):
            if G[idx_i_test[i], idx_j_test[i]] == 1:
                G[idx_i_test[i], idx_j_test[i]] = 0
                target.append(True)
            else:
                target.append(False)

        G = scipy.sparse.coo_matrix(G)
        edge_list = torch.tensor([G.row,G.col]).T
        edge_list = edge_list.long()

"""


"""
Dados de entrada no script

experimento : Define quais pesos deverão ser utilizados. Exemplo: experimento = "YOLOv5_UAVDT_0"

input_folder : Define a pasta contendo as imagens a serem classificadas pela rede treinada no experimento.
               Pode ser uma pasta com imagens.
               Pode ser uma pasta com outras pastas em seu interior contendo imagens. Como se fosse uma
               espécie de dataset, contendo vários vídeos.

output_folder : Pasta para guardar o arquivo de texto único contendo informações a respeito
                das bounding boxes para cada frame. O nome do arquivo de texto é dado automaticamente:
                nome_do_filme_sendo_analisado + "results.txt"    dataset_name = input_folder.split("/")[-2]

Filosofia:
    Dado um input_path contendo imagens ou pastas com imagens, para cada vídeo analisado será criado um arquivo
    txt com os bounding boxes detectados pela rede e será colocado na pasta output_path. Simples assim.
    Demais rotinas devem ser executadas pelo usuário que chama este script.

Padrões utilizados:
    1) Todos as imagens possuem em seu nome o frame a que correspondem.
        O número do frame está localizado imediatamente antes do "." que separa o nome do formato da imagem.
        Exemplos: img_00001.jpg => Frame = 1
                  img3013uav000021.png => Frame = 21
    2) Os frames começam a ser contados do número 1 e não do número zero.
    3) Supor que todas as images de um vídeo possuem as mesmas dimensões de altura e largura.

Exemplo de execução:

    experimento = "YOLOv5_UAVDT_0"
    input_folder = "../Datasets/UAVDT/UAV-benchmark-M/M0101"
    output_folder = "./YOLOv5_UAVDT_0/results/inference/UAVDT_Inference/"

$ python this_file_name.py -e {experimento} -i {input_folder} -o {output_folder}

# Futuro:
Carregar o endereço dos pesos a partir de um banco de dados local.
Dado o experimento, localizar o endereço dos pesos no banco de dados.

# Debug:
    python exec_inference.py -e YOLOv5_UAVDT_0 -i ./TesteFolder -o ./TesteFolder
"""

import os
import shutil
import subprocess
import pathlib
import tempfile
import re
import argparse
from PIL import Image as PILImage
from glob import glob
import random

data_yaml = """
# train and val datasets (image directory or *.txt file with image paths)

train: ../../../Datasets/UAVDT_YOLOv5/train/images/
test: ../../../Datasets/UAVDT_YOLOv5_Dataset/test/images/

# number of classes
nc: 3

# class names
names: ['car', 'truck', 'bus']
"""

# Weights Relatitve Paths "Database"
yv5_weigth_path = lambda exp, date: os.path.join(".",exp,"YOLOv5_UAVDT_train",f"{exp}-{date}","weights","best.pt")

weight_paths = {"YOLOv5_UAVDT_0" : yv5_weigth_path("YOLOv5_UAVDT_0", "21_Feb_2021_18h_17m"),
                "YOLOv5_UAVDT_1" : yv5_weigth_path("YOLOv5_UAVDT_1", "21_Feb_2021_19h_26m")}

# Argument Parser
opt = argparse.ArgumentParser()
opt.add_argument('-o', '--output', action='store', dest="output_folder", default="")
opt.add_argument('-i', '--input', action='store', dest="input_folder", default="")
opt.add_argument('-e', '--experiment', action='store', dest="experiment", default="")

opt.add_argument('-r', '--resolution', action='store', dest="resolution", default= 640,
                help="Resolução da imagem para utilizar na detecção. Default = 640.")
opt.add_argument('-t', '--iou-threshold', action='store', dest="iou_thresh", default= 0.5,
                help="IOU threshold para utilizar na detecção. Default = 0.5.")
opt.add_argument('-c', '--conf-threshold', action='store', dest="conf_thresh", default= 0.5,
                help="Detection confidende para utilizar na detecção. Default = 0.5.")
opt.add_argument('-b', '--batch-size', action='store', dest="batch_size", default= 16,
                help="Batch size para utilizar na detecção. Default = 16.")
opt.add_argument('--task', action='store', dest="task", default= "test",
                help="Detection task: test, study, speed. Default = test")
                # Study task: Varia as resoluções das imagens e anota o mAP para cada size.
                # Sizes estudados: range(256, 1536 + 128, 128))  # x axis (image sizes)
opt.add_argument('-d','--device', action='store', dest="device", default= "cpu",
                help="Detection using device: cpu, 0, 1, 2, 3. Default = cpu")
opt.add_argument('-s','--single class', action='store_true', dest="single_class",
                help="Detection trear the dataset as single class")
opt.add_argument('--verbose', action='store_true', help='report mAP by class')
opt.add_argument('--save-txt', action='store_false', help='save results to *.txt')
opt.add_argument('--save-conf', action='store_false', help='save confidences in --save-txt labels')
opt.add_argument('--save-json', action='store_false', help='save a cocoapi-compatible JSON results file')
opt.add_argument('--project', default='runs/test', help='save to project/name')
opt.add_argument('--name', default='exp', help='save to project/name')

opt = opt.parse_args()

if opt.output_folder == "" or opt.input_folder == "" or opt.experiment == "":
    raise Exception("The input, output or experiment is an empty strings.")

# Main Function
class main():

    def __init__(self, opt, clear_io=True):
        self.opt = opt
        self.experimento = self.opt.experiment
        if self.experimento not in weight_paths.keys():
            raise Exception(f"Experimento '{self.experimento}' não encontrado." +\
                             "Experimentos disponíveis: {weight_paths.keys()}.")

        self.input_folder = opt.proje
        self.output_folder = self.opt.output_folder
        self.clear_io = clear_io #Clear ouput folder before saving new files
        self.package = False # False: Not a folder inside a folder. True, otherwise.
        self.videos_paths = None

    def check_input_and_output_dirs(self):
        """
        Verify if the folders are ok. If they aren't, raise an Exception or fix the problem.
        """
        # Check if the folders paths terminate with a os.sep. If don't, force it.
        if not self.input_folder[-1] == os.sep: self.input_folder += os.sep
        if not self.output_folder[-1] == os.sep: self.output_folder += os.sep

        # Check if input folder is a valid folder, i.e, it exists.
        if not os.path.isdir(self.input_folder):
            raise Exception(f'O caminho do input_folder "{self.input_folder}" não é um diretório.')

        else:
            ## Check for files/ folders inside input path
            ## If there is files and folders, raise an Exception.
            ## The folder should contain only files or only folders.
            objects = glob(self.input_folder + "*")
            self.package = os.path.isdir(objects[0])
            for obj in objects:
                # not XOR to check if all file are equals.
                if not (package ^ os.path.isdir(obj)):
                    pass
                else:
                    raise Exception(f"There is files and folders mixed together inside" +\
                                     "'{self.input_folder}'. That isn't permitted.")

            videos_paths = []
            if self.package:
                for directory in objects:
                    self.videos_paths.append(directory)
            else:
                self.videos_paths.append(self.input_folder)

        # Analysis of each video
        for video_path in videos_paths:
            # Check if the output folder exists. If doesn't, create it.
            self.craete_empty_folder(self.output_folder)

            # Create the output file path
            video_name = video_path.split(os.sep)[-2]
            output_file_path = self.output_folder + video_name + "_results.txt"

            # If for some reason the output file already exists, remove it.
            # If it's non empty directory, raise an Exception.
            if os.path.isdir(output_file_path):
                os.remove(output_file_path)
            if os.path.isfile(output_file_path):
                if self.clear_io:
                    os.remove(output_file_path)
                else:
                    raise Exception(f"{output_file_path} already exists and clear_io == False.")

        # Create output dir
        if os.path.exists(self.output_folder):
            if os.path.isdir(self.output_folder):
                if not os.listdir(self.output_folder):
                    # Empty directory, ok..
                    pass
                elif self.clear_io:
                    # Clear output directory
                    shutil.rmtree(self.output_folder)
                    pathlib.Path(self.output_folder).mkdir(parents=True, exist_ok=True)
                else:
                    raise Exception(f"{self.output_folder} not empty and clear_io == False.")
            if os.path.isfile(self.output_folder):
                raise Exception(f"{self.output_folder} is a file, not a directory.")
        else:
            raise Exception(f"Unknown output folder/file: '{self.output_folder}'.")

    def run_inference(self):
        """
        This function makes the things happen.
        """
        # Check input and output dirs
        self.check_input_and_output_dirs()

        # Check experiment neural network model name:
        network = self.experimento.split("_")[0]

        if network == "YOLOv5":
            try:
                for video_path in self.videos_paths:
                    # Remove old yolov5 files and replace by a new one copy.
                    yv5_path = os.path.join(".", self.experimento, f"yolov5_w_det_temp")
                    if os.path.exists(yv5_path):
                        shutil.rmtree(yv5_path)
                    os.symlink(os.path.join("..","..","Submodules","yolov5_w",), yv5_path)

                # Create a temporary directory to store intermediate results
                    tempdir = tempfile.mkdtemp()
                    print("\nDiretório temporário: ", tempdir)

                    # Now, run the inference
                    weights_file_path = weight_paths[self.experimento]
                    detect_py_path = os.path.join(yv5_path, "detect.py")
                    data_yaml_path = os.path.join(".", self.experimento, "data_detection.yaml")
                    with open(data_yaml_path, 'w') as arq:
                        arq.write(data_yaml)

                    opt = self.opt
                    original_path = os.getcwd()
                    os.chdir(yv5_path)
                    shell_command = ["python", detect_py_path,
                                    "--weights", weights_file_path,
                                    "--data", data_yaml_path,
                                    "--batch-size", opt.batch_size,
                                    "--img-size", opt.resolution,
                                    "--conf_thres", opt.conf_thresh,
                                    "--iou-thres", opt.iou_thres,
                                    "--task", opt.task,
                                    "--device", opt.device,
                                    "--single-cls",opt.single_cls,
                                    "--verbose", opt.verbose,
                                    "--save-txt", opt.save_txt,
                                    "--save-conf", opt.save_conf,
                                    "--save-json", opt.save_json,
                                    "--project", opt.project,
                                    "--name", opt.name]

                    process = subprocess.Popen(shell_command,
                                    stdout=subprocess.PIPE,
                                    universal_newlines=True)

                    while True:
                        output = process.stdout.readline()
                        print(output.strip())
                        return_code = process.poll()
                        if return_code is not None:
                            print('RETURN CODE', return_code)
                            # Process has finished, read rest of the output
                            for output in process.stdout.readlines():
                                print(output.strip())
                            break
                    os.chdir(original_path)
                    # Resume all outputs to one txt file
                    txt_files_paths = glob(os.path.join(tempdir, "*.txt"))
                    img_files_paths = glob(os.path.join(tempdir, "*.jpg"))

                    pattern = re.compile("\d+\.")
                    frame_number_aux = lambda name: pattern.search(name)
                    frame_number = lambda name: int(frame_number_aux(name).group()[:-1])

                    txt_files_paths.sort(key = frame_number)
                    img_files_paths.sort(key = frame_number)

                    frame_boxes = {}
                    for txt_path, img_path in zip(txt_files_paths, img_files_paths):
                        if frame_number(txt_path) != frame_number(img_path):
                            raise Exception("Problema com a numeração das imagens e files preditos pela rede.")
                        frame = frame_number(txt_path)

                        with PILImage.open(img_path) as img:
                            width, height = img.size

                        with open(txt_path) as arq:
                            lines = arq.readlines()
                            for line in lines:
                                if line == "": continue
                                line = line.split(" ")
                                classe, x, y, w, h = int(line[0]), float(line[1]), float(line[2]), float(line[3]), float(line[4])
                                x = x - w/2
                                y = y - h/2
                                x, w = x*width, w*width
                                y, h = y*height, h*height
                                if frame in frame_boxes:
                                    frame_boxes[frame].append([frame, x, y, w, h, classe + 1])
                                else:
                                    frame_boxes[frame] =[ [frame, x, y, w, h, classe + 1] ]

                    print(f"[INFO] Salvando resultados em {self.output_file_path}")
                    counter = 0
                    with open(self.output_file_path, 'a') as arq:
                        for boxes in frame_boxes.values():
                            for box in boxes:
                                box = [str(i) for i in box]
                                if counter == 0:
                                    arq.write(",".join(box))
                                    counter += 1
                                else: arq.write("\n" +",".join(box))

            except Exception as e:
                print(e)

            finally:
                print("[INFO] Limpando arquivos...")
                # Clear all outputs txt files, except the resume file
                print("[INFO] Removendo diretório temporário.")
                shutil.rmtree(tempdir)
                # Clear yolov5 folder
                print(f"[INFO] Removendo o subdretório yolov5 do experimento {self.experimento}.")
                shutil.rmtree(yv5_path)
                # Final msg
                print("[INFO] Fim da execução.")

        ### Debug mode for Visual Studio Code..
        debug_mode = False
        if debug_mode:
            print("\n\nCurrent dir: ", os.getcwd())
            os.chdir("./RedesNeurais")
            opt.parse_args() # Put the args here
        ###

        run_inference(opt= opt)


from flask import Flask,render_template,request,jsonify
import datetime
import pickle
import numpy as np

app= Flask(__name__)

@app.route('/',methods=['GET','POST'])
def forecast():
    if request.method=="POST":

        startdate = datetime.datetime.strptime( request.form['sdate'],'%Y-%m-%d')
        enddate = datetime.datetime.strptime(request.form['edate'], '%Y-%m-%d')
        loadmodel = pickle.load(open('sarimax.pkl', 'rb'))
        results=np.expm1(loadmodel.predict(start=startdate, end=enddate, dynamic=False)).sum()
        results=str(round(results))
        return ("REVENUE FORECASTING FOR GIVEN DATE RANGE IS : "+results)

    return render_template('index.html')

if __name__=="__main__":
    app.run(debug=True)


import matplotlib.colors
import numpy as np
import time
import pandas as pd
import matplotlib.pyplot as plt
from scipy.ndimage import gaussian_filter
import tcod

np.random.seed(5)
tempType = "normal"
rainType = "normal"

def diamond_square(n, bias=False):
    # The array must be square with edge length 2**n + 1
    N = 2 ** n + 1

    arr = np.zeros((N, N))
    # f scales the random numbers at each stage of the algorithm
    f = 1.0
    if not bias:
        # Initialise the array with random numbers at its corners
        arr[0::N - 1, 0::N - 1] = np.random.uniform(-1, 1, (2, 2))
    else:
        arr[0] = np.random.uniform(-1.5, -.5, N)
        arr[N - 1] = np.random.uniform(.5, 1.5, N)

    side = N - 1
    nsquares = 1
    while side > 1:
        sideo2 = side // 2

        # Diamond step
        for ix in range(nsquares):
            for iy in range(nsquares):
                x0, x1, y0, y1 = ix * side, (ix + 1) * side, iy * side, (iy + 1) * side
                xc, yc = x0 + sideo2, y0 + sideo2
                # Set this pixel to the mean of its "diamond" neighbours plus
                # a random offset.
                arr[yc, xc] = (arr[y0, x0] + arr[y0, x1] + arr[y1, x0] + arr[y1, x1]) / 4
                arr[yc, xc] += f * np.random.uniform(-1, 1)

        # Square step: NB don't do this step until the pixels from the preceding
        # diamond step have been set.
        for iy in range(2 * nsquares + 1):
            yc = sideo2 * iy
            for ix in range(nsquares + 1):
                xc = side * ix + sideo2 * (1 - iy % 2)
                if not (0 <= xc < N and 0 <= yc < N):
                    continue
                tot, ntot = 0., 0
                # Set this pixel to the mean of its "square" neighbours plus
                # a random offset. At the edges, it has only three neighbours
                for (dx, dy) in ((-1, 0), (1, 0), (0, -1), (0, 1)):
                    xs, ys = xc + dx * sideo2, yc + dy * sideo2
                    if not (0 <= xs < N and 0 <= ys < N):
                        continue
                    else:
                        tot += arr[ys, xs]
                        ntot += 1
                arr[yc, xc] += tot / ntot + f * np.random.uniform(-1, 1)
        side = sideo2
        nsquares *= 2
        f /= 2

    #now we need to normalize the maps
    #get the min value
    minValue = 0
    for y in arr:
        if min(y) < minValue:
            minValue = min(y)
    arr = arr + (minValue * -1)
    maxValue = 1
    for y in arr:
        if max(y) > maxValue:
            maxValue = max(y)
    arr = arr/maxValue
    #add the negative to all the numbers to get the lowest value to 0
    #divide all the numbers by the maximum value
    #now it's between 0 and 1

    return arr

mapSize = 8
N = 2**mapSize+1

st = time.time()
heightMap = diamond_square(mapSize)
dt = round(time.time() - st, 1)
print("generated heightMap\t\t{} sec".format(dt))

st = time.time()
rainMap = diamond_square(mapSize)
dt = round(time.time() - st, 1)
print("generated rainMap\t\t{} sec".format(dt))

st = time.time()
tempMap = diamond_square(mapSize)
dt = round(time.time() - st, 1)
print("generated tempMap\t\t{} sec".format(dt))

def normalize_map(data):
    return (data - np.min(data)) / (np.max(data) - np.min(data))

#adjuting temperature in a different way
#add or subtract 1/10th of the distance from 0 or 1 (depending on if you're making it hotter or colder
def heat_world(temp_map, h):
    #h is the heat intensity modifier
    for y in range(len(temp_map)):
        for x in range(len(temp_map)):
            temp_map[y][x] += (1 - temp_map[y][x])/h
    return temp_map

def cool_world(temp_map, h):
    #h is the heat intensity modifier
    for y in range(len(temp_map)):
        for x in range(len(temp_map)):
            temp_map[y][x] -= (temp_map[y][x])/h
    return temp_map

def wet_world(rain_map, h):
    #h is the heat intensity modifier
    for y in range(len(rain_map)):
        for x in range(len(rain_map)):
            rain_map[y][x] += (1 - rain_map[y][x])/h
    return rain_map

def dry_world(rain_map, h):
    #h is the heat intensity modifier
    for y in range(len(rain_map)):
        for x in range(len(rain_map)):
            rain_map[y][x] -= (rain_map[y][x])/h
    return rain_map

heightMap = normalize_map(heightMap)

# as the height increases the temperature decreases
#tempMap = tempMap - (np.sqrt(heightMap)/2)

# there are 8 levels for rain
# fuck with the rain to get what we want
st = time.time()
rainMap = normalize_map(rainMap)

#rainMap = dry_world(rainMap, -3)
#rainMap = wet_world(rainMap, -2)

if rainType == "dry":
    rainSplines = [0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.95]
elif rainType == "normal":
    #rainSplines = [0.05, 0.1, 0.3, 0.45, 0.6, 0.75, 0.9]
    rainSplines = [0.1, 0.15, 0.3, 0.45, 0.6, 0.8, 0.9]
elif rainType == "wet":
    rainSplines = [0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6]
for y in range(len(rainMap)):
    for x in range(len(rainMap)):
        if 0 <= rainMap[y][x] < rainSplines[0]:
            rainMap[y][x] = 0
        elif rainSplines[0] <= rainMap[y][x] < rainSplines[1]:
            rainMap[y][x] = 1
        elif rainSplines[1] <= rainMap[y][x] < rainSplines[2]:
            rainMap[y][x] = 2
        elif rainSplines[2] <= rainMap[y][x] < rainSplines[3]:
            rainMap[y][x] = 3
        elif rainSplines[3] <= rainMap[y][x] < rainSplines[4]:
            rainMap[y][x] = 4
        elif rainSplines[4] <= rainMap[y][x] < rainSplines[5]:
            rainMap[y][x] = 5
        elif rainSplines[5] <= rainMap[y][x] < rainSplines[6]:
            rainMap[y][x] = 6
        elif rainSplines[6] <= rainMap[y][x] :
            rainMap[y][x] = 7
rainMap = rainMap.astype(int)
dt = round(time.time() - st, 1)
print("splined rainMap\t\t\t{} sec".format(dt))

# there are 7 for temperature
st = time.time()
tempMap = normalize_map(tempMap)

#tempMap = heat_world(tempMap, -2)
#tempMap = cool_world(tempMap, -3)

if tempType == "hot":
    tempSplines = [0.05, 0.1, 0.2, 0.3, 0.4, 0.5]
elif tempType == "normal":
    #tempSplines = [0.05, 0.1, 0.2, 0.4, 0.6, 0.8]
    tempSplines = [0.1, 0.15, 0.2, 0.4, 0.8, 0.9]
elif tempType == "cold":
    tempSplines = [0.2, 0.3, 0.5, 0.7, 0.8, 0.95]
for y in range(len(tempMap)):
    for x in range(len(tempMap)):
        if 0 <= tempMap[y][x] < tempSplines[0]:
            tempMap[y][x] = 0
        elif tempSplines[0] <= tempMap[y][x] < tempSplines[1]:
            tempMap[y][x] = 1
        elif tempSplines[1] <= tempMap[y][x] < tempSplines[2]:
            tempMap[y][x] = 2
        elif tempSplines[2] <= tempMap[y][x] < tempSplines[3]:
            tempMap[y][x] = 3
        elif tempSplines[3] <= tempMap[y][x] < tempSplines[4]:
            tempMap[y][x] = 4
        elif tempSplines[4] <= tempMap[y][x] < tempSplines[5]:
            tempMap[y][x] = 5
        elif tempSplines[5] <= tempMap[y][x] :
            tempMap[y][x] = 6

tempMap = tempMap.astype(int)
dt = round(time.time() - st, 1)
print("splined tempMap\t\t\t{} sec".format(dt))

##############
#plt.imshow(heightMap, cmap='magma')
#plt.axis('off')
#plt.show()
#
#plt.imshow(rainMap, cmap='magma')
#plt.axis('off')
#plt.show()
#
#plt.imshow(tempMap, cmap='turbo')
#plt.axis('off')
#plt.show()
#
##############
st = time.time()
biomeGuide = [
    [1,  1,  1,  2,  2,  2,  2,  2],
    [1,  1,  1,  3,  3,  4,  4,  5],
    [6,  6,  7,  8,  8,  8,  8,  5],
    [6,  6,  7,  9,  9, 10, 11, 12],
    [13, 14, 15, 16, 17, 10, 11, 12],
    [13, 14, 15, 16, 18, 19, 20, 21],
    [13, 14, 22, 23, 24, 25, 25, 26]
]
#biome mapping
# 0   ocean
# 1   polar desert
# 2   ice cap
# 3   tundra
# 4   wet tundra
# 5   polar wetlands
# 6   cool desert
# 7   step
# 8   boreal forest
# 9   temperate woodlands
# 10  temperate forest
# 11  temperate wet forest
# 12  temperate wetlands
# 13  extreme desert
# 14  desert
# 15  subtropical scrub
# 16  subtropical wetlands
# 17  mediterranean
# 18  subtropical dry forest
# 19  subtropical forest
# 20  subtropical wet forest
# 21  subtropical wetlands
# 22  tropical scrub
# 23  tropical woodlands
# 24  tropical dry forest
# 25  tropical wet forest
# 26  tropical wetlands

seaLevel = np.median(heightMap)

biomeMap = np.zeros((N, N))
for y in range(len(biomeMap)):
    for x in range(len(biomeMap)):
        if heightMap[y][x] < seaLevel:
            biomeMap[y][x] = 0
        else:
            biomeMap[y][x] = biomeGuide[tempMap[y][x]][rainMap[y][x]]
dt = round(time.time() - st, 1)
print("generated biomeMap\t\t{} sec".format(dt))

np.savetxt("map_m3.csv", biomeMap, delimiter=",")

# generate cities
st = time.time()
cityMap = np.zeros((N,N))
numCities = N/2
while numCities > 0:
    rY = np.random.randint(0,N)
    rX = np.random.randint(0,N)
    if heightMap[rY][rX] > seaLevel:
        if not biomeMap[rY][rX] in [1, 2, 13]:
            cityMap[rY][rX] = 1
            numCities -= 1

# adjust the size
# pick a random city to add 1 pop to
# add that city back into the pool again
# get the list of cities
cityList = []
for y in range(len(cityMap)):
    for x in range(len(cityMap)):
        if cityMap[y][x] > 0:
            cityList.append([y, x])

worldPop = len(cityList)
for i in range(worldPop):
    cityNum = np.random.randint(0,len(cityList))
    cityToAdjust = cityList[cityNum]

    # this makes it zipfian
    # adjust based on temp and rainfall
    if biomeMap[cityToAdjust[0]][cityToAdjust[1]] in [0, 1, 2, 3, 4, 5, 6, 7, 13, 14, 15, 22, 26, 25, 21]:
        if np.random.uniform(0,1) < 1/4:
            cityMap[cityToAdjust[0]][cityToAdjust[1]] += 1
            cityList.append(cityToAdjust)
    else:
        cityMap[cityToAdjust[0]][cityToAdjust[1]] += 1
        cityList.append(cityToAdjust)

dt = round(time.time() - st, 1)
print("generated cityMap\t\t{} sec".format(dt))

np.savetxt("citymap_m3.csv", cityMap, delimiter=",")

st = time.time()
# making roads
numRoads = 100
# make a heatmap that shows the distance to the nearest city tile
# have a pathfinding thing pick two random cities and connect them via a walk
# remove any that are on water

# set a map to 100
cost = np.ones((N,N))
cost *= 100

# subtract from it the population of the city
cost = cost - cityMap

# blur it
cost = gaussian_filter(cost, sigma=4)
cost = normalize_map(cost)
cost *= 100

#add the mountains
for y in range(len(heightMap)):
    for x in range(len(heightMap)):
        if not heightMap[y][x] <= seaLevel:
            cost[y][x] += heightMap[y][x]*100

# subtract the ocean
for y in range(len(cost)):
    for x in range(len(cost)):
        if heightMap[y][x] <= seaLevel:
            cost[y][x] = 0

# convert floats to ints
cost = cost.astype(int)

#add some randomness
for y in range(len(cost)):
    for x in range(len(cost)):
        if cost[y][x] > 0:
            cost[y][x] += np.random.randint(0,50)

#add a penalty for certain biomes
for y in range(len(cost)):
    for x in range(len(cost)):
        if biomeMap[y][x] in [0, 1, 2, 3, 4, 5, 6, 7, 13, 14, 15, 22, 26, 25, 21]:
            cost[y][x] *= 5

graph = tcod.path.CustomGraph((N, N))
CARDINAL = [
    [141, 100, 141],
    [100, 0, 100],
    [141, 100, 141],
]

roadMap = np.zeros((N, N))

#add from random points on the edge to make the roads not be self contained to the map
#we want at least 2
numBorderRoads = mapSize - 3
for i in range(numBorderRoads):
    #pick a cardinal direction
    border = np.random.randint(0,4)
    if border == 0:
        cityList.append([0, np.random.randint(0,N)])
    elif border == 1:
        cityList.append([N - 1, np.random.randint(0, N)])
    elif border == 2:
        cityList.append([np.random.randint(0, N), 0])
    elif border == 3:
        cityList.append([np.random.randint(0, N), N-1])

# randomize the city list
#cityList = cityList * 2
np.random.shuffle(cityList)
startCity = cityList[0]

from scipy.spatial import distance
def closest_node_loop(node, nodes, n):
    for i in range(n):
        closest_index = distance.cdist([node], nodes).argmin()
        if i < n-1:
            del nodes[closest_index]
    return nodes[closest_index]

cityIndexes = np.random.randint(0, len(cityList), 2)

result = []
for i in cityList:
    if i not in result:
        result.append(i)

cityList = result.copy()

#connect each city to its nth closest neighbor
for n in range(1,4):
    for j in range(len(cityList)):
        startCity = cityList[j]
        #cityIndexes = np.random.randint(0, len(cityList), 2)
        #remove the city from the cityList
        cityListSubset = cityList.copy()
        del cityListSubset[j]
        endCity = closest_node_loop(startCity, cityListSubset,n)
        # get the path
        graph.add_edges(edge_map=CARDINAL, cost=cost)
        pf = tcod.path.Pathfinder(graph)
        pf.add_root((startCity[0], startCity[1]))
        road = pf.path_to((endCity[0], endCity[1]))
        #make the road map
        for i in road:
            roadMap[i[0]][i[1]] += 1
            #adjust the cost based on the roadMap so the roads converge
            cost[i[0]][i[1]] /= 3
        #startCity = endCity

dt = round(time.time() - st, 1)
print("generated roadMap\t\t{} sec".format(dt))

np.savetxt("roadmap_m3.csv", roadMap, delimiter=",")

print("done")


import os
import torch
import json
import errno
import codecs
from tqdm import tqdm

if not os.path.exists('data/raw/train-images-idx3-ubyte'):
    try:
        os.makedirs(os.path.join('data', 'raw'))
        os.makedirs(os.path.join('data', 'processed'))
    except OSError as e:
        if e.errno == errno.EEXIST:
            pass
        else:
            raise
    from six.moves import urllib
    import gzip
    urls = [
        'http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz',
        'http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz',
        'http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz',
        'http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz',
    ]
    for url in urls:
        print('Downloading ' + url)
        data = urllib.request.urlopen(url)
        filename = url.rpartition('/')[2]
        file_path = os.path.join('data', 'raw', filename)
        with open(file_path, 'wb') as f:
            f.write(data.read())
        with open(file_path.replace('.gz', ''), 'wb') as out_f, \
             gzip.GzipFile(file_path) as zip_f:
            out_f.write(zip_f.read())
        os.unlink(file_path)

def get_int(b):
    return int(codecs.encode(b, 'hex'), 16)

def parse_byte(b):
    if isinstance(b, str):
        return ord(b)
    return b

def read_label_file(path):
    with open(path, 'rb') as f:
        data = f.read()
        assert get_int(data[:4]) == 2049
        length = get_int(data[4:8])
        labels = [parse_byte(b) for b in tqdm(data[8:], total=length)]
        assert len(labels) == length
        return torch.LongTensor(labels)

def read_image_file(path):
    with open(path, 'rb') as f:
        data = f.read()
        assert get_int(data[:4]) == 2051
        length = get_int(data[4:8])
        num_rows = get_int(data[8:12])
        num_cols = get_int(data[12:16])
        images = []
        idx = 16
        for l in tqdm(range(length)):
            img = []
            images.append(img)
            for r in range(num_rows):
                row = []
                img.append(row)
                for c in range(num_cols):
                    row.append(parse_byte(data[idx]))
                    idx += 1
        assert len(images) == length
        return torch.FloatTensor(images)

print("Loading training set")
training_set = (
    read_image_file('data/raw/train-images-idx3-ubyte'),
    read_label_file('data/raw/train-labels-idx1-ubyte'),
)
print("Saving training set")
with open('data/processed/training.pt', 'wb') as f:
    torch.save(training_set, f)

print("Loading test set")
test_set = (
    read_image_file('data/raw/t10k-images-idx3-ubyte'),
    read_label_file('data/raw/t10k-labels-idx1-ubyte')
)
print("Saving test set")
with open('data/processed/test.pt', 'wb') as f:
    torch.save(test_set, f)


from collections.abc import Callable, Sequence
import functools
from typing import Any

from jax import jit
from jax import lax
from jax import numpy as jnp
from jaxonnxruntime.core import handler
from jaxonnxruntime.core import onnx_node

@handler.register_op("LRN")
class LRN(handler.Handler):
  """Implementation of the ONNX LRN operator."""

  @classmethod
  def _prepare(
      cls, node: onnx_node.OnnxNode, inputs: Sequence[Any], onnx_jax_impl: Any
  ):
    node.attrs_dict["alpha"] = node.attrs.get("alpha", float(0.0001))
    node.attrs_dict["beta"] = node.attrs.get("beta", float(0.75))
    node.attrs_dict["bias"] = node.attrs.get("bias", float(1.0))
    node.attrs_dict["size"] = int(node.attrs.get("size"))
    assert node.attrs_dict["size"] is not None

  @classmethod
  def version_1(
      cls, node: onnx_node.OnnxNode, inputs: Sequence[Any]
  ) -> Callable[..., Any]:
    """ONNX version_1 LRN op."""
    cls._prepare(node, inputs, onnx_lrn)
    return onnx_lrn

  @classmethod
  def version_13(
      cls, node: onnx_node.OnnxNode, inputs: Sequence[Any]
  ) -> Callable[..., Any]:
    """ONNX version_13 LRN op."""
    cls._prepare(node, inputs, onnx_lrn)
    return onnx_lrn

@functools.partial(jit, static_argnames=("alpha", "beta", "bias", "size"))
def onnx_lrn(*input_args, alpha, beta, bias, size):
  """https://github.com/onnx/onnx/blob/v1.12.0/docs/Operators.md#LRN for more details."""
  assert len(input_args) == 1
  x = input_args[0]
  shape = x.shape
  div = jnp.reshape(jnp.multiply(x, x), (shape[0], 1, shape[1], shape[2], -1))
  kernel_shape = (1, 1, size, 1, 1)
  strides = (1, 1, 1, 1, 1)
  pads = "SAME"
  div = (
      lax.reduce_window(
          div,
          jnp.array(0, dtype=div.dtype),
          lax.add,
          kernel_shape,
          strides,
          pads,
      )
      / size
  )
  div = jnp.reshape(div, shape)
  div = jnp.power(jnp.add(jnp.multiply(div, alpha), bias), beta)
  return jnp.true_divide(x, div)


from django.shortcuts import render,redirect
from django.http import JsonResponse
from ..message .models import Post
from ..users.models import User
from ..pokes.models import Poke
from ..friends.models import Friend
# Create your views here.

def homePage(req):

    if 'user_id' not in req.session:
        return redirect("users:registration")

    context={
        'posts':Post.objects.all().order_by("-created_at"),
        'friends':User.objects.filter(friended_from_user__friend_user=req.session['user_id']).filter(friend_user__friend_from=req.session['user_id']),
        'user':User.objects.get(id=req.session['user_id'])
    }
    return render(req,"dashboard/homePage.html",context)

def profile(req,user_id):

    poke_list = Poke.objects.filter(poke_user__id=user_id)
    friend_list=User.objects.filter(friended_from_user__friend_user=user_id).filter(friend_user__friend_from=user_id)
    Are_you_Friend=False
    waitingForConfirmation=True
    if int(user_id) != req.session['user_id']:

        # checking if they are friends and still waiting for confirmation.....
        try:
            Friend.objects.get(friend_from=req.session['user_id'], friend_user=user_id)
            waitingForConfirmation=True

            try:
                Friend.objects.get(friend_from=user_id,friend_user=req.session['user_id'])
                Are_you_Friend=True
            except:
                Are_you_Friend=False

        except:
            waitingForConfirmation=False
            print("Not friends")

    context={
        'user': User.objects.get(id=user_id),
        'friends':User.objects.filter(friended_from_user__friend_user=user_id).filter(friend_user__friend_from=user_id),
        'poke_list': poke_list,
        'poke_count': poke_list.count(),
        'totalFriend': friend_list.count(),
        'waitingForConfirmation':waitingForConfirmation,
        'Are_you_Friend':Are_you_Friend,
        'profile':True
    }
    return render(req,"dashboard/profilePage.html",context)

def find_friends(req):

    context={
        'friend_request':User.objects.filter(friended_from_user__friend_user=req.session['user_id']).exclude(friend_user__friend_from=req.session['user_id']),
        'potentialFriends':User.objects.exclude(friend_user__friend_from=req.session['user_id']).exclude(id=req.session['user_id']),
        'SearchFriend':True,
        'user': User.objects.get(id=req.session['user_id'])

    }

    return render(req, "dashboard/find_friends.html",context)

def searchUsers(req):
    users=User.objects.filter(first_name__startswith=req.POST['user_name'])

    context={
        'users':users,
        'SearchFriend':True
    }
    return render(req, "dashboard/ajaxFriendSearch.html",context)

# ----------->>>>>>>>>>>Ajax Behavior<<<<<<<<<<_---------

def searchFriends(req):
    friends=User.objects.filter(friended_from_user__friend_user=req.session['user_id']).filter(friend_user__friend_from=req.session['user_id']).filter(first_name__startswith=req.POST['keyword'])

    context={
        'users':friends,

    }
    return render(req, "dashboard/ajaxFriendSearch.html",context)

def searchPostByName(req):
    print(req.POST['keyword'])

    posts=Post.objects.filter(user__first_name__startswith=req.POST['keyword'])

    print("*"*60)
    print(posts)
    print("*"*60)

    context={
        'posts':posts
    }
    return render(req, "dashboard/ajaxPostSearch.html",context)

def FetchMyPost(request):
    print(request.GET['user_id'])

    context={
        'posts':Post.objects.filter(user=request.GET['user_id']).order_by("-created_at"),
        'profile_page':True
    }
    return render(request, "dashboard/ajaxPostSearch.html",context)


import optparse
import sys
from data_mangle.cv_fold_sparse_reader import CVFoldSparseReader
from data_mangle.cv_fold_lol_sparse_reader import CVFoldLoLSparseReader
from data_mangle.cv_fold_dense_reader import CVFoldDenseReader
from utils import constants

def parse_ml_parameters():
    if len(sys.argv) < 2:
        print('no argument set. use default.')
        return None

    parser = optparse.OptionParser(usage="usage: %prog [options]")
    # FM
    parser.add_option("--fm_order", dest="fm_order", type="int", default=0)
    parser.add_option("--fm_rank", dest="fm_rank", type="int", default=0)
    parser.add_option("--fm_epoch", dest="fm_epoch", type="int", default=0)
    parser.add_option("--fm_reg", dest="fm_reg", type="float", default=0.0)
    parser.add_option("--fm_featconfig", dest="fm_featconfig", type="string", default='')
    # NN
    parser.add_option("--nn_hidden", dest="nn_hidden", type="int", default=0)
    parser.add_option("--nn_featconfig", dest="nn_featconfig", type="string", default='')
    #GBDT
    parser.add_option("--gbdt_featconfig", dest="gbdt_featconfig", type="string", default='')
    parser.add_option("--gbdt_ntree", dest="gbdt_ntree", type="int", default=100)
    parser.add_option("--gbdt_lr", dest="gbdt_lr", type="float", default=0.1)
    parser.add_option("--gbdt_maxdepth", dest="gbdt_maxdepth", type="int", default=3)
    parser.add_option("--gbdt_minsampleleaf", dest="gbdt_minsampleleaf", type="int", default=1)
    # general
    parser.add_option("--density", dest='density', type='string', default='')
    parser.add_option("--dataset", dest='dataset', type='string', default='')
    parser.add_option("--fold", dest='fold', type='int', default=3)
    parser.add_option("--seed", dest='seed', type='int', default=718)
    (kwargs, args) = parser.parse_args()
    return kwargs

def parse_reader(dataset, feature_config, density, fold=10, seed=None):
    if dataset == 'lol':
        if density == 'sparse':
            reader = CVFoldLoLSparseReader(data_path=constants.lol_pickle, folds=fold,
                                           feature_config=feature_config, seed=seed)
        else:
            raise NotImplementedError
    elif dataset == 'lol2':
        if density == 'dense':
            reader = CVFoldDenseReader(data_path=constants.lol2_pickle, folds=fold,
                                       feature_config=feature_config, seed=seed)
    elif dataset == 'dota':
        if density == 'dense':
            reader = CVFoldDenseReader(data_path=constants.dota_pickle, folds=fold,
                                       feature_config=feature_config, seed=seed)
        elif density == 'sparse':
            reader = CVFoldSparseReader(data_path=constants.dota_pickle, folds=fold,
                                        feature_config=feature_config, seed=seed)
        else:
            raise NotImplementedError
    elif dataset == 'dota2':
        if density == 'dense':
            reader = CVFoldDenseReader(data_path=constants.dota2_pickle, folds=fold,
                                       feature_config=feature_config, seed=seed)
        elif density == 'sparse':
            reader = CVFoldSparseReader(data_path=constants.dota2_pickle, folds=fold,
                                        feature_config=feature_config, seed=seed)
        else:
            raise NotImplementedError
    elif dataset == 'dota3':
        if density == 'dense':
            reader = CVFoldDenseReader(data_path=constants.dota3_pickle, folds=fold,
                                       feature_config=feature_config, seed=seed)
        elif density == 'sparse':
            reader = CVFoldSparseReader(data_path=constants.dota3_pickle, folds=fold,
                                        feature_config=feature_config, seed=seed)
        else:
            raise NotImplementedError
    else:
        raise NotImplementedError
    return reader

def parse_mcts_exp_parameters():
    if len(sys.argv) < 2:
        print('no argument set. use default.')
        return None

    parser = optparse.OptionParser(usage="usage: %prog [options]")

    parser.add_option("--num_matches", dest="num_matches", type="int", default=0)
    parser.add_option("--p0", dest="p0", type="string", default='')
    parser.add_option("--p1", dest="p1", type="string", default='')
    parser.add_option("--env_path", dest="env_path", type="string", default='')
    (kwargs, args) = parser.parse_args()
    return kwargs

def parse_mcts_maxiter_c(player_str):
    assert player_str.startswith('mcts')
    _, maxiter, c = player_str.split('_')
    return int(maxiter), float(c)

def parse_rave_maxiter_c_k(player_str):
    assert player_str.startswith('rave')
    _, maxiter, c, k = player_str.split('_')
    return int(maxiter), float(c), float(k)


import cv2
import numpy as np
import glob
from imutils.video import VideoStream
from imutils.video import FPS
import argparse
import imutils
import time
def select_roi(event, x, y, flags, param):
    global refPt, cropping
    if event == cv2.EVENT_LBUTTONDOWN:
        refPt = [(x, y)]
        cropping = True
    elif event == cv2.EVENT_LBUTTONUP:
        refPt.append((x, y))
        cropping = False
        cv2.rectangle(image, refPt[0], refPt[1], (0, 255, 0), 2)
        cv2.imshow("image", image)

refPt = []
cropping = False

image_files = sorted(glob.glob('/home/t1rant/Downloads/DriftCar1/img/*.jpg'))
start_time = time.time()
image = cv2.imread(image_files[0], cv2.IMREAD_COLOR)
clone = image.copy()
cv2.namedWindow("image")
cv2.setMouseCallback("image", select_roi)

while True:
    cv2.imshow("image", image)
    key = cv2.waitKey(1) & 0xFF
    if key == ord("r"):
        image = clone.copy()
    elif key == ord("c"):
        break

cv2.destroyAllWindows()

roi = (refPt[0][0], refPt[0][1], refPt[1][0]-refPt[0][0], refPt[1][1]-refPt[0][1])  # x, y, w, h

hsv_roi = cv2.cvtColor(clone[roi[1]:roi[1]+roi[3], roi[0]:roi[0]+roi[2]], cv2.COLOR_BGR2HSV)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# for every other image
for idx, image_file in enumerate(image_files[1:]):
    frame = cv2.imread(image_file, cv2.IMREAD_COLOR)
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(dst)

    roi_center = maxLoc

    print(f'Frame {idx}: ROI Center (x, y) = {roi_center}')

    cv2.drawMarker(frame, roi_center, (0, 255, 0), markerType=cv2.MARKER_CROSS, markerSize=20)
    cv2.imshow('Manual Tracking', frame)

    if cv2.waitKey(1) & 0xFF == 27:  # Press 'Esc' key to exit
        break
# End timestamp
end_time = time.time()

# Calculate execution time
execution_time = end_time - start_time
print("Execution time: {:.2f} seconds".format(execution_time))
cv2.destroyAllWindows()


from django.db import models
from django.contrib.sites.models import Site

class ProviderManager(models.Manager):

    def get_queryset(self):
        return super(models.Manager, self).get_queryset().select_related(
            'site',
            'site__siteprofile',
        )

    def public(self):
        return self.filter(is_public=True, )

class Provider(models.Model):

    site = models.ForeignKey(
        Site,
    )

    name = models.CharField(
        max_length=16,
        unique=True,
    )

    feed_url = models.URLField(
        blank=True,
        null=True,
        unique=True,
    )

    is_public = models.BooleanField(
        default=True,
    )

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = ProviderManager()

    class Meta:
        ordering = ['name', ]

    def __str__(self):
        return self.name

    def update_tidbits(self):
        """Add/Update provider tidbits from a RSS/Atom feed."""
        import feedparser

        feed_result = feedparser.parse(self.feed_url)

        for item in feed_result.entries:

            tidbit, created = self.tidbit_set.get_or_create(
                original_url=item.id,
            )

            if created:
                tidbit.title = item.title
                tidbit.author = item.author
                tidbit.content = item.description
                tidbit.save()


import sys
import math
import time
from collections import defaultdict

class grid():
    def __init__(self, la_map):
        self.grille = la_map

    def show(self):
        for each_line in self.grille:
            print(each_line, file=sys.stderr)

    def update_map(self, pos1, pos2, dist):
        for y in range(h):
            for x in range(w):
                if self.grille[y][x] == 0:
                    if (x,y) in memo_dist.keys():
                        dist1 = memo_dist[(x,y)]
                    else:
                        dist1 = math.sqrt((pos1[0]-x)**2+(pos1[1]-y)**2) #distance from previous point
                    dist2 = math.sqrt((pos2[0]-x)**2+(pos2[1]-y)**2) #distance from latest position
                    memo_dist[(x,y)]=dist2
                    if dist == "COLDER" and dist1 > dist2: #si on s'eloigne et que la distance d'origine est plus grande que la nouvelle
                        self.grille[y][x]=1
                        del memo_dist[(x,y)]
                    elif dist == "WARMER" and dist2 > dist1:
                        self.grille[y][x]=1
                        del memo_dist[(x,y)]
                    elif dist == "SAME" and dist1 != dist2:
                        self.grille[y][x]=1
                        del memo_dist[(x,y)]

class aDallas():
    def __init__(self, X0, Y0):
        self.position = (X0, Y0)
        self.previous_position = (-1,-1)
        self.distance = "UNKNOWN"

    def move(self, new_x, new_y):
        global tower
        tower.grille[new_y][new_x] = 1
        self.previous_position = self.position
        self.position = (new_x, new_y)
        print(str(new_x), str(new_y))

    def update_sensor(self, result):
        self.distance = result

    def first_move(self):
        self.move((w-1)-self.position[0], (h-1)-self.position[1])

    def next_move(self, carte):
        max_dist = 0
        position = (0,0)
        for y in range(h):
            for x in range(w):
                if carte[y][x]==0:
                    dist = memo_dist[(x,y)]
                    if dist > max_dist:
                        max_dist = dist
                        position = (x,y)
        self.move(position[0], position[1])

memo_dist = defaultdict(list)
# w: width of the building.
# h: height of the building.
w, h = [int(i) for i in input().split()]
carte = [[0 for x in range(w)] for x in range(h)]
tower = grid(carte)
#tower.show()

n = int(input())  # maximum number of turns before game over.
x0, y0 = [int(i) for i in input().split()]
batman = aDallas(x0, y0)
start_time_global = time.time()
# game loop
while True:
    bomb_dir = input()  # Current distance to the bomb compared to previous distance (COLDER, WARMER, SAME or UNKNOWN)
    if bomb_dir == "UNKNOWN":
        batman.first_move()
    else:
        print(bomb_dir, file=sys.stderr)
        start_time_round = time.time()
        batman.update_sensor(bomb_dir)
        tower.update_map(batman.previous_position, batman.position, batman.distance)
        #tower.show()
        batman.next_move(tower.grille)
        interval = time.time() - start_time_round
        print("Round time : ", interval, file=sys.stderr)
        interval_global = time.time() - start_time_global
        print("Total time : ", interval_global, file=sys.stderr)

    # Write an action using print
    # To debug: print("Debug messages...", file=sys.stderr)

CG/training/very hard/trilateration v2 62%.py


from __future__ import print_function
import numpy as np
import argparse
import torch
import torch.optim as optim
from torch.autograd import Variable
from sklearn.metrics import precision_score,f1_score
from EvoMIL.Models.model import Attention,GatedAttention
import pandas as pd
from evaluation import aucscore,get_confusion,results2CSV_test

# test settings
parser = argparse.ArgumentParser(description='PyTorch PreTLM-MIL')
parser.add_argument('--epochs', type=int, default=150, metavar='N',
                    help='number of epochs to train (default: 20)')
parser.add_argument('--lr', type=float, default=0.0005, metavar='LR',
                    help='learning rate (default: 0.0005)')
parser.add_argument('--reg', type=float, default=10e-5, metavar='R',
                    help='weight decay')
parser.add_argument('--seed', type=int, default=1, metavar='S',
                    help='random seed (default: 1)')
parser.add_argument('--no-cuda', action='store_true', default=False,
                    help='disables CUDA training')
parser.add_argument('--model', type=str, default='attention', help='Choose b/w attention and gated_attention')

"""
We make changes on Attention_based MIL (Copyright © 2018 ilse.maximilian@gmail.com.) to test viral protein embeddings.
"""
args = parser.parse_args()
args.cuda = not args.no_cuda and torch.cuda.is_available()

torch.manual_seed(args.seed)
if args.cuda:
    torch.cuda.manual_seed(args.seed)
    print('\n GPU is ON!')

print('Load Train and Test Set')
loader_kwargs = {'num_workers': 1, 'pin_memory': True} if args.cuda else {}

print('Init Model')
if args.model=='attention':
    model = Attention()
elif args.model=='gated_attention':
    model = GatedAttention()
if args.cuda:
    model.cuda()

optimizer = optim.Adam(model.parameters(), lr=args.lr, betas=(0.9, 0.999), weight_decay=args.reg)

if __name__ == "__main__":
    # Eukaryota/Prokaryote
    output='../Results/euk_binary/'
    input_data_path="../Data/examples/euk_5fold_cv/"
    # virus_pos_neg_path= input+'virus_'
    virus_host = pd.read_csv(input_data_path+'hostname_count.csv')
    length=virus_host.shape[0]
    for m in [4]:
        hostname=virus_host.iloc[m,0]
        test_loader=torch.load(input_data_path + hostname + '_test_loader')
        for j in range(5):
                model.load_state_dict(torch.load(output + hostname+'_model.'+str(j+1)))
                with torch.no_grad():
                    test_loss=0.
                    test_error=0.
                    test_acc=0.
                    #start validation
                    instance_label_list=[]
                    label_list=[]
                    predicted_label_list=[]
                    pred=[]
                    Y_hats=[]
                    for batch_idx, (dataset,ids,label) in enumerate(test_loader):
                            bag_label = label.gt(0)
                            label_list.append(bag_label.squeeze(0).tolist())
                            data = dataset.unsqueeze(0)
                            data = dataset.view(ids.shape[1], dataset.shape[1])

                            if args.cuda:
                                data, bag_label = data.cuda(), bag_label.cuda()
                            data, bag_label = Variable(data), Variable(bag_label)
                            temp=ids
                            if(label==1):
                                for i in range(len(temp[0,])):
                                    temp[0,i]=1
                            else:
                                for i in range(len(temp[0,])):
                                    temp[0,i]=-1
                            instance_labels = temp.gt(0)
                            loss,acc,attention_weights,Y_prob,Y_hat = model.calculate_objective(data, bag_label)
                            error, predicted_label = model.calculate_classification_error(data, bag_label)
                            test_loss += loss.data[0]
                            test_acc += acc
                            # test_error += error
                            Y_prob_value=Y_prob.cpu().squeeze(0).squeeze(0).tolist()
                            pred.append(Y_prob_value)
                            instance_label_list.append(instance_labels)
                            Y_hats.append(Y_hat.item())
                            predicted_label_list.append(int(predicted_label.cpu().data.numpy()[0][0]))

                test_loss /= len(test_loader)
                test_acc /= len(test_loader)
                # test_error /= len(test_loader)
                test_loss=test_loss.cpu().numpy()[0]
                label_list=torch.tensor(label_list).detach()
                label_list_int=np.array(label_list, dtype='int').tolist()
                Y_hats_int=list(map(int,Y_hats))
                acc,spec,sens = get_confusion(torch.tensor(predicted_label_list), torch.tensor(label_list))
                # calculating precision and reall
                f1= f1_score(label_list_int,Y_hats_int)
                prec = precision_score(label_list_int, Y_hats_int)
                # recall = recall_score(label_list_int, pred)
                auc_score= aucscore(pred, label_list_int)

                csvfile=output+'virus_testset_5fold_cross_validation_epoch150_10.csv'
                results= {'Hostname': hostname,'AUC':str(round(np.array(auc_score).mean(),4)),'Accuracy':round(np.array(acc).mean(),4),'f1':round(np.array(f1).mean(),4),'spec':round(np.array(spec).mean(),4), 'sens':round(np.array(sens).mean(),4),'prec':round(np.array(prec).mean(),4)}
                results2CSV_test(results, hostname,csvfile)


# coding: utf-8
"""
a proof of concept implementation of SQLite FTS tokenizers in Python
"""
import sys

from cffi import FFI  # type: ignore

SQLITE_OK = 0
SQLITE_DONE = 101

ffi = FFI()

if sys.platform == "win32":
    import sqlite3  # noqa

    dll = ffi.dlopen("sqlite3.dll")
else:
    from ctypes.util import find_library

    try:
        # try to use _sqlite3.so first
        import _sqlite3  # noqa

        dll = ffi.dlopen(_sqlite3.__file__)
    except:
        dll = ffi.dlopen(find_library("sqlite3"))

if hasattr(sys, "getobjects"):
    # for a python built with Py_TRACE_REFS
    ffi.cdef(
        """
typedef struct sqlite3 sqlite3;
typedef struct {
  void *_ob_next;
  void *_ob_prev;
  size_t ob_refcnt;
  void *ob_type;
  sqlite3 *db;
} PyObject;
"""
    )
else:
    ffi.cdef(
        """
typedef struct sqlite3 sqlite3;
typedef struct {
  size_t ob_refcnt;
  void *ob_type;
  sqlite3 *db;
} PyObject;
"""
    )

def get_db_from_connection(c):
    db = getattr(c, "_db", None)
    if db:
        # pypy's SQLite3 connection has _db using cffi
        db = ffi.cast("sqlite3*", db)
    else:
        db = ffi.cast("PyObject *", id(c)).db
    return db

__all__ = ["get_db_from_connection", "SQLITE_OK", "SQLITE_DONE"]


# -*- coding: utf-8 -*-

import sys
import argparse

from maestral.daemon import freeze_support as freeze_support_daemon

def main():
    """
    This is the main entry point. It starts the GUI with the given config.
    """

    from .app import run

    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--config-name", default="maestral")
    parsed_args, _ = parser.parse_known_args()

    run(parsed_args.config_name)

def freeze_support_cli():
    """
    Provides support to start the CLI from a frozen executable.
    """

    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("--cli", action="store_true")
    parsed_args, remaining = parser.parse_known_args()

    if parsed_args.cli:
        from maestral.cli import main

        sys.argv = ["maestral"] + remaining
        main(prog_name="maestral")
        sys.exit()

if __name__ == "__main__":
    freeze_support_cli()
    freeze_support_daemon()
    main()


import os
import json
from .shell_agent import ShellAgent
from .sysadmin_agent import SysAdminAgent
from .utils import SpecialAction
from .cat_agent import CatAgent
import openai
import sys

openai.api_key = os.getenv("OPENAI_API_KEY")

CONTEXT_LENGTH = 50

class Game:
    def __init__(self):
        self.history = []
        self.agent_stack = []
        self.nextAgent = None

    def pushToNextAgent(self, agent):
        self.history = []
        self.agent_stack.append(agent)
        self.nextAgent = agent

    def popToNextAgent(self):
        if len(self.agent_stack) == 0:
            raise Exception("Cannot pop agent from empty stack")
        self.agent_stack.pop()
        self.nextAgent = self.agent_stack[len(self.agent_stack) - 1]

    def applyNextAgent(self):
        if self.nextAgent is None:
            raise Exception("Cannot apply next agent when next agent is None")
        self.history = []
        self.agent = self.nextAgent
        self.nextAgent = None

    def handleInput(self, line):
        self.history.append({ "role": "user", "content": line })

        userMessages = self.history[-CONTEXT_LENGTH:]

        override = self.agent.overrideCompletion(line)

        if override is not None:
            res = override

            special = override.get("special")

            if special is SpecialAction.TURN_INTO_CAT:
                self.pushToNextAgent(CatAgent())
            if special is SpecialAction.POP:
                self.popToNextAgent()

        else:
            completion = openai.ChatCompletion.create(
                model="gpt-3.5-turbo-0613",
                messages=[
                    {"role": "system", "content": self.agent.systemPrompt},
                ]
                + userMessages,
                functions=[{"name": "fn", "parameters": self.agent.schema}],
                function_call={"name": "fn"},
                temperature=0.7,
            )
            res = json.loads(completion.choices[0].message.function_call.arguments)  # type: ignore

            self.agent.handleGptOutput(res)

            self.history.append({ "role": "assistant", "content": self.agent.completion_to_history(res) })

            print(json.dumps(self.history), file=sys.stderr)

            if isinstance(self.agent, SysAdminAgent) and res.get("shell") == "true":
                self.pushToNextAgent(ShellAgent())

        response = self.agent.print(res)

        if self.nextAgent:
            self.applyNextAgent()

        return {"response": response, "prompt": self.agent.prompt()}

    def run(self):
        while True:
            print(self.agent.prompt(), end="")

            line = input().strip()
            self.history.append(line)

            userMessages = list(
                map(
                    lambda l: {"role": "user", "content": l},
                    self.history[-CONTEXT_LENGTH:],
                )
            )

            override = self.agent.overrideCompletion(line)

            if override is not None:
                res = override

                special = override.get("special")

                if special is SpecialAction.TURN_INTO_CAT:
                    self.pushToNextAgent(CatAgent())
                if special is SpecialAction.POP:
                    self.popToNextAgent()

            else:
                completion = openai.ChatCompletion.create(
                    model="gpt-4-0613",
                    messages=[
                        {"role": "system", "content": self.agent.systemPrompt},
                    ]
                    + userMessages,
                    functions=[{"name": "fn", "parameters": self.agent.schema}],
                    function_call={"name": "fn"},
                    temperature=0.7,
                )
                res = json.loads(completion.choices[0].message.function_call.arguments)  # type: ignore

                self.agent.handleGptOutput(res)

                if isinstance(self.agent, SysAdminAgent) and res.get("shell") == "true":
                    self.pushToNextAgent(ShellAgent())

            print(self.agent.print(res), end="")

            if self.nextAgent:
                self.applyNextAgent()


# cuda env instead of taichi env provide the api similar to taichi env and mpm simulators.
import os
import yaml
from tools import CN, Configurable, merge_inputs
# from plb import load
from .simulator import MPMSimulator
from .renderer import Renderer

FILEPATH = os.path.dirname(os.path.abspath(__file__))

class CudaEnv(Configurable):
    def __init__(
        self,
        cfg:CN=None,
        cfg_path='configs/plb_cuda.yml',
        SIMULATOR=None,
        PRIMITIVES:CN=None,
        RENDERER:CN=Renderer.get_default_config(),
        SHAPES=None,
    ):
        super().__init__()
        # if PRIMITIVES is None or len(PRIMITIVES) == 0:
        #     PRIMITIVES = load(os.path.join(FILEPATH, cfg_path)).PRIMITIVES
        n_bodies, kwargs = self.parse_tools(PRIMITIVES)
        self.simulator = MPMSimulator(n_bodies, cfg=SIMULATOR)
        self.simulator.init_bodies(**kwargs)
        self.renderer = Renderer(cfg=RENDERER)
        import numpy as np
        self.particle_colors = np.zeros(self.simulator.n_particles) + (((((255)<<8)+255)<<8)+255)
        self.simulator.states[0].x.upload(np.random.random(size=(self.simulator.n_particles, 3)) * 0.2 + np.array((0.4, 0.1, 0.4)))

    def default_tool_config(self):
        cfg = CN()
        cfg.shape = ''
        cfg.init_pos = (0.3, 0.3, 0.3)  # default color
        cfg.init_rot = (1., 0., 0., 0.)  # default color
        cfg.color = (0.3, 0.3, 0.3)  # default color
        cfg.lower_bound = (0., 0., 0.)  # default color
        cfg.upper_bound = (1., 1., 1.)  # default color
        cfg.friction = 0.9  # default color
        cfg.variations = None  # TODO: not support now
        cfg.mass = 1.
        cfg.stiffness = 0.

        action = cfg.action = CN()
        action.dim = 0  # in this case it can't move ...
        action.scale = ()
        return cfg

    def parse_tools(self, cfgs):
        tools = []

        for i in cfgs:
            if isinstance(i, CN):
                cfg = i
            else:
                cfg = CN(new_allowed=True)
                cfg = cfg._load_cfg_from_yaml_str(yaml.safe_dump(i))

            cfg = merge_inputs(self.default_tool_config(), **cfg)
            tools.append(cfg)

        self.action_dims = [0]
        outs = []

        types = []
        softness = []
        pos = []
        rot = []
        mu = []
        round = []
        args = []
        action_scales = []

        for i in tools:
            #primitive = eval(i.shape)(cfg=i, dim=dim, max_timesteps=max_timesteps, dtype=dtype)
            #self.primitives.append(primitive)
            #self.action_dims.append(self.action_dims[-1] + primitive.action_dim)
            if i['shape'] == 'Box':
                types.append(0)
                args.append([*i['size'], 0])
            elif i['shape'] == 'Capsule':
                types.append(1)
                args.append([*i['size'], 0, 0])

            action_scales.append(i['action']['scale'])
            softness.append(666.)
            mu.append(i['friction'])
            round.append(i['round'])
            pos.append(i.init_pos)
            rot.append(i.init_rot)

        return len(tools), {
            'types': types,
            'softness': softness,
            'mu': mu,
            'round': round,
            'args': args,
            'action_scales': action_scales,
            'pos': pos,
            'rot': rot
        }


import tempfile

import h5py
import imageio

def create_video_file(suffix=".mp4", byte_contents=None):
    # Create Temporary File #
    temp_file = tempfile.NamedTemporaryFile(suffix=suffix)
    filename = temp_file.name

    # If Byte Contents Provided, Write To File #
    if byte_contents is not None:
        with open(filename, "wb") as binary_file:
            binary_file.write(byte_contents)

    return filename

def get_hdf5_length(hdf5_file, keys_to_ignore=[]):
    length = None

    for key in hdf5_file.keys():
        if key in keys_to_ignore:
            continue

        curr_data = hdf5_file[key]
        if isinstance(curr_data, h5py.Group):
            curr_length = get_hdf5_length(curr_data, keys_to_ignore=keys_to_ignore)
        elif isinstance(curr_data, h5py.Dataset):
            curr_length = len(curr_data)
        else:
            raise ValueError

        if length is None:
            length = curr_length
        assert curr_length == length

    return length

def load_hdf5_to_dict(hdf5_file, index, keys_to_ignore=[]):
    data_dict = {}

    for key in hdf5_file.keys():
        if key in keys_to_ignore:
            continue

        curr_data = hdf5_file[key]
        if isinstance(curr_data, h5py.Group):
            data_dict[key] = load_hdf5_to_dict(curr_data, index, keys_to_ignore=keys_to_ignore)
        elif isinstance(curr_data, h5py.Dataset):
            data_dict[key] = curr_data[index]
        else:
            raise ValueError

    return data_dict

class TrajectoryReader:
    def __init__(self, filepath, read_images=True):
        self._hdf5_file = h5py.File(filepath, "r")
        is_video_folder = "observations/videos" in self._hdf5_file
        self._read_images = read_images and is_video_folder
        self._length = get_hdf5_length(self._hdf5_file)
        self._video_readers = {}
        self._index = 0

    def length(self):
        return self._length

    def read_timestep(self, index=None, keys_to_ignore=[]):
        # Make Sure We Read Within Range #
        if index is None:
            index = self._index
        else:
            assert not self._read_images
            self._index = index
        assert index < self._length

        # Load Low Dimensional Data #
        keys_to_ignore = [*keys_to_ignore.copy(), "videos"]
        timestep = load_hdf5_to_dict(self._hdf5_file, self._index, keys_to_ignore=keys_to_ignore)

        # Load High Dimensional Data #
        if self._read_images:
            camera_obs = self._uncompress_images()
            timestep["observations"]["image"] = camera_obs

        # Increment Read Index #
        self._index += 1

        # Return Timestep #
        return timestep

    def _uncompress_images(self):
        # WARNING: THIS FUNCTION HAS NOT BEEN TESTED. UNDEFINED BEHAVIOR FOR FAILED READING. #
        video_folder = self._hdf5_file["observations/videos"]
        camera_obs = {}

        for video_id in video_folder:
            # Create Video Reader If One Hasn't Been Made #
            if video_id not in self._video_readers:
                serialized_video = video_folder[video_id]
                filename = create_video_file(byte_contents=serialized_video)
                self._video_readers[video_id] = imageio.get_reader(filename)

            # Read Next Frame #
            camera_obs[video_id] = yield self._video_readers[video_id]
            # Future Note: Could Make Thread For Each Image Reader

        # Return Camera Observation #
        return camera_obs

    def close(self):
        self._hdf5_file.close()


from collections import Counter
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        start = 0
        end = 0
        count = Counter()
        max_length = 0
        while start < len(s):
            if end < len(s) and count[s[end]] == 0 and ((len(count) == 0) or (len(count) > 0 and count.most_common()[0][1] <= 1)):
                count.update(s[end])
                end += 1
                if (end -start) > max_length:
                    max_length = end - start
            else:
                count.subtract(s[start])
                start += 1
            #print(start, end, count)
        return max_length


"""Trains model and exposes predictor class objects"""

import logging
import operator
import pickle

from hyperopt import fmin, hp, tpe, Trials
from joblib import dump, load
import matplotlib.pyplot as plt
from melo import Melo
import numpy as np
import pandas as pd

from .data import load_games
from . import cachedir

class MeloCFB(Melo):
    """
    Generate college football point-spread or point-total predictions
    using the Margin-dependent Elo (MELO) model.

    """
    def __init__(self, mode, kfactor, home_field, halflife, fatigue):

        # hyperparameters
        self.mode = mode
        self.kfactor = kfactor
        self.home_field = home_field
        self.halflife = halflife
        self.fatigue = fatigue

        # model operation mode: 'spread' or 'total'
        if self.mode not in ['spread', 'total']:
            raise ValueError(
                "Unknown mode; valid options are 'spread' and 'total'")

        # mode-specific training hyperparameters
        self.commutes, self.compare, self.lines = {
            'total': (True, operator.add, np.arange(-0.5, 146.5)),
            'spread': (False, operator.sub, np.arange(-85.5, 86.5)),
        }[mode]

        # connect to college football stats database
        games_ = load_games(refresh=False)
        self.games = self.format_gamedata(games_)

        # instantiate the Melo base class
        super(MeloCFB, self).__init__(
            self.kfactor, lines=self.lines, sigma=1.0,
            regress=self.regress, regress_unit='year',
            commutes=self.commutes)

        # calibrate the model using the game data
        self.fit(
            self.games.date,
            self.games.team_home,
            self.games.team_away,
            self.compare(
                self.games.score_home,
                self.games.score_away,
            ),
            self.games.home_bias
        )

        # compute mean absolute error for calibration
        burnin = 2183
        residuals = self.residuals()
        self.loss = np.abs(residuals[burnin:]).mean()

    def format_gamedata(self, games):
        """
        Generator that yields a tuple of attributes for each game.

        """
        # sort games by date
        games.date = pd.to_datetime(games.date)
        games.sort_values('date', inplace=True)

        # game dates for every team
        game_dates = pd.concat([
            games[['date', 'team_home']].rename(
                columns={'team_home': 'team'}
            ),
            games[['date', 'team_away']].rename(
                columns={'team_away': 'team'}
            ),
        ]).sort_values('date')

        # calculate rest days
        for team in ['home', 'away']:
            games_prev = game_dates.rename(
                columns={'team': 'team_{}'.format(team)}
            )
            games_prev['date_{}_prev'.format(team)] = games.date

            games = pd.merge_asof(
                games, games_prev,
                on='date', by='team_{}'.format(team),
                allow_exact_matches=False
            )

        # add rest days columns
        rested = pd.Timedelta('255 days')
        games['home_rest'] = (games.date - games.date_home_prev).fillna(rested)
        games['away_rest'] = (games.date - games.date_away_prev).fillna(rested)

        # add bias factors
        home_fatigue = self.fatigue * np.exp(-games.home_rest.dt.days / 7.)
        away_fatigue = self.fatigue * np.exp(-games.away_rest.dt.days / 7.)
        relative_fatigue = self.compare(home_fatigue, away_fatigue)
        games['home_bias'] = self.home_field - relative_fatigue

        # drop unwanted columns
        games.drop(columns=['date_home_prev', 'date_away_prev'], inplace=True)

        return games

    def regress(self, years):
        """
        Regresses future ratings to the mean.

        """
        with np.errstate(divide='ignore'):
            return 1 - .5**np.divide(years, self.halflife)

    def bias(self, home_rest_days, away_rest_days):
        """
        Computes circumstantial bias factor given each team's rest.
        Accounts for home field advantage and rest.

        """
        home_fatigue = self.fatigue * np.exp(-home_rest_days / 7.)
        away_fatigue = self.fatigue * np.exp(-away_rest_days / 7.)

        return self.home_field - self.compare(home_fatigue, away_fatigue)

    def probability(self, times, labels1, labels2, bias=None, lines=0):
        """
        Survival function probability distribution

        """
        bias = self.home_field if bias is None else bias
        return super(MeloCFB, self).probability(
            times, labels1, labels2, bias=bias, lines=lines
        )

    def percentile(self, times, labels1, labels2, bias=None, p=50):
        """
        Distribution percentiles

        """
        bias = self.home_field if bias is None else bias
        return super(MeloCFB, self).percentile(
            times, labels1, labels2, bias=bias, p=p
        )

    def quantile(self, times, labels1, labels2, bias=None, q=.5):
        """
        Distribution quantiles

        """
        bias = self.home_field if bias is None else bias
        return super(MeloCFB, self).quantile(
            times, labels1, labels2, bias=bias, q=q
        )

    def mean(self, times, labels1, labels2, bias=None):
        """
        Distribution mean

        """
        bias = self.home_field if bias is None else bias
        return super(MeloCFB, self).mean(
            times, labels1, labels2, bias=bias
        )

    def median(self, times, labels1, labels2, bias=None):
        """
        Distribution median

        """
        bias = self.home_field if bias is None else bias
        return super(MeloCFB, self).median(
            times, labels1, labels2, bias=bias
        )

    def sample(self, times, labels1, labels2, bias=None, size=100):
        """
        Sample the distribution

        """
        bias = self.home_field if bias is None else bias
        return super(MeloCFB, self).sample(
            times, labels1, labels2, bias=bias, size=size
        )

    @classmethod
    def from_cache(cls, mode, steps=200, retrain=False):
        """
        Optimizes the MeloCFB model hyper parameters. Returns cached values
        if retrain is False and the parameters are cached, otherwise it
        optimizes the parameters and saves them to the cache.

        """
        cachefile = cachedir / '{}.pkl'.format(mode)

        if not retrain and cachefile.exists():
            logging.debug('loading {} model from cache', mode)
            model = load(cachefile)
            return model

        def objective(params):
            return cls(mode, *params).loss

        space = (
            hp.uniform('kfactor', 0.0, 1.0),
            hp.uniform('home_field', 0.0, 0.5),
            hp.uniform('halflife', 0.0, 40.0),
            hp.uniform('fatigue', 0.0, 1.0),
        )

        trials = Trials()

        logging.info(f'optimizing {mode} hyperparameters')

        parameters = fmin(objective, space, algo=tpe.suggest,
                          max_evals=steps, trials=trials,
                          show_progressbar=False)

        plotdir = cachedir / 'plots'
        plotdir.mkdir(exist_ok=True)

        fig, axes = plt.subplots(
            ncols=4, figsize=(12, 3), sharey=True)

        losses = trials.losses()

        for ax, (label, vals) in zip(axes.flat, trials.vals.items()):
            c = plt.cm.coolwarm(np.linspace(0, 1, len(vals)))
            ax.scatter(vals, losses, c=c)
            ax.axvline(parameters[label], color='k')
            ax.set_xlabel(label)
            if ax.is_first_col():
                ax.set_ylabel('Mean absolute error')

        plotfile = plotdir / '{}_params.pdf'.format(mode)
        plt.tight_layout()
        plt.savefig(str(plotfile))

        model = cls(mode, **parameters)

        logging.info('writing cache file %s', cachefile)

        cachefile.parent.mkdir(exist_ok=True)
        dump(model, cachefile, protocol=pickle.HIGHEST_PROTOCOL)

        return model


import torch
from torch import nn
import torch.nn.functional as F
from torch.nn import Linear, LayerNorm, ReLU

from torch_scatter import scatter
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import add_self_loops, degree, softmax
from torch_geometric.nn import global_add_pool, global_mean_pool, global_max_pool

from auglichem.utils import NUM_ATOM_TYPE, NUM_CHIRALITY_TAG, NUM_BOND_TYPE, NUM_BOND_DIRECTION

class GINEConv(MessagePassing):
    def __init__(self, emb_dim, aggr="add"):
        super(GINEConv, self).__init__()
        self.mlp = nn.Sequential(
            nn.Linear(emb_dim, 2*emb_dim),
            nn.ReLU(),
            nn.Linear(2*emb_dim, emb_dim))
        self.edge_embedding1 = nn.Embedding(NUM_BOND_TYPE, emb_dim)
        self.edge_embedding2 = nn.Embedding(NUM_BOND_DIRECTION, emb_dim)

        nn.init.xavier_uniform_(self.edge_embedding1.weight.data)
        nn.init.xavier_uniform_(self.edge_embedding2.weight.data)
        self.aggr = aggr

    def forward(self, x, edge_index, edge_attr):
        # add self loops in the edge space
        edge_index = add_self_loops(edge_index, num_nodes=x.size(0))[0]
        # print(edge_index)

        # add features corresponding to self-loop edges.
        self_loop_attr = torch.zeros(x.size(0), 2)
        self_loop_attr[:,0] = 4 #bond type for self-loop edge
        self_loop_attr = self_loop_attr.to(edge_attr.device).to(edge_attr.dtype)
        edge_attr = torch.cat((edge_attr, self_loop_attr), dim=0)

        edge_embeddings = self.edge_embedding1(edge_attr[:,0]) + self.edge_embedding2(edge_attr[:,1])

        # return self.propagate(self.aggr, edge_index, x=x, edge_attr=edge_embeddings)
        return self.propagate(edge_index, x=x, edge_attr=edge_embeddings)

    def message(self, x_j, edge_attr):
        return x_j + edge_attr

    def update(self, aggr_out):
        return self.mlp(aggr_out)

class GINE(nn.Module):
    def __init__(self,
                 task='classification',
                 emb_dim=300,
                 feat_dim=256,
                 num_layer=5,
                 pool='mean',
                 drop_ratio=.0,
                 output_dim=None,
                 **kwargs):

        super(GINE, self).__init__()
        self.num_layer = num_layer
        self.emb_dim = emb_dim
        self.feat_dim = feat_dim
        self.drop_ratio = drop_ratio
        self.task = task
        if(output_dim == None):
            self.output_dim = 1
        else:
            self.output_dim = output_dim

        if self.num_layer < 2:
            raise ValueError("Number of GNN layers must be greater than 1.")

        self.x_embedding1 = nn.Embedding(NUM_ATOM_TYPE + 1, emb_dim)
        self.x_embedding2 = nn.Embedding(NUM_CHIRALITY_TAG, emb_dim)

        nn.init.xavier_uniform_(self.x_embedding1.weight.data)
        nn.init.xavier_uniform_(self.x_embedding2.weight.data)

        # List of MLPs
        self.gnns = nn.ModuleList()
        for layer in range(num_layer):
            self.gnns.append(GINEConv(emb_dim, aggr="add"))

        # List of batchnorms
        self.batch_norms = nn.ModuleList()
        for layer in range(num_layer):
            self.batch_norms.append(nn.BatchNorm1d(emb_dim))

        if pool == 'mean':
            self.pool = global_mean_pool
        elif pool == 'add':
            self.pool = global_add_pool
        elif pool == 'max':
            self.pool = global_max_pool
        else:
            raise ValueError('Not defined pooling!')

        self.feat_lin = nn.Linear(self.emb_dim, self.feat_dim)

        if self.task == 'classification':
            self.output_dim *= 2
            self.pred_lin = nn.Sequential(
                nn.Linear(self.feat_dim, self.feat_dim//2),
                nn.ReLU(inplace=True),
                nn.Linear(self.feat_dim//2, self.output_dim)
            )
        elif self.task == 'regression':
            self.pred_lin = nn.Sequential(
                nn.Linear(self.feat_dim, self.feat_dim//2),
                nn.ReLU(inplace=True),
                nn.Linear(self.feat_dim//2, self.feat_dim//2),
                nn.ReLU(inplace=True),
                nn.Linear(self.feat_dim//2, self.feat_dim//4),
                nn.ReLU(inplace=True),
                nn.Linear(self.feat_dim//4, self.output_dim)
            )

    def forward(self, data):
        x = data.x
        edge_index = data.edge_index
        edge_attr = data.edge_attr

        h = self.x_embedding1(x[:,0]) + self.x_embedding2(x[:,1])

        for layer in range(self.num_layer):
            h = self.gnns[layer](h, edge_index, edge_attr)
            h = self.batch_norms[layer](h)

            h = F.dropout(F.relu(h), self.drop_ratio, training=self.training)

        h = self.feat_lin(h)
        h = self.pool(h, data.batch)

        return h, self.pred_lin(h)

    def load_my_state_dict(self, state_dict):
        own_state = self.state_dict()
        for name, param in state_dict.items():
            if name not in own_state:
                continue
            if isinstance(param, nn.parameter.Parameter):
                param = param.data
            own_state[name].copy_(param)

class EMA:
    def __init__(self, model: torch.nn.Module, decay: float):
        self.decay = decay
        self.shadow = {}
        self.original = {}

        # Register model parameters
        for name, param in model.named_parameters():
            if param.requires_grad:
                self.shadow[name] = param.clone().detach()

    def __call__(self, model):
        with torch.no_grad():
            for name, param in model.named_parameters():
                if param.requires_grad:
                    assert name in self.shadow
                    new_average = (1.0 - self.decay) * param + self.decay * self.shadow[
                        name
                    ]
                    self.shadow[name] = new_average

    def assign(self, model: torch.nn.Module):
        for name, param in model.named_parameters():
            if param.requires_grad:
                self.original[name] = param.clone()
                param.data.copy_(self.shadow[name].data)

    def resume(self, model: torch.nn.Module):
        for name, param in model.named_parameters():
            if param.requires_grad:
                param.data.copy_(self.original[name].data)