import graphviz as gv
from graphvizual import *

class Edge:
    def __init__(self,node_0,node_1,weight):
        self.node_0 = node_0
        self.node_1 = node_1
        self.weight= weight

class Graph_0:
    def __init__(self):
        self.list_edges =[]

    def add_edge(self,start,end,weight):
        self.list_edges.append(Edge(start,end,weight))
        self.buble_sort()
        return self

    def list_nodes(self):
        list=[]
        for i in self.list_edges:
            if i.node_0 not in list:
                list.append(i.node_0)
            if i.node_1 not in list:
                list.append(i.node_1)
        return list

    def buble_sort(self):
        length = len(self.list_edges) - 1
        sorted = False
        while not sorted:
            sorted = True
            for element in range(0, length):
                if self.list_edges[element].weight > self.list_edges[element + 1].weight:
                    sorted = False
                    hold = self.list_edges[element + 1]
                    self.list_edges[element + 1] = self.list_edges[element]
                    self.list_edges[element] = hold
        return self

    def making_friends(self,node):
        list=[]
        for i in self.list_edges:
            if i.node_0==node:
                list.append(i)
        return list

    def print_list_edges(self):
        list_e=[]
        for i in self.list_edges:
            list_e.append([i.node_0,i.node_1,i.weight])
        print(list_e)

    def sort_friends(self,friends):
        length = len(friends) - 1
        sorted = False
        while not sorted:
            sorted = True
            for element in range(0,length):
                # if friends[element][1] > friends[element + 1][1]:
                if friends[element].weight > friends[element + 1].weight:
                    sorted = False
                    hold = friends[element + 1]
                    friends[element + 1] = friends[element]
                    friends[element] = hold
        return friends

    def creating_antecendents(self):
        antecendents = {}
        for i in self.list_nodes():
            antecendents[str(i)]=0
        return(antecendents)

    def nodes_values(self):
        nodes_values = {}
        for i in self.list_nodes():
            nodes_values[str(i)] = 100
        return (nodes_values)

    def dijkstra_alg(self,node_start,node_end):
        nodes_values=self.nodes_values()
        antecendents=self.creating_antecendents()
        nodes_values[node_start]=0
        list_visited_nodes=[str(node_start)]
        list_visited_edges=[]
        friends=[]
        roar=1
        while roar!=20:
            for k in list_visited_nodes:
                if roar==20:
                    break
                friends_i=self.making_friends(k)
                for i in friends_i:
                    if i.weight+nodes_values[str(i.node_0)]<nodes_values[str(i.node_1)]:
                        nodes_values[i.node_1]=nodes_values[i.node_0]+i.weight
                        antecendents[i.node_1]=i.node_0

                for i in friends_i:
                    if i not in friends:
                        friends.append(i)
                        self.sort_friends(friends)
                for k in friends:
                    if k not in list_visited_edges and k.node_1 not in list_visited_nodes and k.node_0 !=node_end:
                        list_visited_edges.append(k)
                        if k.node_0 not in list_visited_nodes:
                            list_visited_nodes.append(k.node_0)
                            if k.node_0==node_end:
                                roar=20
                                break
                        if k.node_1 not in list_visited_nodes:
                            list_visited_nodes.append(k.node_1)
                            if k.node_1==node_end:
                                roar=20
                                break

        node=node_end
        path_d=[]
        while antecendents[node] != 0:
            # path_d.append(antecendents[node])
            node_ant=antecendents[node]
            # node=antecendents[node]
        # path_visible=[]
            for i in list_visited_edges:
                if i.node_0==node_ant and i.node_1==node:
                    # path_d.append([i.node_0,i.node_1,i.weight])
                    path_d.insert(0,[i.node_0,i.node_1,i.weight])
                    break
            node=node_ant
        # for i in list_visited_edges:
        #     path_visible.append([i.node_0,i.node_1,i.weight])
        # path_visible.append(nodes_values[node_end])

        return path_d

    def drawing(self,path):
        Drawing = gv.Digraph(format='png')
        list_e = [['B', 'C', 1], ['C', 'E', 1], ['E', 'A', 2], ['A', 'B', 3], ['D', 'E', 3], ['A', 'D', 3], ['C', 'D', 5], ['B', 'D', 6]]
        for item in list_e:
            node_00 = str(item[0])
            node_11 = str(item[1])
            wei = str(item[2])
            Drawing.edge(node_00, node_11, wei, color='black')
        Drawing = apply_styles(Drawing, styles)
        start = Drawing.render(filename=str(10))
        Drawing.render(view=True)
        list = []
        Drawing = Graph(format='png')
        for i in range(1, len(path) + 1):
            print(path)
            Drawing = gv.Digraph(format='png')
            list.append([str(path[i - 1][0]), str(path[i - 1][1]), str(path[i - 1][2])])
            for item in list_e:
                node_00 = str(item[0])
                node_11 = str(item[1])
                wei = str(item[2])
                if [node_00, node_11, wei] in list:
                    Drawing.edge(node_00, node_11, wei, color='red')
                elif [node_11, node_00, wei] in list:
                    Drawing.edge(node_00, node_11, wei, color='red')
                else:
                    Drawing.edge(node_00, node_11, wei, color='black')

            Drawing = apply_styles(Drawing, styles)
            i = Drawing.render(filename=str(i))
            Drawing.render(view=True)

if __name__ == "__main__":
    d=Graph_0()
    d.add_edge('A', 'B', 3)
    d.add_edge('B', 'C', 1)
    d.add_edge('B', 'D', 6)
    d.add_edge('C', 'E', 1)
    d.add_edge('C', 'D', 5)
    d.add_edge('D', 'E', 3)
    d.add_edge('E', 'A', 2)
    d.add_edge('A', 'D', 3)
    # print(d.dijkstra_alg('C','B'))
    path=d.dijkstra_alg('C','B')
    d.drawing(path)
    # print(d.list_nodes())


from .base_page import BasePage
from .locators import ProductPageLocators
from selenium.common.exceptions import NoAlertPresentException
from selenium.webdriver.common.by import By
import math
import webbrowser

class ProductPage(BasePage):
    def go_product_basket_add(self):
        self.browser.find_element(*ProductPageLocators.BTN_ADD_BASKET).click()

    def solve_quiz_and_get_code(self):
        alert = self.browser.switch_to.alert
        x = alert.text.split(" ")[2]
        answer = str(math.log(abs((12 * math.sin(float(x))))))
        alert.send_keys(answer)
        alert.accept()
        try:
            alert = self.browser.switch_to.alert
            alert_text = alert.text
            print(f"Your code: {alert_text}")
            alert.accept()
        except NoAlertPresentException:
            print("No second alert presented")

    def should_be_name_product(self):
        product_name = self.is_element_present(*ProductPageLocators.PRODUCT_NAME)
        message = self.is_element_present(*ProductPageLocators.CONFIRM_MESSAGE)
        assert product_name == message, "Наименование товара отсутсвует в корзине"

    def should_be_price_product(self):
        product_price = self.browser.find_element(*ProductPageLocators.PRODUCT_PRICE).text
        message_price = self.browser.find_element(*ProductPageLocators.PRICE_BASKET).text
        assert product_price in message_price, "Цена товара не соответствует цене в корзине"

    def should_not_be_success_message(self):
        assert self.is_not_element_present(*ProductPageLocators.SUCCESS_MESSAGE), \
            "Success message is presented, but should not be"

    def should_not_be_success_message_disappeared(self):
        assert self.is_disappeared(*ProductPageLocators.SUCCESS_MESSAGE), \
            "Success message is presented, but should not be"


import time
import random
import pandas as pd
import multiprocessing as mp
import numpy as np
import os
import torch
import torch.nn.functional as F
import copy

from .utils import strToListF
from .models import makeDataSet_Vec
from .utils import strToListF, colorizar, getSTime

# models
from .drlearning import Agent_DQL, ExperienceReplay, ICM as ICM_DQL

