import logging
import argparse
import ast
from collections import OrderedDict
import torch
import os
from datetime import datetime
import numpy as np
import json
irange = range
import networkx as nx

def mylogger(logpath='./param.log'):
    logger = logging.getLogger('mylogger')
    logger.setLevel('DEBUG')
    logger.propagate = False
    BASIC_FORMAT = "%(asctime)s:%(levelname)s:%(message)s"
    DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
    formatter = logging.Formatter(BASIC_FORMAT, DATE_FORMAT)
    fhlr = logging.FileHandler(logpath) #
    fhlr.setFormatter(formatter)
    logger.addHandler(fhlr)
    str_sharp = '#####################################################################'
    logger.info(str_sharp +'Record Experiment Information and Conditions\n')
    # logger.info('  Experiment Setting and Running Logs\n\n')

    chlr = logging.StreamHandler() #
    chlr.setFormatter(formatter)
    chlr.setLevel('DEBUG')  #
    logger.addHandler(chlr)

def parseArg ():
    parseArgs = argparse.ArgumentParser(description='Arguments for project.')
    parseArgs.add_argument('--alpha', type=float, default=0.1, help='the value of alpha for pageRank')
    parseArgs.add_argument('--batch_size',type=int, default= 512, help='Number of batch size')
    parseArgs.add_argument('--baseline', action='store_true', default=False, help='the mode of training baseline or our model')
    parseArgs.add_argument('--regression', action='store_true', default=False, help='the mode of training regression model or others')
    parseArgs.add_argument('--baseLr', type=float, default = '0.001', help='The base learning rate for optimizer')
    parseArgs.add_argument('--dataset',type=str,default = 'PROTEINS', help='specify the training dataset')
    parseArgs.add_argument('--datapath',type=str,default = './data', help='specify the path to the dataset')
    parseArgs.add_argument('--dropout_ratio', type=float, default=0.0, help='dropout ratio')
    parseArgs.add_argument('--epoch_start',type=int, default= 0, help='the num of training epoch for restore,0 means training from scrach')
    parseArgs.add_argument('--epochs',type=int, default= 300, help='the num of max iteration')
    parseArgs.add_argument('--exp_att',type=str, default='test', help='the name of current experiment')
    parseArgs.add_argument('--eps', type=float, default=0, help='used for clipping edges')
    parseArgs.add_argument('--edge_ratio', type=float, default=0.6, help='ratio to select the edges')
    parseArgs.add_argument('--Gamma', default=None)
    parseArgs.add_argument('--gpu_ids',type=str, default= '', help='the ids of GPUs')
    parseArgs.add_argument('--Init', type=str,choices=['SGC', 'PPR', 'NPPR', 'Random', 'WS', 'Null'], default='PPR')
    parseArgs.add_argument('--info', '-I', type=str, default='Info for running program', help='This info is used to record the running conditions for the current program, which is stored in param.log')
    parseArgs.add_argument('--K',type=int, default= 10, help='the num of pageRank step')
    parseArgs.add_argument('--l2', type=float, default=1.0, help='gate loss(i.e. the final classification loss) weight')
    parseArgs.add_argument('--local_rank', default=0, type=int, help='node rank for distributed training')
    parseArgs.add_argument('--logfile',type=str, default= './logs.log', help='the name of log file')
    parseArgs.add_argument('--log_interval',type=int, default= 200, help='the interval of training epoch for logging')
    parseArgs.add_argument('--modelname',type=str, default= 'HGPSL', help='the name of DNN for explaining')
    parseArgs.add_argument('--num_classes',type=int, default= 2, help='the num of classes in dataset')
    parseArgs.add_argument('--num_layers',type=int, default= 3, help='the num of conv layers in model')
    parseArgs.add_argument('--max_num_nodes',type=int, default= 100, help='the max num of nodes in a dataset')
    parseArgs.add_argument('--nhid', type=int, default=128, help='hidden size')
    parseArgs.add_argument('--target_dim', type=int, default=0, help='regression target for QM9')
    parseArgs.add_argument('--noise_ratio', type=float, default=0.0, help='the probability of removing edges/node features')
    parseArgs.add_argument('--noise_type',type=str, default= 'randomnodes_-1', help='Use for path conflict')
    parseArgs.add_argument('--pooling_ratio', type=float, default=0.5, help='pooling ratio')
    parseArgs.add_argument('--patience',type=int, default=50, help='the patience of optimizer')
    parseArgs.add_argument('--path_conflict',type=str, default= '', help='Use for path conflict')
    parseArgs.add_argument('--phase',type=str, default= 'test', help='train or test')
    parseArgs.add_argument('--res_dir',type=str, default='./experiments', help='the path for saving results')
    parseArgs.add_argument('--restore_file',type=str, default='', help='the path/file for restore models')
    parseArgs.add_argument('--save_flag', type=ast.literal_eval, default=False, help='save figures or not')
    parseArgs.add_argument('--seed', type=int, default=200, help='the seed for random selection')
    parseArgs.add_argument('--test_batch',type=int, default= 512, help='Number of test batch size')
    parseArgs.add_argument('--v', type=ast.literal_eval, default = False, help='display the debug info or not')
    parseArgs.add_argument('--weight_decay', type=float, default=0.05, help='weight decay')

    return parseArgs.parse_args()

def loadArgs(args, r_iterms):
    filename = os.path.join(args.restore_file, 'parameters.txt')
    argsDict = args.__dict__
    with open(filename, 'r') as f:
        arg = json.load(f)
    for itm in r_iterms:
        argsDict[itm] = arg[itm]
    return args

class AverageMeter(object):
    """Computes and stores the average and current value"""
    def __init__(self, name, fmt=':f'):
        self.name = name
        self.fmt = fmt
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

    def __str__(self):
        fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})'
        return fmtstr.format(**self.__dict__)

def accuracy(output, target, topk=(1,)):
    """Computes the accuracy over the k top predictions for the specified values of k"""
    with torch.no_grad():
        maxk = max(topk)
        batch_size = target.size(0)

        _, pred = output.topk(maxk, 1, True, True)
        pred = pred.t()
        correct = pred.eq(target.view(1, -1).expand_as(pred))

        res = []
        for k in topk:
            correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True)
            res.append(correct_k.mul_(100.0 / batch_size))
        return res

def time_stamp():
  TIMESTAMP = "{0:%Y-%m-%dT%H-%M-%S}".format(datetime.now())
  return TIMESTAMP

def get_para(model): # calculate the number of parameters
    para_num = 0
    for para in model.parameters():
        para_num += para.numel()
    return para_num

def create_name_experiment(parameters, attribute_experiment):
    name_experiment = '{}/{}'.format(parameters['dataset'], attribute_experiment)

    print('Name experiment: {}'.format(name_experiment))

    return name_experiment

def create_folder(folder, force=True):
    if not os.path.exists(folder):
        os.makedirs(folder, exist_ok=True)
    else:
        if force:
            folder = folder+str(np.random.randint(100))
            os.makedirs(folder, exist_ok=True)
    return folder

def loadweights(model, filename_model, gpu_ids=''):
    '''
    @Description: Load weights for pytorch model in different hardware environments
    @param {type} : {model: pytorch model, model that waits for loading weights
                     filename_model: str, name of pretrained weights
                     gpu_ids: list, available gpu list}
    @return:
    '''
    if filename_model != '' and os.path.exists(filename_model):
        if len(gpu_ids) == 0:
            # load weights to cpu
            state_dict = torch.load(filename_model, map_location=lambda storage, loc: storage)
            # create new OrderedDict that does not contain `module.`
            new_state_dict = OrderedDict()
            for k, v in state_dict.items():
                name = k.replace('module.','') # remove `module.`
                new_state_dict[name] = v
            state_dict = new_state_dict
        elif len(gpu_ids) == 1:
            state_dict = torch.load(filename_model)
            # create new OrderedDict that does not contain `module.`
            new_state_dict = OrderedDict()
            for k, v in state_dict.items():
                name = k.replace('module.','') # remove `module.`
                new_state_dict[name] = v
            state_dict = new_state_dict
        else:
            state_dict = torch.load(filename_model)
            new_state_dict = OrderedDict()
            for k, v in state_dict.items():
                if 'module' not in k:
                    name = ''.join(['module.',k]) # add `module.`
                    new_state_dict[name] = v
            if new_state_dict:
                state_dict = new_state_dict
    else:
         state_dict = ''
    return model, state_dict

def construct_graph(edge_index, batch, nodes_index, cur_nodes_index, node_attr):
    edge_index = edge_index.cpu().detach().numpy()
    nodes_index = nodes_index.cpu().detach().numpy()
    cur_nodes_index = cur_nodes_index.cpu().detach().numpy()
    # if edge_attr is not None:
    #     edge_attr = np.round(edge_attr.cpu().detach().numpy(), 3)
    batch = batch.cpu().detach().numpy()
    g = nx.Graph()

    for idx in range(edge_index.shape[1]):
        edge_index[0][idx] = nodes_index[edge_index[0][idx]]
        edge_index[1][idx] = nodes_index[edge_index[1][idx]]
    if node_attr is not None:
        node_attr = node_attr.cpu().detach().numpy()
        nodes_added={}
        if node_attr.shape[1] == 7:
            # tmp_str = ['C', 'N', 'O', 'F', 'I', 'Cl', 'Br']
            tmp_str = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2']
            node_labels = [np.where(r==1)[0][0] for r in node_attr]
            node_symbols = [tmp_str[nl] for nl in node_labels]
            for idx in range(cur_nodes_index.shape[0]):
                nodes_added[cur_nodes_index[idx]]=node_symbols[idx]
        nodes_added_sort = dict(sorted(nodes_added.items(), key=lambda kv: kv[0]))
        g.add_nodes_from(nodes_added_sort.keys())
        for idx, value in nodes_added_sort.items():
            g.nodes[idx]['color'] = value
    else:
        cur_nodes_index.sort()
        g.add_nodes_from(cur_nodes_index)
    g.add_edges_from(edge_index.transpose())
    # if edge_attr is not None:
    #     for i in range(edge_index.shape[1]):
    #         g.edges[edge_index[0][i],edge_index[1][i]]['weight'] = edge_attr[i]
    return g


from classes.puzzle import Puzzle
from classes.result import Result
from classes.player import Player

Player.drop_table()
Puzzle.drop_table()
Result.drop_table()

Player.create_table()
Puzzle.create_table()
Result.create_table()

puzzle1 = Puzzle.create("harpy")
puzzle2 = Puzzle.create("lemon")
puzzle3 = Puzzle.create("smell")
puzzle4 = Puzzle.create("overt")
puzzle5 = Puzzle.create("route")

player1 = Player.create("jess99")
player2 = Player.create("wumbo")
player3 = Player.create("meridith")

result1 = Result.create(player1.id, puzzle3.id, 150, 4)
result2 = Result.create(player2.id, puzzle3.id, 300, 1)
result3 = Result.create(player3.id, puzzle3.id, 200, 3)
result4 = Result.create(player1.id, puzzle2.id, 100, 5)
result5 = Result.create(player3.id, puzzle2.id, 250, 2)
result6 = Result.create(player1.id, puzzle1.id, 0, 6)


"""Este modulo desarrolla una API del núcleo de la aplicación"""

# Conexiones por arquitectura
import ibmq_chemical_core
import ibmq_chemical_comun

# Dependencias
from ibmq_chemical_api import la_api
from flask import Response, abort, request

import json

