import pygame
from random import randrange

# O pygame usa o sistema RGB (Red, Green, Blue) para definição de cores e utiliza tupla.
branco = (255, 255, 255)
preto = (0, 0, 0,)
vermelho = (255, 0, 0)
verde = (0, 255, 0)
azul = (0, 0, 255)

try:
    pygame.init()
except:
    print('O módulo pygame não foi inicializado com sucesso!')

largura = 320
altura = 280
tamanho = 10
placar = 40
velocidade_x = 0
velocidade_y = 0

# Variável que recebe parte do comando limitador de frames
relogio = pygame.time.Clock()

# Define o tamanho da tela, sendo a larguar e o altura apresentado em uma tupla
fundo = pygame.display.set_mode((largura, altura))
# Define o nome da janela
pygame.display.set_caption('Snake')

def texto(msg, cor, tam, x, y):
    font = pygame.font.SysFont(None, tam)
    texto1 = font.render(msg, True, cor)
    fundo.blit(texto1, [x, y])

def cobra(CobraXY):
    for XY in CobraXY:
        pygame.draw.rect(fundo, preto, [XY[0], XY[1], tamanho, tamanho])

def maca(pos_x, pos_y):
    pygame.draw.rect(fundo, vermelho, [pos_x, pos_y, tamanho, tamanho])

def lerArquivo(nome):
    try:
        a = open(nome, 'rt')
    except:
        print('ERRO ao ler o arquivo!')
    else:
        c = 0
        for linha in a:
            dado = linha.split(';')
            dado[1] = dado[1].replace('\n', '')
            print(f'{dado[0]:<30}{dado[1]:>5} pontos')
            texto(dado[0], preto, 20, 10, 50 + (20 * c))
            texto(dado[1], preto, 20, 200, 50 + (20 * c))
            c += 1
    finally:
        a.close()

def cadastrar(arq, nome='desconhecido', pontuação=0):
    try:
        a = open(arq, 'at')
    except:
        print('Houve um ERRO na abertura do arquivo!')
    else:
        try:
            a.write(f'{nome};{pontuação}\n')
        except:
            print('Houve um ERRO na hora de escrever os dados!')
        else:
            print(f'Novo cadastro de {nome} com {pontuação} foi adicionado.')

def ranking():
    rankon = True
    while rankon:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return False
        fundo.fill(branco)
        texto('Nome', preto, 40, 10, 10)
        texto('Pontuação', preto, 40, 150, 10)
        lerArquivo('Ranking.txt')
        pygame.display.update()

def menu():
    menu_on = True
    sairranking = False
    while menu_on:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                x = pygame.mouse.get_pos()[0]
                y = pygame.mouse.get_pos()[1]
                if 90 <= x <= 230 and 100 <= y <= 150:
                    menu_on = False
                    return True
                if 90 <= x <= 230 and 160 <= y <= 210:
                    sairranking = ranking()
                    if not sairranking:
                        menu_on = False
                        return False
                if 90 <= x <= 230 and 220 <= y <= 270:
                    return False
        fundo.fill(branco)
        texto('SNAKE', preto, 80, 60, 30)
        pygame.draw.rect(fundo, preto, [90, 100, 140, 50])
        texto('Jogar', branco, 40, 120, 110)
        pygame.draw.rect(fundo, preto, [90, 160, 140, 50])
        texto('Ranking', branco, 40, 102, 170)
        pygame.draw.rect(fundo, preto, [90, 220, 140, 50])
        texto('Sair', branco, 40, 130, 232)
        pygame.display.update()

def jogo(naosair):
    sair = naosair
    fimdejogo = False
    pos_x = randrange(0, largura - tamanho, 10)
    pos_y = randrange(0, altura - tamanho - placar, 10)
    maca_x = randrange(0, largura - tamanho, 10)
    maca_y = randrange(0, altura - tamanho - placar, 10)
    velocidade_x = 0
    velocidade_y = 0
    CobraXY = []
    CobraComp = 1
    pontos = 0
    while sair:
        while fimdejogo:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sair = False
                    fimdejogo = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_c:
                        sair = True
                        fimdejogo = False
                        pos_x = randrange(0, largura - tamanho, 10)
                        pos_y = randrange(0, altura - tamanho - placar, 10)
                        maca_x = randrange(0, largura - tamanho, 10)
                        maca_y = randrange(0, altura - tamanho - placar, 10)
                        velocidade_x = 0
                        velocidade_y = 0
                        CobraXY = []
                        CobraComp = 1
                        pontos = 0
                    if event.key == pygame.K_s:
                        sair = False
                        fimdejogo = False
                if event.type == pygame.MOUSEBUTTONDOWN:
                    x = pygame.mouse.get_pos()[0]
                    y = pygame.mouse.get_pos()[1]
                    if 45 < x < 180  and 120 < y < 147:
                        sair = True
                        fimdejogo = False
                        pos_x = randrange(0, largura - tamanho, 10)
                        pos_y = randrange(0, altura - tamanho - placar, 10)
                        maca_x = randrange(0, largura - tamanho, 10)
                        maca_y = randrange(0, altura - tamanho - placar, 10)
                        velocidade_x = 0
                        velocidade_y = 0
                        CobraXY = []
                        CobraComp = 1
                        pontos = 0
                    elif 190 < x < 265 and 120 < y < 147:
                        sair = False
                        fimdejogo = False
            fundo.fill(branco)
            texto('Fim de jogo', vermelho, 50, 65, 30)
            texto('Pontuação Final: ' + str(pontos), preto, 30, 70, 80)
            pygame.draw.rect(fundo, preto, [45, 120, 135, 27])
            texto('Continuar(C)', branco, 30, 50, 125)
            pygame.draw.rect(fundo, preto, [190, 120, 75, 27])
            texto('Sair(S)', branco, 30, 195, 125)
            pygame.display.update()
        # Identifica um comando do teclado
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sair = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT and velocidade_x != tamanho:
                    velocidade_x = -tamanho
                    velocidade_y = 0
                if event.key == pygame.K_RIGHT and velocidade_x != -tamanho:
                    velocidade_x = tamanho
                    velocidade_y = 0
                if event.key == pygame.K_UP and velocidade_y != tamanho:
                    velocidade_x = 0
                    velocidade_y = -tamanho
                if event.key == pygame.K_DOWN and velocidade_y != -tamanho:
                    velocidade_x = 0
                    velocidade_y = tamanho
        if sair:
            # Estabelece como branco o fundo
            fundo.fill(branco)
            for c in range(0, largura, 10):
                pygame.draw.rect(fundo, preto, [c, 0, 1, altura])
            for c in range(0, altura, 10):
                pygame.draw.rect(fundo, preto, [0, c, largura, 1])
            # Faz um forma quadrilátera usando a tela, cor do objeto e a posição XY e a extenção de cada eixo.
            pos_x += velocidade_x
            pos_y += velocidade_y
            if pos_x == maca_x and pos_y == maca_y:
                maca_x = randrange(0, largura - tamanho - placar, 10)
                maca_y = randrange(0, altura - tamanho - placar, 10)
                CobraComp += 1
                pontos += 1
            if pos_x + tamanho > largura:
                pos_x = 0
            if pos_x < 0:
                pos_x = largura - tamanho
            if pos_y + 10 > altura - placar:
                pos_y = 0
            if pos_y < 0:
                pos_y = altura - tamanho - placar
            # Finaliza o jogo se o usuário atingir uma das paredes
            #if pos_x + tamanho > largura:
            #    fimdejogo = True
            #if pos_x < 0:
            #    fimdejogo = True
            #if pos_y + tamanho > altura:
            #    fimdejogo = True
            #if pos_y < 0:
            #    fimdejogo = True
            CobraInicio = []
            CobraInicio.append(pos_x)
            CobraInicio.append(pos_y)
            CobraXY.append(CobraInicio)
            if len(CobraXY) > CobraComp:
                del CobraXY[0]
            for bloco in CobraXY:
                c = CobraXY.count(bloco)
                if c == 2:
                    fimdejogo = True
            pygame.draw.rect(fundo, preto, [0, altura - placar, largura, placar])
            texto('Pontuação: ' + str(pontos), branco, 20, 10, altura - 30)
            cobra(CobraXY)
            maca(maca_x, maca_y)
            # Atualiza a tela em exibição
            pygame.display.update()
            # LIMITA o loop a 15 frames por segundo
            relogio.tick(15)

escolha = menu()
jogo(escolha)
# Encerra o sistema
pygame.quit()


import re
import enum
import sys
from os.path import exists

# Set holding our lexeme units. We use a set of regular expressions to match for lexemes for parsing later.
class Tokens(enum.Enum):
    keyword = r'(chapa|kama|jaza|kwisha|kwanza|eleza|aina|rudisha)'  # Regular expression for keywords
    function = r'([a-zA-Z_][a-zA-Z0-9_]*)\s*\('
    divider = r'(\\[|\\]|\(|\))'  # Regular expression for dividers
    boolean = r'true|false'  # Regular expression for booleans
    integer = r'\.\b[0-9]+|[0-9]+'  # Regular expression for integers
    string = r'"(.*?)"|\'(.*?)\'|\b[0-9]+'  # Regular expression for strings
    variable = r'((\'[^\']*\'|([A-Za-z_]\w*(?:\.[a-z_]\w*)*))(?!\"\')|("[^"]*"|([a-z_]\w*(?:\.[a-z_]\w*)*))(?!\"\'))'  # Regular expression for variables
    operator = r'[\*\/\+\-\=\,]'  # Regular expression for operators

class LexicalParser:
    def __init__(self, script,flag=None):
        # Class constructor with script (Hamri script) and an empty token_list array
        self.script = self.read_source(script) if flag== 'f' else script.split('\n')
        self.token_list = []

    def read_source(self, arg):
        # Function to read in our Hamri script from source
        script = None

        # function to return the file extension

        if exists(arg):
            import pathlib

            if pathlib.Path(arg).suffix == '.ham':
                content = open(arg, "r")
                script = content.readlines()
                content.close()

            else:
                print('The file you provided is not a hamri script file')

                sys.exit(1)
        else:
            print('The file path you provided does not exist')
            sys.exit(1)

        return script

    def parse(self):
        index = 0
        all_tokens = []

        for i, v in enumerate(self.script):
            # Iterate over each line in the script

            # Find all matches for the regular expressions defined in Tokens enum
            tokens = [
                (x.group(), x.span()[0], i) for x in re.compile(r'{}'.format('|'.join(
                    [t.value for t in Tokens]
                    )
                                                                             )
                                                                ).finditer(v)
            ]

            # Append the found tokens to the all_tokens list
            for n in tokens:
                all_tokens.append(n)

        id_ = 0
        # Assign a unique identifier to each token and store them in the token_list
        for t_ in all_tokens:
            for t in Tokens:
                if self.find_token_match(t_[0], t.value):

                    self.token_list.append(
                        TokenObj(t.name,
                                 t_[0].replace('"', '').replace('\'', '') if t.name == 'string' else t_[0].replace('(','') if t.name == 'function' else t_[0],
                                 t_[1], t_[2], id_
                                 )
                    )
                    break
            id_ = id_ + 1

        return self

    def print_tokens(self, type_='all'):
        # Print the tokens stored in the token_list
        for i in self.token_list:
            if type_ == 'all':
                print('-----------\nType: {}\nValue: {}\nLine: {}\nPosition: ({},{})\nOffset: {}\n-----------'.format(
                    i.token_type,
                    i.value,
                    i.line,
                    i.span()[0],
                    i.span()[0] + i.size(),
                    i.position()
                ))
            else:
                if type_ == i.token_type:
                    print('-----------\nType: {}\nValue: {}\n-----------'.format(
                        i.token_type,
                        i.value, i.start,
                        i.start + i.len_
                    ))

    def count_tokens(self):
        # Count the number of tokens in the token_list and print the count
        count = len(self.token_list)
        print('-----------\nTokens: {}\n-----------'.format(count))
        return count

    def find_token_match(self, search_str, pat_):
        # Check if the search string matches the given pattern
        pattern = re.compile(pat_)
        return_match = True if len(pattern.findall(search_str)) > 0 else False

        # Strict check to make sure integers in strings are avoided
        if pat_ == Tokens.integer.value:
            if len(re.compile(r'[\"\']').findall(search_str)) > 0:
                return_match = False

        return return_match