class VecDataEnvironment:
    ''' If this environment return done=True, reset it or some errors may apears'''
    VERY_BAD_REWARD = -1.
    def __init__(self, data_path, eval_path=None, max_backpack_size=200, vname='vecs', lname='is_humor', frmethod='acc', rdata_weval=False):
        self.data = pd.read_csv(data_path)
        self.data_eval = None

        self.max_backpack_size = max_backpack_size
        self.vec_size = len(self.data.loc[0,vname].split())
        self.vname = vname
        self.lname = lname

        self.done = False
        self.backpack = []
        self.backpack_l = []

        self.pos_gone = None
        self.iterator = [i for i in range(len(self.data))]
        self.iter_modulo = len(self.data)
        self.iter_pos = None

        self.current_vector = None
        self.final_reward = None
        self.frmethod = frmethod

        if eval_path is not None:
            self.data_eval  = pd.read_csv(eval_path)
            if rdata_weval:
                self.resetIterator(True)

    def mulIterModulo(self, mul=1.0):
        tmp = int(self.iter_modulo * mul)
        self.iter_modulo = min(len(self.data), tmp)
        self.iter_pos = None

    def resetIterator(self, use_reduced=False, porsion=1.):
        if not use_reduced:
            self.iterator = [i for i in range(len(self.data))]
            self.iter_modulo = int(len(self.data) * porsion)
            self.iter_pos = 0
        else:
            print ('# Reducing Data trick')
            file_path = os.path.join('data', 'itEnvRed.npy')
            if os.path.isfile(file_path):
                rel = np.load(file_path)
                self.iterator = rel.tolist()
                self.iter_modulo = len(self.iterator)

                del rel
                ides = dict([(i,1) for i in self.iterator])
                for i in range(len(self.data)):
                    if i not in ides:
                        self.iterator.append(i)
                del ides
                print ('  Taken from', colorizar(file_path))

            else:
                cnt = mp.cpu_count()
                pool = mp.Pool(cnt)

                dx = int(len(self.data_eval) / cnt )
                dx = [(i*dx, i*dx + dx + (0 if i != cnt-1 else len(self.data_eval) % cnt)) for i in range(cnt)]
                label_list = pool.map(self.reduceData, dx)
                del pool
                del cnt
                del dx

                ides = {}
                for li in label_list:
                    for v in li:
                        ides.update({v:1})
                del label_list

                self.iterator = [ v for v in ides ]
                self.iter_modulo = len(self.iterator)
                save = np.array(self.iterator, dtype=np.int64)
                np.save(file_path, save)
                del save

                for i in range(len(self.data)):
                    if i not in ides:
                        self.iterator.append(i)

                del ides

    def reduceData(self, ini_fin):
        sol = []
        for k in range(ini_fin[0],ini_fin[1]):
            vec = np.array(strToListF(self.data_eval.loc[k, self.vname]), dtype=np.float32)
            lab = int(self.data_eval.loc[k, self.lname])
            ide, dist = None, None
            for i in range(len(self.data)):
                curr_vec = np.array(strToListF(self.data.loc[i, self.vname]), dtype=np.float32)
                curr_lab = int(self.data.loc[i, self.lname])
                if lab != curr_lab: continue

                distance = np.sqrt(((curr_vec - vec) ** 2).sum()).item()
                if dist is None or dist > distance:
                    dist = distance
                    ide = i
            sol.append(ide)
        del self.data_eval
        del self.data

        return sol

    def __next(self):
        if self.iter_pos is None:
            self.iter_pos = 0
            selection_part = self.iterator[:self.iter_modulo]
            other_part     = self.iterator[self.iter_modulo:]
            random.shuffle(selection_part) # RANDOMIZE
            random.shuffle(other_part)
            self.iterator = selection_part + other_part

        self.iter_pos += 1
        if (self.iter_pos >= len(self.iterator)) or ((self.iter_pos % self.iter_modulo == 0) and self.iter_pos > 0):
            self.done = True
            self.__calculate_final_R()
            return None, None

        i = self.iterator[self.iter_pos]
        cad = strToListF(self.data.loc[i, self.vname])
        lab = int(self.data.loc[i, self.lname])
        return cad, lab

    def export_prototypes(self, file_list, label_list, silense=False):
        ''' export to a .npy the vectors in the backpak\n
            filelist: [f1:Str, f2:str, ... , fn:str] \n
            label_list: [l1:int, l2:int, ..., ln:int] \n
            the vectors with li label will be placed in fi file for all i'''
        for file_, label_ in zip(file_list, label_list):
            if not silense:
                print ('# Exporting prototypes to', colorizar(os.path.basename(file_)))
            expo = []
            for v,l in zip(self.backpack, self.backpack_l):
                if l != label_: continue
                expo.append(v.reshape(1,-1))
            expo = np.concatenate(expo, axis=0)
            np.save(file_+'.npy', expo)

    def proto_cmp_data_csv(self, ini_fin):
        ''' function used with paralellism to calculate the labels of the data with the prototypes.\n
            ini_fin:pair (ini:int, fin:int) the initial and final position of data, accesed by data.loc[i, vname] for i in [ini,fin) '''
        sol = []
        for i in range(ini_fin[0], ini_fin[1]):
            # lab   = int(data.loc[i, lname])
            vec = None
            if self.data_eval is not None:
                vec = np.array(strToListF(self.data_eval.loc[i, self.vname]), dtype=np.float32)
            else:
                vec = np.array(strToListF(self.data.loc[i, self.vname]), dtype=np.float32)
            min_val, l_min = None, None
            for v, l in zip(self.backpack, self.backpack_l):
                if l is None : continue
                # euclidiean distance
                current_value = np.sqrt(((v - vec) ** 2).sum())
                if min_val is None or min_val > current_value:
                    min_val = current_value
                    l_min   = l
            if l_min is None:
                break
            sol.append(l_min)

        del self.data
        if self.data_eval is not None:
            del self.data_eval
        return np.array(sol, np.int32) # check this later, the int32 ------------------------------------------ OJO -----------------

    def __calculate_final_R(self):
        ''' Inside this, self.iterator is seted to None, be aware of future errors '''
        cnt = mp.cpu_count()
        pool = mp.Pool(cnt)

        if self.data_eval is not None:
            dx = int(len(self.data_eval) / cnt )
            dx = [(i*dx, i*dx + dx + (0 if i != cnt-1 else len(self.data_eval) % cnt)) for i in range(cnt)]
        else:
            dx = int(len(self.data) / cnt )
            dx = [(i*dx, i*dx + dx + (0 if i != cnt-1 else len(self.data) % cnt)) for i in range(cnt)]

        label_list = pool.map(self.proto_cmp_data_csv, dx)
        del pool
        label_list = np.concatenate(label_list, axis=0)

        if label_list.shape[0] <= 0:
            # The backpack is empty !
            self.final_reward = self.VERY_BAD_REWARD
            return

        if self.data_eval is not None:
            original_label = np.array(self.data_eval[self.lname].tolist(), dtype=np.int32)
        else:
            original_label = np.array(self.data[self.lname].tolist(), dtype=np.int32)
        if self.frmethod == 'acc':
            self.final_reward = ((label_list == original_label).sum() / original_label.shape[0]).item()
        del label_list
        del original_label

    def __reset_backpack(self):
        if len(self.backpack) <= 0:
            for _ in range(self.max_backpack_size):
                self.backpack.append(np.array([0 for _ in range(self.vec_size)], dtype=np.float32))
                self.backpack_l.append(None)
        else:
            for k in range(self.max_backpack_size):
                self.backpack[k] = np.array([0 for _ in range(self.vec_size)], dtype=np.float32)
                self.backpack_l[k] = None

    def __makeState(self):
        self.current_vector = self.__next()
        backP = np.stack(self.backpack, axis=0)
        if self.done:
            vecI = np.zeros(self.vec_size, dtype=np.float32)
        else:
            vecI  = np.array(self.current_vector[0], dtype=np.float32)
        return (backP, vecI)

    def reset(self):
        ''' Return the pair: a np.array of shape (max_backpack_size, vec_size) and a np.array of shape (vec_size).

        They are: (backpack state, incoming vector from data). '''
        self.done = False
        self.final_reward = None

        if (self.iter_pos is not None) and (self.iter_pos >= len(self.iterator)):
            self.iter_pos = None

        self.__reset_backpack()
        s,v = self.__makeState()
        return s,v

    def step(self, action:int):
        ''' Return four objects: \n
            \t BackPack State, Incoming Vector from data, reward, done \n
            \t types: np.array(max_backpack_size, vec_size) , np.array (vec_size), float, bool '''
        if action < 0 or action > self.max_backpack_size:
            raise ValueError('ERROR in action input variable, action: {} not in [0,{}]'.format(action,self.max_backpack_size))

        self.pos_gone = action if action < self.max_backpack_size else None
        reward = 0.

        if action < self.max_backpack_size:
            self.backpack[action] = np.array(self.current_vector[0], dtype=np.float32)
            self.backpack_l[action] = int(self.current_vector[1])

        s,v = self.__makeState()
        if self.final_reward is not None: reward += self.final_reward

        return s, v, reward, self.done

def prepareBackpackState(blist, vec):
    state = np.concatenate([blist,vec.reshape(1,-1)], axis=0)
    state = torch.from_numpy(state)
    return state

def __policy_dql(qvalues, nactions=12,eps=None):
    with torch.no_grad():
        if eps is not None:
            if torch.rand(1) < eps:
                return torch.randint(low=0,high=nactions, size=(1,))
            else:
                return torch.argmax(qvalues)
        else:
            return torch.multinomial(F.softmax(F.normalize(qvalues), dim=0), num_samples=1)

def __minibatch_train_dql(Qmodel, Qtarget, qloss, replay, params, DEVICE, icm=None):
    state1_batch, action_batch, reward_batch, state2_batch = replay.get_batch()
    action_batch = action_batch.view(action_batch.shape[0],1).to(device=DEVICE)
    reward_batch = reward_batch.view(reward_batch.shape[0],1).to(device=DEVICE)

    state1_batch = state1_batch.to(device=DEVICE)
    state2_batch = state2_batch.to(device=DEVICE)

    forward_pred_err , inverse_pred_err = 0., 0.
    reward = reward_batch

    if icm is not None:
        forward_pred_err , inverse_pred_err = icm(state1_batch, action_batch, state2_batch)
        i_reward = (1. / float(params['eta'])) * forward_pred_err
        reward += i_reward.detach()

    # qvals = Qmodel(state2_batch) # recordar usar target net later
    qvals = Qtarget(state2_batch)
    reward += float(params['gamma']) * torch.max(qvals)

    reward_pred = Qmodel(state1_batch)
    reward_target = reward_pred.clone()
    indices = torch.stack((torch.arange(action_batch.shape[0]).to(device=DEVICE),action_batch.squeeze().to(device=DEVICE)), dim=0)
    indices = indices.tolist()
    reward_target[indices] = reward.squeeze()
    q_loss = 1e5 * qloss(F.normalize(reward_pred), F.normalize(reward_target.detach()))

    return forward_pred_err, inverse_pred_err, q_loss

def __loss_fn(q_loss, inverse_loss, forward_loss, params):
    loss_  = (1 - float(params['beta'])) * inverse_loss
    loss_ += float(params['beta']) * forward_loss
    loss_ = loss_.mean() # loss_.sum() / loss.flatten().shape[0]
    loss = loss_ + float(params['lambda']) * q_loss
    return loss

# params (data_path, lcolumn, vcolumn, param)
def __prototypes_with_dql(params):
    print ('# Start:','Deep Q Learning algorithm. Relax, this will take a wille.')
    BACKPACK_SIZE, EPS  = int(params['max_prototypes']),  float(params['eps'])
    EPOCHS, LR, BSIZE = int(params['epochs']), float(params['lr']), int(params['batch_size'])
    DMODEL = int(params['d_model'])
    target_refill, i_targetFill = int(params['target_refill']), 0
    use_icm = params['ICM']

    losses = []
    switch_to_eps_greedy = int(EPOCHS * (2/5))

    env = VecDataEnvironment(params['data_path'], eval_path=params['eval_data_path'], max_backpack_size=BACKPACK_SIZE, vname=params['vcolumn'], lname=params['lcolumn'], rdata_weval=bool(params['reduced_data_prototypes']))
    DEVICE = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")

    # max_len : 5000, antes BACKPACK_SIZE+11, de esta forma quisas se adapte a ir cresiendo poco a poco
    max_len = min(5000, BACKPACK_SIZE+100)
    Qmodel = Agent_DQL(BACKPACK_SIZE+1, nhead=int(params['nhead']),nhid=int(params['nhid']),d_model=DMODEL,nlayers=int(params['n_layers']), max_len=max_len,dropout=float(params['dropout']))
    qloss = torch.nn.MSELoss().to(device=DEVICE)

    # seting up the taget net, and memory replay stuff
    Qtarget = copy.deepcopy(Qmodel).to(device=DEVICE)
    Qtarget.load_state_dict(Qmodel.state_dict())
    replay = ExperienceReplay(N=int(params['memory_size']), batch_size=BSIZE)
    all_model_params = list(Qmodel.parameters())

    icm = None
    if use_icm:
        icm = ICM_DQL(BACKPACK_SIZE+1, DMODEL*(BACKPACK_SIZE+1), DMODEL, max_len=max_len, forward_scale=1., inverse_scale=1e4, nhead=int(params['nhead']),hiden_size=int(params['nhid']),nlayers=int(params['n_layers']), dropout=float(params['dropout']))
        all_model_params += list(icm.parameters())
        icm.train()

    opt = torch.optim.Adam(lr=LR, params=all_model_params)
    Qmodel.train()

    greater_reward = -(2**30)
    greater_reward_c = greater_reward
    triple_sch = [float(i) / 100. for i in params['distribution_train'].split('-')]
    for i in range(1,len(triple_sch)): triple_sch[i] += triple_sch[i-1]
    # triple_sch = [ triple_sch[i] + (triple_sch[i-1] if i > 0 else 0)  for i in range(len(triple_sch))]

    if abs(triple_sch[-1] - 1.) > 1e-9:
        raise ValueError("Parameter 'distribution_train' most add 100, but has {}.".format(triple_sch[-1]*100.))

    pos_tr = 0
    for i in range(EPOCHS):
        print('# Epoch {}/{} {}'.format(i+1, EPOCHS, 'with eps' if i >= switch_to_eps_greedy else 'with softmax policy'))
        while pos_tr < len(triple_sch) and int(EPOCHS * triple_sch[pos_tr]) <= i+1:
            env.mulIterModulo(2.0)
            pos_tr += 1

        all_obj_seeit = False
        state1 = prepareBackpackState(*env.reset()).unsqueeze(0).to(device=DEVICE)
        acc_reward = 0.
        it_episode = 0
        init_time = time.time()

        while not all_obj_seeit:
            # parafernalia ----------------------------
            it_episode += 1
            print ('\r  It {} with reward {:.4f} | {}'.format(it_episode, acc_reward, getSTime(time.time()-init_time)), end=' ')
            # -----------------------------------------

            opt.zero_grad()
            q_val_pred = Qmodel(state1)

            # Use softmax policy only at the begining
            if i >= switch_to_eps_greedy:
                action = int(__policy_dql(q_val_pred, nactions=BACKPACK_SIZE+1,eps=EPS))
            else:
                action = int(__policy_dql(q_val_pred, nactions=BACKPACK_SIZE+1))

            back_state, vec_state , e_reward, done = env.step(action)
            state2 = prepareBackpackState(back_state, vec_state).unsqueeze(0).to(device=DEVICE)

            replay.add_memory(state1, action, e_reward, state2)
            acc_reward += e_reward

            all_obj_seeit = done
            if not done:
                state1 = state2

            if len(replay.memory) < BSIZE:
                continue
            forward_pred_err, inverse_pred_err, q_loss = __minibatch_train_dql(Qmodel, Qtarget, qloss, replay, params, DEVICE, icm=icm)

            loss = __loss_fn(q_loss, forward_pred_err, inverse_pred_err, params)
            loss_list = (q_loss.mean().item(), forward_pred_err.flatten().mean().item(), inverse_pred_err.flatten().mean().item())
            losses.append(loss_list)
            loss.backward()
            opt.step()

            i_targetFill += 1
            if i_targetFill % target_refill == 0:
                i_targetFill = 0
                Qtarget.load_state_dict(Qmodel.state_dict())
        if greater_reward_c < acc_reward:
            greater_reward_c = acc_reward
            env.export_prototypes(file_list  = [os.path.join('data','pos_center'), os.path.join('data','neg_center')], label_list = [1, 0])
        if greater_reward <= acc_reward and (pos_tr >= len(triple_sch)):
            greater_reward = acc_reward
            Qmodel.save(os.path.join('pts', 'dql_model.pt'))
            if icm is not None:
                icm.save(os.path.join('pts', 'icm_model.pt'))
        print ('\r  It {} with reward:{:.4f} | {}'.format(it_episode, acc_reward, getSTime(time.time()-init_time)), end='\n')

    losses_ = np.array(losses)
    np.save(os.path.join('out', 'dql_losses.npy'), losses_)
    del icm
    del opt
    del replay

    # best model
    # Qmodel.load(os.path.join('pts', 'dql_model.pt'))
    # Qmodel.eval()
    # it_episode, acc_reward = 0, 0.
    # init_time = time.time()

    # env.resetIterator()

    print ('# Ending:','Deep Q Learning algorithm')
    # state1 = prepareBackpackState(*env.reset()).unsqueeze(0)
    # with torch.no_grad():
    #     while True:
    #         # parafernalia ----------------------------
    #         it_episode += 1
    #         # -----------------------------------------
    #         q_val_pred = Qmodel(state1)
    #         action = int(__policy_dql(q_val_pred, nactions=BACKPACK_SIZE+1, eps=0.01))

    #         back_state, vec_state , e_reward, done = env.step(action)
    #         state1 = prepareBackpackState(back_state, vec_state).unsqueeze(0)
    #         acc_reward += e_reward

    #         all_obj_seeit = done
    #         if done:
    #             print ('\r  It {} with reward {:.4f} | {}'.format(it_episode, acc_reward, getSTime(time.time()-init_time)))
    #             break
    #         print ('\r  It {} with reward {:.4f} | {}'.format(it_episode, acc_reward, getSTime(time.time()-init_time)), end=' ')

    # esporting final state of the backpack
    # env.export_prototypes(file_list  = [os.path.join('data','pos_center'), os.path.join('data','neg_center')],
                        #   label_list = [1                                , 0])
    del env