# Recursos comunes
@la_api.route("/servidores", methods=["GET"])
def servidores_get():
    """Esta función devuelve los servidores que el usuario puede escoger"""
    servidoresreales, servidoressimuladores, servidor = ibmq_chemical_core.orquestador.obtener_backends()
    servidores = {"servidoresreales": servidoresreales,
                  "servidoressimuladores": servidoressimuladores,
                  "servidor actual": servidor
                  }
    respuesta = _crear_json_resultados(servidores)
    return Response(respuesta, status=200, mimetype='application/json', headers={'content-type': 'application/json'})

@la_api.route("/servidores", methods=["POST"])
def servidores_post():
    """Esta función configura en el orquestador un servidor concreto"""
    configuracion = request.get_json()
    resultado = ibmq_chemical_core.orquestador.configurar_backend(configuracion["servidor"])
    if resultado:
        return Response(status=200)
    else:
        abort(422, "Error 422: El nombre de servidor no coincide con ninguno accesible")

# Recursos de cálculos
@la_api.route("/ejecutar_ibmq_vqe", methods=["POST"])
def ejecutar_ibmq_vqe_post():
    """Esta función permite realiza el cálculo del VQE en Qiskit Aqua de IBMQ"""
    configuracion = request.get_json()
    configuracionproblema = configuracion["problema"]
    configuracionmolecula = configuracion["molecula"]
    configuracioncore = {}
    if "core" in configuracion:
        configuracioncore = configuracion["core"]
    if "dibujo" in configuracioncore:
        dibujo = configuracioncore["dibujo"]
    else:
        dibujo = None

    resultados, consola, distancias = ibmq_chemical_core.orquestador.ejecutar_ibmq_vqe(
        configuracionproblema=configuracionproblema,
        configuracionmolecula=configuracionmolecula,
        dibujo=dibujo
    )
    respuesta = _crear_json_resultados(resultados, consola, distancias)
    return Response(respuesta, status=200, mimetype='application/json', headers={'content-type': 'application/json'})

@la_api.route("/ejecutar_numero_aleatorio", methods=["GET"])
def ejecutar_numero_aleatorio_get():
    """Esta función deuelve al usuario un objeto JSON con un número aleatorio de las cifras requeridas"""
    configuracion = request.get_json()
    cifras = configuracion["cifras"]
    if "backend" in configuracion:
        backend = ibmq_chemical_core.orquestador.set_backend(configuracion["backend"])
    else:
        backend = None
    resultado = ibmq_chemical_core.orquestador.ejecutar_numero_aleatorio(cifras, servidor=backend)
    respuesta = _crear_json_resultados(resultado)
    return Response(respuesta, status=200, mimetype='application/json', headers={'content-type': 'application/json'})

# Internas de la API
def _crear_json_servidores(servidores, consola=None):
    """Esta función encapsula en un archivo JSON los listados de servidores"""
    nombre = ibmq_chemical_comun.interfazsistema.generar_nombre()

    archivo = {"nombre": nombre,
               "servidores": servidores,
               "consola": consola
               }
    return json.dumps(archivo)

def _crear_json_resultados(resultado, consola=None, distancia=None):
    """Esta función encapsula en un archivo JSON algún cálculo"""
    nombre = ibmq_chemical_comun.interfazsistema.generar_nombre()

    archivo = {"nombre": nombre,
               "resultado": resultado,
               "consola": consola,
               "distancias": distancia
               }
    return json.dumps(archivo)


def validate_age(inp_age):

    if inp_age >= 18:

        print("You are ready to vote.")

    elif inp_age < 18:

        print("You are not ready to vote.")

i = 0
while True:
    age_inp= input("Enter the age please :")

    if(age_inp.isdigit):

        validate_age(int(age_inp))

        break

    elif(age_inp.isnotdigit):
        print("Invalid input")
        continue


import socket
import sys
# This is a sample Python script.

# Press Shift+F10  to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.

def main():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    except socket.error as err:
        print("A conexão falhou!!")
        print("Erro: {}".format(err))
        sys.exit()

    print("Socket criado com sucesso!!")
    host_alvo = input("Digite o Host ou Ip a ser conectado: ")
    porta_alvo = input("Digite o porta a ser conectado: ")

    try:
        s.connect((host_alvo, int(porta_alvo)))
        print(f"Client TCP com Sucesso no Host: {host_alvo} e na Porta: {porta_alvo}")
        s.shutdown(2)
    except socket.error as err:
        print(f"A conexão falhou no Host: {host_alvo} e na Porta: {porta_alvo}!")
        print(f"Erro: {err}")
        sys.exit()

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    main()
# See PyCharm help at https://www.jetbrains.com/help/pycharm/


import sqlite3
import csv
from io import StringIO

import o9k.o9k_utils.utils as utils

import requests
from bs4 import BeautifulSoup

DEBUG = True
NULL = "NULL"
DATABASE = "over9000.db"
USERS_TABLE = "USERS"
RESULTS_TABLE = "RESULTS"
USER_HEADERS = ["ID", "NAME", "CSV", "SOCIALS", "TEAM"]
RESULTS_HEADERS = ["Name", "Sex", "Event", "Equipment", "Age", "AgeClass",
                   "BirthYearClass", "Division", "BodyweightKg", "WeightClassKg",
                   "Squat1Kg", "Squat2Kg", "Squat3Kg", "Squat4Kg", "Best3SquatKg",
                   "Bench1Kg", "Bench2Kg", "Bench3Kg", "Bench4Kg", "Best3BenchKg",
                   "Deadlift1Kg", "Deadlift2Kg", "Deadlift3Kg", "Deadlift4Kg", "Best3DeadliftKg",
                   "TotalKg", "Place", "Dots", "Wilks", "Glossbrenner", "Goodlift",
                   "Tested", "Country", "State", "Federation", "ParentFederation",
                   "Date", "MeetCountry", "MeetState", "MeetTown", "MeetName", "CSV", "MeetID"]

reals = RESULTS_HEADERS[9:32]

#                       #
#   DATABASE CREATION   #
#                       #
# TODO: clean up setup code
def setup_db(debug=DEBUG):
    conn = sqlite3.connect(DATABASE)
    cursor = conn.cursor()

    # Check if USERS table exists
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='USERS';")
    if cursor.fetchone():
        print("Table USERS exists.\n Continuing.")
    else:
        print("Table USERS doesn't exist.\n Creating USERS")
        # create the USERS table
        ### NOTES:
        # LIFTER_NAME was natively NAME # NOTE: CHANGED BACK
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS USERS (
                ID TEXT PRIMARY KEY,
                NAME TEXT NOT NULL,
                CSV TEXT NOT NULL,
                SOCIALS TEXT,
                TEAM TEXT,
                UNIQUE (ID) ON CONFLICT IGNORE
            );
        """)
        print("Table OVER9000 created")

    # Check if RESULTS table exists
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='RESULTS';")
    if cursor.fetchone():
        print("Table RESULTS exists.\n Continuing.")
    else:
        print("Table RESULTS doesn't exist.\n Creating RESULTS")
        # create the RESULTS table because it doesn't exist
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS RESULTS (
                Name TEXT,
                Sex TEXT,
                Event TEXT,
                Equipment TEXT,
                Age TEXT,
                AgeClass TEXT,
                BirthYearClass TEXT,
                Division TEXT,
                BodyweightKg TEXT,
                WeightClassKg TEXT,
                Squat1Kg TEXT,
                Squat2Kg TEXT,
                Squat3Kg TEXT,
                Squat4Kg TEXT,
                Best3SquatKg TEXT,
                Bench1Kg TEXT,
                Bench2Kg TEXT,
                Bench3Kg TEXT,
                Bench4Kg TEXT,
                Best3BenchKg TEXT,
                Deadlift1Kg TEXT,
                Deadlift2Kg TEXT,
                Deadlift3Kg TEXT,
                Deadlift4Kg TEXT,
                Best3DeadliftKg TEXT,
                TotalKg TEXT,
                Place TEXT,
                Dots TEXT,
                Wilks TEXT,
                Glossbrenner TEXT,
                Goodlift TEXT,
                Tested TEXT,
                Country TEXT,
                State TEXT,
                Federation TEXT,
                ParentFederation TEXT,
                Date TEXT,
                MeetCountry TEXT,
                MeetState TEXT,
                MeetTown TEXT,
                MeetName TEXT,
                CSV TEXT NOT NULL,
                MeetID TEXT PRIMARY KEY,
                UNIQUE (MeetID) ON CONFLICT IGNORE
            );
        """)
        print("Table RESULTS created")

    # commit the changes and close the connection
    conn.commit()
    return conn

#                       #
#   ENTRY PROCESSING    #
#                       #
def str_cast(value):
    return str("\"" + value + "\"")

def get_csv_link(link):
    # Fetch the page
    response = requests.get(link)

    # Parse the HTML content
    soup = BeautifulSoup(response.content, 'html.parser')

    # Find the h2 tag with "Competition Results" text
    h2_tag = soup.find_all('h2')
    print("H2 TAGS: ", h2_tag)  # DEBUG print
    h2_tag = h2_tag[1]
    print("CSV_LINK in get_csv_link: ", h2_tag)  # DEBUG print

    # Find the a tag within the h2 tag and get its href value
    csv_link = h2_tag.find('a')['href']

    print("get_csv_link", csv_link)  # DEBUG print
    return csv_link

def load_csv_data(csv_link, debug=DEBUG):
    full_link = "https://www.openpowerlifting.org" + csv_link
    # Get the CSV data
    response = requests.get(full_link)  # you may need to adjust the URL
    data = response.content.decode('utf-8')

    # Parse the CSV data into a dictionary
    reader = csv.DictReader(StringIO(data))
    rows = list(reader)

    # Now rows is a list of dictionaries, each dictionary represents a row in the CSV
    print("in load_csv_data, printing data")  # DEBUG print
    utils.debug_print(f"csv before processing: {rows}", debug)  # DEBUG print

    for meet in rows:
        meet["CSV"] = csv_link
        meet["MeetID"] = " ".join([meet["Name"], "-", meet["MeetName"], "-", meet["Division"]])
        for k, v in meet.items():
            if not len(v):
                meet[k] = NULL
            else:
                meet[k] = str_cast(v)
    # TODO: START HERE BUDDY, WE'RE DOING CREATE_ENTRY AND NEED ALL THE FORMATTING DONE OUTSIDE SO THE SQL QUERY IS EASY

    return rows

# Convert dict data to sql entries
def csv_processing(csv_data, debug=DEBUG):
    for meet in csv_data:

        for k, v in meet.items():
            if not len(v):
                meet[k] = NULL
            else:
                meet[k] = str_cast(v)
    # TODO: START HERE BUDDY, WE'RE DOING CREATE_ENTRY AND NEED ALL THE FORMATTING DONE OUTSIDE SO THE SQL QUERY IS EASY

    return csv_data