class TokenObj:
    def __init__(self, token_type, value, start, line, offset):
        # Initialize a token object with its properties
        self.token_type = token_type
        self.value = value
        self.line = line
        self.start = start
        self.offset = offset
        self.len_ = len(self.value)

    def value(self):
        #the value of the actual token
        return self.value

    def position(self):
        #the offset of the token in the script
        return self.offset

    def type(self):
        #the type of the token as matched by the various regex expressions
        return self.token_type

    def size(self):
        #the size (count) of the token type
        return self.len_

    def span(self):
        #a tuple representing the start and end positions of the token
        return (self.start, self.start + self.len_)

    def evaluate(self):
        return self

##- This code defines a lexical parser for the Hamri programming language.
##- It uses regular expressions defined in the 'Tokens' enum to match and extract different lexemes from the Hamri script.
##- The 'LexicalParser' class reads the source script, parses it line by line, and identifies the tokens based on the regular expressions.
##- The tokens are stored in the 'token_list' as 'TokenObj' instances.
##- The code also provides methods to print the tokens, count the tokens, and find token matches.
##- The 'TokenObj' class represents a token object with various properties to store information about the token.


#!/usr/bin/env python
# coding: utf-8
# Author: Tong ZHAO

import torch
import torch.backends.cudnn as cudnn
import torch.nn as nn
from torch.autograd import Variable
from torchvision import models

pretrained_mean = torch.tensor([0.485, 0.456, 0.406], requires_grad = False).view((1, 3, 1, 1))
pretrained_std = torch.tensor([0.229, 0.224, 0.225], requires_grad = False).view((1, 3, 1, 1))

class blockUNet(nn.Module):

    def __init__(self, in_ch, out_ch, name, transposed = False, bn = True, prelu = 0, dropout = 0):
        super(blockUNet, self).__init__()
        block = nn.Sequential()

        if prelu == 0:
            block.add_module('%s_relu' % name, nn.ReLU(inplace=True))
        else:
            block.add_module('%s_leakyrelu' % name, nn.LeakyReLU(prelu, inplace=True))

        if not transposed:
            block.add_module('%s_conv' % name, nn.Conv2d(in_ch, out_ch, 4, 2, 1, bias=False))
        else:
            block.add_module('%s_tconv' % name, nn.ConvTranspose2d(in_ch, out_ch, 4, 2, 1, bias=False))

        if bn:
            block.add_module('%s_bn' % name, nn.BatchNorm2d(out_ch))

        if dropout > 0:
            block.add_module('%s_dropout' % name, nn.Dropout2d(dropout, inplace=True))

        self.layer = block

    def forward(self, x):

        x = self.layer(x)

        return x

class UNet(nn.Module):

    def __init__(self, nf, bnd = True, prelud = 0.2, dropoutd = 0, bnu = True, preluu = 0, dropoutu = 0):
        # nf: 2 if gray, 4 if rgb

        super(UNet, self).__init__()
        # 224 x 224 x nf -> 112 x 112 x (2 nf)
        self.d1 = blockUNet(nf, nf * 2, "down_1", transposed = False, bn = bnd, prelu = prelud, dropout = dropoutd)
        # 112 x 112 x (2 nf) -> 56 x 56 x (4 nf)
        self.d2 = blockUNet(nf * 2, nf * 4, "down_2", transposed = False, bn = bnd, prelu = prelud, dropout = dropoutd)
        # 56 x 56 x (4 nf) -> 28 x 28 x (8 nf)
        self.d3 = blockUNet(nf * 4, nf * 8, "down_3", transposed = False, bn = bnd, prelu = prelud, dropout = dropoutd)
        # 28 x 28 x (8 nf) -> 14 x 14 x (8 nf)
        self.d4 = blockUNet(nf * 8, nf * 8, "down_4", transposed = False, bn = bnd, prelu = prelud, dropout = dropoutd)

        # 14 x 14 x (8 nf) -> 28 x 28 x (8 nf)
        self.u1 = blockUNet(nf * 8, nf * 8, "up_4", transposed = True, bn = bnu, prelu = preluu, dropout = dropoutu)
        # 28 x 28 x (16 nf) -> 56 x 56 x (4 nf)
        self.u2 = blockUNet(nf * 16, nf * 4, "up_3", transposed = True, bn = bnu, prelu = preluu, dropout = dropoutu)
        # 56 x 56 x (8 nf) -> 112 x 112 x (2 nf)
        self.u3 = blockUNet(nf * 8, nf * 2, "up_2", transposed = True, bn = bnu, prelu = preluu, dropout = dropoutu)
        # 112 x 112 x (4 nf) -> 224 x 224 x 1
        self.u4 = blockUNet(nf * 4, 1, "up_1", transposed = True, bn = bnu, prelu = preluu, dropout = dropoutu)
        self.active = nn.Sigmoid()

    def forward(self, x):

        x1 = self.d1(x)
        x2 = self.d2(x1)
        x3 = self.d3(x2)
        x4 = self.d4(x3)

        x = self.u1(x4)
        x = self.u2(torch.cat([x, x3], 1))
        x = self.u3(torch.cat([x, x2], 1))
        x = self.u4(torch.cat([x, x1], 1))

        return self.active(x)

def choose_vgg(name):

    f = None

    if name == 'vgg11':
        f = models.vgg11(pretrained = True)
    elif name == 'vgg11_bn':
        f = models.vgg11_bn(pretrained = True)
    elif name == 'vgg13':
        f = models.vgg13(pretrained = True)
    elif name == 'vgg13_bn':
        f = models.vgg13_bn(pretrained = True)
    elif name == 'vgg16':
        f = models.vgg16(pretrained = True)
    elif name == 'vgg16_bn':
        f = models.vgg16_bn(pretrained = True)
    elif name == 'vgg19':
        f = models.vgg19(pretrained = True)
    elif name == 'vgg19_bn':
        f = models.vgg19_bn(pretrained = True)

    for params in f.parameters():
        params.requires_grad = False

    return f

class VGGNet(nn.Module):

    def __init__(self, name, layers, cuda = True):

        super(VGGNet, self).__init__()
        self.vgg = choose_vgg(name)
        self.layers = layers

        features = list(self.vgg.features)[:max(layers) + 1]
        self.features = nn.ModuleList(features).eval()

        self.mean = pretrained_mean.cuda() if cuda else pretrained_mean
        self.std = pretrained_std.cuda() if cuda else pretrained_std

    def forward(self, x):

        x = (x - self.mean) / self.std

        results = []

        for ii, model in enumerate(self.features):
            x = model(x)
            if ii in self.layers:
                results.append(x.view(x.shape[0], -1))

        return results

class TopologyNet(nn.Module):

    def __init__(self, unet, vggnet, K = 1):

        super(TopologyNet, self).__init__()
        self.unet = unet
        self.vggnet = vggnet
        self.K = K

    def forward(self, x, y):

        results = []

        for i in range(self.K):
            input = torch.cat((x, y), dim = 1)
            y = self.unet(input)
            y_topo = self.vggnet(torch.cat((y, y, y), dim = 1))
            results.append([y, y_topo])

        return results


from  jax.experimental.ode import odeint
import jax.numpy as jnp
from jax.experimental.host_callback import id_print
import os

#==============================================================================
# Define functions
#==============================================================================

# General contraction function
def contract(A,B):
    """ General contract function: gets shape and calls appropriate contraction function. """
    if A.ndim == B.ndim == 2:
        con = con2(A,B)
    if A.ndim != B.ndim:
        if A.ndim == 4:
            if B.ndim == 2:
                con = con4(A,B)
        if A.ndim == 2:
            if B.ndim == 4:
                con = -1*con4(B,A)

    return con

# Contract square matrices (matrix multiplication)
def con2(A,B):
    return jnp.einsum('ij,jk->ik',A,B) - jnp.einsum('ki,ij->kj',B,A)

# Contract rank-4 tensor with square matrix
def con4(A,B):

    con = jnp.einsum('abcd,df->abcf',A,B)
    con += -jnp.einsum('abcd,ec->abed',A,B)
    con += jnp.einsum('abcd,bf->afcd',A,B)
    con += -jnp.einsum('abcd,ea->ebcd',A,B)

    return con

def int_ode(y,l,index_list):

    # Extract various components of the Hamiltonian from the ijnput array 'y'
    H2 = y[0]                           # Define quadratic part of Hamiltonian
    n,_ = H2.shape
    H2_0 = jnp.diag(jnp.diag(H2))       # Define diagonal quadratic part H0
    V0 = H2 - H2_0                      # Define off-diagonal quadratic part

    Hint = y[1]                         # Define quartic part of Hamiltonian
    Hint0 = jnp.zeros((n,n,n,n))        # Define diagonal quartic part
    for index in [[0,0,0,0]]:                  # Load Hint0 with values
        id_print(index)
        id_print(Hint[jnp.array(index)])
        Hint0 = Hint0.at[jnp.array(index)].set(Hint[jnp.array(index)])
    # id_print(Hint0)
    Vint = Hint-Hint0                   # Define off-diagonal quartic part

    # Compute the generator eta
    eta0 = contract(H2_0,V0)
    eta_int = contract(Hint0,V0) + contract(H2_0,Vint)

    # Compute the RHS of the flow equation dH/dl = [\eta,H]
    sol = contract(eta0,H2)
    sol2 = contract(eta_int,H2) + contract(eta0,Hint)

    return [sol,sol2]

def indices(n):
    """ Gets indices of diagonal elements of quartic tensor. """
    mat = jnp.zeros((n,n,n,n),dtype=jnp.int8)
    for i in range(n):
        for j in range(n):
            if i != j:
                # Zero the diagonal values (n_i n_j or c^dag_i c_j c^dag_j c_i)
                mat = mat.at[i,i,j,j].set(1)
                mat = mat.at[i,j,j,i].set(1)
    # mat = mat.reshape(n**4)
    indices = jnp.argwhere(mat)
    return indices