def extractPrototypes(method, params):
    """ Apply a method to extract prototypes from data. \n

    method: the method used to select prototypes, most be in [\'dql\', \'dql-intrinsic\']\n

    data_path:str a path to a \'.csv\' file with at most the columns [vcolumn, lcolumn]. \n
    eval_data_path: same as data_path, but treated as evaluation data \n

    The column vcolumn most be a list a floating points, a vector.\n

    The column lcolumn is the label of the vectors, [0,1]. """
    __paramu = {'intrinsic':True, 'lambda':0.1, 'eta':1.0, 'gamma':0.2, 'eps':0.15, 'beta':0.2,
                'lcolumn':'is_humor', 'vcolumn':'vecs', 'max_prototypes':20, # 200
                'batch_size':10, 'lr':0.001, 'epochs':20, 'memory_size':50}
    __paramu.update(params)

    methods_ = [('dql', __prototypes_with_dql), ('dql-intrinsic', __prototypes_with_dql)]

    for mname, fun in methods_:
        if method == mname:
            fun(__paramu)
            return
    print ('ERROR::extractPrototypes Method parameter', '\''+method+'\'', 'is not in [', ' , '.join(['\''+s+'\'' for s,_,_ in methods_]), '] !!!!')


from global_variables import stop_event
from hatch_controller import hc
from beamer.mqtt import mqtt_client, fsmQueue, TRAPPE_TOPIC, HDMI_TOPIC
from beamer.hdmi import hdmi_relay
import logging
import time

MQTT_OPEN = b"OPEN"
MQTT_CLOSE = b"CLOSE"
MQTT_STOP = b"STOP"

class State():
    def __init__(self):
        self.enter_time = time.time()
        logging.info(f'COVER: Current state: {str(self)}')
        self.on_enter()

    def on_enter(self) -> None:
        pass

    def update(self, mqtt_command=""):
        return self

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return self.__class__.__name__

class Open(State):
    def on_enter(self):
        mqtt_client.publish(f"{TRAPPE_TOPIC}/state", "open")

    def update(self, mqtt_command=""):

        if mqtt_command == MQTT_CLOSE:
            return Closing()

        return self

class Closed(State):

    def on_enter(self):
        mqtt_client.publish(f"{TRAPPE_TOPIC}/state", "closed")

    def update(self, mqtt_command=""):

        if mqtt_command == MQTT_OPEN:
            return Opening()

        return self

class Stopped(State):
    def on_enter(self):
        hc.stop()
        mqtt_client.publish(f"{TRAPPE_TOPIC}/state", "stopped")
        logging.info(f"Stopped at {hc.get_position()}")

    def update(self, mqtt_command=""):

        if mqtt_command == MQTT_CLOSE:
            return Closing()
        elif mqtt_command == MQTT_OPEN:
            return Opening()

        return self

class Opening(State):
    def on_enter(self):
        mqtt_client.publish(f"{TRAPPE_TOPIC}/state", "opening")
        hc.set_target_position(hc.opened_position)

    def update(self, mqtt_command=""):
        if mqtt_command == MQTT_CLOSE:
            return Closing()
        elif mqtt_command == MQTT_STOP:
            return Stopped()

        return self

class Closing(State):

    def on_enter(self) -> None:
        mqtt_client.publish(f"{TRAPPE_TOPIC}/state", "closing")
        hc.enable_control()
        hc.set_target_position(hc.closed_position)
        return

    def update(self, mqtt_command=""):
        if mqtt_command == MQTT_OPEN:
            return Opening()
        elif mqtt_command == MQTT_STOP:
            # stop hc
            mqtt_client.publish(f"{TRAPPE_TOPIC}/state", "stopped")
            return Stopped()

        return self

class CoverStateMachine():
    def __init__(self) -> None:
        self.state = Closed()

    def control_loop(self):
        while not stop_event.is_set():

            if hc.target_position_reached():
                if hc.get_position() <= hc.closed_position + 1:
                    self.state = Closed()
                elif hc.get_position() >= hc.opened_position - 10:
                    self.state = Open()

            mqtt_command = ""
            if fsmQueue.not_empty:
                mqtt_msg = fsmQueue.get()
                if mqtt_msg.topic == f"{HDMI_TOPIC}/set":
                    if mqtt_msg.payload == b"ON":
                        hdmi_relay.enable()
                        mqtt_client.publish(f"{HDMI_TOPIC}/state", b"ON")
                    elif mqtt_msg.payload == b"OFF":
                        hdmi_relay.disable()
                        mqtt_client.publish(f"{HDMI_TOPIC}/state", b"OFF")

                elif mqtt_msg.topic == f"{TRAPPE_TOPIC}/set":
                    mqtt_command = mqtt_msg.payload
                    logging.info(f"command: {mqtt_command}")
            self.state = self.state.update(mqtt_command)
            time.sleep(50 * 1e-3)  # 50 ms loop

coverFSM = CoverStateMachine()


from youtubesearchpython import VideosSearch
import os
import glob

#     __       _       _
#    /  \     | |     | |
#   /    \    | | /\  | | /\   _   _
#  /  /\  \   | |/ /  | |/ /  | | | |
# /  ____  \  | |\ \  | |\ \  | |_| |
#/__/    \__\ |_| \_\ |_| \_\  \___/
#
# Copyright of Akash, 2021
# https://www.github.com/akkupy
# https://t.me/akkupy

def yt_music(song_name, chat_id, msg_id, bot):
    try:
        videosSearch = VideosSearch(song_name, limit=1)

        result = videosSearch.result()
        first_result = result["result"]
        yt_url = first_result[0]["link"]
        yt_title = first_result[0]["title"]
        yt_pub_time = first_result[0]["publishedTime"]
        yt_id = first_result[0]["id"]
        yt_duration = first_result[0]["duration"]

        if not os.path.isdir("./music/"):
            os.makedirs("./music/")
        yt_song = (
                f'youtube-dl --force-ipv4 -q -o "./music/{yt_title}.%(ext)s" --extract-audio --audio-format mp3 --audio-quality 128k '
                + yt_url
        )

        os.system(yt_song)
        try:
            a = glob.glob("./music/*.webm")
            b = a[0]
            c = b[8:]
        except:
            a = glob.glob("./music/*.mp3")
            b = a[0]
            c = b[8:]
        dir = f"./music/{c}"
        dir1 = f"./music/{c}"
        capy = f"**Song Name ➠** `{yt_title}` \n**Published On ➠** `{yt_pub_time}` \n**Duration ➠** `{yt_duration}` \n**Link ➠** `{yt_url}`"
        if os.path.exists(dir):
            try:
                bot.sendChatAction(chat_id=chat_id, action="upload_audio")
                bot.send_audio(audio=open(dir, 'rb'), caption=capy, chat_id=chat_id, reply_to_message_id=msg_id)
                os.remove(dir)
            except:
                bot.sendMessage(chat_id=chat_id, text="Audio Size is too large,Check the link below",
                                reply_to_message_id=msg_id)
                bot.sendMessage(chat_id=chat_id, text=yt_url, reply_to_message_id=msg_id)
                os.remove(dir)
        elif os.path.exists(dir1):
            try:
                bot.sendChatAction(chat_id=chat_id, action="upload_audio")
                bot.send_audio(audio=open(dir1, 'rb'), caption=capy, chat_id=chat_id, reply_to_message_id=msg_id)
                os.remove(dir1)
            except:
                bot.sendMessage(chat_id=chat_id, text="Audio Size is too large,Check the link below",
                                reply_to_message_id=msg_id)
                bot.sendMessage(chat_id=chat_id, text=yt_url, reply_to_message_id=msg_id)
                os.remove(dir1)

        else:
            bot.sendChatAction(chat_id=chat_id, action="typing")
            bot.sendMessage(chat_id=chat_id, text="Song Not Found!", reply_to_message_id=msg_id)

    except:
        bot.sendChatAction(chat_id=chat_id, action="typing")
        bot.sendMessage(chat_id=chat_id, text="Unable to retreive the Song :( Check out the link", reply_to_message_id=msg_id)
        if yt_url is not "":
            bot.sendMessage(chat_id=chat_id, text=yt_url, reply_to_message_id=msg_id)


import os

from setuptools import setup

basedir = os.path.dirname(__file__)