class Database:
    def __init__(self):
        self.user_headers = USER_HEADERS
        self.results_headers = RESULTS_HEADERS
        self.conn = setup_db()

    def create_lifter(self, op_link, csv_data, csv_link, debug=DEBUG):
        LIFTER_HEADERS = ",".join(self.user_headers)

        lifter_entry = [str_cast(op_link), csv_data[0]["Name"], csv_data[0]["CSV"], NULL, NULL]
        utils.debug_print(f"values list: {lifter_entry}", debug)  # DEBUG print
        LIFTER_VALUES = ",".join(lifter_entry)

        create_lifter_command = f"INSERT INTO {USERS_TABLE} ({LIFTER_HEADERS}) " \
                               f"VALUES ({LIFTER_VALUES})"

        utils.debug_print(f"create_lifter SQL: {create_lifter_command}", debug)  ## work on format_csv_data, values are not cast properly
        self.conn.execute(create_lifter_command)
        self.conn.commit()

    # TODO: abstract some of this to crud, crud.create() not doing anything right now
    # create entry into OVER9000 and related entries into RESULTS
    def create_entry(self, op_links, debug=DEBUG):
        utils.debug_print(f"create_entry:: \nop_links: {op_links}", debug)

        for op_link in op_links:
            utils.debug_print(f"create_entry:: \nop_link: {op_link}", debug)
            csv_link = get_csv_link(op_link)
            csv_data = load_csv_data(csv_link)

            cursor = self.conn.execute('select * from RESULTS')
            print("\n COLNAMES \n")
            colnames = cursor.description
            for row in colnames:
                print(row[0])
                print(row[1])

            utils.debug_print(f"csv after processing: {csv_data}", debug)  # DEBUG print
            # Create LIFTER entry
            self.create_lifter(op_link, csv_data, csv_link)

            # Create RESULTS entry
            # self.create_results(csv_data, )
            RESULTS_SQL_HEADERS = ",".join(self.results_headers)

            # TODO: can use a multiple execute here if I knew how to SQL
            for meet in csv_data:
                RESULTS_SQL_VALUES = ",".join(meet.values())

                sql_results_command = f"INSERT INTO {RESULTS_TABLE} ({RESULTS_SQL_HEADERS}) " \
                                      f"VALUES ({RESULTS_SQL_VALUES})"

                print("SQL_RESULT_COMMAND: ", sql_results_command)
                self.conn.execute(sql_results_command)

            self.conn.commit()
        # CONTINUE here

    # SELECT from test
    def read_entry(self, lifter_id, fields):
        pass

    def update_entry(self, lifter_id, table, fields, new_vals):
        pass

    def delete_entry(self, lifter_id):
        pass

    def refresh_entry(self, lifter_id):
        pass


# coding: utf-8

# In[8]:

import csv
txt_file=r"SemEval2018-T3-train-taskA_emoji_ironyHashtags.txt"
csv_file=r"data1.csv"
in_txt= csv.reader(open(txt_file,'r',errors='ignore'),delimiter='\t')
out_csv=csv.writer(open(csv_file,'w'))
out_csv.writerows(in_txt)

# In[22]:

import emoji
import re
import nltk
from nltk.tokenize import word_tokenize
from nltk.tag import pos_tag
with open('data1.csv')as csvfile:
    de_emojize=emoji.demojize(csvfile.read())
    commonurl_str = re.sub(r'\w+:\/{2}[\d\w-]+(\.[\d\w-]+)*(?:(?:\/[^\s/]*))*', 'http://someurl', de_emojize)
    replace_username=re.sub('(?<=^|(?<=[^a-zA-Z0-9-_\.]))@([A-Za-z]+[A-Za-z0-9-_]+)','@someuser',commonurl_str)
    input_txt=replace_username+'\n'
print(input_txt)
input_tokenized=nltk.word_tokenize(input_txt)
#print(input_tokenized)
input_posTag=nltk.pos_tag(input_tokenized)
print(input_posTag)


def get_row(row_index):
    if row_index == 0:
        return [1]

    row = [1]
    for i in range(1, row_index + 1):
        new_row = [1]
        for j in range(1, i):
            new_row.append(row[j - 1] + row[j])
        new_row.append(1)
        row = new_row

    return row


import libs
class Data:
    """A class used to manage the words and their display

    Attributes
    ----------
    word: str
        The word that needs to be guessed during a game
    isGuessed: bool
        A Boolean indicating if the world has been guessed during a game or not (Not really used for now)
    revealed: [str]
        List containing the letters that have been guessed
    mistakes: [str]
        List containing the letters that I have been wrongly proposed
    size: int
        Length of the word

    Methods
    ----------
    display(self)
        Prints the world with '_' for the hidden letters while displaying the revealed letters
    update(self,guess)
        Updates revealed and mistakes depending on if the guess is correct or not
    reveal_word(self)
        Displays the full word
    get_word(index)
        Retrieves a word in the dictionary
     """

    def __init__(self,word,isGuessed=False):
        """
        Parameters
        ----------
        word: str
            The word to be guessed
        isGuessed:Bool
            Boolean indicating if the word has been guessed or not (default is False)
        """
        self.word=word
        self.isGuessed=isGuessed
        self.revealed=[]
        self.mistakes=[]
        self.size=len(word)

    def __len__(self):
        return len(self.word)

    def display(self):
        """
        Display the world in the console

        Prints the world with '_' for the hidden letters while displaying the revealed letters
        """

        hidden_word='-'*self.size
        for i,letter in enumerate(self.word):
            if letter in self.revealed:
                temp=list(hidden_word)
                temp[i]=letter
                hidden_word=''.join(temp)
        print(hidden_word)

    def update(self,guess):
        """
        Updates revealed and mistakes depending on if the guess is correct or not

        Parameters
        ----------
        guess: str
        Tentative guess from the user
        """

        #print('Update') #For debug purposes
        if guess in self.word:
            self.revealed.append(guess)
            return True
        else:
            self.mistakes.append(guess)
            return False

    def reveal_word(self):
        """
        Displays the full word
        """

        print(self.word)

    def get_word(index):
        """
        Retrieves a word in the dictionary

        Parameters
        ----------
        index: int
        Position of the word to be retrieved in the dictionary
        """
        with open('dictionary.txt','r') as dictionary_file:
            dictionary =dictionary_file.readlines()
            return dictionary[index][:len(dictionary[index])-1] #the output string of readlines contain /n that needs to be removed
    get_word=staticmethod(get_word)


# -*- coding: utf-8 -*-
"""
Created on Thu Nov 12 09:57:31 2020

@author: linghui
"""
import os
from shutil import copyfile

num = 100
def buildAllapps(cgbench):
    allBenchmarks = os.path.join(cgbench, "allBenchmarks")
    if not os.path.exists(allBenchmarks):
        os.mkdir(allBenchmarks)
    allGroundTruth = os.path.join(cgbench, "allGroundTruth")
    if not os.path.exists(allGroundTruth):
        os.mkdir(allGroundTruth)
    count = 0
    for d in os.listdir(cgbench):
        pomFile = os.path.join(cgbench, d, "pom.xml")
        appDir = os.path.join(cgbench, d)
        targetDir = os.path.join(appDir, "target")
        if os.path.exists(pomFile):
           os.chdir(appDir)
           ssFile = d+"_SourcesAndSinks.txt"
           if os.path.exists(ssFile):
                fromFile = os.path.join(appDir, ssFile)
                toFile = os.path.join(allBenchmarks, ssFile)
                copyfile(fromFile,toFile)

           json_files = [pos_json for pos_json in os.listdir(appDir) if pos_json.endswith('.json')]
           if len(json_files)>0:
               groundtruth = json_files[0]
               print("copy ground truth file "+groundtruth)
               fromFile = os.path.join(appDir,groundtruth)
               toFile = os.path.join(allGroundTruth, groundtruth)
               copyfile(fromFile, toFile)
               toFile = os.path.join(allBenchmarks, groundtruth)
               copyfile(fromFile, toFile)

           print("building "+d)
           os.system("mvn install -DskipTests")
           if os.path.exists(targetDir):
               for f in os.listdir(targetDir):
                   if f.endswith(".jar"):
                       print(f)
                       fromFile = os.path.join(targetDir, f)
                       toFile = os.path.join(allBenchmarks, d+".jar")
                       copyfile(fromFile,toFile)
                       count = count + 1
                       if count == num:
                          return;
    os.system("ls "+allBenchmarks)

cgbench = os.path.dirname(os.path.abspath(__file__))
buildAllapps(cgbench)


from lyricsgenius import Genius
from requests.exceptions import HTTPError, Timeout
import json

keyjson = json.load(open("keys.json", "r"))
key = keyjson["genius-access"]

genius = Genius(key)

search_term = input("search...")

songsearch = genius.search_songs(search_term)
hits = songsearch["hits"]

c = 0
for hit in hits:
    result = hit["result"]
    print("{0} : {1} by {2}".format(c, result["title"], result["artist_names"]))
    c += 1

i = int(input("select input"))

songtitle = hits[i]["result"]["title"]
artistname = hits[i]["result"]["artist_names"]

songobj = genius.search_song(songtitle, artist=artistname)
print(songobj.lyrics)

def get_hits_from_search(search_term = "") -> list:
    try:
        searchresult = genius.search_songs(search_term)
    except HTTPError as e:
        print(f"bad repsonce, code '{e.errno}' @get_hits_from_search")
        return []
    except Timeout as t:
        print(f"timed out @get_hits_from_search")
        return []

    if "hits" in searchresult:
        return searchresult["hits"]
    else:
        return []

def get_artistsong_obj_from_hits(hits_obj = None) -> list:
    if hits_obj == None:
        return []

    artistsongobj = []
    for hit in hits_obj:
        result = hit["result"]
        hitobj = {}

        hitobj["title"] = result["title"]
        hitobj["artist"] = result["artist_names"]

        artistsongobj.append(hits_obj)

    return artistsongobj


import hlt
from hlt import NORTH, EAST, SOUTH, WEST, STILL, Move, Square
import random
import math
import time
import sys
import operator

myID, game_map = hlt.get_init()
hlt.send_init("MyBot5")

rev = {}
rev[NORTH] = SOUTH
rev[SOUTH] = NORTH
rev[EAST] = WEST
rev[WEST] = EAST
fsock=open("log.txt","w")
sys.stderr=fsock
dir2=[[0,1,3],[3,7,10],[10,11,8],[1,8,4]]
dir3=[[0,3,4,1],[3,7,10,4],[4,10,11,8],[1,4,8,4]]
dir1=[2,6,9,5] #N E S W
d2=[0,7,11,4]
d3=[0,3,7,10,11,8,4,1]
dir_dia=[1,3,10,8]#NW NE SE SW
Pat=[0, 0, 0, 0]
strength_max=[0, 0, 0, 0]
strength_min=[0, 0, 0, 0]
dic_strength = {}
width=game_map.width
height=game_map.height
turns=math.sqrt(width*height)
dic_e={}
dic_s={}
max_d=(game_map.width+ game_map.height) / 2
dis1={}
dis2={}
def find_nearest_enemy_direction(square):
    direction = NORTH
    max_distance = min(game_map.width, game_map.height) / 2
    st = 1000
    for d in (NORTH, EAST, SOUTH, WEST):
        distance = 0
        current = square
        while current.owner == myID and distance <= max_distance:
            distance += 1
            current = game_map.get_target(current, d)
        if distance < max_distance:
            direction = d
            max_distance = distance
            st=target_strength(square,d)
        elif distance == max_distance and target_strength(square,d)<st:
            direction = d
            max_distance = distance
            st=target_strength(square,d)
    return direction