#==============================================================================
# Run program
#==============================================================================

if __name__ == '__main__':

    # Define variables
    dl_list = jnp.linspace(0,10,100)
    cutoff = 1e-3
    n = int(os.sys.argv[1])

    # Set up Hamiltonian (H2 = quadratic part, Hint = quartic part)
    H2 = jnp.zeros((n,n))
    for i in range(n):
        # Initialise Hamiltonian with linearly increasing on-site terms (Wannier-Stark)
        H2 = H2.at[i,i].set(i)
    H2 += jnp.diag(jnp.ones(n-1),1) + jnp.diag(jnp.ones(n-1),-1)

    Hint = jnp.zeros((n,n,n,n))
    for i in range(n):
        for j in range(i,n):
            if abs(i-j)==1:
                # Initialise nearest-neighbour interactions
                Hint = Hint.at[i,i,j,j].set(0.5)

    index_list = jnp.array(indices(n))
    print(index_list)

    # Set up integration variables
    k=1
    sol2 = jnp.zeros((len(dl_list),n,n))
    sol4 = jnp.zeros((len(dl_list),n,n,n,n))
    sol2 = sol2.at[0].set(H2)
    sol4 = sol4.at[0].set(Hint)
    J0 = 1

    # Do integration step by step until the max off-diagonal term is smaller than the cutoff, then exit
    while k <len(dl_list) and J0 > cutoff:
        print(k)
        soln = odeint(int_ode,[sol2[k-1],sol4[k-1]],dl_list[k:k+2],index_list)
        sol2 = sol2.at[k].set(soln[0][-1])
        sol4 = sol4.at[k].set(soln[1][-1])
        J0 = jnp.max(jnp.abs(soln[0][-1] - jnp.diag(jnp.diag(soln[0][-1]))))
        k += 1


from flask import (
    request,
)
from typing import Tuple
from ApplicationModels.RegisterWebUserForm import RegisterWebUserForm
from ApplicationModels.PageContents import PageContents, RegisterFormData

class ViewRegisterUseCase():
    def execute(
        self,
        page_contents: PageContents[RegisterFormData]
    ) -> Tuple[PageContents[RegisterFormData], RegisterWebUserForm]:
        page_contents.page_title = 'ユーザー登録'
        form = RegisterWebUserForm(request.form)

        form.name.data = page_contents.data.login_name
        form.email.data = page_contents.data.login_email

        return page_contents, form


#import cartopy.crs as ccrs
import xarray as xr
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import pylab
#import pandas as pd
#import numpy as np
#import datetime
#from datetime import datetime
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter

from matplotlib.ticker import StrMethodFormatter, MultipleLocator, FormatStrFormatter, AutoMinorLocator

#import cartopy

def serieTemporal(prev):
    prev = str(prev)

    config = {
      'Regiao'  :['SUL' ,'SUDESTE'  ,'CENTRO-OESTE' ,'NORDESTE' ,'NORTE'    ,'SUDESTE'  ,'NORTE'    ],
      'Setor'   :['B1'  ,'B2'       ,'B3'           ,'B4'       ,'B5'       ,'B6'       ,'B7'       ],
      'latNorte':[ 75   ,130        ,130            ,195        ,195        ,130        ,195        ],
      'latSul'  :[-182  ,-119       ,-119           ,-45        ,-45        ,-139       ,-45        ],
      'lonOeste':[-157  ,-78        ,-157           ,-79        ,-157       ,-78        ,-210       ],
      'lonLest' :[-69   ,-1         ,-79            ,-1         ,-79        ,-1        ,-153        ]
    }

    for ind in range(0,7,1):
        print('ind',ind)

        for indVars in range(0,8,1):
            print('indVars',indVars)

        #for ind in range(0,7,1):
        #    print('ind',ind)

            pylab.rcParams['figure.figsize'] = (30,10)

            anomes = '201401'
            path_1 = "/dados/dmdpesq/Experimento_umidade_do_solo/umidade_GL/"
            name_file_1 = 'JAN2014_'+ prev +'Z_12Z_interp.nc'

            path_3 = "/dados/dmdpesq/Experimento_umidade_do_solo/umidade_Nova/"
            name_file_3 = 'JAN2014_'+ prev +'Z_12Z_interp.nc'

            path_out ="/dados/dmdpesq/Experimento_umidade_do_solo/out/"

            latNorte    = config['latNorte'][ind]
            latSul      = config['latSul'][ind]
            lonOeste    = config['lonOeste'][ind]
            lonLest     = config['lonLest'][ind]

            sns.set_style("darkgrid", {"axes.facecolor": ".9"})
            sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})
            plt.tight_layout()

            plt.gca().yaxis.set_major_formatter(StrMethodFormatter('{x:,.3f}')) # Com 3 casas decimais
            plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=1))
            plt.gca().xaxis.set_major_formatter(DateFormatter("%Y-%m-%d"))

            DS_NCEP = xr.open_dataset(path_1 + name_file_1)
            DS_NCEP_umidade_nova = xr.open_dataset(path_3 + name_file_3)

            vars = {
            'ds':[
                DS_NCEP.prec
                ,DS_NCEP.ussl
                ,DS_NCEP.uzrs
                ,DS_NCEP.uzds
                ,DS_NCEP.cssf
                ,DS_NCEP.clsf
                ,DS_NCEP.t2mt
                ,DS_NCEP.q2mt   ],
            'ds_nova_umidade':[
                DS_NCEP_umidade_nova.prec
                ,DS_NCEP_umidade_nova.ussl
                ,DS_NCEP_umidade_nova.uzrs
                ,DS_NCEP_umidade_nova.uzds
                ,DS_NCEP_umidade_nova.cssf
                ,DS_NCEP_umidade_nova.clsf
                ,DS_NCEP_umidade_nova.t2mt
                ,DS_NCEP_umidade_nova.q2mt],
            'variavel':[
                'PREC'
                ,'USSL'
                ,'UZRS'
                ,'UZDS'
                ,'CSSF'
                ,'CLSF'
                ,'T2MT'
                ,'Q2MT'       ]
            }

            longName = vars['ds'][indVars].attrs['long_name']
            longNameEditNameVAR = longName[10:50]
            print(longNameEditNameVAR)

            plt.figtext(.5,.94,'20140101 12Z  ' + prev +'h' , fontsize=20, ha='center')
            plt.figtext(.5,.90,'Serie Temporal  ' + longNameEditNameVAR ,fontsize=20,ha='center')
            plt.figtext(.86,.90,'Região: '+ config['Regiao'][ind] +' Setor: '+ config['Setor'][ind] ,fontsize=20,ha='right')

            #longName = DS_NCEP.prec.attrs['long_name']
            longName = vars['ds'][indVars].attrs['long_name']

            xTickTime = DS_NCEP.prec['time'].isel(time=slice(None, 31))

            p1 = vars['ds'][indVars].isel(time=slice(None, 31), lat=slice(latNorte,latSul), lon=slice(lonOeste,lonLest)).mean(dim="lat").mean(dim="lon")
            plt.plot(xTickTime,p1,color='orange', label='umidade GL')
            plt.xticks(rotation=45)

            #DS_NCEP_umidade_nova = xr.open_dataset(path_3 + name_file_3)
            p3 = vars['ds_nova_umidade'][indVars].isel(time=slice(None, 31), lat=slice(latNorte,latSul), lon=slice(lonOeste,lonLest)).mean(dim="lat").mean(dim="lon")
            plt.plot(xTickTime,p3,color='r', label='Nova umidade')
            plt.xticks(rotation=45)

            #plt.ylim(0,25)

            if indVars == 0:
            #Para Precipitação
                longNameEditUnit = longName[51:63]
                plt.ylabel(longName[15:30] + ' [ '+ longNameEditUnit + ']', labelpad=30)
            else:
            #Para a demais variaveis
                longNameEditUnit = longName[51:54]
                plt.ylabel(longName[8:30] + ' [ '+ longNameEditUnit + ']', labelpad=30)

            #plt.ylabel(longName[8:30], labelpad=30)
            plt.xlabel('', labelpad=30)

            title = 'previsao_'+ prev +'_regiao_'+ config['Regiao'][ind] +'_'+ config['Setor'][ind]+'_SerieTemporal_'+ vars['variavel'][indVars] +'.png'
            plt.legend(fontsize=17, frameon=True)
            plt.savefig(path_out + title, bbox_inches='tight', pad_inches=.2, dpi=300, figsize=(15,15))
            print('Saved: {}'.format(title))
            plt.cla() #means clear current axis
            plt.clf() #means clear current figure
            plt.close()
            DS_NCEP.close()
            DS_NCEP_umidade_nova.close()

    return

var= 'prec'
prev = '24'
for prev in range(24,192,24):
  print('prev',prev)
  serieTemporal(prev)


import numpy as np
from pydub import AudioSegment

def encode_audio_to_array(audio_file, output_file):
    try:
        audio = AudioSegment.from_file(audio_file)
        samples = np.array(audio.get_array_of_samples())
        encoded_array = ','.join(map(str, samples))
        with open(output_file, 'w') as outfile:
            outfile.write(encoded_array)
        print(f"Encoded audio array exported to {output_file}!")
    except FileNotFoundError:
        print("File not found!")

# Provide the path to your MP3 audio file
audio_file_path = 'C:/Users/GEORGIE/Downloads/converted2.mp3'
# Provide the desired output file path
output_file_path = 'C:/Users/GEORGIE/Downloads/output.txt'

encode_audio_to_array(audio_file_path, output_file_path)


import logging
import http.client as http_client
import os

SEARCH_API_URL_FORMAT = 'https://api.{env}.bookshareunifiedsearch.org/search'
INGESTION_URL_FORMAT = 'https://ingest.{env}.bookshareunifiedsearch.org/records'
DELETE_URL_FORMAT = 'https://ingest.{env}.bookshareunifiedsearch.org/recordDeletes'
GET_URL_FORMAT = 'https://ingest.{env}.bookshareunifiedsearch.org/recordGets'

SEARCH_API_URL = "unset"
INGESTION_URL = "unset"
DELETE_URL = "unset"
GET_URL = "unset"

def set_servers(env):
    global SEARCH_API_URL
    global INGESTION_URL
    global DELETE_URL
    global GET_URL
    if not env:
        env = 'qa'

    SEARCH_API_URL = SEARCH_API_URL_FORMAT.format(env=env)
    INGESTION_URL = INGESTION_URL_FORMAT.format(env=env)
    DELETE_URL = DELETE_URL_FORMAT.format(env=env)
    GET_URL = GET_URL_FORMAT.format(env=env)

    if env == 'prod':
        SEARCH_API_URL = SEARCH_API_URL.replace('.prod', '')
        INGESTION_URL = INGESTION_URL.replace('.prod', '')
        DELETE_URL = DELETE_URL.replace('.prod', '')
        GET_URL = GET_URL.replace('.prod', '')

EMMA_API_KEY = os.environ.get('EMMA_API_KEY', 'none')

http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True


import random
from db_conn import get_db_connection
from subprocess import STARTF_USESTDHANDLES
from flask import Blueprint, request