def readme():
    with open(os.path.join(basedir, "README.rst")) as f:
        return f.read()

about = {}
with open(os.path.join(basedir, "pysyncgateway", "__about__.py")) as f:
    exec(f.read(), about)

setup(
    name=about["__name__"],
    version=about["__version__"],
    description=about["__description__"],
    long_description=readme(),
    url="https://github.com/constructpm/pysyncgateway",
    author=about["__author__"],
    author_email=about["__email__"],
    license="Apache License 2.0",
    install_requires=["requests>=2.23.0", "six>=1.13"],
    packages=["pysyncgateway"],
    python_requires=">=3.5, <4",
    zip_safe=False,
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: Apache Software License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python",
    ],
)


from django.views.generic import View
from .forms import CorrectionSendingForm
from apps.article_review.models import Review
from django.contrib import messages
from django.shortcuts import redirect
# Create your views here.
from apps.correction_reception.models import ArticleCorrection

# * Importar los modelos

class CorrectionSendingView(View):

    def post(self, request, *args, **kwargs):

        # * get review
        review = Review.objects.get(pk=kwargs['pk'])

        form = CorrectionSendingForm(request.POST)

        if form.is_valid():
            # * Hacer algo con el formulario
            val = form.cleaned_data.get('btn')

            if val == 'Si':

                review.enviado = True

                review.save()

                assignment = review.assignment

                # * if all reviews are sent then change the status of assignment to completed

                # * get all reviews of the assignment

                reviews = Review.objects.filter(assignment=assignment)

                # * check if all reviews are sent

                for review in reviews:
                    if review.enviado == False:
                        messages.success(
                            request, 'Se ha cargado la corrección. Se notificará al autor cuando se hayan cargado todas las correcciones pendientes por los otros arbitros.')
                        return redirect('core_dashboard:dashboard')
                else:
                    assignment.completed = True
                    assignment.save()

                    ArticleCorrection.objects.get_or_create(article=assignment.article)

                    messages.success(
                        request, 'Se ha enviado la corrección y se ha notificado al autor.')

                    from django.contrib.sites.shortcuts import get_current_site
                    from django.core.mail import EmailMessage
                    from django.urls import reverse

                    email = EmailMessage(
                        subject='Artículo arbitrado',
                        body=f'Estimado(a) {review.assignment.article.author.user.get_full_name()},\n\n'
                        f'Le informamos que el artículo {review.assignment.article.title} ha sido arbitrado y tiene correciones pendientes por realizar.\n\n'
                        f'Para acceder al artículo puede verlo en su tablero de actividades, por favor ingrese a la siguiente dirección:\n\n'
                        f'{get_current_site(request).domain + reverse("core_dashboard:dashboard")}\n\n'
                        f'Atentamente,\n\n'
                        f'Comité Editorial de Ciencia y Tecnología',
                        from_email='jonathan90090@gmail.com',
                        to=[review.assignment.article.author.user.email]
                    )

                    email.send()

                    return redirect('core_dashboard:dashboard')

        else:
            return redirect('core_dashboard:dashboard')


from unittest import TestCase
import os
from yapic_io.connector import io_connector
import numpy as np
from numpy.testing import assert_array_almost_equal, assert_array_equal
from yapic_io import TiffConnector, Dataset, PredictionBatch
import pytest

from tifffile import memmap

base_path = os.path.dirname(__file__)

class TestPredictionBatch(TestCase):

    @pytest.fixture(autouse=True)
    def setup(self, tmpdir):
        self.tmpdir = tmpdir.strpath

    def test_computepos_1(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path)
        d = Dataset(c)

        size = (1, 1, 1)
        batch_size = 1

        p = PredictionBatch(d, batch_size, size)

        self.assertEqual(len(p._all_tile_positions), 6 * 4 * 3)
        tilepos = [(p[0], tuple(p[1])) for p in p._all_tile_positions]

        self.assertEqual(len(tilepos),
                         len(set(tilepos)))

    def test_computepos_2(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path)
        d = Dataset(c)

        size = (3, 6, 4)
        batch_size = 1

        p = PredictionBatch(d, batch_size, size)

        val = [(0, (0, 0, 0))]
        for pos, valpos in zip(p._all_tile_positions, val):
            assert_array_equal(pos[1], np.array(valpos[1]))
            self.assertEqual(pos[0], valpos[0])

    def test_computepos_3(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path)
        d = Dataset(c)

        size = (2, 6, 4)
        batch_size = 1

        p = PredictionBatch(d, batch_size, size)

        val = [(0, (0, 0, 0)), (0, (1, 0, 0))]
        for pos, valpos in zip(p._all_tile_positions, val):
            assert_array_equal(pos[1], np.array(valpos[1]))
            self.assertEqual(pos[0], valpos[0])

    def test_getitem_1(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path)
        d = Dataset(c)

        size = (1, 6, 4)
        batch_size = 2

        p = PredictionBatch(d, batch_size, size)

        # batch size is 2, so the first 2 tiles go with the first batch
        # (size two), the third tile in in the second batch. the second
        # batch has only size 1 (is smaller than the specified batch size),
        # because it contains the rest.

        self.assertEqual(len(p), 2)
        self.assertEqual(p[0].pixels().shape, (2, 3, 1, 6, 4))
        self.assertEqual(p[1].pixels().shape, (1, 3, 1, 6, 4))

    def test_getitem_2(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path)
        d = Dataset(c)

        size = (1, 6, 4)
        batch_size = 3

        p = PredictionBatch(d, batch_size, size)
        # batch size is 3, this means all3 tempplates fit in one batch

        self.assertEqual(len(p), 1)
        self.assertEqual(p[0].pixels().shape, (3, 3, 1, 6, 4))

    def test_current_tile_positions(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path)
        d = Dataset(c)

        size = (1, 6, 4)
        batch_size = 2
        p = PredictionBatch(d, batch_size, size)

        val = [(0, (0, 0, 0)), (0, (1, 0, 0))]
        for pos, valpos in zip(p[0].current_tile_positions, val):
            assert_array_equal(pos[1], np.array(valpos[1]))
            self.assertEqual(pos[0], valpos[0])

        val = [(0, (2, 0, 0))]
        for pos, valpos in zip(p[1].current_tile_positions, val):
            assert_array_equal(pos[1], np.array(valpos[1]))
            self.assertEqual(pos[0], valpos[0])

    def test_put_probmap_data(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path, savepath=self.tmpdir)
        d = Dataset(c)

        size = (1, 6, 4)
        batch_size = 1

        p = PredictionBatch(d, batch_size, size)

        data = np.ones((1, 2, 1, 6, 4))
        p[0].put_probmap_data(data)
        p[1].put_probmap_data(data)
        p[2].put_probmap_data(data)

    def test_put_probmap_data_2(self):
        img_path = os.path.abspath(os.path.join(
            base_path,
            '../test_data/tiffconnector_1/im/6width4height3slices_rgb.tif'))
        label_path = os.path.join(base_path, '/path/to/nowhere')

        c = TiffConnector(img_path, label_path, savepath=self.tmpdir)
        d = Dataset(c)

        size = (1, 2, 2)
        batch_size = 1

        p = PredictionBatch(d, batch_size, size)

        pixel_val = 0
        for mb in p:
            pixel_val += 10
            data = np.ones((1, 2, 1, 2, 2)) * pixel_val
            mb.put_probmap_data(data)

        pixelmap = memmap(os.path.join(self.tmpdir,
                          '6width4height3slices_rgb_class_1.tif'))

        # zslice 0
        val_0 = np.array([[10., 10., 30., 30., 50., 50.],
                          [10., 10., 30., 30., 50., 50.],
                          [20., 20., 40., 40., 60., 60.],
                          [20., 20., 40., 40., 60., 60.]])
        assert_array_almost_equal(pixelmap[0, :, :, 0], val_0)

        # zslice 1
        val_1 = np.array([[70.,  70.,  90.,  90., 110., 110.],
                          [70.,  70.,  90.,  90., 110., 110.],
                          [80.,  80., 100., 100., 120., 120.],
                          [80.,  80., 100., 100., 120., 120.]])
        assert_array_almost_equal(pixelmap[1, :, :, 0], val_1)

        # zslice 2
        val_2 = np.array([[130., 130., 150., 150., 170., 170.],
                          [130., 130., 150., 150., 170., 170.],
                          [140., 140., 160., 160., 180., 180.],
                          [140., 140., 160., 160., 180., 180.]])
        assert_array_almost_equal(pixelmap[2, :, :, 0], val_2)

    def test_put_probmap_data_3(self):
        img_path = os.path.abspath(os.path.join(
            base_path, '../test_data/tiffconnector_1/im/*'))
        label_path = os.path.abspath(os.path.join(
            base_path, '../test_data/tiffconnector_1/labels/*'))

        c = TiffConnector(img_path, label_path, savepath=self.tmpdir)
        d = Dataset(c)

        size = (1, 3, 4)
        batch_size = 2

        p = PredictionBatch(d, batch_size, size)

        data = np.ones((2, 3, 1, 3, 4))
        p[0].put_probmap_data(data)

        data = np.ones((2, 3, 1, 3, 4))
        p[1].put_probmap_data(data)

        data = np.ones((2, 3, 1, 3, 4))
        p[2].put_probmap_data(data)

    def test_put_probmap_data_when_no_labels_available(self):

        img_path = os.path.abspath(os.path.join(
            base_path, '../test_data/tiffconnector_1/im/*'))

        c = io_connector(img_path, '', savepath=self.tmpdir)
        d = Dataset(c)

        size = (1, 3, 4)
        batch_size = 2

        p = PredictionBatch(d, batch_size, size)

        data = np.ones((2, 2, 1, 3, 4))
        p[0].put_probmap_data(data)

        data = np.ones((2, 2, 1, 3, 4))
        p[1].put_probmap_data(data)

        data = np.ones((2, 2, 1, 3, 4))
        p[2].put_probmap_data(data)

        val = ['40width26height3slices_rgb_class_1.tif',
               '40width26height3slices_rgb_class_2.tif']
        self.assertEqual(sorted(os.listdir(self.tmpdir)), val)

    def test_put_probmap_data_multichannel_label(self):
        img_path = os.path.abspath(os.path.join(
            base_path, '../test_data/tiffconnector_1/im/*'))
        label_path = os.path.abspath(os.path.join(
            base_path, '../test_data/tiffconnector_1/labels_multichannel/*'))

        c = TiffConnector(img_path, label_path, savepath=self.tmpdir)
        d = Dataset(c)

        original_labels = c.original_label_values_for_all_images()
        res = c.calc_label_values_mapping(original_labels)

        d = Dataset(c)

        size = (1, 3, 4)
        batch_size = 1

        p = PredictionBatch(d, batch_size, size)

        data = np.ones((1, 6, 1, 3, 4))
        p[0].put_probmap_data(data)

    def test_prediction_loop(self):
        # mock classification function
        def classify(pixels, value):
            return np.ones(pixels.shape) * value

        # define data locations
        pixel_image_dir = os.path.join(
            base_path, '../test_data/tiffconnector_1/im/*.tif')
        label_image_dir = os.path.join(
            base_path, '../test_data/tiffconnector_1/labels/*.tif')

        tile_size = (1, 5, 4)  # size of network output layer in zxy
        padding = (0, 0, 0)  # padding of network input layer in zxy,
        # in respect to output layer

        # Make training_batch mb and prediction interface p with
        # TiffConnector binding.
        c = TiffConnector(pixel_image_dir,
                          label_image_dir, savepath=self.tmpdir)
        p = PredictionBatch(Dataset(c), 2, tile_size, padding_zxy=padding)

        self.assertEqual(len(p), 255)
        self.assertEqual(p.labels, {1, 2, 3})

        # classify the whole bound dataset
        for counter, item in enumerate(p):
            pixels = item.pixels()  # input for classifier
            mock_classifier_result = classify(pixels, counter)
            # pass classifier results for each class to data source
            item.put_probmap_data(mock_classifier_result)

    def test_pixel_dimensions(self):

        img_path = os.path.abspath(os.path.join(
            base_path, '../test_data/tiffconnector_1/im/*'))
        c = io_connector(img_path, '', savepath=self.tmpdir)
        d = Dataset(c)

        size = (1, 5, 4)
        batch_size = 2

        p = PredictionBatch(d, batch_size, size)[0]

        print(p.pixels().shape)
        self.assertEqual((2, 3, 1, 5, 4), p.pixels().shape)

        p.set_pixel_dimension_order('bzxyc')
        self.assertEqual((2, 1, 5, 4, 3), p.pixels().shape)