def heuristic(square,direction):
    a=((0, -1), (1, 0), (0, 1), (-1, 0))
    dx, dy = a[direction]
    xo = square.x
    yo = square.y
    neighbors = [[] for i in range(6)]
    for i in range(3):
        for j in range(-i-1, i + 2):
            x = dx * (i) + j * dy
            y = dy * (i) + j * dx
            dis = abs(x) + abs(y)
            neighbors[dis].append(game_map.contents[(yo + y) % height][(xo + x) % width])

    if any(ne.owner not in (myID,0) for ne in neighbors[1]):
        self=game_map.get_target(square,rev[direction])
        prod_sum=sum(nei.production-ave_prod[myID] for i in range(3) for nei in neighbors[i] if nei.owner!=myID)
        strength_sum = sum(nei.strength/math.pow(2, i+1) for i in range(3) for nei in neighbors[i] if nei.owner != myID)
        if self.strength<min(strength_sum+square.strength,255) or prod_sum<0:
            return -100,1
        else:
            return sum(min(neighbor.strength,self.strength) for neighbor in game_map.neighbors(square) if neighbor.owner not in (0, myID)),1
    elif square.owner == 0 and square.strength> 0:
        th=square.production/square.strength
        sum_pro = list(
            nei.production / max(nei.strength, 10) * math.pow(0.5, i) for i in range(5) for nei in neighbors[i] if
            nei.owner != myID)
        #denom=[sum(x) for x in zip(*sum_pro)]
        return sum(sum_pro),0
    elif square.owner == 0:
        a = sum(neighbor.strength for neighbor in game_map.neighbors(square) if neighbor.owner not in (0, myID))
        if a==0:
            return square.production,0
        else:
            return a,0
    else:
        # return total potential damage caused by overkill when attacking this square
        return sum(neighbor.strength for neighbor in game_map.neighbors(square) if neighbor.owner not in (0,  myID)),1

def goto_battle(square):
    direction = STILL
    s=None
    if len(dis1) > 0:
        d2t, t = min(((game_map.get_distance(square, t), t) for t in dis1 if 1< game_map.get_distance(square, t) <=max_d and dis1[t]+square.strength<=260), default=(max_d, None), key=lambda t: t[0])
        if t is not None:
            m_group = list(
                (game_map.get_target(square, i),i) for i in range(4) if game_map.get_target(square, i).owner == myID)
            s, direction = min(((m, m[1]) for m in m_group if game_map.get_distance(t, m[0]) < d2t), default=(None, 5),
                               key=lambda t: square.strength)
    else:
        s = None
        direction = STILL
    return s,direction

def target_strength(square, direction):
    target = game_map.get_target(square, direction)
    coor=(target.x,target.y)
    if coor not in dic_strength:
        dic_strength[coor]=target.strength*(target.owner==myID)*(target not in dic or dic[target]==STILL)
    return square.strength + dic_strength[coor]

def update_strength(square,direction):
    self=(square.x,square.y)
    if direction==STILL:
        if self not in dic_strength:
            dic_strength[self] =min(square.strength + square.production, 255)*(square.owner==myID)-square.strength *(square.owner!=myID)
    else:
        if self not in dic_strength:
            dic_strength[self] = 0
        else:
            dic_strength[self]-=square.strength
        target=game_map.get_target(square, direction)
        coor = (target.x, target.y)
        if coor in dic_strength:
            dic_strength[coor] +=square.strength
        else:
            dic_strength[coor] = square.strength+(target.owner==myID)*target.strength

def update_map(square):
    if square.owner not in st_map:
        st_map[square.owner]=square.strength
        prod_map[square.owner]=square.production
        count_map[square.owner]=1
    else:
        st_map[square.owner]+=square.strength
        prod_map[square.owner]+=square.production
        count_map[square.owner]+=1

def get_move(square):
    global dic_e, c, e,p,pe, st_s, st_e,tn
    update_map(square)
    if square.owner not in (myID, 0):
        update_strength(square, STILL)
        if square.owner not in dic_e:
            dic_e[square.owner] = (square, None, max_d)
        else:
            enemy, self, distance = dic_e[square.owner]
            if self is not None:
                dis = game_map.get_distance(square, self)
                if dis < distance:
                    dic_e[square.owner] = (square, self, dis)
    elif square.owner == myID:
        for key in dic_e:
            target, self, distance = dic_e[key]
            dis = game_map.get_distance(square, target)
            if dis < distance:
                distance = dis
                dic_e[key] = (target, square, distance)
        neighbors = [neighbor for neighbor in game_map.neighbors(square, 2)]
        enemy_e = any(neighbors[k].owner not in (0,myID) for k in dir1)  # find out if there is enemy in distance<=2

        if any(ne.owner==0 for ne in neighbors):
            target, direction,sc = max(
                ((neighbor, direction, heuristic(neighbor,direction)) for direction, neighbor in enumerate(game_map.neighbors(square)) if
                 neighbor.owner != myID), default=(None, STILL,(-100,0)), key=lambda t: t[3][0])
            score = sc[0]
            ind=sc[1]
            st=1000
            if target is not None:
                if target.strength >= square.strength or target_strength(square, direction) >= 280:
                    direction = STILL
                for i in (NORTH, EAST, SOUTH, WEST):
                    t1 = neighbors[dir1[i]]
                    if t1.owner == myID:
                        t2, direction2 = max(((neighbors[dir3[i][k]], k) for k in range(4) if neighbors[dir3[i][k]].owner != myID and k!=rev[i]),
                                    default=(None, None), key=lambda t: heuristic(t[0],t[1]))
                        if t2 is not None and (t1.strength + t1.production) <= t2.strength :
                            eva,ind2 = heuristic(t2,direction2)
                            if eva > score and target_strength(square,i) <= 280:
                                score = eva
                                t2s = t2
                                t1s = t1
                                direction = i if t2s.strength < t1s.strength + t1s.production + square.strength else STILL
            else:
                for i in (NORTH, EAST, SOUTH, WEST):
                    #t2, _ = max(((neighbors[k], k) for k in dir2[i] if neighbors[k].owner != myID),default=(None, None), key=lambda t: heuristic(t[0]))
                    t2= sum((heuristic(neighbors[dir3[i][k]],k)+0.01) for k in range(4) if neighbors[dir3[i][k]].owner != myID and k!=rev[i])/(sum(1 for k in range(4) if neighbors[dir3[i][k]].owner!= myID and k!=rev[i])+0.01)
                    eva = t2
                    if eva >= score and target_strength(square,i)<280:
                        score=eva
                        direction=i if square.strength > 5*square.production else STILL
            dic[square]=direction
            update_strength(square,direction)
            return
        elif square.strength < square.production * 5:
             dic[square]= STILL
             update_strength(square, STILL)
             return

        border = any(neighbor.owner != myID for neighbor in game_map.neighbors(square))
        if not border:
             direction=find_nearest_enemy_direction(square)
             dic[square]= direction
             update_strength(square, direction)
        else:
            #wait until we are strong enough to attack
             dic[square]= STILL
             update_strength(square, STILL)
        return
tn=0
st_map = {}
prod_map = {}
count_map = {}
while True:
    game_map.get_frame()
    n_boarder=0
    moves=[]
    dic = {}

    for square in game_map:
        if square not in dic:
            get_move(square)
    for key in dic:
        c = c + 1
        p+=key.production
        st_s += key.strength
        if key.strength < key.production*3:
            moves.append(Move(key,STILL))
        else:
            moves.append(Move(key, dic[key]))
    del dis1[:]
    dis1 = dis2
    fsock.write(str(len(dis2)) + "\n")
    fsock.flush()
    dis2 = {}
    ave_prod = {key : prod_map[key] / (max(count_map[key], 1)) for key in prod_map}
    dic_strength = {}
    st_map = {}
    prod_map = {}
    count_map = {}

    hlt.send_frame(moves)


import datetime
from email.Header import Header
from twisted.mail import smtp
from twisted.mail import relaymanager
from twisted.internet import protocol
from twisted.internet import reactor
from twisted.internet import defer
from twisted.internet import threads
from twisted.application import internet
from twisted.enterprise import adbapi
from zope.interface import implements
import spf
import srs

from config import *

# Gloabls for database pool and MX DNS lookup ---------------------------------
dbpool = adbapi.ConnectionPool(DBDRIVER, DBCONNECTION_STRING)
mxCalc = relaymanager.MXCalculator()

# Schedule housekeeping job for Greylist --------------------------------------
reactor.callLater(60, lambda: GreylistDB.remove_old_entries())

# Database classes for Greylist and Forwarding rules --------------------------
class GreylistDB(object):

    @staticmethod
    def is_permitted_to_send(user):
        query = """
            SELECT timestamp FROM greylist WHERE
            hostname = '%s'                AND
            ip = '%s'                      AND
            sender_address = '%s'
            """
        deferred = dbpool.runQuery(query % (
            user.helo[0],
            user.helo[1],
            user.orig.addrstr))
        deferred.addCallback(GreylistDB._handle_db_results, user)
        return deferred

    @staticmethod
    def _handle_db_results(results, user):
        if results:
            return True
        else:
            GreylistDB._add_to_grey_list(user)
            raise smtp.SMTPServerError(451, 'Temporary mailbox error.')

    @staticmethod
    def _add_to_grey_list(user):
        query = """
            INSERT INTO greylist (hostname, ip, sender_address, timestamp)
            VALUES ('%s', '%s', '%s', '%s')
            """
        dbpool.runOperation(query % (
            user.helo[0],
            user.helo[1],
            user.orig.addrstr,
            datetime.datetime.now()))

    @staticmethod
    def remove_old_entries():
        date = datetime.datetime.now() - datetime.timedelta(
            seconds=GREYLIST_EXPIRY)
        dbpool.runOperation("DELETE FROM greylist WHERE timestamp < '%s'" % date)
        reactor.callLater(
            GREYLIST_CLEANUP_INTERVAL,
            GreylistDB.remove_old_entries)

class AliasDB(object):

    @staticmethod
    def get_receiver_for(user):
        query = """
            SELECT target_address, ref_user FROM email_alias WHERE
            source_address = '%s'
            """ % user.dest.addrstr[1:-1]
        deferred = dbpool.runQuery(query)
        deferred.addCallback(AliasDB._handle_db_results, user)
        return deferred

    @staticmethod
    def _handle_db_results(results, user):
        if results:
            return results[0]
        else:
            dbpool.runOperation("INSERT INTO spam_counter (dummy) VALUES ('')")
            raise smtp.SMTPBadRcpt(user)

class CreditsDB(object):

    @staticmethod
    def debit_account(ref_user, amount=1):
        query = """
            UPDATE account_balance SET credits = credits - %i WHERE ref_user =
            '%s' """ % (amount, ref_user)
        dbpool.runOperation(query)

# SMTP Classes ----------------------------------------------------------------
class MessageForwarder(object):
    implements(smtp.IMessage)

    def __init__(self, from_address, to_address, ref_user):
        self.from_address = from_address
        self.to_address = to_address
        self.ref_user = ref_user
        self.message = []

    def lineReceived(self, line):
        self.message.append(line)

    def connectionLost(self):
        del(self.lines)

    def eomReceived(self):
        username, domain = self.to_address.split('@')
        deferred = mxCalc.getMX(domain)
        deferred.addCallback(self._send_mail)
        return deferred

    def _send_mail(self, mxRecord):
        smtp_server = mxRecord.exchange.name
        deferred = smtp.sendmail(
            smtp_server,
            self.from_address,
            [self.to_address],
            '\n'.join(self.message))
        deferred.addCallback(self._handle_send_success)
        deferred.addErrback(self._handle_send_error)
        return deferred

    def _handle_send_success(self, status):
        CreditsDB.debit_account(self.ref_user)
        dbpool.runOperation("INSERT INTO messaging_counter (dummy) \
            VALUES ('')")

    def _handle_send_error(self, error):
        raise smtp.SMTPServerError(451, error.getErrorMessage())