from users import get_single_user

quality = Blueprint('quality', __name__)

@quality.route('/quality', methods=['GET'])
def get_quality_info():
    conn = get_db_connection()
    info = conn.execute('SELECT dispenser_quality, filter_quality, water_quality FROM quality ORDER BY id DESC').fetchone()
    result = dict(info)
    conn.close()
    return result

@quality.route('/quality', methods=['POST'])
def set_quality_info():
    conn = get_db_connection()
    quality_info = {
        "water_quality": random.random(),
        "filter_quality": random.random(),
        "dispenser_quality": random.random()
    }
    conn.execute("INSERT INTO quality(water_quality,filter_quality,dispenser_quality) VALUES (?, ?, ?)",
        (quality_info["water_quality"], quality_info['filter_quality'], quality_info['dispenser_quality']))
    conn.commit()
    conn.close()
    return {"message":"Quality inserted successfully!"}


import json
from db import db
from flask import Flask
from flask import request
from db import Party
from db import User
import os

app = Flask(__name__)

app = Flask(__name__)
db_filename = "findmyparty.db"

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///%s" % db_filename
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
app.config["SQLALCHEMY_ECHO"] = True

db.init_app(app)
with app.app_context():
    db.create_all()

def success_response(data, code=200):
    return json.dumps(data), code

def failure_response(message, code=404):
    return json.dumps({"error": message}), code

@app.route("/api/parties/")
def get_all_parties():
    print('called-route')
    return success_response(
        {"parties":[party.serialize() for party in Party.query.all()]}
    )

@app.route("/api/parties/host/", methods=['POST'])
def host_party():
    body = json.loads(request.data)
    host = body.get("host")
    location = body.get("location")
    photoURL = body.get("photoURL")
    dateTime = body.get("dateTime")
    theme = body.get("theme")
    if not (body or host or location or photoURL or dateTime):
        return failure_response("The request is badly formatted.", 400)
    new_party = Party(
        host=host,
        location=location,
        photoURL=photoURL,
        dateTime=dateTime,
        theme=theme,
        attendees=[]
    )
    print(new_party)
    db.session.add(new_party)
    db.session.commit()
    return success_response(
        new_party.serialize(),
        201
    )
@app.route("/api/party/<int:party_id>/")
def get_party_by_id(party_id):
    party = Party.query.filter_by(id=party_id).first()
    if not party:
        return failure_response(f"Party with ID {party_id} does not exist!")
    return success_response(party.serialize())

@app.route("/api/users/", methods=["POST"])
def add_user():
    body = json.loads(request.data)
    name = body.get("name")
    email = body.get("email")
    photoURL = body.get("photoURL")
    if  not (name or email or photoURL):
        return failure_response("The request is badly formatted.", 400)
    new_user = User(
        name=name,
        email=email,
        photoURL=photoURL,
        parties = []
    )
    db.session.add(new_user)
    db.session.commit()
    return success_response(
        new_user.serialize(),
        201
    )

@app.route("/api/user/<int:user_id>/")
def get_user_by_id(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        return failure_response(f"User with ID {user_id} does not exist!")
    return success_response(user.serialize())

@app.route("/api/party/<int:party_id>/attend/", methods=["POST"])
def attend_party(party_id):
    body = json.loads(request.data)
    id = body.get("user_id")
    if not id:
        return failure_response(f"The request is badly formatted.")
    user = User.query.filter_by(id=id).first()
    if not user:
        return failure_response(f"User with ID {id} does not exist!")
    party = Party.query.filter_by(id=party_id).first()
    if not party:
        failure_response(f"Party with ID {party_id} does not exist!")
    user.parties.append(party)
    party.users.append(user)
    db.session.commit()
    return success_response(
        party.serialize(),
        200
    )

@app.route("/api/party/<int:party_id>/attendees/")
def get_attendees(party_id):
    party = Party.query.filter_by(id=party_id).first()
    if not party:
        failure_response(f"Party with ID {party_id} does not exist!")
    attendees = party.serialize()["attendees"]
    return success_response(attendees, 200)

@app.route("/api/user/<int:user_id>/parties/")
def get_parties(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        return failure_response(f"User with ID {user_id} does not exist!")
    parties = user.serialize()["parties"]
    return success_response(parties, 200)

@app.route("/api/user/email/", methods=['POST'])
def get_user_by_email():
    body = json.loads(request.data)
    email = body.get("email")
    if not email:
        return failure_response("No email provided")
    user = User.query.filter_by(email=email).first()
    if not user:
        return failure_response(f"User with email {email} does not exist!")
    return success_response(user.serialize(), 200)

@app.route("/api/user/delete/", methods=["DELETE"])
def delete_user_by_email():
    body = json.loads(request.data)
    email = body.get("email")
    if not email:
        return failure_response("No email provided")
    user = User.query.filter_by(email=email).first()
    if not user:
        return failure_response(f"User with email {email} does not exist!")
    db.session.delete(user)
    db.session.commit()
    return success_response(user.serialize())

@app.route("/api/party/<int:id>/delete/", methods=["DELETE"])
def delete_party_by_id(id):
    party = Party.query.filter_by(id=id).first()
    if not party:
        return failure_response(f"Party with id {id} does not exist!")
    db.session.delete(party)
    db.session.commit()
    return success_response(party.serialize())

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)


# -*- coding: utf-8 -*-
"""
Created on Wed Oct 13 11:28:11 2021

@author: Jouni Kuusisto

* insert filename in if __name__ == '__main__': section at the bottom

*numpy-stl library displays error message of a not closed mesh when calling get_mass_properties() even
 when a closed mesh (from FreeCAD v0.18 as .SLT file) is loaded. Volume and cog agree with FreeCAD and manual calculation.
"""

import numpy as np
import math
from stl import mesh
from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt

#Loading mesh and add vectors to the plot
def loadMesh(file: str):
    return mesh.Mesh.from_file(file)

def meshPlot(case_mesh: mesh.Mesh):
    figure = plt.figure()
    axes = mplot3d.Axes3D(figure)
    axes.add_collection3d(mplot3d.art3d.Line3DCollection(case_mesh.vectors))
    #Auto scale to mesh size
    scale = case_mesh.points.flatten()
    axes.auto_scale_xyz(scale, scale, scale)
    #Show the plot
    plt.show()

'''
Following function from: https://newbedev.com/matplotlib-equal-unit-length-with-equal-aspect-ratio-z-axis-is-not-equal-to-x-and-y
ax.set_box_aspect([1,1,1]) is also needed before this function is called
This sets axis equal in matplotlibs 3d plots
'''
def set_axes_equal(ax):
    '''Make axes of 3D plot have equal scale so that spheres appear as spheres,
    cubes as cubes, etc..  This is one possible solution to Matplotlib's
    ax.set_aspect('equal') and ax.axis('equal') not working for 3D.

    Input
      ax: a matplotlib axis, e.g., as output from plt.gca().
    '''

    x_limits = ax.get_xlim3d()
    y_limits = ax.get_ylim3d()
    z_limits = ax.get_zlim3d()

    x_range = abs(x_limits[1] - x_limits[0])
    x_middle = np.mean(x_limits)
    y_range = abs(y_limits[1] - y_limits[0])
    y_middle = np.mean(y_limits)
    z_range = abs(z_limits[1] - z_limits[0])
    z_middle = np.mean(z_limits)

    # The plot bounding box is a sphere in the sense of the infinity
    # norm, hence I call half the max range the plot radius.
    plot_radius = 0.5*max([x_range, y_range, z_range])

    ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])
    ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])
    ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])

#Strictly own code from here on

#Calculating center point of triangles. case_mesh.vectors returns a numpy array, where lines represent each triangle and columns coordinates
def triangleCenters(case_mesh: mesh.Mesh):
    tri_center_coordinates = np.zeros((len(case_mesh), 3))
    for count, tri in enumerate(case_mesh.vectors):
        tri_center_coordinates[count,:] = np.mean(tri, axis = 0)
    return tri_center_coordinates

#Calculating triangle areas by cross product of vectors
def triangleAreas(case_mesh: mesh.Mesh):
    areasArray = np.zeros((len(case_mesh), 1))
    for count, tri in enumerate(case_mesh.vectors):
        AB = tri[1,:] - tri[0,:]
        AC = tri[2,:] - tri[0,:]
        areasArray[count] = 0.5 * np.linalg.norm(np.cross(AB, AC))
    return areasArray

#Calculate triangle centers by weighing them by their area
def weightedCenters(case_mesh: mesh.Mesh):
    centers = triangleCenters(case_mesh)
    areas = triangleAreas(case_mesh)
    weightedCenters = centers.copy()
    i = 0
    for center, area in zip(centers, areas):
        weightedCenters[i,:] = area * center
        i += 1
    return weightedCenters

#Calculate mass center, this is done also with stl package method - just to be sure results agree (they did up to decimal level). This is done in accordance to paper by Bisbal
def massCenter(case_mesh: mesh.Mesh):
    return np.sum(weightedCenters(case_mesh), axis = 0) / np.sum(triangleAreas(case_mesh))

#Calculate radius of best fitted sphere. First calculate sum of all radii from center of mass to all triangles weighted by respective triangle areas. Then division by all surface area and number of triangles results AR.
def averageWeightedRadius(case_mesh: mesh.Mesh):
    LA_surface_area = np.sum(triangleAreas(case_mesh))
    LA_mass_center = massCenter(case_mesh)
    return np.sum(triangleAreas(case_mesh) * (np.linalg.norm((triangleCenters(case_mesh) - LA_mass_center), axis = 1))) / (LA_surface_area * len(case_mesh))

#Calculate standard deviation of the AR (Bisbal)
def sdAr(case_mesh: mesh.Mesh):
    AR = averageWeightedRadius(case_mesh)
    LA_surface_area = np.sum(triangleAreas(case_mesh))
    LA_mass_center = LA_mass_center = massCenter(case_mesh)
    return ((np.sum(triangleAreas(case_mesh) * ( np.linalg.norm((triangleCenters(case_mesh) - LA_mass_center), axis = 1) - AR)**2)) / (LA_surface_area * len(case_mesh)))**0.5

#CVS stands for "coefficient of variation of the sphere" (Bisbal)
def cvs(case_mesh: mesh.Mesh): #CVS stands for "coefficient of variation of the sphere" (Bisbal)
    return sdAr(case_mesh)/averageWeightedRadius(case_mesh)

#Calculate LA sphericity as proposed by Bisbal
def laspBisbal(case_mesh: mesh.Mesh, percentage = False): #Method proposed by Bisbal
    lasp = 1-cvs(case_mesh)
    if percentage:
        return lasp*100
    else:
        return lasp

#Calculate own 3D sphericity
def threeDsKuusisto(case_mesh: mesh.Mesh, percentage = False): #Our own method
    volume, _, _ = case_mesh.get_mass_properties()
    threeDs = (math.pi**(1/3) * ((6*volume)**(2/3))) / np.sum(triangleAreas(case_mesh))
    if percentage:
        return threeDs*100
    else:
        return threeDs