from django import http

import six
from django.db.models import ProtectedError
from rest_framework import views, exceptions, status
from rest_framework.exceptions import UnsupportedMediaType
from rest_framework.response import Response

from backpack.serializers_bcv1 import BadgeConnectErrorSerializer
from entity.serializers import V2ErrorSerializer, Rfc7591ErrorSerializer
from entity.authentication import CSRFPermissionDenied

def exception_handler(exc, context):
    version = context.get('kwargs', {}).get('version', 'v1')

    if version in ['v2', 'rfc7591']:
        description = 'miscellaneous error'
        field_errors = {}
        validation_errors = []

        if isinstance(exc, exceptions.ParseError):
            description = 'bad request'
            validation_errors = [exc.detail]

            response_code = status.HTTP_400_BAD_REQUEST

        elif isinstance(exc, exceptions.ValidationError):
            description = 'bad request'

            if isinstance(exc.detail, list):
                validation_errors = exc.detail
            elif isinstance(exc.detail, dict):
                field_errors = exc.detail
            elif isinstance(exc.detail, six.string_types):
                validation_errors = [exc.detail]

            response_code = status.HTTP_400_BAD_REQUEST

        elif isinstance(exc, (exceptions.AuthenticationFailed, exceptions.NotAuthenticated)):
            description = 'no valid auth token found'
            response_code = status.HTTP_401_UNAUTHORIZED

        elif isinstance(exc, CSRFPermissionDenied):
            description = 'no valid csrf token found'
            response_code = status.HTTP_401_UNAUTHORIZED

        elif isinstance(exc, (http.Http404, exceptions.PermissionDenied)):
            description = 'entity not found or insufficient privileges'
            response_code = status.HTTP_404_NOT_FOUND

        elif isinstance(exc, ProtectedError):
            description, protected_objects = exc.args
            response_code = status.HTTP_400_BAD_REQUEST

        elif isinstance(exc, UnsupportedMediaType):
            description = exc.detail
            validation_errors = [exc.detail]
            response_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE

        elif isinstance(exc, exceptions.APIException):
            field_errors = exc.detail
            response_code = exc.status_code

        else:
            # Unrecognized exception, return 500 error
            return None
        if version == 'v2':
            serializer = V2ErrorSerializer(
                instance={}, success=False, description=description,
                field_errors=field_errors, validation_errors=validation_errors
            )
        else:
            serializer = Rfc7591ErrorSerializer(
                instance={}, field_errors=field_errors, validation_errors=validation_errors
            )
        return Response(serializer.data, status=response_code)

    elif version == 'bcv1':
        # Badge Connect errors
        error = None
        status_code = status.HTTP_400_BAD_REQUEST
        status_text = 'BAD_REQUEST'

        if isinstance(exc, exceptions.ParseError):
            error = exc.detail

        elif isinstance(exc, exceptions.ValidationError):
            error = exc.detail
            status_text = 'REQUEST_VALIDATION_ERROR'

        elif isinstance(exc, exceptions.PermissionDenied):
            status_code = status.HTTP_401_UNAUTHORIZED
            status_text = 'PERMISSION_DENIED'

        elif isinstance(exc, (exceptions.AuthenticationFailed, exceptions.NotAuthenticated)):
            status_code = status.HTTP_401_UNAUTHORIZED
            status_text = 'UNAUTHENTICATED'

        elif isinstance(exc, exceptions.MethodNotAllowed):
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            status_text = 'METHOD_NOT_ALLOWED'

        serializer = BadgeConnectErrorSerializer(instance={},
                                                 error=error,
                                                 status_text=status_text,
                                                 status_code=status_code)
        return Response(serializer.data, status=status_code)

    else:
        # Use the default exception-handling logic for v1
        if isinstance(exc, ProtectedError):
            description, protected_objects = exc.args
            return Response(description, status=status.HTTP_400_BAD_REQUEST)
        return views.exception_handler(exc, context)


from flask import Blueprint, render_template, redirect, url_for, flash
from flask_security import current_user
from flask_babel import gettext

from . import route
from dxc.app.models.job.forms import JobForm, JobReportForm
from dxc.services import api_job, api_report

bp = Blueprint('job', __name__, template_folder='templates', static_folder='static', url_prefix='/job')

@route(bp, '/new', methods=['GET', 'POST'])
def create_job():
    form = JobForm()
    if form.validate_on_submit():
        user = None
        if current_user.get_id() is not None:
            user = current_user
        job = api_job.create(user=user, **form.data)
        return redirect(url_for('.detail_job', job_id=job.id))

    return render_template('job/create.html', form=form)

#----------------------------------------------------------------------
@bp.route('/<int:job_id>', methods=['GET'])
def detail_job(job_id):
    """"""
    job = api_job.get_or_404(job_id)
    api_job.update(job, read_count = job.read_count + 1)
    return render_template('job/detail.html', job=job)

#----------------------------------------------------------------------
@bp.route('/jobs/<int:page>', methods=['GET'])
@bp.route('/jobs/', methods=['GET'])
def list_job(page=None):
    """"""
    if page == None or page <= 0:
        page = 1
    jobs = api_job.get_latest_page_filterby(page, status=1)
    return render_template('job/list.html', jobs = jobs)

#----------------------------------------------------------------------
@bp.route('/report/<int:job_id>', methods=['GET', 'POST'])
def report_job(job_id):
    """Report a job
    """
    report_form = JobReportForm()
    if report_form.validate_on_submit():
        api_report.create(job_id=job_id, **report_form.data)
        flash(gettext(u'Thanks for your report. We will check it soon.'))
        return redirect(url_for('.list_job'))
    return render_template('job/report.html', job_id=job_id, report_form=report_form)

#----------------------------------------------------------------------
@bp.route('/reports/<int:job_id>', methods=['GET'])
def list_report(job_id):
    """"""
    job = api_job.get(job_id)
    return render_template('job/report_list.html', job=job, reports=job.reports)

@route(bp, '/profile/published_jobs/','/profile/published_jobs/<int:status>/','/profile/published_jobs/<int:status>/<int:page>', methods=['GET'])
def list_publisedjobs(status=1, page=1):
    """List jobs published by me."""
    jobs = api_job.get_latest_page_filterby(page=page, per_page=2, status=status, user_id=current_user.id)

    return render_template('job/profile_publishedjobs.html', jobs=jobs, status=status)


import logging
from typing import Callable, List
from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .coordinator import UpdateCoordinator
from homeassistant.helpers.entity import DeviceInfo, async_generate_entity_id
from .const import (
    DOMAIN,
)

_LOGGER = logging.getLogger(__name__)

PARALLEL_UPDATES = 1

async def async_setup_entry(
        hass: HomeAssistantType,
        entry: ConfigEntry,
        async_add_entities: Callable[[List[Entity], bool], None],
) -> None:
    """Set up Dolphin switch based on a config entry."""
    coordinator: UpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
    switches = []

    for device in coordinator.data.keys():
        switches.append(ShabbatSwitch(hass=hass, coordinator=coordinator, device=device))
        switches.append(FixedTemperature(hass=hass, coordinator=coordinator, device=device))
        for switch in range(1, 7):
            switches.append(DropSwitch(hass=hass, coordinator=coordinator, index=switch, device=device))

    async_add_entities(switches)

class DropSwitch(CoordinatorEntity, SwitchEntity):

    def __init__(self, hass, coordinator, index, device):
        CoordinatorEntity.__init__(self, coordinator)
        self._hass = hass
        self._id = index
        self._coordinator = coordinator
        self._device = device
        self._is_on = False
        self.entity_id = async_generate_entity_id(DOMAIN + ".{}", None or f"{device}_drop{index}", hass=hass)

    @property
    def unique_id(self):
        return self.entity_id

    @property
    def name(self):
        if self._coordinator.data[self._device].showerTemperature != None:
            showerTemperature = self._coordinator.data[self._device].showerTemperature[self._id - 1]['temp'] if len(
                self._coordinator.data[self._device].showerTemperature) > self._id - 1 else None
        else:
            showerTemperature = None
        return f"{self._id} Shower - {showerTemperature}°C" if self._id == 1 else f"{self._id} Showers - {showerTemperature}°C"

    @property
    def icon(self):
        return "mdi:shower"

    @property
    def available(self):
        """Return availability."""
        if self._coordinator.data[self._device].shabbat:
            return False
        if self._coordinator.data[self._device].power and not self._is_on:
            return False
        if self._coordinator.data[self._device].fixedTemperature:
            return False
        if self._coordinator.data[self._device].showerTemperature != None:
            if len(self._coordinator.data[self._device].showerTemperature) > self._id - 1:
                return True

        return False

    @property
    def is_on(self):
        if not self._coordinator.data[self._device].power:
            self._is_on = False
        return self._is_on

    @property
    def device_info(self) -> DeviceInfo:
        """Return the device info."""
        return DeviceInfo(
            identifiers={
                (DOMAIN, self._device)
            },
        )

    async def async_turn_on(self):

        current_temp = self._coordinator.data[self._device].temperature
        drop_temperature = self._coordinator.data[self._device].showerTemperature[self._id - 1]['temp']

        if current_temp <= drop_temperature and self._coordinator.data[self._device].power == False:
            await self._coordinator.dolphin.turnOnManually(self._coordinator.dolphin._user, drop_temperature,
                                                           self._device)
            self._is_on = True
            await self.coordinator.async_request_refresh()
            self.async_write_ha_state()

    async def async_turn_off(self):

        await self._coordinator.dolphin.turnOffManually(self._coordinator.dolphin._user, self._device)
        self._is_on = False
        await self.coordinator.async_request_refresh()
        self.async_write_ha_state()

class ShabbatSwitch(CoordinatorEntity, SwitchEntity):

    def __init__(self, hass, coordinator, device):
        CoordinatorEntity.__init__(self, coordinator)
        self._hass = hass
        self._coordinator = coordinator
        self._device = device
        self.entity_id = async_generate_entity_id(DOMAIN + ".{}", None or f"{device}_sabbath_mode", hass=hass)

    @property
    def unique_id(self):
        return self.entity_id

    @property
    def name(self):
        return "Sabbath mode"

    @property
    def icon(self):
        return "mdi:star-david"

    @property
    def device_info(self) -> DeviceInfo:
        """Return the device info."""
        return DeviceInfo(
            identifiers={
                (DOMAIN, self._device)
            },
            name=self.name,
        )

    @property
    def is_on(self):
        return self._coordinator.data[self._device].shabbat

    async def async_turn_on(self):
        await self._coordinator.dolphin.enableShabbat(self._coordinator.dolphin._user, self._device)
        self._coordinator.data[self._device].shabbat = True
        self.async_write_ha_state()

    async def async_turn_off(self):
        await self._coordinator.dolphin.disableShabbat(self._coordinator.dolphin._user, self._device)
        self._coordinator.data[self._device].shabbat = False
        self.async_write_ha_state()