class ForwardDelivery(object):
    implements(smtp.IMessageDelivery)

    def receivedHeader(self, helo, origin, recipients):
        myHostname, clientIP = helo
        headerValue = "by %s from %s with ESMTP ; %s" % (
            myHostname, clientIP, smtp.rfc822date( ))
        # email.Header.Header used for automatic wrapping of long lines
        return "Received: %s" % Header(headerValue)

    def validateFrom(self, helo, originAddress):
        # Could check SPF here but SPF FAQ recommends to check RCPT TO first.
        # Also we are not checking the greylist just yet as we only want to
        # greylist if the SPF record check does not return 'pass'.
        return originAddress

    def validateTo(self, user):
        self.user = user
        self.from_address = user.orig.addrstr
        destination = user.dest.addrstr
        if destination.startswith('SRS') and destination.endswith(HOSTNAME):
            # we are dealing with a bounce message
            try:
                self.to_address = srs.SRS(destination, HOSTNAME).unwrap()
            except srs.SRSError:
                raise smtp.SMTPBadRcpt(user)
            else:
                return self._send_message()
        else:
            return self._lookup_alias()

    def _lookup_alias(self):
        deferred = AliasDB.get_receiver_for(self.user)
        deferred.addCallback(self._handle_lookup_alias)
        return deferred

    def _handle_lookup_alias(self, response):
        self.to_address, self.ref_user = response
        return self._check_spf()

    def _check_spf(self):
        deferred = threads.deferToThread(self._evaluate_spf)
        deferred.addCallback(self._handle_evaluate_spf)
        return deferred

    def _evaluate_spf(self):
        return spf.check(
            h=self.user.helo[0],
            i=self.user.helo[1],
            s=self.user.orig.addrstr[1:-1]) #cut off < and >

    def _handle_evaluate_spf(self, result):
        status, code, reason = result
        self.spf_status = status
        if code == 250:
            if status == 'pass':
                return self._forward_message()
            else:
                deferred = GreylistDB.is_permitted_to_send(self.user)
                deferred.addCallback(self._forward_message)
                return deferred
        else:
            raise smtp.SMTPBadSender(self.user.orig.addrstr)

    def _forward_message(self, callback_dummy=None):
        if self.spf_status == 'none':
            return self._send_message()
        else:
            #handle SRS
            self.from_address = srs.SRS(self.from_address, HOSTNAME).wrap()
            return self._send_message()

    def _send_message(self):
        return lambda: MessageForwarder(
            from_address=self.from_address,
            to_address=self.to_address,
            ref_user=self.ref_user)

class SMTPFactory(protocol.ServerFactory):
    def buildProtocol(self, addr):
        delivery = ForwardDelivery()
        protocol = smtp.SMTP(delivery)
        protocol.factory = self
        return protocol

# Mailreactor service for .tac file -------------------------------------------
class MailreactorServer(internet.TCPServer):
    def __init__(self):
        internet.TCPServer.__init__(self, SMTP_PORT, SMTPFactory())

# For testing only ------------------------------------------------------------
def main():
    reactor.listenTCP(SMTP_PORT, SMTPFactory())
    reactor.run()

if __name__ == '__main__':
    main()


n1 = int(input('Primeiro valor: ')) # primeiro valor
n2 = int(input('Segundo valor: ')) # segundo valor

if n1 > n2: # se n1 é maior que n2
    print('O PRIMEIRO valor é maior do que o segundo')
elif n2 > n1: # se o n2 for maior que n1
    print('O SEGUNDO valor é maior do que o primeiro')
elif n1 == n2: # se n1 é igual a n2
    print('Os 2 valores são IGUAIS!')
     # ou else:


'''
Copied and modified from
https://github.com/pytorch/examples/blob/master/mnist/main.py
'''

import argparse
import numpy as np
import os
import statistics
import random
import time
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision.models as models
from datetime import datetime
from torchvision import datasets, transforms
from torch.optim.lr_scheduler import MultiStepLR

# from . import cifar_architecture
from cifar_architecture import resnet
from cifar_architecture import vgg
from cifar_architecture import squeezenet
from cifar_architecture import senet
from cifar_architecture import densenet
import resnet_akamaster

# try:
#     from apex.parallel import DistributedDataParallel as DDP
#     from apex.fp16_utils import *
#     from apex import amp, optimizers
#     from apex.multi_tensor_apply import multi_tensor_applier
# except ImportError:
#     raise ImportError(
#         "Please install apex from https://www.github.com/nvidia/apex to run this example.")

def train(args, model, device, train_loader, optimizer, epoch, scaler=None, enable_amp_autocast=False):
    """Trains for a single epoch

    Args:
        args (Namespace): Arguments
        model ([type]): [description]
        device ([type]): [description]
        train_loader (DataLoader): DataLoader
        optimizer ([type]): [description]
        epoch (int): Epoch id
        scaler ([type], optional): Passed in if using torch.cuda.amp for quantization. Defaults to None.
        enable_amp_autocast (bool, optional): True if using torch.cuda.amp for quantization in the
        current epoch. Defaults to False.
    """
    model.train()
    grad_arrays = []
    for batch_idx, (data, target) in enumerate(train_loader):
        if batch_idx == args.breakpoint:
            print(
                f"[{datetime.now().strftime('%H:%M:%S')}] Hitting breakpoint, exiting", flush=True)
            exit(0)
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        with torch.cuda.amp.autocast(enabled=enable_amp_autocast):
            output = model(data)
            criterion = nn.CrossEntropyLoss().to(device)
            loss = criterion(output, target)
        if args.cuda_amp:  # use torch.cuda.amp for quantization
            scaler.scale(loss).backward()
            scaler.step(optimizer)
            scaler.update()
        elif args.apex_amp is not None or args.apex_amp_dynamic is not None:  # use apex.amp with specified level
            with amp.scale_loss(loss, optimizer) as scaled_loss:
                scaled_loss.backward()
            optimizer.step()
        else:  # no quantization
            loss.backward()
            optimizer.step()
        if batch_idx % args.log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))

        grad_array = [param.grad.data for param in model.parameters() if param.ndim == 4]
        # yield grad_array
        grad_arrays.append(grad_array)
    return iter(grad_arrays)