def plotTriangleCentersAndCenterOfMass(case_mesh: mesh.Mesh, title = "", save = False, save_name=""):
    #LA_surface_area = np.sum(triangleAreas(case_mesh))
    LA_mass_center = massCenter(case_mesh)
    tri_center_coordinates = triangleCenters(case_mesh)
    AR = averageWeightedRadius(case_mesh)
    fig = plt.figure()
    ax = fig.add_subplot(projection='3d')
    ax.view_init(90,0)
    #ax.scatter(tri_center_coordinates[:,0], tri_center_coordinates[:,1], tri_center_coordinates[:,2], c='r', marker="x", s=2)
    ax.scatter(LA_mass_center[0], LA_mass_center[1], LA_mass_center[2], c='r')

    ax.add_collection3d(mplot3d.art3d.Line3DCollection(case_mesh.vectors, linewidths=0.5))

    # draw sphere
    u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
    x = np.cos(u)*np.sin(v)
    y = np.sin(u)*np.sin(v)
    z = np.cos(v)
    x *= AR
    y *= AR
    z *= AR
    x += LA_mass_center[0]
    y += LA_mass_center[1]
    z += LA_mass_center[2]
    ax.plot_wireframe(x, y, z, color="r", alpha=0.5, linewidths = 1)

    plt.title(title)
    ax.set_box_aspect([1,1,1])
    ax.grid(False)
    set_axes_equal(ax)

    if save:
        fig.savefig(save_name,dpi=300)
    plt.show()

def printResults(case_mesh: mesh.Mesh):
    bisbal = laspBisbal(case_mesh)
    kuusisto = threeDsKuusisto(case_mesh)
    volume, _, _ = case_mesh.get_mass_properties()
    print("Volume:           " + str(volume/1000))
    print("LASP (Bisbal):    " + str(bisbal))
    print("3DS (Kuusisto):   " + str(kuusisto))
    return volume, bisbal, kuusisto

if __name__ == '__main__':

    case_mesh = loadMesh("dotu_part2.stl") # insert filename here
    meshPlot(case_mesh)
    plotTriangleCentersAndCenterOfMass(case_mesh)

    #Printing mesh characteristics
    volume, cog, inertia = case_mesh.get_mass_properties()
    print("Mesh Volume                             = {0}".format(volume))
    print("Position of the center of gravity (COG) = {0}".format(cog))

    printResults(case_mesh)


#Đề: Quản lý học sinh
#            tên
#           tuổi
#          lớp
#            điểm toán, văn anh
#        fuc: tính điểm trung bình
#             tính năm sinh

import os
# clearConsole = lambda: os.system('cls' if os.name in ('nt', 'dos') else 'clear')
# clearConsole()
# #Clear console cho nó gọn

import datetime
from tkinter import *
from  tkinter import ttk
from tkinter import messagebox
import webbrowser
import numpy
import csv

class Students:
    def __init__(self,stt, name, age, className, toan, van, anh):
        self.stt = stt
        self.name = name
        self.age = age
        self.className = className
        self.toan = toan
        self.van = van
        self.anh = anh

    def tinhTrungBinh(self):
        self.diemTrungBinh = (self.toan+self.van+self.anh)/3
        return self.diemTrungBinh

    def tinhNamSinh(self):
        x=datetime.datetime.now()
        self.namSinh= x.year - self.age
        return self.namSinh

HocSinh = []

screen = Tk()
screen.geometry("950x450")
screen. resizable(width=False, height=False)
screen.title("Phần mềm quản lí học sinh trường L")

#Row 0
titleLabel = Label(screen)
titleLabel.grid(columnspan = "13", row = "0", padx=5, pady=5)
titleLabel.config(text = "QUẢN LÍ HỌC SINH", font=("Segoe UI bold",15))

#Table row 1

table_frame = Frame(screen)
table_frame.grid(columnspan = "13", row = "1", padx=(30,0), pady=5)

tableScroll = Scrollbar(table_frame)
tableScroll.grid(row = "1", column = "8", sticky = "nsew")

tableData = ttk.Treeview(table_frame)

tableData['columns'] = ('stt', 'name', 'class', 'age', 'toan', 'van', 'anh', 'diemTB')
tableData.grid(row=1, column=0, columnspan=5, rowspan=5, padx=5, pady=5)

tableData.column("#0", width=0,  stretch=NO)
tableData.column("stt",anchor=CENTER, width=70)
tableData.column("name",anchor=CENTER, width=200)
tableData.column("class",anchor=CENTER, width=100)
tableData.column("age",anchor=CENTER, width=100)
tableData.column("toan",anchor=CENTER, width=100)
tableData.column("van",anchor=CENTER, width=100)
tableData.column("anh",anchor=CENTER, width=100)
tableData.column("diemTB",anchor=CENTER, width=100)

tableData.heading("#0",text="",anchor=CENTER)
tableData.heading("stt",text="STT",anchor=CENTER)
tableData.heading("name",text="Tên",anchor=CENTER)
tableData.heading("class",text="Lớp",anchor=CENTER)
tableData.heading("age",text="Tuổi",anchor=CENTER)
tableData.heading("toan",text="Điểm Toán",anchor=CENTER)
tableData.heading("van",text="Điểm Văn",anchor=CENTER)
tableData.heading("anh",text="Điểm Anh",anchor=CENTER)
tableData.heading("diemTB",text="Điểm TB",anchor=CENTER)

global count
data = []
count=0

def openURL():
    webbrowser.open_new(r"https://www.facebook.com/fb.khoanguyen")
    messagebox.showinfo('Hỏi cl?', 'Hỏi gì? Hỏi cl tao đéo trả lời đâu!')

def dtb():
    return round(float(float(toan_entry.get())+float(van_entry.get())+float(anh_entry.get()))/3, 2)

def inputData():
    global count

    tableData.insert(parent='',index='end',iid = count,text='',values=(stt_entry.get(), name_entry.get(), class_entry.get(), age_entry.get(), toan_entry.get(), van_entry.get(), anh_entry.get(), dtb()))

    count += 1

    data.append([stt_entry.get(), name_entry.get(), class_entry.get(), age_entry.get(), toan_entry.get(), van_entry.get(), anh_entry.get(), dtb()])
    print(data)

    stt_entry.delete(0,END)
    name_entry.delete(0,END)
    class_entry.delete(0,END)
    age_entry.delete(0,END)
    toan_entry.delete(0,END)
    van_entry.delete(0,END)
    anh_entry.delete(0,END)

def ExportData():
    global data

    Headers = ['stt', 'name', 'class', 'age', 'toan', 'van', 'anh', 'diemTB']

    dataWithHeaders = data
    dataWithHeaders.insert(0, Headers)
    print(dataWithHeaders)
    dataCSV = numpy.array(dataWithHeaders)
    with open('data.csv', 'w', newline='') as file:
        mywriter = csv.writer(file, delimiter=',')
        mywriter.writerows(dataCSV)

def LoadData():
    global data, tableData, count
    count = 0
    if os.path.exists('./data.csv'):
        with open('data.csv', 'r', newline='') as file:
            CSVdata = csv.reader(file, delimiter=',')
            for rows in CSVdata:
                data.append(rows)
            data.pop(0)

        for i in data:
            tableData.insert(parent='',index='end',iid = count,text='',values=(i[0], i[1],i[2] ,i[3], i[4], i[5], i[6], i[7]))
            count +=1
    else:
        return

def deleteData():
    messagebox.askyesno('Ditmemay ấn cl', 'Cái này chưa code ấn cl à, code giúp tao với?')

Input_frame = Frame(screen)
Input_frame.grid(columnspan = "13", row = "2", padx=(20,0), pady=0)

menuLabel = Label(Input_frame, text = "Menu", font=("Segoe UI Bold",15))
menuLabel.grid(columnspan = "13", row = "2", padx=5, pady=5)

stt = Label(Input_frame,text="STT")
stt.grid(row=3,column=0,padx=5,pady=0)

name = Label(Input_frame,text="Tên")
name.grid(row=3,column=1,padx=5,pady=0)

className = Label(Input_frame,text="Lớp")
className.grid(row=3,column=2,padx=5,pady=0)

age = Label(Input_frame,text="Tuổi")
age.grid(row=3,column=3,padx=5,pady=0)

toan = Label(Input_frame,text="Điểm Toán")
toan.grid(row=3,column=4,padx=5,pady=0)

van = Label(Input_frame,text="Điểm Văn")
van.grid(row=3,column=5,padx=5,pady=0)

anh = Label(Input_frame,text="Điểm Anh")
anh.grid(row=3,column=6,padx=5,pady=0)

stt_entry = Entry(Input_frame, borderwidth=2, width = "6", font=("Segoe UI",12), justify="center", relief="groove")
stt_entry.grid(row=4,column=0,padx=3,pady=0)

name_entry = Entry(Input_frame,borderwidth=2, width = "33", font=("Segoe UI",12), justify="right", relief="groove")
name_entry.grid(row=4,column=1,padx=5,pady=0)

class_entry = Entry(Input_frame,borderwidth=2, width = "7", font=("Segoe UI",12), justify="center", relief="groove")
class_entry.grid(row=4,column=2,padx=5,pady=0)

age_entry = Entry(Input_frame,borderwidth=2, width="7", font=("Segoe UI",12), justify="center", relief="groove")
age_entry.grid(row=4,column=3,padx=5,pady=0)

toan_entry = Entry(Input_frame,borderwidth=2, width="7", font=("Segoe UI",12), justify="center", relief="groove")
toan_entry.grid(row=4,column=4,padx=5,pady=0)

van_entry = Entry(Input_frame,borderwidth=2, width="7", font=("Segoe UI",12), justify="center", relief="groove")
van_entry.grid(row=4,column=5,padx=5,pady=0)

anh_entry = Entry(Input_frame,borderwidth=2, width="7", font=("Segoe UI",12), justify="center", relief="groove")
anh_entry.grid(row=4,column=6,padx=5,pady=0)

Add_button = Button(Input_frame, text="Add", font=("Segoe UI",12), command=inputData, relief=GROOVE, justify="center", bd=2,width = 10)
Add_button.grid(row=4,column=7,columnspan=2,padx=0,pady=5)

Export_button = Button(Input_frame, width = 10, text = "Export", command = ExportData, font=("Segoe UI",12), relief=GROOVE, justify="center", bd=2)
Export_button.grid(row=5,column=7,columnspan=2,padx=0,pady=5)

Input_button = Button(Input_frame,width = 10, text = "Import",command= LoadData, font=("Segoe UI",12), relief=GROOVE, justify="center", bd=2)
Input_button.grid(row=6,column=7,columnspan=2,padx=5,pady=0)

Search_button = Button(Input_frame,width = 10, text = "Search", font=("Segoe UI",12), relief=GROOVE, justify="center", bd=2, command = deleteData)
Search_button.grid(row=5,column=5,columnspan=2,padx=0,pady=5)

Clear_button = Button(Input_frame,width = 10, text = "Clear", font=("Segoe UI",12), relief=GROOVE, justify="center", bd=2, command = deleteData)
Clear_button.grid(row=5,column=3,columnspan=3,padx=0,pady=5)