class FixedTemperature(CoordinatorEntity, SwitchEntity):

    def __init__(self, hass, coordinator, device):
        CoordinatorEntity.__init__(self, coordinator)
        self._hass = hass
        self._coordinator = coordinator
        self._device = device
        self.entity_id = async_generate_entity_id(DOMAIN + ".{}", None or f"{device}_fixed_temperature", hass=hass)

    @property
    def unique_id(self):
        return self.entity_id

    @property
    def name(self):
        return "Fixed temperature"

    @property
    def icon(self):
        return "mdi:home-thermometer-outline"

    @property
    def device_info(self) -> DeviceInfo:
        """Return the device info."""
        return DeviceInfo(
            identifiers={
                (DOMAIN, self._device)
            },
            name=self.name,
        )

    @property
    def is_on(self):
        return self._coordinator.data[self._device].fixedTemperature

    async def async_turn_on(self):
        await self._coordinator.dolphin.turnOnFixedTemperature(self._coordinator.dolphin._user, self._device,
                                                               self._coordinator.data[self._device].targetTemperature)
        self._coordinator.data[self._device].fixedTemperature = True
        await self.coordinator.async_request_refresh()
        self.async_write_ha_state()

    async def async_turn_off(self):
        await self._coordinator.dolphin.turnOffFixedTemperature(self._coordinator.dolphin._user, self._device)
        self._coordinator.data[self._device].fixedTemperature = False
        await self.coordinator.async_request_refresh()
        self.async_write_ha_state()


import mxnet as mx
import time
import gluoncv as gcv
from gluoncv.utils import try_import_cv2

cv2 = try_import_cv2()

net = gcv.model_zoo.get_model(
    # good, fast
    'ssd_512_mobilenet1.0_coco',
    # 'ssd_512_mobilenet1.0_voc',
    # 'ssd_512_mobilenet1.0_voc_int8',
    #
    # 'yolo3_mobilenet1.0_coco',
    # 'yolo3_mobilenet1.0_voc',
    # too slow...
    # 'faster_rcnn_resnet50_v1b_voc',  # too slow...
    # 'faster_rcnn_fpn_syncbn_resnest50_coco',  # too slow...
    pretrained=True)

net.hybridize()

cap = cv2.VideoCapture(0)
time.sleep(1)

while(True):

    ret, frame = cap.read()
    k = cv2.waitKey(1)
    if k == ord('q'):
        break

    frame = mx.nd.array(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)).astype('uint8')

    rgb_nd, frame = gcv.data.transforms.presets.ssd.transform_test(
        frame, short=512, max_size=700
    )
    # rgb_nd, frame = gcv.data.transforms.presets.yolo.transform_test(
    #     frame, short=512, max_size=700
    # )
    # rgb_nd, frame = gcv.data.transforms.presets.rcnn.transform_test(
    #     frame, short=512, max_size=700
    # )

    class_IDs, scores, bounding_boxes = net(rgb_nd)

    img = gcv.utils.viz.cv_plot_bbox(frame,
                                     bounding_boxes[0],
                                     scores[0],
                                     class_IDs[0],
                                     class_names=net.classes)
    gcv.utils.viz.cv_plot_image(img)
    cv2.waitKey(1)

cap.release()
cv2.destroyAllWindows()


'''
    Collection of helper function for the EDA notebooks
'''

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

''' Returns the pairs of variables sorted according to their correlation '''
def getCorrPairs(corr):

    mask = np.zeros_like(corr, dtype=bool)
    mask[np.triu_indices_from(mask)] = True
    corr[mask] = np.nan
    pairs = corr.abs().unstack()
    pairs = pairs.sort_values(ascending = False)

    return pairs

''' Imputes a predictor timeSeries'''
def imputeTS(timeSeries):

    if 'capacity' in timeSeries.name:
        res = _imputeCapacity(timeSeries)
    else:
        res = _imputeGeneric(timeSeries)

    return res

''' Imputes a generic time-series by interpolation or year-ahead, year-prior values '''
def _imputeGeneric(timeSeries,
                  hoursInWeek = 24 * 1,
                  hoursInYear = 24 * 364):

    # Interpolate at most 1 week forwards/backwards in time
    timeSeries = timeSeries.interpolate(
        method          = 'time',
        limit           = hoursInWeek,
        limit_area      = 'inside',
        limit_direction = 'both')

    # Roll-back one year and impute remaining blocks (fills in gaps mostly at the beginning of the time-series)
    timeSeries = timeSeries.combine_first(timeSeries.shift(-hoursInYear))

    # Roll-forward one year and impute (fills in gaps mostly at the end of the time-series)
    timeSeries = timeSeries.combine_first(timeSeries.shift(hoursInYear))

    # Re-interpolate any nans remaining
    timeSeries = timeSeries.interpolate(
        method          = 'time',
        limit_area      = 'inside',
        limit_direction = 'both')

    return timeSeries

''' Imputes capacity timeseries by padding'''
def _imputeCapacity(timeSeries):

    return timeSeries.fillna(method = 'pad')

''' Plots original / imputed time-series'''
def plotImputation(originalTS, imputedTS, withMean = False, hoursInMonth = 24 * 7 * 4):

    imputedTS[~originalTS.isnull()] = np.nan

    plt.figure(figsize = (15, 3))
    plt.plot(originalTS, linewidth = 0.5)
    plt.plot(imputedTS,  linewidth = 0.5)

    if withMean:
        monthMean = imputedTS.rolling(hoursInMonth).mean()
        plt.plot(monthMean, color = 'k')
        plt.legend(['Original', 'Imputed', 'Monthly avg. (rolling)'], ncol = 3);
    else:
        plt.legend(['Original', 'Imputed'], ncol = 2);

    plt.title(originalTS.name + ' Imputed');

    return

''' Fixes information for the areas.csv dataframe '''
def makeAreaMetadata(df):

    df = df.where(pd.notnull(df), None)
    countries, a2Codes, mapCodes, pAreas, bZones, cAreas, mAreas = [], [], [], [], [], [], []

    for _, row in df.iterrows():

        a2code = row['area ID'].split('_')[0]

        if a2code == 'CS': country = 'SerbiaMontenegro' # Does not exist in pycountry
        else:              country = pycountry.countries.get(alpha_2 = a2code).name

        mapcode      = a2code
        primary_area = country + '_default'
        bidZone      = country + '_default'
        control_area = country + '_default'
        market_area  = country + '_default'

        if row['country'] is None: countries.append(country)
        else:                      countries.append(row['country'])

        if row['ISO 3166-1 alpha-2'] is None: a2Codes.append(a2code)
        else:                                 a2Codes.append(row['ISO 3166-1 alpha-2'])

        if row['MapCode ENTSO-E'] is None: mapCodes.append(mapcode)
        else:                              mapCodes.append(row['MapCode ENTSO-E'])

        if row['primary AreaName ENTSO-E'] is None: pAreas.append(primary_area)
        else:                                       pAreas.append(row['primary AreaName ENTSO-E'])

        if row['bidding zone'] is None: bZones.append(bidZone)
        else:                           bZones.append(row['bidding zone'])

        if row['control area'] is None: cAreas.append(control_area)
        else:                           cAreas.append(row['control area'])

        if row['market balance area'] is None: mAreas.append(market_area)
        else:                                  mAreas.append(row['market balance area'])

    df['country']                  = countries
    df['ISO 3166-1 alpha-2']       = a2Codes
    df['MapCode ENTSO-E']          = mapCodes
    df['primary AreaName ENTSO-E'] = pAreas
    df['bidding zone']             = bZones
    df['control area']             = cAreas
    df['market balance area']      = mAreas

    return df

''' Returns areaIDs per concept type'''
def _getAreas(primaryConcept, df):
    return df[df['primary concept'] == primaryConcept]['area ID'].unique().tolist()

''' Checks if a column name appears in a list of area codes and returns area code'''
def areaID(fieldName, conceptType, df):

    for area in _getAreas(conceptType, df):

        if isinstance(area, str):
            if area in fieldName:
                return area

    return None


from collections import Counter
import logging

def find(list, value):
    try:
        return list.index(value)
    except ValueError:
        return None

class DefaultSorter(object):
    def __init__(self, langs='all', weight=1):
        logging.info("Available languages: {}".format(langs))
        self.langs = langs.split(',')

    def bestfn(self, subentry):
        idx = find(self.langs, subentry['SubLanguageID'])
        value = idx if idx is not None else len(self.langs)
        return value

def _similarity(a, b):
    make_pairs = lambda l: (l[i:i+1] for i in xrange(len(l)-1))
    tc = lambda counter: sum(count for count in counter.values())
    sa = Counter(make_pairs(a))
    sb = Counter(make_pairs(b))
    return 2.0 * tc(sa & sb) / (tc(sa) + tc(sb))

class SimilaritySorter(DefaultSorter):
    def __init__(self, langs='all'):
        super(SimilaritySorter, self).__init__(langs)
        self.movie = ''

    def bestfn(self, subentry):
        value = super(SimilaritySorter, self).bestfn(subentry)
        sn = subentry['SubFileName']
        similarity = _similarity(sn[:sn.rindex('.')], self.movie)
        logging.info("{}: Similarity is {}, lang {}".format(
            subentry['SubFileName'], similarity, subentry['SubLanguageID']))
        return 1.1 * value + 1 - similarity


#This file "drives" the car by calling all the required files
#outputs plots of the dynamic/vibration models

import Beeman, car_2014, chassis_2014, driver_sally, ff_2014_5, ff_2014_7, get_DM, get_FF, get_Jx, get_Jy, get_LR, get_MM, get_SD, get_SM, get_cg, motor_2014, speed_bump, suspension_front_2014, suspension_rear_2014, trajectory, wheel_front_2014, wheel_rear_2014
import numpy as np, math
import matplotlib.pyplot as plt

#creating arguments into Beeman
ff = ff_2014_7.ff_data
ffmatrix, ffobject = get_FF.get_FF(ff['t_in'],ff)
X0 = get_SD.get_SD(ff['model'],ff['car'])
DOF = X0.shape[0]
V0 = np.zeros((DOF,1))
A0 = np.zeros((DOF,3))
M = get_MM.get_MM(ff['model'],ff['car'])
C = get_DM.get_DM(ff['model'],ff['car'])
K = get_SM.get_SM(ff['model'],ff['car'])
#create data
T7, X7, V7, A7 = Beeman.Beeman(X0,V0,A0,M,C,K,get_FF.get_FF,ffobject)

#Heave
plt.plot(T7,X7[:,0])
plt.show()

#Pitch


# -*- coding: utf-8 -*-
"""
Created on Tue Jun  6 13:11:44 2017

@author: Francesco
"""

import serial
import numpy as np
import time

PORT = "COM10"
BAUD = 115200
port = serial.Serial(PORT,BAUD,timeout=1)

START = 1
#BUNDLE SHAPE: |!|!|!|CH0_msb|CH0_lsb|ch1_msb|ch1_lsb|......|ch7_lsb|!|!|!|

NUM_CHANNELS = 8
END_BUNDLE_BYTE = 3
BYTE_PER_CHANNEL = 2 #two bytes to represent int
BUNDLE_LENGTH = NUM_CHANNELS*BYTE_PER_CHANNEL

data = np.zeros(NUM_CHANNELS)

graph_data = open('test_100Hz.txt','w')

print("Gathering recordings for dataset")