def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for batch_idx, (data, target) in enumerate(test_loader):
            data, target = data.to(device), target.to(device)
            output = model(data)
            # sum up batch loss
            # test_loss += F.nll_loss(output, target, reduction='sum').item()
            criterion = nn.CrossEntropyLoss().to(device)
            test_loss += criterion(output, target).item()
            # get the index of the max log-probability
            pred = output.max(1, keepdim=True)[1]
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader)
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")
    print('\n[{}] Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format(
        current_time,
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

def get_model(args):
    # choosing the right model is important
    # imagenet: 224*224 input, use default model from torchvision
    # SVHN/CIFAR10/CIFAR100: 32*32 input, use model from cifar_architecture
    if args.model in ["resnet20", "resnet32", "resnet44", "resnet56", "resnet110"]:
        model = getattr(resnet_akamaster, args.model)()
    elif args.dataset == "imagenet":
        model = getattr(models, args.model)(num_classes=args.num_classes)
    elif "resnet" in args.model:
        model = getattr(resnet, args.model)(num_classes=args.num_classes)
    # elif "vgg" in args.model:
    #     model = getattr(vgg, args.model)()  # num_classes not set up
    elif "senet" == args.model:
        model = getattr(senet, "seresnet18")(class_num=args.num_classes)
    elif "densenet" == args.model:
        model = getattr(densenet, "densenet_cifar")(
            num_classes=args.num_classes)
    elif "squeezenet" in args.model:
        model = getattr(squeezenet, "squeezenet_cifar")()
    else:
        print(f"Unsupported model {args.model} or dataset {args.dataset}")
        exit(1)
    if args.dataset == "cifar10" or args.dataset == "svhn":
        print(
            f"WARNING: YOU SHOULD MAKE SURE THE MODEL {args.model} TAKES IN {args.num_classes} NUM_CLASSES FOR DATASET {args.dataset}")
    return model

def get_quantization_schedule(args):
    combination = args.apex_amp_dynamic
    if combination is None:
        return {}
    opt_cr = combination[:2]  # optimization level in critical regime
    opt_non_cr = combination[-2:]  # optimization level in non-critical regime
    ckpt_milestones = {  # hardcode the CR schedule to be 15 epochs after training starts & lr decay
        15: opt_non_cr,  # checkpoint in epoch 14, use O1 starting from epoch 15
        150: opt_cr,
        165: opt_non_cr,
        250: opt_cr,
        265: opt_non_cr
    }
    return ckpt_milestones

def get_lr(args, epoch):
    """Get the learning rate based on the config and epoch number

    Args:
        args (Namespace): Arguments
        epoch (int): 0-based index of current epoch

    Returns:
        float: Current learning rate
    """
    if args.batch_size > 128:
        # bs=512 for 300 epochs:  start from lr=0.1, scale to 0.4 linearly in 5 epochs, decay at 150 and 250
        lrs = [0.1, 0.175, 0.25, 0.325, 0.4] + 145 * \
            [0.4] + 100 * [0.04] + 50 * [0.004]
        return lrs[epoch]
    else:
        lrs = [0.1] * 150 + [0.01] * 100 + [0.001] * 50
        return lrs[epoch]  # does not scale learning rate if bs <= 128

def main():
    print("========================")
    print(f"Current time: {datetime.now().strftime('%H:%M:%S')}")
    print("Doing preparations for the training")
    args = parse_args()
    use_cuda = not args.no_cuda and torch.cuda.is_available()
    torch.manual_seed(args.seed)
    torch.cuda.manual_seed(args.seed)
    random.seed(args.seed)
    np.random.seed(args.seed)
    os.environ["PYTHONHASHSEED"] = str(args.seed)
    torch.backends.cudnn.deterministic = True
    # if we don't need reproducibility across multiple executions, toggle this and get a slight performance improvement
    torch.backends.cudnn.benchmark = True

    torch.manual_seed(args.seed)

    device = torch.device("cuda" if use_cuda else "cpu")
    print(device)

    train_kwargs = {'batch_size': args.batch_size}
    test_kwargs = {'batch_size': args.test_batch_size}
    if use_cuda:
        cuda_kwargs_train = {'num_workers': 8,
                             'pin_memory': True,
                             'shuffle': True,
                             'sampler': None}
        cuda_kwargs_test = {'num_workers': 8,
                            'pin_memory': True,
                            'shuffle': False}
        train_kwargs.update(cuda_kwargs_train)
        test_kwargs.update(cuda_kwargs_test)

    transform_train_dict = {
        "imagenet": transforms.Compose([
            transforms.RandomResizedCrop(224),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
        ]),
        "cifar100": transforms.Compose([
            transforms.RandomCrop(32, padding=4),
            transforms.RandomHorizontalFlip(),
            transforms.RandomRotation(15),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.5070751592371323, 0.48654887331495095, 0.4409178433670343],
                                 std=[0.2673342858792401, 0.2564384629170883, 0.27615047132568404])
        ]),
        "cifar10": transforms.Compose([
            transforms.RandomHorizontalFlip(),
            transforms.RandomCrop(32, padding=4),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
        ]),
        "svhn": transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
        ])
    }

    transform_test_dict = {
        "imagenet": transforms.Compose([
            transforms.Resize(256),
            transforms.CenterCrop(224),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
        ]),
        "cifar100": transforms.Compose([
            # transforms.RandomCrop(32, padding=4),
            # transforms.RandomHorizontalFlip(),
            # transforms.RandomRotation(15),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.5070751592371323, 0.48654887331495095, 0.4409178433670343],
                                 std=[0.2673342858792401, 0.2564384629170883, 0.27615047132568404])
        ]),
        "cifar10": transforms.Compose([
            # transforms.RandomHorizontalFlip(),
            # transforms.RandomCrop(32, padding=4),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                 std=[0.229, 0.224, 0.225])
        ]),
        "svhn": transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
        ])
    }

    transform_train = transform_train_dict[args.dataset]
    transform_test = transform_test_dict[args.dataset]

    default_root = './data'
    if args.dataset == "imagenet":
        train_set = datasets.ImageFolder(
            '~/data/imagenet/train',
            transform=transform_train
        )
        test_set = datasets.ImageFolder(
            '~/data/imagenet/val',
            transform=transform_test
        )
    elif args.dataset == "cifar100":
        train_set = datasets.CIFAR100(
            root=default_root,
            train=True,
            download=True,
            transform=transform_train
        )
        test_set = datasets.CIFAR100(
            root=default_root,
            train=False,
            download=True,
            transform=transform_test
        )
    elif args.dataset == "cifar10":
        train_set = datasets.CIFAR10(
            root=default_root,
            train=True,
            download=True,
            transform=transform_train
        )
        test_set = datasets.CIFAR10(
            root=default_root,
            train=False,
            download=True,
            transform=transform_test
        )
    elif args.dataset == "svhn":
        train_set = datasets.SVHN(
            root=default_root,
            split='train',
            download=True,
            transform=transform_train
        )
        test_set = datasets.SVHN(
            root=default_root,
            split='test',
            download=True,
            transform=transform_test
        )

    train_loader = torch.utils.data.DataLoader(train_set, **train_kwargs)
    test_loader = torch.utils.data.DataLoader(test_set, **test_kwargs)

    num_classes_dict = {
        "imagenet": 200,
        "cifar100": 100,
        "cifar10": 10,
        "svhn": 10
    }

    args.num_classes = num_classes_dict[args.dataset]

    model = get_model(args)

    model = model.to(device)
    optimizer = optim.SGD(model.parameters(), lr=args.lr,
                          momentum=0.9, weight_decay=0.0001)  # previously weight_decay=0.0001
    if args.apex_amp is not None:
        model, optimizer = amp.initialize(
            model, optimizer, opt_level=args.apex_amp)
    if args.apex_amp_dynamic is not None:
        model, optimizer = amp.initialize(
            model, optimizer, opt_level=args.apex_amp_dynamic[:2])
    scaler = torch.cuda.amp.GradScaler(enabled=args.cuda_amp)

    # scheduler = MultiStepLR(optimizer, milestones=[150, 250],
    #                         gamma=args.gamma)  # auto lr decay, schedule copied from accordion

    # set up torch.cuda.amp.autocast schedule
    autocast_schedule = []  # whether to do amp in epoch i
    if args.cuda_amp and args.cuda_amp_dynamic:
        # do full precision training in critical regimes only and amp elsewhere, copied from
        # https://github.com/uw-mad-dash/Accordion/blob/98cd7b1dd6e84cbd265dadc79421ade45e590953/main.py#L224-L248
        for i in range(300):
            if i in range(15) or i in range(150, 165) or i in range(250, 265):
                autocast_schedule.append(False)
            else:
                autocast_schedule.append(True)
    elif args.cuda_amp:  # amp throughout
        autocast_schedule = [True] * 300
    # no quantization, full precision throughout (might still do apex.amp tho)
    else:
        autocast_schedule = [False] * 300

    print("========================")
    print(f"Current time: {datetime.now().strftime('%H:%M:%S')}")
    print(f"Model: {args.model}")
    print(f"Dataset: {args.dataset}")
    print(f"Batch size: {args.batch_size}")
    if args.cuda_amp:
        print(f"Precision: Auto mixed precision using torch.cuda.amp.autocast")
    elif args.apex_amp is not None:
        print(f"Precision: Using apex.amp with level {args.apex_amp}")
    elif args.apex_amp_dynamic is not None:
        print(
            f"Using apex.amp dynamically: {args.apex_amp_dynamic[:2]} at critical regime, {args.apex_amp_dynamic[-2:]} at non-critical regime")
    else:
        print(f"Precision: Default full precision")
    print(f"# epochs: {args.epochs}")
    print(f"Disable test set: {args.no_test}")
    print(f"Starting training...")
    training_start = time.time()
    print("========================")

    ckpt_milestones = get_quantization_schedule(args)

    curr_lr = args.lr  # initial learning rate

    grad_calc_dict = dict()

    for epoch in range(args.epochs):
        if epoch in ckpt_milestones.keys():  # will use new opt_level in current epoch
            print(f"[{datetime.now().strftime('%H:%M:%S')}] Current epoch: {epoch}, \
                switching to opt_level {ckpt_milestones[epoch]}")
            model = get_model(args)
            model = model.to(device)
            optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=0.9)
            checkpoint = torch.load('amp_checkpoint.pt')
            model, optimizer = amp.initialize(
                model, optimizer, opt_level=ckpt_milestones[epoch])  # init with new opt_level
            # warning: according to https://nvidia.github.io/apex/amp.html#checkpointing,
            # initializing with new opt_level is not recommended
            model.load_state_dict(checkpoint['model'])
            optimizer.load_state_dict(checkpoint['optimizer'])
            amp.load_state_dict(checkpoint['amp'])
        grad_array = train(args, model, device, train_loader, optimizer, epoch,
              scaler=(None if not args.cuda_amp else scaler),
              enable_amp_autocast=autocast_schedule[epoch])
        if not args.no_test:
            test(model, device, test_loader)

        # check for critical regime
        # grad_array = [param.grad.data for param in model.parameters()]
        full_rank_accum = [torch.zeros_like(copy_l) for copy_l in model.parameters() if copy_l.ndim == 4]
        for grad_train in grad_array:
            for idx, grad_val in enumerate(grad_train):
                full_rank_accum[idx].add_(grad_val.data)
        grad_calc_dict[epoch] = [torch.norm(pval).item() for pval in full_rank_accum]
        print(f"[Epoch {epoch}] gradient norm for each layer is {grad_calc_dict[epoch]}")
        print(f"[Epoch {epoch}] sum of gradient norm is {sum(grad_calc_dict[epoch])}")

        check_freq = 10
        threshold = 0.5

        if epoch % check_freq == 0:
            current_grad_norms = grad_calc_dict[epoch]
            old_grad_norms = grad_calc_dict[epoch - check_freq] if epoch != 0 else [None] * len(current_grad_norms)

            # # method 1: calculate for each layer, a model is out of cr if all layers are out of cr
            # ratios = []
            # for new_norm, prev_norm in zip(current_grad_norms, old_grad_norms):
            #     if epoch != 0:
            #         ratio = (abs(prev_norm - new_norm))/(prev_norm)
            #         ratios.append(ratio)
            # # if all layers are out of critical regime, then the whole model is out
            # out_of_critical_regime = len(ratios) != 0 and max(ratios) < threshold
            # print(f"len(ratios) is {len(ratios)}, number of cr layers is {sum(1 for ratio in ratios if ratio > threshold)}")
            # print(f"Epoch {epoch}, is {'' if out_of_critical_regime else 'not'} out of critical regime")

            # method 2: sum the gradient norms across all layers and do the computation based on that
            if epoch != 0:
                new_norm_sum = sum(current_grad_norms)
                prev_norm_sum = sum(old_grad_norms)
                ratio = (abs(prev_norm_sum - new_norm_sum))/(prev_norm_sum)
                out_of_critical_regime = ratio < threshold
                print(f"Epoch {epoch}, ratio is {ratio}")
        else:
            out_of_critical_regime = False

        # scale the learning rate if necessary
        prev_lr = curr_lr
        curr_lr = get_lr(args, epoch)
        if curr_lr != prev_lr:
            print(f"Epoch {epoch}, prev lr {prev_lr}, curr lr {curr_lr}\n")
            for group in optimizer.param_groups:
                group['lr'] = curr_lr
        if epoch+1 in ckpt_milestones.keys():  # switch to new opt_level in next epoch
            checkpoint = {
                'model': model.state_dict(),
                'optimizer': optimizer.state_dict(),
                'amp': amp.state_dict()
            }
            torch.save(checkpoint, 'amp_checkpoint.pt')
    training_end = time.time()

    print("========================")
    print(f"Current time: {datetime.now().strftime('%H:%M:%S')}")
    print(f"Model: {args.model}")
    print(f"Dataset: {args.dataset}")
    print(f"Batch size: {args.batch_size}")
    if args.cuda_amp:
        print(f"Precision: Auto mixed precision using torch.cuda.amp.autocast")
    elif args.apex_amp is not None:
        print(f"Precision: Using apex.amp with level {args.apex_amp}")
    elif args.apex_amp_dynamic is not None:
        print(
            f"Using apex.amp dynamically: {args.apex_amp_dynamic[:2]} at critical regime, {args.apex_amp_dynamic[-2:]} at non-critical regime")
    else:
        print(f"Precision: Default full precision")
    print(f"# epochs: {args.epochs}")
    print(f"Disable test set: {args.no_test}")
    print(f"JCT: {round(training_end - training_start, 2)}s")
    print("========================")

def parse_args():
    parser = argparse.ArgumentParser(description='PyTorch ImageNet Example')
    parser.add_argument("--model", default="resnet18", type=str,
                        help="neural net models for the training")
    parser.add_argument("--dataset", default="cifar100", type=str,
                        help="dataset for the training")
    parser.add_argument('--batch-size', type=int, default=128, metavar='N',
                        help='input batch size for training (default: 128)')
    parser.add_argument('--test-batch-size', type=int, default=128, metavar='N',
                        help='input batch size for testing (default: 128)')
    parser.add_argument('--epochs', type=int, default=300, metavar='N',
                        help='number of epochs to train (default: 300)')
    parser.add_argument('--lr', type=float, default=0.1, metavar='LR',
                        help='initial learning rate (default: 0.1)')
    parser.add_argument('--gamma', type=float, default=0.1, metavar='M',
                        help='Learning rate step gamma (default: 0.1)')
    parser.add_argument('--no-cuda', action='store_true', default=False,
                        help='disables CUDA training')
    parser.add_argument('--seed', type=int, default=1234, metavar='S',
                        help='random seed (default: 1234)')
    parser.add_argument('--log-interval', type=int, default=100, metavar='N',
                        help='how many batches to wait before logging training status')
    # mixed/low precision training
    parser.add_argument('--cuda-amp', action='store_true', default=False,
                        help='use torch.cuda.amp.autocast() for auto mixed precision training')
    parser.add_argument('--cuda-amp-dynamic', action='store_true', default=False,
                        help='use dynamic schedule for auto mixed precision training')
    parser.add_argument('--apex-amp', type=str, default=None,
                        help='use apex.amp for custom precision training (O0/O1/O3)')
    parser.add_argument('--apex-amp-dynamic', type=str, default=None,
                        help="use different opt_level for each epoch, format: 'OA-OB' where A,B in set(0,1,3)")
    # skip test set
    parser.add_argument('--no-test', action='store_true', default=False,
                        help='skip the test set for timing purposes')
    # breakpoint for easier profiling
    parser.add_argument('--breakpoint', type=int, default=-1,
                        help='the iteration index to stop at')
    args = parser.parse_args()
    return args

if __name__ == '__main__':
    main()