Gethelp_button = Button(Input_frame,width = 10, text = "Get help?", font=("Segoe UI",12), relief=GROOVE, justify="center", bd=2, command=openURL)
Gethelp_button.grid(row=5,column=2,columnspan=2,padx=0,pady=5)

#CopyRight Label
copyRightLabel = Label(Input_frame)
copyRightLabel.grid(columnspan = "2", column = 0, row = "5", padx=(35,0), pady=(0,5))
copyRightLabel.config(text="Copyright © Khoa Nguyễn & Quang Ngo! For educational purposes only!", font=("Segoe UI light",10),bd="0", relief=GROOVE, justify="center")
screen.mainloop()


# Buddy 챗봇 모델을 API 형태로 발행할 때 필요한 py 파일

import sys
import torch
import torch.nn as nn
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import bson
import base64
from tqdm import tqdm
from flask import Flask, render_template, request, jsonify, json, Response, make_response
from flask_mobility import Mobility

import azure.cognitiveservices.speech as speechsdk
from azure.cognitiveservices.speech import AudioDataStream, SpeechConfig, SpeechSynthesizer, SpeechSynthesisOutputFormat
from azure.cognitiveservices.speech.audio import AudioOutputConfig
import cognitive_face as CF

from transformers import AdamW
from torch.utils.data import dataloader
from dataloader.wellness import WellnessTextClassificationDataset
from model.kobert import KoBERTforSequenceClassfication
from model.kobert import KoBERTforSequenceClassfication, kobert_input
from kobert_transformers import get_tokenizer

# 로컬 폴더 path 추가 & root path 설정
sys.path.append('C:')
sys.path.append('C:/buddy')
root_path = "C:/buddy"

# 해당 파일을 처음 실행시켰을 때, 한 번만 실행되어야 할 것들
# Flask 설정
app = Flask(__name__)
#app.config['SECRET_KEY'] = 'enter-a-very-secretive-key-3479373'

# Azure Speech 서비스 key와 지역 할당
speech_key, service_region = "<YOUR API KEY>", "koreacentral"
speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_region)

# STT/TTS 사전 설정. 한국어와 여성의 음성을 선택
speech_config.speech_synthesis_language = "ko-KR"
speech_config.speech_synthesis_voice_name = "ko-KR-SunHiNeural"

# Face Recogntion
KEY = "<YOUR API KEY>"
CF.Key.set(KEY)
BASE_URL = 'https://koreacentral.api.cognitive.microsoft.com/face/v1.0/'
CF.BaseUrl.set(BASE_URL)
happiness, anger, contempt, disgust, fear, sadness = [0, 0, 0, 0, 0, 0]
img_url = './emotions/frame.png'

# category와 answer 파일 열어서 답변 리스트를 생성하는 함수
def load_wellness_answer():
  category_path = f"{root_path}/data/wellness_dialog_category.txt"
  answer_path = f"{root_path}/data/wellness_dialog_answer.txt"

  c_f = open(category_path, 'r', encoding='UTF-8')
  a_f = open(answer_path, 'r', encoding='UTF-8')

  category_lines = c_f.readlines()
  answer_lines = a_f.readlines()

  category = {}
  answer = {}
  for line_num, line_data in enumerate(category_lines):
    data = line_data.split('    ')
    category[data[1][:-1]]=data[0]

  for line_num, line_data in enumerate(answer_lines):
    data = line_data.split('    ')
    keys = answer.keys()
    if(data[0] in keys):
      answer[data[0]] += [data[1][:-1]]
    else:
      answer[data[0]] =[data[1][:-1]]

  return category, answer

# 챗봇 Model 불러오기 및 실행
# 지난 번 실행이 느렸던건 해당 부분이 chatbotResponse()에 포함되어 반복해서 불러오는 작업을 수행했기 때문
checkpoint_path = f"{root_path}/checkpoint"
save_ckpt_path = f"{checkpoint_path}/kobert-wellnesee-text-classification.pth"

category, answer = load_wellness_answer()

ctx = "cuda" if torch.cuda.is_available() else "cpu"
device = torch.device(ctx)

checkpoint = torch.load(save_ckpt_path, map_location=device) # 저장한 Checkpoint 불러오기

model = KoBERTforSequenceClassfication()
model.load_state_dict(checkpoint['model_state_dict'])

model.to(ctx)
model.eval()

tokenizer = get_tokenizer()

# 기본 home 출력하는 탬플릿
@app.route('/', methods=["GET", "POST"])
def index():
    return render_template('index.html', **locals())

# 대기 시 수행하는 것. 먼저 말을 걸거나 표정이 안좋아보이기 전엔 대기
@app.route('/standby', methods=["GET", "POST"])
def standby():
    if request.method == 'POST': #post 방식으로 전송될 경우
        # files과 json 형식으로 데이터를 받음
        binary_data = {}
        the_files = request.files
        the_data = request.get_json()
        for file in the_files:
            binary_data[file] = the_files[file].read()

        # 받은 png와 wav 파일 저장
        f1 = open('./emotions/frame.png', 'wb')
        f1.write(binary_data['images'])
        f2 = open('./audio/user_voice.wav', 'wb')
        f2.write(binary_data['wave'])
        f1.close()
        f2.close()
        state = float(binary_data['state'])

        # 표정에서 감정 추출
        faces = CF.face.detect(img_url, True, False, "age, gender, emotion")
        for i in faces:
            happiness = i['faceAttributes']['emotion']['happiness']
            anger = i['faceAttributes']['emotion']['anger']
            contempt = i['faceAttributes']['emotion']['contempt']
            disgust = i['faceAttributes']['emotion']['disgust']
            fear = i['faceAttributes']['emotion']['fear']
            sadness = i['faceAttributes']['emotion']['sadness']
        bad_expression = anger + contempt + disgust + fear + sadness

        if happiness < bad_expression:  # 우울해 보일 때
            state = state + 0.1 # 잘못 체크 할 수도 있으니 약간만 증가
            # 무슨 일이 있으신가요? 기분이 안좋아보여요. 제가 도울 수 있는게 있으면 말해주세요.
            open_read = open('./audio/Opening.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state)}

            return Response(json.dumps(dict_data), mimetype='text/plain')
        else:  # 우울해 보이지 않을 땐 버디 이름을 부를때까지 대기
            audio_input = speechsdk.AudioConfig(filename="./audio/user_voice.wav")
            speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config,
                                                           language="ko-KR", audio_config=audio_input)
            the_question = speech_recognizer.recognize_once_async().get()
            if '버디' in the_question.text:  # 이름을 불렀을 때
                # 네, 부르셨나요?
                open_read = open('./audio/call_name.wav', 'rb').read()
                encoded = base64.b64encode(open_read)
                dict_data = {"response": str(encoded), "run_check": "1", "state": str(state)}

                return Response(json.dumps(dict_data), mimetype='text/plain')

        # 아무런 말이 없을 때는 무음 wav를 return한다 (형식을 맞추기 위함)
        open_read = open('./audio/silence.wav', 'rb').read()
        encoded = base64.b64encode(open_read)
        dict_data = {"response": str(encoded), "run_check": "0", "state": str(state)}

        return Response(json.dumps(dict_data), mimetype='text/plain')