movement_time = 2 #2.5 seconds for each movement
sample_time = 0.01 # 100Hz sample frequency
num_samples = int(movement_time/sample_time)
#num_samples = 300
counter = 0
while(START):
    try:
        #print("Flushing")
        #port.flushInput()

        movement = input("\n\
                          0: wrist up\n\
                          1: wrist down\n\
                          2: wrist rotation out\n\
                          3: wrist rotation inside\n\
                          4: hand open\n\
                          5: hand closed\n")
        if(movement == 's'):
            graph_data.close()
            print(port.inWaiting())
            port.close()
            break

        #start communication, for some reason with utf-8 it works

        #start_time = time.time()
        elapsed = 0
        counter = 0
        starttime = time.time()

        while(elapsed < 2):
            port.write('s'.encode('utf-8'))
            a = port.read(END_BUNDLE_BYTE)
            #print(a)
            if(a.decode("raw_unicode_escape") == '!!!'):
                temp = port.read(BUNDLE_LENGTH)

                #unpack values and put them in "data"
                for channel in range(0,NUM_CHANNELS):
                    value = (temp[channel*BYTE_PER_CHANNEL]<<8)|(temp[channel*BYTE_PER_CHANNEL + 1 ])
                    graph_data.write(str(value))
                    graph_data.write(',')
                    #print(value)

                #start a new line in the file
                graph_data.write(movement+'\n')

                #wait the sample time to get a new value
                #time.sleep(sample_time)
                elapsed = time.time() - starttime
                #è allineato con l'if
                #perchè deve aumentare il counter solo quando scrive
                #counter += 1
                #port.write('o'.encode('utf-8'))
                #print(port.inWaiting())

        #write the separator between one movement and the other
        graph_data.write('-\n')
        #any character except 's' is ok to stop the communication
        #port.write('o'.encode('utf-8'))
        print("Movement Acquired - Elapsed Time: %d"%movement_time)

    except KeyboardInterrupt:
        print("Closing")
        port.close()
        graph_data.close()
        break


from flask import Flask, request, jsonify, render_template, send_file
import os
import csv
import json
import base64
import pickle
import logging
from utils import (set_license_key_in_config, get_license_key_from_config,
                    get_dynamodb_table, license_key_is_valid)

# Configure the logging level
logging.basicConfig(level=logging.INFO)

# Get the logger for the current module
logger = logging.getLogger(__name__)

# Create a handler that writes log messages to a file
handler = logging.FileHandler('error.log')

# Create a formatter that specifies the format of the log messages
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

PORT = 8323

# For Production
# app = Flask(__name__,
#             static_folder='frontend/static/', static_url_path='/static/',
#             template_folder='frontend/templates')

# For Development
app = Flask(__name__,
            static_folder='../frontend/static/', static_url_path='/static/',
            template_folder='../frontend/templates')

base_path = os.path.join(app.root_path, 'frontend', 'media')

def remove_uploaded_background_images():
    import glob

    pattern = os.path.join(base_path, 'Background-Image*.png')

    # Using glob to find all matching files
    for file_path in glob.glob(pattern):
        if os.path.exists(file_path):
            os.remove(file_path)
            print(f"Removed: {file_path}")

@app.route('/admin/')
def view_admin_page():
    try:
        license_key = get_license_key_from_config()
        csv_file_path = os.path.join(app.root_path, 'participants.csv')
        if os.path.exists(csv_file_path):
            os.remove(csv_file_path)

        # Remove uploaded images
        remove_uploaded_background_images()

        return render_template('adminPage.html', license_key=license_key)
    except Exception as e:
        logger.error(e)
        print(e)
        # raise(e)
        return "An Error Occurred!"

@app.route('/home/')
def view_home_screen():
    try:
        pickle.dump(dict(request.args), open('admin_conf.pkl', 'wb'))
        return render_template('main.html')
    except Exception as e:
        print(e)
        logger.error(e)
        return 'An error occurred'

@app.route('/saveCSVData/', methods=['POST'])
def save_csv():
    try:
        if request.method == 'POST':
            csv_data = request.get_data()
            # Decode the bytes to string
            csv_data_str = csv_data.decode('utf-8').replace('\\n', '\n').replace('\\r', '').strip('"').replace('\\', '').replace('\\\\','').replace('X', '')
            # Remove extra quotes
            csv_data_str = csv_data_str.replace('\"', '')
            # Split the string into a list of lines
            csv_data_lines = csv_data_str.splitlines()

            numbers = [line.split(',')[0] for line in csv_data_lines[1:]]
            names = [f"{line.split(',')[1]} {line.split(',')[2]}" for line in csv_data_lines[1:]]

            if len(set(numbers)) != len(numbers):
                return jsonify({"error": "All numbers provided in the table must be unique."}), 400

            # Numbers input handling
            for idx, number in enumerate(numbers):
                if not number:
                    return jsonify({"error": f"The number at [ROW # {idx + 1}] cannot be empty."}), 400

                if len(number) > 4:
                    return jsonify({"error": f"The length of {number} at [ROW # {idx + 1}] cannot be more than 4 letters."}), 400

                if not number.isdigit():
                    return jsonify({"error": f"{number} at [ROW # {idx + 1}] is not a valid digit/number."}), 400

            # NAMES must not be empty, input handling
            for idx, name in enumerate(names):
                if name == ' ':
                    return jsonify({"error": f"The name at [ROW # {idx + 1}] cannot be empty."}), 400

            new_csv_data_lines = []
            for line in csv_data_lines[1:]:
                line = line.rstrip(',')
                if line:
                    cell = line.split(',')[0]
                    if not cell.isdigit():
                        continue
                    new_csv_data_lines.append(line)

            csv_data_lines = new_csv_data_lines

            if len(csv_data_lines) < 50:
                return jsonify({"error": "Participants cannot be less than 50"}), 400

            if len(csv_data_lines) > 300:
                return jsonify({"error": "Participants cannot be more than 300"}), 400

            # Open a file in write mode
            with open('participants.csv', newline='', mode='w') as file:
                writer = csv.writer(file)

                # Write each line to the CSV file
                for line in csv_data_lines:
                    writer.writerow(line.split(','))

            return jsonify({"success": f"File has been saved at: participants.csv"})
        else:
            return jsonify({"error": "POST request required."}), 400
    except Exception as e:
        logger.error(e)
        return jsonify({'error': 'An error occurred'}), 500

@app.route('/getCSVData/')
def view_saved_csv():
    try:
        file_path = 'participants.csv'
        if os.path.exists(file_path):
            data_list = []
            with open(file_path, newline='') as f:
                csv_data = csv.reader(f)
                # headers = next(csv_data, None)  # returns the headers or `None` if the input is empty
                headers = ['assign-number', 'first-name', 'last-name', 'date-added']
                if headers:
                    for row in csv_data:
                        data_list.append({headers[i]: value for i, value in enumerate(row)})
                return jsonify({"data": data_list})
        else:
            return jsonify({"error": "File not found"}), 404

    except Exception as e:
        logger.error(e)
        return jsonify({'error': 'An error occurred'}), 500

@app.route('/getAdminConf/')
def get_admin_conf():
    try:
        obj = pickle.load(open('admin_conf.pkl', 'rb'))
        return jsonify(obj)
    except Exception as e:
        logger.error(e)
        return jsonify({'error': 'An error occurred'}), 500

@app.route('/saveImage/', methods=['POST'])
def save_image():
    try:
        if request.method == 'POST':
            data = json.loads(request.get_data(as_text=True))
            image_name = data.get('image_name', None)
            img_data = data['image'].split(',')[1]  # Split off the header, keep only the actual image content
            img_data = base64.b64decode(img_data)
            file_path = os.path.join(base_path, 'frontend', f'media', f'{image_name}.png')  # Or where you want to save it

            if image_name == 'Logo':
                file_path = os.path.join(fr'media\{image_name} Uploaded.png')  # Or where you want to save it

            elif image_name == None:
                # Background Image Uploaded
                file_path = get_image_path_name()

            with open(file_path, 'wb') as f:
                f.write(img_data)

            return jsonify({"message": "Image saved successfully.", 'file_path': file_path})
        else:
            return jsonify({"error": "Wrong method type."})

    except Exception as e:
        logger.error(e)
        return jsonify({'error': 'An error occurred'}), 500

@app.route('/validateLicenseKey/<string:licenseKey>/', methods=['POST'])
def view_validate_license_key(licenseKey):
    try:
        table = get_dynamodb_table()
        licenseCreatedDate = license_key_is_valid(licenseKey, table)
        # If license exists, write/update it to config file
        if licenseCreatedDate:
            set_license_key_in_config(licenseKey, licenseCreatedDate)
            return jsonify({'success': 'License Key successfully validated'}), 200
        return jsonify({'error': 'License Key couldn\'t be validated'}), 404

    except Exception as e:
        from traceback import print_exc
        logger.error(e)
        print_exc()
        return jsonify({'error': str(e)}), 500

@app.route('/licenseKeyIsValid/')
def view_license_key_validated():
    license_key = get_license_key_from_config()
    if license_key:
        return jsonify({'success': 'License Key is validated!'}), 200
    return jsonify({'error': 'Please enter a valid License Key in order to use this software.'}), 400

@app.route('/media/<filename>')
def get_media_file(filename):
    return send_file(os.path.join('../frontend', 'media', filename))

def get_image_path_name():
    # Background Image Uploaded
    file_name = 'Background-Image'
    extension = '.png'
    counter = 0

    # Loop to find the next available file name
    while True:
        if counter == 0:
            file_path = os.path.join(base_path, f'{file_name}{extension}')
        else:
            file_path = os.path.join(base_path, f'{file_name} {counter}{extension}')

        # Check if file already exists
        if not os.path.exists(file_path):
            break # Exit loop if file does not exist

        counter += 1

    return file_path

if __name__ == "__main__":
    app.run(port=PORT)


from subprocess import Popen, PIPE
import sys

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog

from config import config
from theme import theme