'''
========================
Reaction Diffusion Field
========================
'''
import copy
import os
import numpy as np
from pint import Quantity
from scipy import constants
from scipy.ndimage import convolve

from vivarium.core.process import Process, assoc_path
from vivarium.core.composition import PROCESS_OUT_DIR
from vivarium.core.engine import Engine
from vivarium.library.units import units
from vivarium.library.dict_utils import deep_merge

from ecoli.library.lattice_utils import (
    get_bin_site,
    get_bin_volume,
    apply_exchanges,
    ExchangeAgent,
    make_gradient,
    make_diffusion_schema,
)
from vivarium.library.topology import get_in
from ecoli.plots.snapshots import plot_snapshots

NAME = 'reaction_diffusion'

# laplacian kernel for diffusion
LAPLACIAN_2D = np.array([[0.0, 1.0, 0.0], [1.0, -4.0, 1.0], [0.0, 1.0, 0.0]])
AVOGADRO = constants.N_A

class ReactionDiffusion(Process):
    '''
    Reaction and Diffusion in 2-dimensional fields of molecules, with agent
    uptake and secretion at agent locations.

    Parameters: TODO

    '''

    name = NAME
    defaults = {
        'time_step': 1,
        'molecules': [],
        'n_bins': [10, 10],
        'bounds': [10 * units.um, 10 * units.um],
        'depth': 3000.0 * units.um,  # um
        # Diffusion coefficient: 10.1016/j.cej.2015.01.130
        'diffusion': 600 * units.um**2 / units.sec,

        'exchanges_path': ('boundary', 'exchanges'),
        'external_path': ('boundary', 'external'),
        'location_path': ('boundary', 'location'),

        # these parameters are not in diffusion_field
        'reactions': {},
        'kinetic_parameters': {},
        'internal_time_step': 1,

        # these parameters are in diffusion_field
        # 'initial_state': {},
        'gradient': None,
    }

    def __init__(self, parameters=None):
        super().__init__(parameters)

        # initial state
        self.molecule_ids = self.parameters['molecules']

        # parameters
        self.n_bins = self.parameters['n_bins']
        self.bounds = self.parameters['bounds']
        depth = self.parameters['depth']
        self.bin_volume = get_bin_volume(self.n_bins, self.bounds, depth)

        # diffusion
        diffusion = self.parameters['diffusion']
        bins_x = self.n_bins[0]
        bins_y = self.n_bins[1]
        length_x = self.bounds[0]
        length_y = self.bounds[1]
        dx = length_x / bins_x
        dy = length_y / bins_y
        dx2 = dx * dy
        self.diffusion = diffusion / dx2
        self.diffusion_dt = 0.01 * units.sec
        # self.diffusion_dt = 0.5 * dx ** 2 * dy ** 2 / (2 * self.diffusion * (dx ** 2 + dy ** 2))
        self.exchanges_path = tuple(self.parameters['exchanges_path'])
        self.external_path = tuple(self.parameters['external_path'])
        self.location_path = tuple(self.parameters['location_path'])

        # check reactions
        molecule_ids = set(self.molecule_ids)
        for rxn_id, rxn_config in self.parameters['reactions'].items():
            # check that 'stoichiometry' and 'catalyzed by' parameters
            # are the only parameters in 'reactions', and that all declared
            # reaction molecules are also in the declared molecule_ids
            stoichiometry = rxn_config.get('stoichiometry')
            catalyst = rxn_config.get('catalyzed by')
            assert stoichiometry, f'reaction {rxn_id} is missing a stoichiometry'
            assert catalyst, f'reaction {rxn_id} is missing a catalyst'
            factors = set(stoichiometry.keys())
            assert factors.issubset(molecule_ids), \
                f'reaction {rxn_id} molecules {factors} ' \
                f'are not in declared fields {molecule_ids}'
            assert catalyst in molecule_ids, \
                f'reaction {rxn_id} catalyst {catalyst} ' \
                f'is not in declared fields {molecule_ids}'

            # check corresponding kinetics. Each reaction must also have an entry
            # under 'kinetic_parameters, with the catalyst id mapping to a kcat_f
            # parameter and a km for one molecule in the environment
            rxn_kinetics = self.parameters['kinetic_parameters'].get(rxn_id)
            # TODO: Need better way to handle units
            for rxn_kinetic_params in rxn_kinetics.values():
                for param_name, rxn_kinetic_param in rxn_kinetic_params.items():
                    if isinstance(rxn_kinetic_param, Quantity):
                        rxn_kinetic_params[param_name] = rxn_kinetic_param.magnitude
            assert rxn_kinetics, \
                'each reaction must have corresponding kinetic_parameters'
            kinetics_catalyst = rxn_kinetics.keys()
            assert len(kinetics_catalyst) == 1, \
                'each kinetic_parameters reaction must have only one enzyme'
            assert set(kinetics_catalyst).issubset(molecule_ids), \
                f'kinetic_parameters reaction {rxn_id} catalyst {catalyst} ' \
                f'is not in declared fields {molecule_ids}'
            kinetics_params = list(rxn_kinetics[list(kinetics_catalyst)[0]].keys())
            assert 'kcat_f' in kinetics_params, f'kinetic_parameters reaction {rxn_id} ' \
                                                f'needs a kcat_f parameters'
            kinetics_params.remove('kcat_f')
            assert len(kinetics_params) == 1, f'only one km allowed'
            assert set(kinetics_params).issubset(molecule_ids), \
                f'kinetic_parameters reaction {rxn_id} substrate {kinetics_params} ' \
                f'is not in declared fields {molecule_ids}'

    def initial_state(self, config=None):
        """
        sets uniform initial state at the concentration provided for each the molecule_id in `config`
        """
        config = config or {}
        initial = {
            'fields': {},
            'dimensions': {
                'bounds': self.parameters['bounds'],
                'n_bins': self.parameters['n_bins'],
                'depth': self.parameters['depth']}}

        # initialize gradient fields
        gradient_molecules = []
        gradient = self.parameters.get('gradient')
        if gradient:
            gradient_molecules = list(gradient['molecules'].keys())
            unitless_bounds = [
                bound.to(units.um).magnitude for bound in self.bounds]
            gradient_fields = make_gradient(
                gradient, self.n_bins, unitless_bounds)
            initial['fields'].update(gradient_fields)

        # uniform field for all molecules not in gradient
        for mol_id in self.molecule_ids:
            if mol_id not in gradient_molecules:
                initial['fields'][mol_id] = config.get(mol_id, 0.0) * self.ones_field()

        return initial

    def ports_schema(self):
        return make_diffusion_schema(
            self.exchanges_path,
            self.external_path,
            self.location_path,
            self.parameters['bounds'],
            self.parameters['n_bins'],
            self.parameters['depth'],
            self.molecule_ids,
            self.ones_field(),
        )

    def next_update(self, timestep, states):
        fields = states['fields']
        agents = states['agents']
        dimensions = states['dimensions']

        # volume, to convert between counts and concentration
        self.n_bins = dimensions['n_bins']
        self.bounds = dimensions['bounds']
        self.bin_volume = get_bin_volume(
            self.n_bins,
            self.bounds,
            dimensions['depth'])

        # make new fields for the updated state
        new_fields = copy.deepcopy(fields)

        ###################
        # apply exchanges #
        ###################
        new_fields, agent_updates = apply_exchanges(
            agents,
            new_fields,
            self.exchanges_path,
            self.location_path,
            self.n_bins,
            self.bounds,
            self.bin_volume)

        #####################
        # react and diffuse #
        #####################
        t = 0
        while t < timestep:
            new_fields = self.react(new_fields, timestep)
            new_fields = self.diffuse(new_fields, timestep)
            t += self.parameters['internal_time_step']

        # get total delta from exchange, diffusion, reaction
        delta_fields = {
            mol_id: new_fields[mol_id] - field
            for mol_id, field in fields.items()}

        # get each agent's new local environment
        local_environments = self.get_local_environments(agents, new_fields)

        update = {
            'fields': delta_fields,
            'agents': local_environments}

        deep_merge(update['agents'], agent_updates)

        return update

    def get_bin_site(self, location):
        return get_bin_site(location, self.n_bins, self.bounds)

    def get_single_local_environments(self, location, fields):
        bin_site = self.get_bin_site(location)
        local_environment = {}
        for mol_id, field in fields.items():
            local_environment[mol_id] = {
                '_value': field[bin_site] * units.mM,
                '_updater': 'set'}
        return local_environment

    def get_local_environments(self, agents, fields):
        local_environments = {}
        if agents:
            for agent_id, specs in agents.items():
                assoc_path(
                    local_environments,
                    (agent_id,) + self.external_path,
                    self.get_single_local_environments(
                        get_in(specs, self.location_path),
                        fields,
                    ),
                )
        return local_environments

    def zeros_field(self):
        return np.zeros((self.n_bins[0], self.n_bins[1]), dtype=np.float64)

    def ones_field(self):
        return np.ones((self.n_bins[0], self.n_bins[1]), dtype=np.float64)

    def diffusion_delta(self, field, timestep):
        '''calculate new concentrations resulting from diffusion'''
        field_new = field.copy()
        t = 0.0
        dt = min(timestep, self.diffusion_dt.to(units.sec).magnitude)
        diffusion = self.diffusion.to(1 / units.sec).magnitude
        while t < timestep:
            field_new += diffusion * dt * convolve(field_new, LAPLACIAN_2D, mode='reflect')
            t += dt
        return field_new

    def diffuse(self, fields, timestep):
        new_fields = {}
        for mol_id, field in fields.items():

            # run diffusion if molecule field is not uniform
            if len(set(field.flatten())) != 1:
                new_field = self.diffusion_delta(field, timestep)
            else:
                new_field = field
            new_fields[mol_id] = new_field

        return new_fields

    def react(self, fields, timestep):
        new_fields = fields.copy()
        reactions = self.parameters['reactions']
        kinetic_parameters = self.parameters['kinetic_parameters']
        for rxn_id, rxn in reactions.items():

            # get the parameters
            kinetics = kinetic_parameters[rxn_id]
            stoich = rxn['stoichiometry']
            substrate_ids = list(stoich.keys())

            # catalyst
            catalyst_id = rxn['catalyzed by']
            kcat = kinetics[catalyst_id]['kcat_f']
            catalyst_field = fields[catalyst_id]

            for substrate_id in substrate_ids:
                substrate_km = kinetics[catalyst_id].get(substrate_id)
                substrate_field = fields[substrate_id]

                if np.sum(catalyst_field) > 0.0 and np.sum(substrate_field) > 0.0:

                    # calculate flux and delta
                    flux = kcat * catalyst_field * substrate_field
                    # add km term if declared
                    if substrate_km:
                        denominator = substrate_field + substrate_km
                        flux /= denominator
                    delta = stoich[substrate_id] * flux * timestep

                    # updates
                    new_fields[substrate_id] += delta

        return new_fields