# 본격적인 대화 부분
@app.route('/chatbot', methods=["GET", "POST"])
def chatbotResponse():
    if request.method == 'POST': #post 방식으로 전송될 경우
        # files 형식으로 데이터를 받음
        binary_data = {}
        the_files = request.files
        for file in the_files:
            binary_data[file] = the_files[file].read()

        # 받은 png와 wav 파일 저장
        f1 = open('./emotions/frame.png', 'wb')
        f1.write(binary_data['images'])
        f2 = open('./audio/user_voice.wav', 'wb')
        f2.write(binary_data['wave'])
        f1.close()
        f2.close()
        state = float(binary_data['state'])
        silence = int(binary_data['silence'])

        faces = CF.face.detect(img_url, True, False, "age, gender, emotion")
        for i in faces:
            happiness = i['faceAttributes']['emotion']['happiness']
            anger = i['faceAttributes']['emotion']['anger']
            contempt = i['faceAttributes']['emotion']['contempt']
            disgust = i['faceAttributes']['emotion']['disgust']
            fear = i['faceAttributes']['emotion']['fear']
            sadness = i['faceAttributes']['emotion']['sadness']
        bad_expression = anger + contempt + disgust + fear + sadness

        if happiness < bad_expression:  # 우울해 보일 때
            state = state + bad_expression * 0.5

        # STT API로 사용자의 발화를 문자로 변환
        audio_input = speechsdk.AudioConfig(filename="./audio/user_voice.wav")
        speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config,
                                                           language="ko-KR", audio_config=audio_input)
        the_question = speech_recognizer.recognize_once_async().get()

        if '종료' in the_question.text:  # 종료를 원할 때
            # 네. 종료하겠습니다.
            open_read = open('./audio/end.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "0", "state": str(0),
                         "silence": str(0), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        elif '음악' in the_question.text:  # 음악 재생을 바랄 때
            # 음악을 재생합니다.
            open_read = open('./audio/music_start.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "0", "state": str(0),
                         "silence": str(0), "music": str(1)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        elif state >= 10.0 :  # 기준 수치 초과
            # 마음이 소란 스러울 때, 듣기 좋은 음악을 들어보시는 건 어떤가요? 원하신다면 음악 틀어줘, 라고 말해주세요.
            open_read = open('./audio/suggestion.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state),
                         "silence": str(silence), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        elif len(str(the_question.text)) <= 1: # 사용자가 침묵하고 있을 때
            silence = silence + 1
            open_read = open('./audio/silence.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state),
                         "silence": str(silence), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        else : # 음성이 녹음되어 있을 때
            data = kobert_input(tokenizer, str(the_question.text), device, 512)

            output = model(**data)

            logit = output[0]
            softmax_logit = torch.softmax(logit, dim=-1)
            softmax_logit = softmax_logit.squeeze()

            max_index = torch.argmax(softmax_logit).item()
            max_index_value = softmax_logit[torch.argmax(softmax_logit)].item()

            answer_list = answer[category[str(max_index)]]
            answer_len = len(answer_list) - 1
            answer_index = random.randint(0, answer_len)

            response = answer_list[answer_index]
            state = state + 1

            # TTS API로 음성 답변 생성
            audio_config = AudioOutputConfig(filename="./audio/response.wav")
            synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
            synthesizer.speak_text_async(response)

            open_read = open('./audio/response.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state),
                         "silence": str(silence), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5000', debug=True)


import pygame
from pygame.locals import *
from sys import exit
from random import randint

pygame.init()

red = (255, 0, 0)
black = (0, 0, 0)
white = (255, 255, 255)
green = (10, 10, 255)

width = 640
height = 480

x_cobra = int(width/2)
y_cobra = int(height/2)

vel = 10
x_control = vel
y_control = 0

xc = randint(40, 600)
yc = randint(50, 430)

pontos = 0
font = pygame.font.SysFont('arial', 40, bold=True)

screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Snake')
clock = pygame.time.Clock()

listC = []
comprimentoIni = 5
gameOver= False

def upCobra(listC):
    for XeY in listC:
        pygame.draw.rect(screen, green, (XeY[0], XeY[1], 20, 20))

def reset():
    global pontos, comprimentoIni, x_cobra, y_cobra, listC, listCab, xc, yc, gameOver
    pontos = 0
    comprimentoIni = 5
    x_cobra = int(width/2)
    y_cobra = int(height/2)
    listC = []
    listCab = []
    xc = randint(40, 600)
    yc = randint(50, 430)
    gameOver = False

while True:
    clock.tick(30)
    screen.fill((255, 255, 255))
    mens = f'Pontos: {pontos}'
    txtF = font.render(mens, True, black)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()

        if event.type == KEYDOWN:
            if event.key == K_a:
                if x_control == vel:
                    pass
                else:
                    x_control = -vel
                    y_control = 0
            if event.key == K_d:
                if x_control == -vel:
                    pass
                else:
                    x_control = vel
                    y_control = 0
            if event.key == K_w:
                if y_control == vel:
                    pass
                else:
                    y_control = -vel
                    x_control = 0
            if event.key == K_s:
                if y_control == -vel:
                    pass
                else:
                    y_control = vel
                    x_control = 0

        x_cobra += x_control
        y_cobra += y_control

        cobra = pygame.draw.rect(screen, (green), (x_cobra, y_cobra, 20, 20))
        com = pygame.draw.rect(screen, red, (xc, yc, 20, 20))

        if cobra.colliderect(com):
            xc = randint(40, 600)
            yc = randint(50, 430)
            pontos += 1
            comprimentoIni += 1

        listCab = []
        listCab.append(x_cobra)
        listCab.append(y_cobra)

        listC.append(listCab)

        if listC.count(listCab) > 1:
            fonte = pygame.font.SysFont('arial', 20, True, False)
            mens = 'Game over! Precione R para jogar novamente'
            textF = fonte.render(mens, True, white)
            retTxt = textF.get_rect()
            gameOver = True
            while gameOver:
                screen.fill(white)
                for event in pygame.event.get():
                    if event.type == QUIT:
                        pygame.quit()
                        exit()
                    if event.type == KEYDOWN:
                        if event.key == K_r:
                            reset()
                retTxt.center = (width/2, height/2)
                screen.blit(txtF, retTxt)
                pygame.display.update()

        if x_cobra > width:
            x_cobra = 0
        if x_cobra < 0:
            x_cobra = width
        if y_cobra < 0:
            y_cobra = height
        if y_cobra > height:
            y_cobra = 0

        if len(listC) > comprimentoIni:
            del listC[0]

        upCobra(listC)

        screen.blit(txtF, (450, 40))

        pygame.display.update()


# python soln.py  0.09s user 0.02s system 70% cpu 0.161 total

import itertools

# ---------------- Class Setup ----------------------

class Octopus:
    def __init__(self, level):
        self.level = level
        self.flashed_this_step = False

    def __repr__(self):
        return f"{str(self.level):>2}"

class OctoGrid:
    def __init__(self, grid):
        self.grid = grid
        self.height = len(self.grid)
        self.width = len(self.grid[0])
        self.addresses = [(i, j) for i in range(self.height) for j in range(self.width)]
        self.flash_count = 0
        self.step_num = 0

    def __repr__(self):
        msg = f"Step Count: {self.step_num}\nFlash Count: {self.flash_count}\nGrid:\n"
        for i in self.grid:
            msg = msg + str(i) + "\n"
        return msg

    def get_adjs(self, coord):
        adjs = [
            x for x in list(itertools.product([1, 0, -1], [1, 0, -1])) if x != (0, 0)
        ]
        return [
            (coord[0] + adj[0], coord[1] + adj[1])
            for adj in adjs
            if 0 <= coord[0] + adj[0] < self.height
            and 0 <= coord[1] + adj[1] < self.width
        ]

    def get_flash_octs(self):
        return [
            (i, j)
            for (i, j) in self.addresses
            if self.grid[i][j].level > 9 and not self.grid[i][j].flashed_this_step
        ]

    def get_flashed_octs(self):
        return [
            (i, j) for (i, j) in self.addresses if self.grid[i][j].flashed_this_step
        ]

    def flash(self, coord):
        adjs = self.get_adjs(coord)
        for i, j in adjs:
            self.grid[i][j].level += 1

        self.grid[coord[0]][coord[1]].flashed_this_step = True
        self.flash_count += 1

    def step(self):
        # increment each octopus
        for i, j in self.addresses:
            grid[i][j].level += 1

        # flash all octopuses > 9 that haven't flashed - keep doing this
        flash_oct_addrs = self.get_flash_octs()
        while len(flash_oct_addrs) > 0:
            for i, j in flash_oct_addrs:
                self.flash((i, j))
            flash_oct_addrs = self.get_flash_octs()

        # reset flashed octs to 0 and reset all flash indicators
        flashed_octs = self.get_flashed_octs()
        for i, j in flashed_octs:
            self.grid[i][j].level = 0
            self.grid[i][j].flashed_this_step = False
        self.step_num += 1

    def multi_step(self, step_count):
        for i in range(step_count):
            self.step()

    def all_octs_just_flashed(self):
        return all(self.grid[i][j].level == 0 for (i, j) in self.addresses)

# -------------------- P1 -----------------------------

with open("input.txt") as in_file:
    grid = [[Octopus(int(o)) for o in line.strip()] for line in in_file.readlines()]

octo_grid = OctoGrid(grid)
octo_grid.multi_step(100)

print(f"P1 Soln: {octo_grid.flash_count}")

# -------------------- P2 -----------------------------

while not octo_grid.all_octs_just_flashed():
    octo_grid.step()

print(f"P2 Soln: {octo_grid.step_num}")


import torch
import os
import numpy as np
import re

from src.config import cfg
from src.data import make_gallery_loader, make_query_loader
from src.modeling import build_model
from src.data.transforms import build_transforms

def Singleton(cls):
    _instance = {}

    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton

@Singleton
class ReidModel(object):
    """
    """
    def __init__(self, config = cfg, config_file="configs/softmax_triplet.yml"):
        """ initialize a ReidModel object
        :param:
            :config_file: a relative path of yml file, which specify the model type, model weight path etc.
        """
        # build kernel
        config.merge_from_file(os.path.join(os.path.dirname(__file__), config_file))
        self.__cfg = config
        self.__kernel = None
        self.__build_kernel(config)

        # load or extract gallery features
        self.__gallery_image_features = None
        self.__gallery_image_paths = None
        self.__load_gallery_features()

        self.__transform = build_transforms(config)

    def __build_kernel(self, config):
        """ build reid algorighm kernel object. only for extracting image features
        :param:
            config: CfgNode object; specifiy model structure, weight path etc.
        :return: reid algorighm kernel object
        """
        kernel = build_model(config)
        kernel.load_param(config.TEST.WEIGHT)
        kernel.eval()
        kernel.cuda()
        self.__kernel = kernel

    def __update_gallery_feature(self, feature_dir="./Features"):
        """ forece to update the gallery feature in case of gallery change
        :param:
            :feature_path: archive path of gallery features:
        """
        # update features in memory
        gallery_loader = make_gallery_loader(self.__cfg)
        gallery_image_features, gallery_image_paths = self.__extract_gallery_features(gallery_loader)
        self.__gallery_image_features = gallery_image_features
        self.__gallery_image_paths = gallery_image_paths

        # update features archived
        os.makedirs(feature_dir, exist_ok=True)
        feature_path = os.path.join(feature_dir, "feautures.pt")
        torch.save(gallery_image_features, feature_path)

        image_list_path = os.path.join(feature_dir, "image_paths.txt")
        with open(image_list_path, 'w') as f:
            for image_path in gallery_image_paths:
                f.write(image_path+'\n')

    def __load_gallery_features(self, feature_dir="./Features"):
        """ load gallery features if exists, otherwise extract gallery features and store it.
        :param:
            :feature_path: archive path of gallery features
        """
        feature_path = os.path.join(feature_dir, "feautures.pt")
        image_list_path = os.path.join(feature_dir, "image_paths.txt")

        if os.path.exists(feature_path) and os.path.exists(image_list_path):
            self.__gallery_image_features = torch.load(feature_path)
            with open(image_list_path) as f:
                self.__gallery_image_paths = f.readlines()
                self.__gallery_image_paths = [image_path.rstrip('\n') for image_path in self.__gallery_image_paths]
        else:
            self.__update_gallery_feature(feature_dir=feature_dir)

    def __extract_single_feature(self, image):
        """ extract feature for a single image. usually for query image
        :param:
            :image: PIL.Image.Image object; image to process.
        """
        image = image.convert('RGB')
        image = self.__transform(image)
        image = image.unsqueeze(0)              # 从(c,h,w) _ (1,c,h,w)适配模型的输入
        image = image.to(self.__cfg.MODEL.DEVICE)
        with torch.no_grad():
            feature = self.__kernel(image)
            feature = torch.nn.functional.normalize(feature, dim=1, p=2)            # nomralization for compute cosine distance
            return feature

    def __extract_gallery_features(self, dataloader):
        features = []
        image_paths = []
        g_pids = []
        g_camids = []

        with torch.no_grad():
            for batch in dataloader:
                data, pids, camids, img_paths = batch
                data = data.to(self.__cfg.MODEL.DEVICE)
                feat = self.__kernel(data)
                features.append(feat)
                image_paths += img_paths
                g_pids.extend(pids)
                g_camids.extend(camids)

            self.__g_pids = g_pids
            self.__g_camids = g_camids
            features = torch.cat(features, dim=0)
            features = torch.nn.functional.normalize(features, dim=1, p=2)
            return features, image_paths

    def __compute_distance_matrix(self, qf, gf):
        """ compute the distance between query feature and gallery features
        :param:
            qf: query feature
            gf: gallery feature
        :return: distmat: a [1xn] matrix, matrix[0][i] indicates the distance between query feature and ith gallery feature.
        """
        # nomalize the query feature and gallery feature
        print("The query feature is normalized")

        m, n = qf.shape[0], gf.shape[0]
        distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \
                  torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t()
        distmat.addmm_(qf, gf.t(), beta=1, alpha=-2)

        return distmat

    def get_gallery_size(self):
        return len(self.__gallery_image_paths)

    def get_similar_image_rank_list(self, query, max_length=10):
        """ get a rank list of similary images of input image.
        :param:
            query: image to match the gallery images.
        :return: a list of image path, the distance between query image and each in the list ascends.
        image path format like "/path/0001_c0_f0123456.jpg"
        """
        query_feature = self.__extract_single_feature(query)
        distmat = self.__compute_distance_matrix(query_feature, self.__gallery_image_features)
        rank_list = np.argsort(distmat.cpu(), axis=1)
        rank_list = rank_list.squeeze()
        return [self.__gallery_image_paths[index] for index in rank_list[:max_length]]

    def evaluate_performance_on_origin_dataset(self):
        """ to verify the implementation is correct
        """
        from src.utils.eval_reid import eval_func

        # extrack all query features
        query_loader = make_query_loader(self.__cfg)
        query_image_features = []
        query_image_paths = []
        q_pids = []
        q_camids = []
        with torch.no_grad():
            for batch in query_loader:
                data, pids, camids, img_paths = batch
                data = data.to(self.__cfg.MODEL.DEVICE)
                feat = self.__kernel(data)
                query_image_features.append(feat)
                query_image_paths += img_paths
                q_pids.extend(pids)
                q_camids.extend(camids)

            query_image_features = torch.cat(query_image_features, dim=0)
            query_image_features = torch.nn.functional.normalize(query_image_features, dim=1, p=2)

        # calculate distance matrix
        distmat = self.__compute_distance_matrix(query_image_features, self.__gallery_image_features)
        cmc, mAP = eval_func(distmat.cpu(), np.asarray(q_pids), np.asarray(self.__g_pids), np.asarray(q_camids), np.asarray(self.__g_camids))
        return cmc[0], mAP


from typing import Iterable, Optional

from django.contrib.auth import get_user_model
from django.db import models

TASK_STATUS_CHOICES = [
    ('N', 'NEW'),
    ('I', 'IN PROGRESS'),
    ('P', 'IN PAUSE'),
    ('D', 'DONE'),
]

TASK_PRIORITY_CHOICES = [
    ('HH', 'Highest'),
    ('H', 'High'),
    ('M', 'Medium'),
    ('L', 'Low'),
    ('LL', 'Lowest'),
]

User = get_user_model()

class Task(models.Model):
    description = models.CharField(max_length=255)
    status = models.CharField(choices=TASK_STATUS_CHOICES, max_length=2)
    priority = models.CharField(
        choices=TASK_PRIORITY_CHOICES, default='M')
    owner = models.ForeignKey(User, on_delete=models.CASCADE)


from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static

admin.site.site_header = "Mickey Ice Creams Admin"
admin.site.site_title = "Mickey Ice Creams Admin Portal"
admin.site.index_title = "Welcome to Mickey Ice Creams"

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('home.urls')),
]


# import the opencv library
import cv2
import os
from time import time
import numpy as np
from buffer import Buffer
from face_detect import FaceDetection, pixelate

once = True

tracker = cv2.TrackerMIL_create()

backtracker = cv2.TrackerMIL_create()
detector = FaceDetection()

frame_buffer = Buffer(30)
my_img_1 = np.zeros((1280, 720, 1), dtype="uint8")

filename = "output.mp4"
frames_per_second = 30.0
res = "720p"

def change_res(cap, width, height):
    cap.set(3, width)
    cap.set(4, height)

# Standard Video Dimensions Sizes
STD_DIMENSIONS = {
    "480p": (640, 480),
    "720p": (1280, 720),
    "1080p": (1920, 1080),
    "4k": (3840, 2160),
}

def get_dims(cap, res="1080p"):
    width, height = STD_DIMENSIONS["480p"]
    # if res in STD_DIMENSIONS:
    #     width, height = STD_DIMENSIONS[res]
    ## change the current caputre device
    ## to the resulting resolution
    change_res(cap, width, height)
    return width, height

VIDEO_TYPE = {
    "avi": cv2.VideoWriter_fourcc(*"XVID"),
    "mp4": cv2.VideoWriter_fourcc(*"mp4v"),
}

def get_video_type(filename):
    filename, ext = os.path.splitext(filename)
    if ext in VIDEO_TYPE:
        return VIDEO_TYPE[ext]
    return VIDEO_TYPE["mp4"]

# define a video capture object
# vid = cv2.VideoCapture(0, cv2.CAP_DSHOW)
vid = cv2.VideoCapture("input.mp4")
out = cv2.VideoWriter(filename, get_video_type(filename), 25, get_dims(vid, res))
start_time = time()
print_delay = True
detect = True
bbox = None
write_frame = None

input_frames = []
output_frames = []

while True:
    ret, frame = vid.read()
    if not ret:
        break
    input_frames.append(frame)
    out.write(frame)
vid.release()

counter = 0

while True:
    try:
        frame = input_frames.pop(0)
    except IndexError:
        frame = False

    if not isinstance(frame, bool):
        frame, detect, bbox = detector.detect_or_track(frame, detect, tracker)
        if once and not detect:
            once = False
            backtracker.init(frame, bbox)
            frames = frame_buffer.get_buffer_frames()
            for i in range(len(frames) - 2, 0, -1):
                cur_frame = frames[i]
                status, bbox = backtracker.update(cur_frame)
                if status:
                    x, y, w, h = bbox
                    cur_frame = pixelate(cur_frame, x, y, w, h)
                    cv2.rectangle(cur_frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
                    frame_buffer.update_frame(cur_frame, i)
        status = frame_buffer.add_frames(frame)

    ret_frame = frame_buffer.get_frames()
    if isinstance(ret_frame, bool):
        if not ret_frame and isinstance(frame, bool):
            break
        if not ret_frame:
            write_frame = my_img_1
    else:
        write_frame = ret_frame
        if print_delay:
            frame_start_time = time()
            print("Frame Lag ", frame_start_time - start_time)
            print_delay = False

    cv2.imshow("frame", write_frame)
    output_frames.append(write_frame)
    counter += 1
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

for frame in output_frames:
    out.write(frame)

out.release()
# Destroy all the windows
cv2.destroyAllWindows()


from __future__ import annotations

from typing import Any, Tuple

from langchain.chains.query_constructor.ir import (
    Comparator,
    Comparison,
    Operation,
    Operator,
    StructuredQuery,
    Visitor,
)
from langchain.vectorstores.redis import Redis
from langchain.vectorstores.redis.filters import (
    RedisFilterExpression,
    RedisFilterField,
    RedisFilterOperator,
    RedisNum,
    RedisTag,
    RedisText,
)
from langchain.vectorstores.redis.schema import RedisModel

_COMPARATOR_TO_BUILTIN_METHOD = {
    Comparator.EQ: "__eq__",
    Comparator.NE: "__ne__",
    Comparator.LT: "__lt__",
    Comparator.GT: "__gt__",
    Comparator.LTE: "__le__",
    Comparator.GTE: "__ge__",
    Comparator.CONTAIN: "__eq__",
    Comparator.LIKE: "__mod__",
}

class RedisTranslator(Visitor):
    """Translate"""

    allowed_comparators = (
        Comparator.EQ,
        Comparator.NE,
        Comparator.LT,
        Comparator.LTE,
        Comparator.GT,
        Comparator.GTE,
        Comparator.CONTAIN,
        Comparator.LIKE,
    )
    """Subset of allowed logical comparators."""
    allowed_operators = (Operator.AND, Operator.OR)
    """Subset of allowed logical operators."""

    def __init__(self, schema: RedisModel) -> None:
        self._schema = schema

    def _attribute_to_filter_field(self, attribute: str) -> RedisFilterField:
        if attribute in [tf.name for tf in self._schema.text]:
            return RedisText(attribute)
        elif attribute in [tf.name for tf in self._schema.tag or []]:
            return RedisTag(attribute)
        elif attribute in [tf.name for tf in self._schema.numeric or []]:
            return RedisNum(attribute)
        else:
            raise ValueError(
                f"Invalid attribute {attribute} not in vector store schema. Schema is:"
                f"\n{self._schema.as_dict()}"
            )

    def visit_comparison(self, comparison: Comparison) -> RedisFilterExpression:
        filter_field = self._attribute_to_filter_field(comparison.attribute)
        comparison_method = _COMPARATOR_TO_BUILTIN_METHOD[comparison.comparator]
        return getattr(filter_field, comparison_method)(comparison.value)

    def visit_operation(self, operation: Operation) -> Any:
        left = operation.arguments[0].accept(self)
        if len(operation.arguments) > 2:
            right = self.visit_operation(
                Operation(
                    operator=operation.operator, arguments=operation.arguments[1:]
                )
            )
        else:
            right = operation.arguments[1].accept(self)
        redis_operator = (
            RedisFilterOperator.OR
            if operation.operator == Operator.OR
            else RedisFilterOperator.AND
        )
        return RedisFilterExpression(operator=redis_operator, left=left, right=right)

    def visit_structured_query(
        self, structured_query: StructuredQuery
    ) -> Tuple[str, dict]:
        if structured_query.filter is None:
            kwargs = {}
        else:
            kwargs = {"filter": structured_query.filter.accept(self)}
        return structured_query.query, kwargs

    @classmethod
    def from_vectorstore(cls, vectorstore: Redis) -> RedisTranslator:
        return cls(vectorstore._schema)


import matplotlib.pyplot as plt
import numpy as np

def barChart():
    x = np.arange(4)
    y1 = np.random.randint(20, 50, 4)
    y2 = np.random.randint(10, 60, 4)
    plt.figure(figsize=(6, 4), dpi=120)
    # 通过横坐标的偏移，让两组数据对应的柱子分开
    # width参数控制柱子的粗细，label参数为柱子添加标签
    plt.bar(x - 0.1, y1, width=0.2, label='销售A组')
    plt.bar(x + 0.1, y2, width=0.2, label='销售B组')
    # 定制横轴的刻度
    plt.xticks(x, labels=['Q1', 'Q2', 'Q3', 'Q4'])
    # 定制显示图例
    plt.legend()
    plt.show()

def stackGraph():
    x = np.arange(4)
    y1 = np.random.randint(20, 50, 4)
    y2 = np.random.randint(10, 60, 4)
    labels = ['Q1', 'Q2', 'Q3', 'Q4']
    plt.figure(figsize=(6, 4), dpi=120)
    plt.bar(labels, y1, width=0.4, label='销售A组')
    # 注意：堆叠柱状图的关键是将之前的柱子作为新柱子的底部
    # 可以通过bottom参数指定底部数据，新柱子绘制在底部数据之上
    plt.bar(labels, y2, width=0.4, bottom=y1, label='销售B组')
    plt.legend(loc='lower right')
    plt.show()

def pie():
    data = np.random.randint(100, 500, 7)
    labels = ['苹果', '香蕉', '桃子', '荔枝', '石榴', '山竹', '榴莲']

    plt.figure(figsize=(5, 5), dpi=120)
    plt.pie(
        data,
        # 自动显示百分比
        autopct='%.1f%%',
        # 饼图的半径
        radius=1,
        # 百分比到圆心的距离
        pctdistance=0.8,
        # 颜色（随机生成）
        colors=np.random.rand(7, 3),
        # 分离距离
        # explode=[0.05, 0, 0.1, 0, 0, 0, 0],
        # 阴影效果
        # shadow=True,
        # 字体属性
        textprops=dict(fontsize=8, color='black'),
        # 楔子属性（生成环状饼图的关键）
        wedgeprops=dict(linewidth=1, width=0.35),
        # 标签
        labels=labels
    )
    # 定制图表的标题
    plt.title('水果销售额占比')
    plt.show()

if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Songti SC']
    plt.rcParams['axes.unicode_minus'] = False
    #plt.figure(figsize=(8, 4), dpi=120, facecolor='darkgray')
    #plt.subplot(2, 2, 1)

    # barChart()
    # stackGraph()
    pie()