class PluginGui:

    _route = None
    _button = None
    _target = None

    def __init__(self, parent, route):
        self._route = route

        self._button = tk.Frame(parent)
        g = {'row': 1, 'column': 1, 'sticky': tk.NSEW}
        self._button_open = ttk.Button(self._button)
        self._button_open.grid(g)
        self._button_open.configure(command=self._load_route)
        self._button_open.bind('<Double-Button-1>', self._clear_route)

        self._button_theme = tk.Label(self._button)
        self._button_theme.grid(g)
        self._button_theme.bind('<Double-Button-1>', self._clear_route)
        theme.register_alternate((self._button_open, self._button_theme), g)
        theme.button_bind(self._button_theme, self._load_route)

        self._target = tk.Label(parent, text='', anchor=tk.W)
        self._target.bind('<Button-1>', self._to_clipboard)

        self.update_ui()

    def get_ui(self):
        return (self._button, self._target)

    def update_ui(self):
        waypoints = len(self._route)
        if waypoints == 0:
            self._button_open['text'] = '  Open  '
            self._target['text'] = 'no waypoints'
        else:
            self._button_open['text'] = f'{waypoints}'
            self._target['text'] = self._route.next()
        self._button_theme['text'] = self._button_open['text']
        self._to_clipboard()

    def _to_clipboard(self, event=None):
        if len(self._route) == 0:
            return

        target = self._route.next()
        if sys.platform == "linux" or sys.platform == "linux2":
            command = Popen(["xclip", "-selection", "c"], stdin=PIPE)
            command.communicate(input=target.encode(), timeout=1)
        else:
            self._parent.clipboard_clear()
            self._parent.clipboard_append(target)
            self._parent.update()

    def _clear_route(self, event=None):
        self._route.clear()
        self.update_ui()

    def _load_route(self, event=None):
        if len(self._route) > 0:
            return

        ftypes = [
            ('All supported files', '*.csv *.txt'),
            ('CSV files', '*.csv'),
            ('Text files', '*.txt'),
        ]
        logdir = config.get_str('journaldir',
                                default=config.default_journal_dir)
        filename = filedialog.askopenfilename(initialdir=logdir,
                                              filetypes=ftypes)
        if self._route.load(filename):
            self.update_ui()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""Text Emotion Detection."""

from dataclasses import dataclass

from transformers import AutoTokenizer, AutoModelWithLMHead
from transformers import pipeline

__all__ = (
    "Emotion",
    "EmotionDetectorT5",
    "EmotionDetectorRoberta",
)

@dataclass
class Emotion:
    """Emotion."""

    tag: str
    emoji: str

def get_emotion_emoji(tag: str) -> str:
    # Define the emojis corresponding to each sentiment
    emoji_mapping = {
        "disappointment": "😞",
        "sadness": "😢",
        "annoyance": "😠",
        "neutral": "😐",
        "disapproval": "👎",
        "realization": "😮",
        "nervousness": "😬",
        "approval": "👍",
        "joy": "😄",
        "anger": "😡",
        "embarrassment": "😳",
        "caring": "🤗",
        "remorse": "😔",
        "disgust": "🤢",
        "grief": "😥",
        "confusion": "😕",
        "relief": "😌",
        "desire": "😍",
        "admiration": "😌",
        "optimism": "😊",
        "fear": "😨",
        "love": "❤",
        "excitement": "🎉",
        "curiosity": "🤔",
        "amusement": "😄",
        "surprise": "😲",
        "gratitude": "🙏",
        "pride": "🦁"
    }
    return emoji_mapping.get(tag, "")

class EmotionDetectorT5:
    """Emotion Detector from T5 model."""

    # https://huggingface.co/mrm8488/t5-base-finetuned-emotion/

    # emotions = ["joy", "sad", "dis", "sup", "fea", "ang"]
    # emotions = ["sadness", "joy", "love", "anger", "fear", "surprise"]

    def __init__(self) -> None:
        """Init Sentiment Analysis."""
        self.model_name = "mrm8488/t5-base-finetuned-emotion"
        self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
        self.model = AutoModelWithLMHead.from_pretrained(self.model_name)

    def get(self, text: str) -> Emotion:
        """Check emotion from text string."""
        input_ids = self.tokenizer.encode(text + '</s>', return_tensors='pt')
        output = self.model.generate(input_ids=input_ids,
               max_length=2)
        dec = [self.tokenizer.decode(ids) for ids in output]
        emo = dec[0].replace("<pad>", "").strip()
        return Emotion(tag=emo, emoji=get_emotion_emoji(emo))

class EmotionDetectorRoberta:
    """Emotion Detector from Roberta."""

    # https://huggingface.co/SamLowe/roberta-base-go_emotions

    # emotions = [
    #     "admiration",
    #     "amusement",
    #     "anger",
    #     "annoyance",
    #     "approval",
    #     "caring",
    #     "confusion",
    #     "curiosity",
    #     "desire",
    #     "disappointment",
    #     "disapproval",
    #     "disgust",
    #     "embarrassment",
    #     "excitement",
    #     "fear",
    #     "gratitude",
    #     "grief",
    #     "joy",
    #     "love",
    #     "nervousness",
    #     "optimism",
    #     "pride",
    #     "realization",
    #     "relief",
    #     "remorse",
    #     "sadness",
    #     "surprise",
    #     "neutral",
    # ]

    def __init__(self) -> None:
        """Init."""
        self.model_name = "SamLowe/roberta-base-go_emotions"
        self.nlp = pipeline("sentiment-analysis", framework="pt", model=self.model_name)

    def get(self, text: str) -> Emotion:
        """Get Emotion from text str."""
        try:
            results = self.nlp(text)
        except RuntimeError as err:
            print(f"len(text) = {len(text)}")
            print(f"text: {text}")
            raise(err)

        data = {result['label']: result['score'] for result in results}
        tag, score = "", 0
        for key, value in data.items():
            if value > score:
                tag = key
                score = value
        return Emotion(
            tag=tag,
            emoji=get_emotion_emoji(tag=tag),
        )


#!/usr/bin/env python3
import sys
sys.setrecursionlimit(10**6)
INF = 10 ** 9 + 1  # sys.maxsize # float("inf")
MOD = 10 ** 9 + 7

def debug(*x):
    print(*x, file=sys.stderr)

def solve(N, AS):
    sum = 0
    sumSq = 0
    for i in range(N):
        sum += AS[i]
        sum %= MOD
        sumSq += AS[i] * AS[i]
        sumSq %= MOD

    ret = (sum * sum - sumSq) % MOD
    if ret % 2 == 0:
        return ret // 2
    else:
        return (ret + MOD) // 2

def main():
    # parse input
    N = int(input())
    AS = list(map(int, input().split()))
    print(solve(N, AS))

# tests
T1 = """
3
1 2 3
"""
TEST_T1 = """
>>> as_input(T1)
>>> main()
11
"""

T2 = """
4
141421356 17320508 22360679 244949
"""
TEST_T2 = """
>>> as_input(T2)
>>> main()
437235829
"""

def _test():
    import doctest
    doctest.testmod()
    g = globals()
    for k in sorted(g):
        if k.startswith("TEST_"):
            doctest.run_docstring_examples(g[k], g, name=k)

def as_input(s):
    "use in test, use given string as input file"
    import io
    f = io.StringIO(s.strip())
    g = globals()
    g["input"] = lambda: bytes(f.readline(), "ascii")
    g["read"] = lambda: bytes(f.read(), "ascii")

input = sys.stdin.buffer.readline
read = sys.stdin.buffer.read

if sys.argv[-1] == "-t":
    print("testing")
    _test()
    sys.exit()

main()


#!/bin/python3

import sys
import os
import mysql.connector
import datetime
from sys import argv
import requests
import json
from requests.exceptions import HTTPError
from slack import WebClient
from slack.errors import SlackApiError
import logging
logging.basicConfig(level=logging.DEBUG)

database_conf = "/var/lib/jenkins/engine.cnf"
operator_name_list = argv[1].split(",")
start_payment_date = argv[2]
finish_payment_date = argv[3]
game_cycle_file = "rounds.txt"
default_round_log = "round-close.log"
operator_id_list = []
search_list = ["| closed", "| not closed", "| game cycle is already in completed game cycle table"]
slack_channel = "#customer_support"

def collect_operator_id(operator_name: str) -> int:
    sql_operator_id = ("select operator_id from core_operator where operator_name='{}'".format(operator_name))
    cursor.execute(sql_operator_id)
    operator_results = cursor.fetchall()
    for op_id in operator_results:
        operator_id = op_id[0]
        return operator_id

def collect_game_cycle(operator_data: str):
    sql_game_cycle = """
        SELECT distinct(game_cycle_id) FROM tx_payment_journal a
        left join tx_completed_game_cycle b on a.game_cycle_id=b.payment_reference
        left join tx_player c on a.from_player_id=c.player_id
        where a.transaction_id>=(SELECT transaction_id FROM tx_payment_journal where payment_date >= '{0}' limit 1)
        and a.transaction_id<(SELECT transaction_id FROM tx_payment_journal where payment_date >= '{1}' limit 1)
        and a.to_player_id=1 and a.complete=1 and a.cancelled=0 and a.current_balance>0 and b.completed_tx_id is null
        and c.operator_id={2};""".format(start_payment_date, finish_payment_date, operator_data)
    print(sql_game_cycle)
    cleanup(game_cycle_file)
    cursor.execute(sql_game_cycle)
    result_table = cursor.fetchall()
    for collumn in result_table:
        game_cycle = collumn[0]
        with open(game_cycle_file, "a") as rounds_list:
            rounds_list.write("{}\n".format(game_cycle))

def close_rounds(operator_id_close: int):
    try:
        if os.path.exists(game_cycle_file):
            print("*** Closing game rounds")
            cleanup(default_round_log)
            os.system("cp /var/lib/jenkins/devops-prod/scripts/close_rounds/application.properties .")
            os.system("java -jar /var/lib/jenkins/devops-prod/scripts/close_rounds/close-round.jar {0} {1}".format(game_cycle_file, operator_id_close))
        else:
            print("*** No rounds were collected from database, please check data.")
            open(default_round_log, "a").close()
    except OSError as e:
        print("*** Error occurs: {}".format(sys.exc_info()[1]))
        exit()

def notify_slack(operator_data: str, prev_date: str, now_date: str, pattern: str, pattert_count: str):
    slack_token = "xoxp-229522615970"
    client = WebClient(token=slack_token)
    user="jenkins-bot"
    try:
        if pattern == "game cycle is already in completed game cycle table":
            completed_pattern = "already closed"
            response = client.chat_postMessage(
                channel = slack_channel,
                text = """Finished processing issued rounds for {0} operator:
                        Period: {1} - {2}
                        Rounds {3}: {4}
                     """.format(operator_data.replace(" ", ""), prev_date, now_date, completed_pattern, pattert_count)
            )
        else:
            response = client.chat_postMessage(
                channel = slack_channel,
                text = """Finished processing issued rounds for {0} operator:
                        Period: {1} - {2}
                        Rounds {3}: {4}
                     """.format(operator_data.replace(" ", ""), prev_date, now_date, pattern, pattert_count)
            )
        if os.path.exists(filename):
            response = client.files_upload(
                channels = slack_channel,
                file = filename,
                title = custom_pattern
            )
    except SlackApiError as e:
        # You will get a SlackApiError if "ok" is False
        assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
    except FileNotFoundError as e:
        print("*** Pattern for search was not found: {}".format(sys.exc_info()[1]))

def parse_log(message: str, operatorname: str):
    global total_pattert_count
    global custom_pattern
    global filename

    custom_pattern = message.replace("| ", "")
    if message == "| closed":
        filename = "Rounds_closed.log"
    elif message == "| not closed":
        filename = "Rounds_not_closed.log"
    elif message == "| game cycle is already in completed game cycle table":
        filename = "Rounds_already_closed.log"
    total_pattert_count = 0
    with open(default_round_log, "r") as log_file:
        for line in log_file:
            if message in line:
                total_pattert_count += 1
                with open(filename, "a") as closed_rounds:
                    closed_rounds.write(line)
    print("File was created: {}".format(filename))
    notify_slack(operatorname, start_payment_date, finish_payment_date, custom_pattern, total_pattert_count)
    cleanup(filename)

def cleanup(item: str):
    try:
        if os.path.exists(item):
            os.system("rm -rf {}".format(item))
            print("*** {} was successfully removed from workspace".format(item))
    except OSError as e:
        print("*** Error occurs: {}".format(sys.exc_info()[1]))
        exit()

def main():
    try:
        db_connection = mysql.connector.connect(option_files=database_conf, option_groups="client")
        cursor = db_connection.cursor()
        for operator in operator_name_list:
            print("Processing {} operator:".format(operator))
            collect_game_cycle(collect_operator_id(operator))
            close_rounds(collect_operator_id(operator))
            for search_pattern in search_list:
                parse_log(search_pattern, operator)

    except mysql.connector.Error as e:
        print("*** ERROR: {}".format(e.msg))
        exit()
    finally:
        if (db_connection.is_connected()):
            db_connection.close()
            cursor.close()
        cleanup(game_cycle_file)
        cleanup(default_round_log)

if __name__ == '__main__':
    main()