def main():
    total_time = 100
    depth = 2 * units.um
    n_bins = [50, 50]
    bounds = [50 * units.um, 50 * units.um]

    # make the reaction diffusion process
    params = {
        # 'boundary_path': ('a', 'b', 'c'), # needs to be 'boundary' for snapshots plot
        'molecules': [
            'beta-lactam',
            'beta-lactamase',
        ],
        'n_bins': n_bins,
        'bounds': bounds,
        'depth': depth,
        'reactions': {
            'antibiotic_hydrolysis': {
                'stoichiometry': {
                    'beta-lactam': -1,
                },
                'catalyzed by': 'beta-lactamase'
            }
        },
        'kinetic_parameters': {
            'antibiotic_hydrolysis': {
                'beta-lactamase': {
                    'kcat_f': 10.0,  # kcat for forward reaction
                    'beta-lactam': 0.1,  # Km
                },
            },
        },
    }
    rxn_diff_process = ReactionDiffusion(params)

    # make the toy exchange agent
    agent_id = '0'
    agent_params = {'mol_ids': ['beta-lactamase']}
    agent_process = ExchangeAgent(agent_params)

    # get initial fields
    initial_fields = rxn_diff_process.initial_state({
        'beta-lactam': 1.0})
    # initial_agents = {'agents': {agent_id: {'boundary': {'angle': 0.0}}}}

    # put them together in a simulation
    sim = Engine(
        processes={
            'rxn_diff': rxn_diff_process,
            'agents': {
                agent_id: {
                    'exchange': agent_process
                }
            }
        },
        topology={
            'rxn_diff': {
                port: (port,)
                for port in rxn_diff_process.ports_schema().keys()
            },
            'agents': {
                agent_id: {
                    'exchange': {'boundary': ('boundary',)}
                }
            }
        },
        initial_state=initial_fields
    )
    sim.update(total_time)

    # plot
    data = sim.emitter.get_data_unitless()

    # add empty angle back in for the plot (this is undesirable)
    for t in data.keys():
        data[t]['agents'][agent_id]['boundary']['angle'] = 0.0
        data[t]['agents'][agent_id]['boundary']['length'] = 1.0
        data[t]['agents'][agent_id]['boundary']['width'] = 1.0

    out_dir = os.path.join(PROCESS_OUT_DIR, 'environment', NAME)
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
    snapshots_fig = plot_snapshots(
        n_snapshots=6,
        bounds=get_in(data, (max(data), 'dimensions', 'bounds')),
        agents={
            time: d['agents']
            for time, d in data.items()
        },
        fields={
            time: d['fields']
            for time, d in data.items()
        },
        out_dir=out_dir,
        filename='snapshots',
    )

# python ecoli/processes/environment/reaction_diffusion_field.py
if __name__ == '__main__':
    main()


import datetime
import enum
import ipaddress

from cnaas_nac.db.session import sqla_session
from sqlalchemy import Column, Integer, Unicode, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class NasPort(Base):
    __tablename__ = 'nas_port'
    __table_args__ = (
        None,
        UniqueConstraint('id'),
    )

    id = Column(Integer, autoincrement=True, primary_key=True)
    username = Column(Unicode(64), nullable=False, index=True, unique=True)
    nas_identifier = Column(Unicode(64), nullable=False)
    nas_port_id = Column(Unicode(64), nullable=False)
    nas_ip_address = Column(Unicode(64), nullable=False)
    calling_station_id = Column(Unicode(64), nullable=False)
    called_station_id = Column(Unicode(64), nullable=False)

    def as_dict(self):
        """Return JSON serializable dict."""
        d = {}
        for col in self.__table__.columns:
            value = getattr(self, col.name)
            if issubclass(value.__class__, enum.Enum):
                value = value.value
            elif issubclass(value.__class__, Base):
                continue
            elif issubclass(value.__class__, ipaddress.IPv4Address):
                value = str(value)
            elif issubclass(value.__class__, datetime.datetime):
                value = str(value)
            d[col.name] = value
        return d

    @classmethod
    def get(cls, username=None):
        with sqla_session() as session:
            if username:
                nas: NasPort = session.query(NasPort).filter(NasPort.username ==
                                                             username).one_or_none()
            else:
                nas: NasPort = session.query(NasPort).one_or_none()
            if nas is None:
                return None
            return nas.as_dict()

    @classmethod
    def add(cls, username, nas_ip_address, nas_identifier, nas_port_id,
            calling_station_id,
            called_station_id):
        if cls.get(username):
            return ''
        with sqla_session() as session:
            nas = NasPort()
            nas.username = username
            nas.nas_ip_address = nas_ip_address
            nas.nas_identifier = nas_identifier
            nas.nas_port_id = nas_port_id
            nas.calling_station_id = calling_station_id
            nas.called_station_id = called_station_id
            session.add(nas)
        return ''

    @classmethod
    def delete(cls, username):
        if not cls.get(username):
            return ''
        with sqla_session() as session:
            port: NasPort = session.query(NasPort).filter(NasPort.username ==
                                                          username).one_or_none()
            session.delete(port)
            session.commit()
        return ''


# 두 수를 입력받는다.
a, b = map(int, input().split())

# 이후 최소 공배수를 구하기 위해 두 값을 곱해둔다.
LCM = a*b

# 유클리드 호제법을 사용하기 위해 항상 a>b가 되도록 만든다.
if a < b:
    a,b = b,a

# 유클리드 호제법 함수.
def gcd(a,b) :
    while b > 0 :
        tmp = a%b
        a = b
        b = tmp
    return a

GCD = gcd(a, b)
print(GCD)

# 최대 공약수를 알면 최소 공배수는 쉽게 구할 수 있다.
# LCM = 값1 * 값2 / GCD
print(int(LCM/GCD))

solution/bang/1차시 - 수학/06. 최대공약수와 최소공배수 (2609).py


'''
 Write a program that polls users about their dream vacation. Write a prompt similar to If you could visit one place in the world, where
would you go? Include a block of code that prints the results of the poll.

'''

responses = {}

# setting a flag, indicating poll is active.
polling_active = True
repeat_active = True

# polling
while polling_active:
    name = input("What is your name?: ")
    response = input("If you could visit one place in the world, where would you go?: ")

    # storing polls into the dict
    responses[name] = response

    repeat = ''
    while repeat_active:
        repeat = input("Would you like to let another person response? yes/no?: ")
        if repeat == 'no':
            polling_active = False
            break
        elif repeat == 'yes':
            repeat_active = False
    # reset flag
    repeat_active = True

# polling complete, printing results
print('\n --- Poll Results ---')
for name, response in responses.items():
    print(f"{name.capitalize()} would like to go to {response.title()}")


from __future__ import print_function
from __future__ import absolute_import

import os
import cv2
import random
import torch
import PIL.Image as Image
import numpy as np
from torchvision.utils import save_image
from config import settings

#random.seed(1385)

class all_voc_train():

    """Face Landmarks dataset."""

    def __init__(self, args, size, transform=None, mode='train'):
        """
        Args:
            csv_file (string): Path to the csv file with annotations.
            root_dir (string): Directory with all the images.
            transform (callable, optional): Optional transform to be applied
                on a sample.
        """
        self.num_classes = 20
        self.group = args.group
        self.num_folds = args.num_folds
        self.mode = mode
        #self.binary_map_dir = os.path.join(settings.DATA_DIR, 'VOCdevkit2012/VOC2012/', 'Binary_map_aug/train') #val
        if mode == 'train':
            self.data_list_file = '/media/meng2/disk2/ZRT/dataset/VOC2010/train_for_component_aug.txt'
            self.img_dir = '/media/meng2/disk2/ZRT/dataset/VOC2010/JPEGImages'
            self.mask_dir = '/media/meng2/disk2/ZRT/dataset/VOC2010/color_segmentation_14'
            self.part_mask_dir = '/media/meng2/disk2/ZRT/dataset/VOC2010/color_part_segmentation_28'
        elif mode == 'test_voc':
            self.data_list_file = '/media/meng2/disk2/ZRT/dataset/VOC2010/val_for_component_aug.txt'
            #self.data_list_file = '/media/meng2/disk2/ZRT/dataset/VOC2010/train_for_component_aug.txt'
            #self.data_list_file = '/media/meng2/disk2/ZRT/dataset/VOC2010/voc_cat/voc_dog.txt' # 4:0.72 +  5:0.80 -- m : 0.68
            self.img_dir = '/media/meng2/disk2/ZRT/dataset/VOC2010/JPEGImages'
            self.mask_dir = '/media/meng2/disk2/ZRT/dataset/VOC2010/color_segmentation_14'
            self.part_mask_dir = '/media/meng2/disk2/ZRT/dataset/VOC2010/color_part_segmentation_28'
        elif mode == 'test_coco':
            self.data_list_file = '/media/meng2/disk2/ZRT/dataset/COCO2017/coco_cat/coco_giraffe.txt' # 2:0.74  ---  0.76
            #self.data_list_file = '/media/meng2/disk2/ZRT/dataset/COCO2017/coco_classification_train_sort.txt'
            #self.data_list_file = '/media/meng2/disk2/ZRT/dataset/COCO2017/coco_classification_val_sort.txt'
            self.img_dir = '/media/meng2/disk2/ZRT/dataset/COCO2017/trainval2017'
            self.mask_dir = '/media/meng2/disk2/ZRT/dataset/COCO2017/coco_segmentation_20_new'
        else:
            print('running mode error!')

        #self.binary_mask_dir = os.path.join(settings.DATA_DIR, 'VOCdevkit2012/VOC2012/', 'Binary_map_aug/train/')

        self.train_list = self.get_train_list()

        self.transform = transform
        self.count = 0
        self.random_generator = random.Random()
        self.size = size
        #self.random_generator.shuffle(self.list_splite)
        #self.random_generator.seed(1385)

    def get_train_list(self):
        f = open(self.data_list_file)
        data_list = []
        while True:
            img_name = f.readline()[:-1]
            if img_name == '':
                break
            data_list.append(img_name)
        return data_list

    def read_img(self, name):
        path = os.path.join(self.img_dir, name + '.jpg')
        img = Image.open(path)
        return img

    def read_mask(self, name):
        path = os.path.join(self.mask_dir, name + '.png')
        mask = Image.open(path)
        return mask

    def read_part_mask(self, name):
        path = os.path.join(self.part_mask_dir, name + '.png')
        mask = Image.open(path)
        return mask

    def load_frame(self, img_name):
        img = self.read_img(img_name)
        mask = self.read_mask(img_name)
        if self.mode == 'train' or self.mode =='test_voc':
            part_mask = self.read_part_mask(img_name)
            return img, mask, part_mask
        elif self.mode =='test_coco':
            return img, mask

    def get_class_idx(self, mask):
        class_idx_list = np.sort(np.unique(mask))
        zero_index = np.argwhere(class_idx_list == 0)
        class_idx_list = np.delete(class_idx_list, zero_index)
        return class_idx_list

    def mask_convert(self, mask):
        mask = np.asarray(mask).astype(np.float32)
        idx_list = np.unique(mask).astype(np.uint8).tolist()
        cat_idx = np.zeros((21))
        cat_idx[idx_list] = 1.0
        return mask, cat_idx

    def part_mask_convert(self, part_mask):
        mask_return = np.asarray(part_mask).astype(np.float32)
        return mask_return

    def __len__(self):
        # return len(self.image_list)
        return  len(self.train_list)

    def __getitem__(self, idx):
        if self.mode == 'train' or self.mode =='test_voc':
            img, mask, part_mask = self.load_frame(self.train_list[idx])
            mask, cat_idx = self.mask_convert(mask)
            part_mask = self.part_mask_convert(part_mask)
            img, mask, part_mask = self.transform(img, mask, part_mask)
            return img, mask, part_mask, cat_idx

        elif self.mode == 'test_coco':
            name = self.train_list[idx].split(" ")[0]
            img, mask = self.load_frame(name)
            mask, cat_idx = self.mask_convert(mask)
            img, mask = self.transform(img, mask, None)
            if img.size(0) == 1:
                img = img.repeat(3, 1, 1)
            return img, mask, torch.tensor(0), cat_idx