from tkinter import *
from tkinter import messagebox

print("hello world");
print("hello world");
print("hello world");
print("hello world");

root = Tk()
root.title("Simple Calculator")
root.geometry("350x300")
root.resizeable(0,0)
root.configure(bg="#77526b")
equa = ""
equation = StringVar()
Calculation = Label(root, textvariable=equation, bg="#77526b", fg="#e6a4ff", font="Tahoma", justify=CENTER)
equation.set("Enter your expression")
Calculation.grid(columnspan=4)

def buttonPress(number):
    global equa
    equa = equa + str(number)
    equation.set(equa)

def equalButtonPress():
    try:
        member = 0
        global equa
        total = str(eval(equa))
        for char in total:
            member += 1
        if member > 20:
            raise ValueError
        equation.set(total)
        equa = ""
    except ZeroDivisionError:
        messagebox.showwarning(title="Mathematic error", message="Division by Zero")
    except ValueError:
        messagebox.showerror(title="value Error", message="Too Big Number!")
    except:
        messagebox.showerror(title="Syntax error", message="an error occurd please try again")

def clearButtonPress():
    global equa
    equa = ""
    equation.set("")

btn0 = Button(root, text="0", width=7, height=2, command=lambda: buttonPress(0), padx=2, pady=2, relief=RAISED,
              bg="#e0b34a", font="Tahoma")
btn0.grid(row=4, column=1)

btn1 = Button(root, text="1", width=7, height=2, command=lambda: buttonPress(1), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn1.grid(row=1, column=0)

btn2 = Button(root, text="2", width=7, height=2, command=lambda: buttonPress(2), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn2.grid(row=1, column=1)

btn3 = Button(root, text="3", width=7, height=2, command=lambda: buttonPress(3), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn3.grid(row=1, column=2)

btn4 = Button(root, text="4", width=7, height=2, command=lambda: buttonPress(4), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn4.grid(row=2, column=0)

btn5 = Button(root, text="5", width=7, height=2, command=lambda: buttonPress(5), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn5.grid(row=2, column=1)

btn6 = Button(root, text="6", width=7, height=2, command=lambda: buttonPress(6), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn6.grid(row=2, column=2)

btn7 = Button(root, text="7", width=7, height=2, command=lambda: buttonPress(7), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn7.grid(row=3, column=0)

btn8 = Button(root, text="8", width=7, height=2, command=lambda: buttonPress(8), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn8.grid(row=3, column=1)

btn9 = Button(root, text="9", width=7, height=2, command=lambda: buttonPress(9), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
btn9.grid(row=3, column=2)

plus = Button(root, text="+", width=7, height=2, command=lambda: buttonPress('+'), padx=2, pady=2, relief=RAISED,
              font="Tahoma", bg="#e0b34a")
plus.grid(row=1, column=3)

minus = Button(root, text="-", width=7, height=2, command=lambda: buttonPress('-'), padx=2, pady=2, relief=RAISED,
               font="Tahoma", bg="#e0b34a")
minus.grid(row=2, column=3)

multiply = Button(root, text="×", width=7, height=2, command=lambda: buttonPress('*'), padx=2, pady=2, relief=RAISED,
                  font="Tahoma", bg="#e0b34a")
multiply.grid(row=3, column=3)

divide = Button(root, text="÷", width=7, height=2, command=lambda: buttonPress('/'), padx=2, pady=2, relief=RAISED,
                font="Tahoma", bg="#e0b34a")
divide.grid(row=4, column=3)

equal = Button(root, text="=", width=7, height=2, command=equalButtonPress, padx=2, pady=2, relief=RAISED,
               font="Tahoma", bg="#e0b34a")
equal.grid(row=4, column=2)

clear = Button(root, text="c", width=7, height=2, command=clearButtonPress, padx=2, pady=2, relief=RAISED,
               font="Tahoma", bg="#e0b34a")
clear.grid(row=4, column=0)

root.mainloop()


from json import JSONDecoder, dumps

from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from rest_framework.views import APIView

from django.db.models import ObjectDoesNotExist

from api.models import Record, KeysToken, ChildRecord, User, UnregisteredRecord
from api.serializer import RecordSerializer, UserSerializer, ChildRecordSerializer

from serv.MRDApi import Cryptographer, NotValid

class Editor(APIView):
    cryp = Cryptographer()

    def put(self, req):
        token = get_object_or_404(
            KeysToken.objects.all(),
            token=req.data['token'])
        user = token.user
        if token.is_valid():
            token.update_activity()
            user_data = req.data['usr']
            errors = [None, None]
            try:
                errors[0] = self._update_user_data(user_data, user)
            except NotValid:
                return Response(status=400, data="lel")
            if errors[0] != None:
                return Response(status=400, data=errors[0])

            record_data = req.data['rec']
            try:
                errors[1] = self._update_record_data(record_data, user)
            except NotValid:
                return Response(status=400)
            if errors[1] != None:
                return Response(status=400, data=errors[1])

            return Response(status=200)
        else:
            return Response(status=401)

    def _update_user_data(self, user_data, user):
        unique_status, errors = self._unique_user_creds(user_data, user)

        if unique_status:
            usr_ser = UserSerializer(instance=user, data=user_data, partial=True)
            if usr_ser.is_valid():
                usr_ser.save()
            else:
                raise NotValid
        if errors == None:
            return None
        return errors

    def _update_record_data(self, record_data, user):
        record = get_object_or_404(Record.objects.all(), owner=user)
        unique_status, errors = self._unique_record_creds(record_data, record)
        if unique_status:
            rec_ser = RecordSerializer(
                instance=record,
                data=record_data,
                partial=True)
            if rec_ser.is_valid():
                rec_ser.save()
            else:
                raise NotValid
        if errors == None:
            return None
        return errors

    def  _unique_record_creds(self, record_data, record_instance):
        record = None
        errors = []
        if 'serial_number' in record_data.keys():
            try:
                record = Record.objects.get(serial_number=record_data['serial_number'])
            except ObjectDoesNotExist:
                record = None
            if record:
                errors.append('serialNumberError')

            try:
                snum = record_data['serial_number']
                unreg_rec = UnregisteredRecord.objects.get(serial_number=snum)
            except ObjectDoesNotExist:
                errors.append('noSuchRecord')
                unreg_rec = None

            if unreg_rec and unreg_rec.code == record_data['code']:
                if not record or record == record_instance:
                    record_instance.serial_number = record_data['serial_number']
                    record_instance.save()
                    unreg_rec.delete()
                    return True, None
            return False, errors
        return True, None

    def _unique_user_creds(self, user_data, user_instance):
        user = None
        errors = []
        if 'username' in user_data.keys():
            try:
                user = User.objects.get(username=user_data['username'])
            except ObjectDoesNotExist:
                user = None
            if user:
                errors.append('usernameError')
        if 'email' in user_data.keys():
            try:
                user = User.objects.get(email=user_data['email'])
            except ObjectDoesNotExist:
                user = None
            if user:
                errors.append('emailError')
        if 'telephone' in user_data.keys():
            try:
                user = User.objects.get(telephone=user_data['telephone'])
            except ObjectDoesNotExist:
                user = None
            if user:
                errors.append('phoneError')
        if 'email' in user_data.keys() or 'username' in user_data.keys() or 'telephone' in user_data.keys():
            if user != user_instance and errors:
                return False, errors
            elif not user or user == user_instance:
                return True, None
        return True, None

class ChildEditor(APIView):
    def put(self, req):
        token = get_object_or_404(
            KeysToken.objects.all(),
            token=req.data['token'])
        user = token.user
        child_rec = get_object_or_404(
            ChildRecord.objects.all(),
            serial_number=req.data['id'])
        if token.is_valid() and child_rec.parent == user:
            data = req.data['data']
            rec = ChildRecordSerializer(
                instance=child_rec, data=data, partial=True)
            if rec.is_valid():
                rec.save()

            parent_record = Record.objects.get(owner=user)

            json_decoder = JSONDecoder()
            children = json_decoder.decode(parent_record.children)

            if rec.is_valid() and (
                    data['first_name'] or data['last_name'] or data['second_name']):
                for each in children:
                    if each['serial_number'] == req.data['id']:
                        tmp = f'{rec.data["last_name"]} '
                        tmp += f'{rec.data["first_name"]} '
                        tmp += f'{rec.data["second_name"]}'
                        each['name'] = tmp
                parent_record.children = dumps(
                    children, separators=(
                        ',', ':'), ensure_ascii=False)
                parent_record.save()

            token.update_activity()
            return Response(status=200)
        else:
            return Response(status=403)


# List
transports = ["airplane", "car", "ferry"]
modes = ["air", "ground", "water"]

# Lists contain simple data (index based item) and can be edited after being assigned.
# E.g. as transport types are not as limited as in this list, it can be updated by adding or removing.

# Let's create a couple of functions for adding and removing items, and use them.
print("\nLIST DATA TYPE")
print("--------------\n")   # just for formatting the output in order to keep it clean

# Adding items to the list

def add_transport():   # first parameter is for the name, second one is for the mode of the transport
    global transports
    global modes

    message = input("Do you want to ADD a new transport? [Type yes/no]: ").lower().strip()
    # validating the input by lower-casing the letters and shrinking the spaces

    if message == "yes":
        name = input(" Insert the transport name: ")

        if name in transports:
            print("\n!!! This transport is already in the list\n")
            add_transport()
        else:
            mode = input(" Insert the transportation mode: ")
            transports.append(name)   # append() method is used to add a new item
            modes.append(mode)

        print("\nSuccessfully added!")
        print("--------------\n")  # just for formatting the output in order to keep it clean
        add_transport()
    elif message == "no":
        print("--------------\n")  # just for formatting the output in order to keep it clean
        return
    else:
        print("\n!!! Please, answer properly\n")
        add_transport()

add_transport()   # calling the function to add a new transport

# Removing items from the list

def remove_transport():   # receives an integer as an index
    global transports
    global modes

    message = input("Do you want to REMOVE any transport? [Type yes/no]: ").lower().strip()
    # validating the input by lower-casing the letters and shrinking the spaces

    if message == "yes":
        print("You have the transports below:")

        for number, transport in enumerate(transports, 1):   # looping the enumerated list to print the items
            print("", str(number) + ")", transport)

        removing_index = input("Insert the number of the transport you want to delete: ")

        try:   # trying to convert the input into integer
            index = int(removing_index)
            transports.pop(index - 1)   # since enumeration has started with 1, we should subtract 1
            modes.pop(index - 1)
            print("\nSuccessfully removed!")
            print("--------------\n")  # just for formatting the output in order to keep it clean
            remove_transport()
        except ValueError:
            print("\n!!! Please, insert only numbers\n")
            remove_transport()
    elif message == "no":
        print("--------------\n")  # just for formatting the output in order to keep it clean
        return
    else:
        print("\n!!! Please, answer properly\n")
        remove_transport()

remove_transport()   # calling the function to remove an existing transport

# Check the type of the transport
# zip() can be used to merge relative items of two lists according to their index.

def check_transport():
    global transports
    global modes

    message = input("Do you want to CHECK the mode of any transport? [Type yes/no]: ").lower().strip()
    # validating the input by lower-casing the letters and shrinking the spaces

    if message == "yes":
        print("Choose a transport to check:")

        for number, transport in enumerate(transports, 1):
            print("", str(number) + ")", transport)

        checking_index = input("Insert the number of the transport you want to check: ")

        try:
            index = int(checking_index)
            print("\n", transports[index-1][0].upper() + transports[index-1][1:], "moves on the", modes[index-1] + ".")
            print("--------------\n")  # just for formatting the output in order to keep it clean
            check_transport()
        except ValueError:
            print("\n!!! Please, insert only numbers!\n")
            check_transport()
    elif message == "no":
        print("--------------\n")  # just for formatting the output in order to keep it clean
        print(" Thank you for using this app! Good bye!")
        return
    else:
        print("\n!!! Please, answer properly!\n")
        check_transport()

check_transport()  # calling the function to check the mode af a transport


# -*- coding: utf-8 -*-
"""
Created on Sun May  9 23:54:21 2021

@author: zacha
"""

import Customer
import Department

def main():

    #Testing Customer class with inputs
    nam = input("Enter Name: ")
    stre = input("Enter Street: ")
    cit = input("Enter City: ")
    zipc = input("Enter Zip Code: ")

    #Testing Department class with inputs
    deptname = input("Enter Department Name: ")
    deptnum = input("Enter Department Number: ")
    descr = input("Enter Description: ")
    deptid = input("Enter Department ID: ")

    custo = Customer.Customer(nam,stre,cit,zipc)
    dept = Department.department(deptname,deptnum,descr,deptid)

    print("Data entered: ")
    print("Customer name: ", custo.get_name())
    print("Street name: ", custo.get_street())
    print("Department name: ", dept.get_department_name())
    print("Department number: ", dept.get_department_number())

main()


import numpy as np
import pandas as pd
from collections import defaultdict
import matplotlib.pyplot as plt
from datetime import datetime

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
import torch.optim as optim

import os, sys

class SDAE(nn.Module):
    def __init__(self, input_dim, hidden_dim, embed_dim):
        super(SDAE, self).__init__()
        self.input_dim = input_dim
        self.hidden_dim = hidden_dim
        self.embed_dim = embed_dim
        self.enc1 = nn.Linear(input_dim, hidden_dim)
        self.enc2 = nn.Linear(hidden_dim, hidden_dim)
        self.enc3 = nn.Linear(hidden_dim, embed_dim)

        self.dec1 = nn.Linear(embed_dim, hidden_dim)
        self.dec2 = nn.Linear(hidden_dim, hidden_dim)
        self.dec3 = nn.Linear(hidden_dim, input_dim)

    def forward(self, x):
        x = F.relu(self.enc1(x))
        x = F.relu(self.enc2(x))
        latent = F.relu(self.enc3(x))
        x = F.relu(self.dec1(latent))
        x = F.relu(self.dec2(x))
        x = self.dec3(x)
        return latent, x

class CDL:

    def __init__(self, train_imp, test_imp, input_dim, hidden_dim, dim_f, dataloader, seed, device, config):
        self.dim_f = dim_f
        self.user_num = train_imp.shape[0]
        self.item_num = train_imp.shape[1]
        self.input_dim = input_dim

        self.R_tr = train_imp
        self.R_tst = test_imp
        self.C = np.where(self.R_tr > 0, 1, 0)
        self.C_u = np.zeros((self.item_num, self.item_num))
        self.C_i = np.zeros((self.user_num, self.user_num))

        np.random.seed(seed)
        self.X = np.random.standard_normal((self.user_num, dim_f))
        self.Y = np.random.standard_normal((self.item_num, dim_f))

        self.loss_tr = defaultdict(float)
        self.loss_ae = defaultdict(float)
        self.loss_tst = defaultdict(float)

        self.ae = SDAE(input_dim=input_dim, hidden_dim=hidden_dim, embed_dim=dim_f).to(device)
        self.optimizer = optim.Adam(self.ae.parameters(), lr=config.learning_rate, weight_decay=config.lambda_w)
        self.dataloader = dataloader

        self.lambda_u = config.lambda_u
        self.lambda_w = config.lambda_w
        self.lambda_v = config.lambda_v
        self.lambda_n = config.lambda_n

        self.device = device
        self.config = config

    def ae_train(self):
        latent_np = np.zeros((self.item_num, self.dim_f))
        loss_ae = []
        for batch in self.dataloader:
            y = batch['clean'].to(self.device)
            x = batch['corrupt'].to(self.device)
            idx = batch['idx']
            latent, pred = self.ae(x)
            latent_ = latent.detach().cpu().numpy()
            latent_np[idx.numpy()] = latent_

            loss = self.loss_fn(pred, y, idx.to(self.device), latent_)
            loss.backward()
            self.optimizer.step()
            loss_ae.append(loss.item())

        return latent_np, np.mean(loss_ae)

    def fit(self):
        start = datetime.now()
        for epoch in range(self.config.epochs):
            start_epoch = datetime.now()
            self.ae.train()
            self.latent_feat, self.loss_ae[epoch] = self.ae_train()
            n = 0
            for u in range(self.user_num):
                yty = np.dot(self.Y.T, self.Y)
                self.X[u, :] = self.update_user_vector(u, yty)

            for i in range(self.item_num):
                xtx = np.dot(self.X.T, self.X)
                self.Y[i, :] = self.update_item_vector(i, xtx)

            phat = self.scoring()

            train_loss = self.evaluate(train_eval=True)
            test_loss = self.evaluate(train_eval=False)

            self.loss_tr[epoch] = train_loss
            self.loss_tst[epoch] = test_loss

            print(f'EPOCH {epoch+1} : TRAINING RANK {self.loss_tr[epoch]:.5f}, VALID RANK {self.loss_tst[epoch]:.5f}')

            print(f'Time per one epoch {datetime.now() - start_epoch}')
        end = datetime.now()
        print(f'Training takes time {end-start}')

    def scoring(self):

        return np.dot(self.X, self.Y.T)

    def update_user_vector(self, u, yty):
        np.fill_diagonal(self.C_u, (self.C[u, :] - 1))
        comp1 = yty
        comp2 = np.dot(self.Y.T, self.C_u).dot(self.Y)
        comp3 = np.identity(self.config.dim_f) * self.config.lambda_u
        comp = np.linalg.inv(comp1 + comp2 + comp3)
        self.C_u = self.C_u + np.identity(self.C_u.shape[0])
        comp = np.dot(comp, self.Y.T).dot(self.C_u)

        return np.dot(comp, self.R_tr[u, :])

    def update_item_vector(self, i, xtx):
        np.fill_diagonal(self.C_i, (self.C[:, i] - 1))
        comp1 = xtx
        comp2 = np.dot(self.X.T, self.C_i).dot(self.X)
        comp3 = np.identity(self.config.dim_f) * self.config.lambda_v
        comp = np.linalg.inv(comp1 + comp2 + comp3)
        self.C_i = self.C_i + np.identity(self.C_i.shape[0])
        comp4 = self.X.T.dot(self.C_i).dot(self.R_tr[:, i])
        comp5 = self.lambda_v * self.latent_feat[i, :]

        return np.dot(comp, comp4+comp5)

    def loss_fn(self, pred, xc, idx, latent_feat):
        X = torch.tensor(self.X).to(self.device)
        Y = torch.tensor(self.Y).to(self.device)[idx, :]
        R = torch.tensor(self.R_tr).float().to(self.device)[:, idx]
        C = torch.tensor(self.C).float().to(self.device)[:, idx]
        latent = torch.tensor(latent_feat).to(self.device)

        comp1 = (X**2).sum(axis=1).sum() * self.lambda_u/2
        comp2 = ((Y - latent)**2).sum(axis=1).sum() * self.lambda_v/2
        comp3 = ((pred - xc)**2).sum(axis=1).sum() * self.lambda_n/2
        comp4 = torch.sum((torch.mm(X, Y.T) - R)**2 * C/2)

        return comp1+comp2+comp3+comp4

    def evaluate(self, train_eval):
        if train_eval:
            R = self.R_tr
        else:
            R = self.R_tst

        phat = self.scoring()
        rank_mat = np.zeros(phat.shape)
        for u in range(self.user_num):
            pred_u = phat[u, :] * -1
            rank = pred_u.argsort().argsort()
            rank = rank / self.item_num
            rank_mat[u, :] = rank

        return np.sum(R * rank_mat) / np.sum(R)


from src.mappers.event_mapper import EventMapper
from src.domain.entities.event import Event
from src.mappers.person_mapper import PersonMapper
from src.repositories.entities.event import Event as DataEvent
from src.repositories.entities.participation import Participation as DataParticipation

class EventRepository(object):

    def update(self, event: Event):
        data = DataEvent.update(name=event.name, group_name=event.group_name, link=event.link,
                                local_date=event.local_date, local_time=event.local_time, status=event.status)\
            .where(DataEvent.id == event.id)

        data.execute()
        return self.get_by_id(int(event.id))

    def get_by_id(self, id: int):
        data_event = DataEvent.select().where(DataEvent.id == id).first()

        if data_event:
            domain_event = EventMapper.data_to_domain(data_event)

            data_participations = DataParticipation.select().where(DataParticipation.event == id)
            domain_event.persons = [PersonMapper.data_to_domain(data_participation.person) for data_participation in data_participations]

            return domain_event

    def get_all(self):
        data_events = DataEvent.select()
        domain_events = [EventMapper.data_to_domain(data_event) for data_event in data_events]

        for domain_event in domain_events:
            data_participations = DataParticipation.select().where(DataParticipation.event == domain_event.id)
            domain_event.persons = [PersonMapper.data_to_domain(data_participation.person) for data_participation in
                                    data_participations]

        return domain_events

    def insert(self, event):
        data = DataEvent.create(id=event.id, name=event.name, group_name=event.group_name, link=event.link,
                                local_date=event.local_date, local_time=event.local_time, status=event.status)

        data.save()

        return self.get_by_id(int(event.id))


''' (c) 2008 by the GunGame Coding Team

    Title: gg_elimination
    Version: 5.0.498
    Description: Players respawn after their killer is killed.

    Originally for ES1.3 created by ichthys:
        http://addons.eventscripts.com/addons/view/3972
'''

# ==============================================================================
#  IMPORTS
# ==============================================================================
# EventScripts imports
import es
import gamethread

# Python imports
import time

# GunGame imports
import gungamelib

# ==============================================================================
#  ADDON REGISTRATION
# ==============================================================================
# Register this addon with EventScripts
info = es.AddonInfo()
info.name     = 'gg_elimination (for GunGame5)'
info.version  = '5.0.498'
info.url      = 'http://gungame5.com/'
info.basename = 'gungame/included_addons/gg_elimination'
info.author   = 'GunGame Development Team'

# ==============================================================================
#  GLOBALS
# ==============================================================================
# Set up variables for use throughout gg_elimination
dict_addonVars = {}
dict_addonVars['roundActive'] = 0
dict_addonVars['currentRound'] = 0

# Player Database
dict_playersEliminated = {}

# ==============================================================================
#  GAME EVENTS
# ==============================================================================
def load():
    # Register addon with gungamelib
    gg_elimination = gungamelib.registerAddon('gg_elimination')
    gg_elimination.setDisplayName('GG Elimination')
    gg_elimination.loadTranslationFile()

    # Add dependencies
    gg_elimination.addDependency('gg_turbo', 1)
    gg_elimination.addDependency('gg_dead_strip', 1)
    gg_elimination.addDependency('gg_dissolver', 1)
    gg_elimination.addDependency('gg_knife_elite', 0)

    # Get userids of all connected players
    for userid in es.getUseridList():
        dict_playersEliminated[str(userid)] = []

def unload():
    # Unregister this addon with gungamelib
    gungamelib.unregisterAddon('gg_elimination')

def es_map_start(event_var):
    global dict_addonVars

    # Reset round tracking
    dict_addonVars['roundActive'] = 0
    dict_addonVars['currentRound'] = 0

def round_start(event_var):
    # Round tracking
    dict_addonVars['roundActive'] = 1
    dict_addonVars['currentRound'] += 1

    # Reset all eliminated player counters
    for player in dict_playersEliminated:
        dict_playersEliminated[player] = []

    gungamelib.msg('gg_elimination', '#all', 'RoundInfo')

def round_end(event_var):
    # Set round inactive
    dict_addonVars['roundActive'] = 0

def player_activate(event_var):
    userid = event_var['userid']

    # Create player dictionary
    dict_playersEliminated[userid] = []

def player_disconnect(event_var):
    userid = event_var['userid']

    # Remove diconnecting player from player dict
    if userid in dict_playersEliminated:
        respawnEliminated(userid, dict_addonVars['currentRound'])
        del dict_playersEliminated[userid]

def player_death(event_var):
    # Check to see if the round is active
    if not dict_addonVars['roundActive']:
        return

    # Get userid and attacker userids
    userid = event_var['userid']
    attacker = event_var['attacker']

    # Was suicide?
    if userid == attacker or attacker == '0':
        gamethread.delayed(5, respawnPlayer, (userid, dict_addonVars['currentRound']))
        gungamelib.msg('gg_elimination', userid, 'SuicideAutoRespawn')

    # Was a teamkill?
    elif event_var['es_userteam'] == event_var['es_attackerteam']:
        gamethread.delayed(5, respawnPlayer, (userid, dict_addonVars['currentRound']))
        gungamelib.msg('gg_elimination', userid, 'TeamKillAutoRespawn')

    # Was a normal death
    else:
        # Add victim to the attackers eliminated players
        dict_playersEliminated[attacker].append(userid)

        # Tell them they will respawn when their attacker dies
        index = gungamelib.getPlayer(attacker)['index']
        gungamelib.saytext2('gg_elimination', userid, index, 'RespawnWhenAttackerDies', {'attacker': event_var['es_attackername']})

    # Check if victim had any Eliminated players
    gamethread.delayed(1, respawnEliminated, (userid, dict_addonVars['currentRound']))

# ==============================================================================
#  HELPER FUNCTIONS
# ==============================================================================
def respawnPlayer(userid, respawnRound):
    # Make sure the round is active
    if not dict_addonVars['roundActive']:
        return

    # Check if respawn was issued in the current round
    if dict_addonVars['currentRound'] != respawnRound:
        return

    # Make sure the player is respawnable
    if not respawnable(userid):
        return

    index = gungamelib.getPlayer(userid)['index']

    # Tell everyone that they are respawning
    gungamelib.saytext2('gg_elimination', '#all', index, 'RespawningPlayer', {'player': gungamelib.getPlayer(userid).name})

    # Respawn player
    gungamelib.respawn(userid)

def respawnEliminated(userid, respawnRound):
    # Check if round is over
    if not dict_addonVars['roundActive']:
        return

    # Check if respawn was issued in the current round
    if dict_addonVars['currentRound'] != respawnRound:
        return

    # Check to make sure that the userid still exists in the dictionary
    if userid not in dict_playersEliminated:
        return

    # Check the player has any eliminated players
    if not dict_playersEliminated[userid]:
        return

    # Set variables
    players = []
    index = 0

    # Respawn all victims eliminated players
    for playerid in dict_playersEliminated[userid]:
        # Make sure the player exists
        if not respawnable(playerid):
            continue

        # Respawn player
        gungamelib.respawn(playerid)

        # Add to message format
        players.append('\3%s\1' % gungamelib.getPlayer(playerid).name)

        # Get index
        if not index:
            index = gungamelib.getPlayer(playerid)['index']

    # Tell everyone that they are respawning
    gungamelib.saytext2('gg_elimination', '#all', index, 'RespawningPlayer', {'player': ', '.join(players)})

    # Clear victims eliminated player list
    dict_playersEliminated[userid] = []

def respawnable(userid):
    # Check if player is on a team (checks for existancy also)
    if gungamelib.isSpectator(userid):
        return False

    # Make sure the player is alive
    if not gungamelib.isDead(userid):
        return False

    return True


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.distributions import Bernoulli
from torch.autograd import Variable
import torch.optim as optim
import numpy as np
import random
import math
import sys
import os

torch.manual_seed(0)

class armax_model(nn.Module):
    def __init__(self, no_of_glucose_inputs = 10, no_of_insulin_inputs = 10, no_of_meal_inputs = 10):

        output_dim = 1
        super(armax_model, self).__init__()

        self.glucose_weights = nn.Parameter(torch.randn((no_of_glucose_inputs, output_dim)))
        self.insulin_weights = nn.Parameter(torch.randn((no_of_insulin_inputs, output_dim)))
        self.meal_weights = nn.Parameter(torch.randn((no_of_meal_inputs, output_dim)))

        self.bias = nn.Parameter(torch.randn((output_dim,)))

    def forward(self, glucose, insulin, meal):
        glucose_term = torch.matmul(glucose, self.glucose_weights)
        # Enforcing insulin having negative effects
        insulin_term = torch.matmul(insulin, -torch.abs(self.insulin_weights))
        meal_term = torch.matmul(meal, self.meal_weights)

        y = glucose_term + insulin_term + meal_term
        return y

def fit_model(all_states, all_controls, all_next_states, glucose_normalizer, insulin_normalizer, meal_normalizer, filename):
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    episode_count = 100
    batch_size = 64

    model = armax_model().to(device)
    learning_rate = 1e-3
    # criterion = nn.SmoothL1Loss()
    criterion = nn.MSELoss()

    optimizer = optim.Adam(model.parameters(), lr = learning_rate)

    all_train_states = np.concatenate((all_states['main']['train'], all_states['omega']['train']), axis=0)
    all_train_controls = np.concatenate((all_controls['main']['train'], all_controls['omega']['train']), axis=0)
    all_train_next_states = np.concatenate((all_next_states['main']['train'], all_next_states['omega']['train']), axis=0)
    T = 10

    num_datapoints = len(all_train_states)
    for episode in range(episode_count):
        number_of_batches = math.ceil(float(num_datapoints) / float(batch_size))

        total_loss = 0.0

        for batch_index in range(number_of_batches):
            start = batch_index * batch_size
            end = min(start + batch_size, num_datapoints)
            loss_list = []
            optimizer.zero_grad()

            # for entry in range(start, end):
            #     glucose_input = all_train_states[entry, :T] * glucose_normalizer
            #     glucose_input = torch.from_numpy(glucose_input).float().to(device)
            #     insulin_input = all_train_states[entry, T:2*T] * insulin_normalizer
            #     insulin_input = torch.from_numpy(insulin_input).float().to(device)
            #     meal_input = all_train_states[entry, 2*T:3*T] * meal_normalizer
            #     meal_input = torch.from_numpy(meal_input).float().to(device)
            #     target = all_train_next_states[entry, :] * glucose_normalizer
            #     target = torch.from_numpy(target).float().to(device)
            #     prediction = model.forward(glucose_input, insulin_input, meal_input)
            #     loss = criterion(prediction, target).to(device)
            #     loss_list.append(loss)
            #     # Computing loss for tracking
            #     total_loss += loss.item()

            glucose_input = all_train_states[start:end, :T] * glucose_normalizer
            glucose_input = torch.from_numpy(glucose_input).float().to(device)

            insulin_input = all_train_states[start:end, T:2*T] * insulin_normalizer
            insulin_input = torch.from_numpy(insulin_input).float().to(device)

            meal_input = all_train_states[start:end, 2*T:3*T] * meal_normalizer
            meal_input = torch.from_numpy(meal_input).float().to(device)

            target = all_train_next_states[start:end, :] * glucose_normalizer
            target = torch.from_numpy(target).float().to(device)

            prediction = model.forward(glucose_input, insulin_input, meal_input)

            loss = criterion(prediction, target).to(device)

            # Computing loss for tracking
            total_loss += loss.item() * (end-start)

            loss.backward()
            optimizer.step()

        print("At episode - ", episode, " avg loss computed - ", total_loss / float(len(all_train_states)))
        if (episode+1)%10 == 0 or episode == 0:
            test_loss = test_model(model, all_states, all_controls, all_next_states, glucose_normalizer, insulin_normalizer, meal_normalizer, T)
            print("At episode - ", episode, " avg test loss computed - ", test_loss )

        torch.save(model.state_dict(), filename)

    return model

def test_model(model, all_states, all_controls, all_next_states, glucose_normalizer, insulin_normalizer, meal_normalizer, T):
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    all_test_states = np.concatenate((all_states['main']['test'], all_states['omega']['test']), axis=0)
    all_test_controls = np.concatenate((all_controls['main']['test'], all_controls['omega']['test']), axis=0)
    all_test_next_states = np.concatenate((all_next_states['main']['test'], all_next_states['omega']['test']), axis=0)

    total_loss = 0.0
    for index in range(len(all_test_states)):

        glucose_input = all_test_states[index, :T] * glucose_normalizer
        glucose_input = torch.from_numpy(glucose_input).float().to(device)

        insulin_input = all_test_states[index, T:2*T] * insulin_normalizer
        insulin_input = torch.from_numpy(insulin_input).float().to(device)

        meal_input = all_test_states[index, 2*T:3*T] * meal_normalizer
        meal_input = torch.from_numpy(meal_input).float().to(device)

        target = all_test_next_states[index, :] * glucose_normalizer
        target = torch.from_numpy(target).float().to(device)

        prediction = model.forward(glucose_input, insulin_input, meal_input)
        prediction = prediction.cpu().detach().numpy()[0]

        loss = abs( prediction - target)**2
        total_loss += loss

    avg_error = total_loss / float(len(all_test_states))

    return avg_error.item()

def extract_state_dict():

    filename = os.path.join("./networks/", "diabetes_armax_model.nt")
    model = torch.load(filename)
    torch.save(model.state_dict(), "./networks/diabetes_armax_model_state_dict.nt")


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor

df = pd.read_csv('Franchise_Dataset.csv')
df.head()

X =df.iloc[:, 1:2].values
y =df.iloc[:, 2].values

model = RandomForestRegressor(n_estimators = 10, random_state = 0)
model.fit(X, y)

y_pred =model.predict([[6]])
print(y_pred)

X_grid_data = np.arange(min(X), max(X), 0.01)
X_grid_data = X_grid_data.reshape((len(X_grid_data), 1))
plt.scatter(X, y, color = 'red')
plt.plot(X_grid_data,model.predict(X_grid_data), color = 'blue')
plt.title('Random Forest Regression')
plt.xlabel('Counter Sales')
plt.ylabel('Net Profit')
plt.show()


try:
	import sys
	import os.path
	sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
	import os, errno
	import logging # http://www.onlamp.com/pub/a/python/2005/06/02/logging.html
	from logging import handlers
	import argparse
	#sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'pysunspec'))
	from datetime import datetime, date, time, timedelta
#	import jsonpickle # pip install jsonpickle
	import json
	from sit_logger import SitLogger
	from sit_constants import SitConstants
	#from sit_date_time import SitDateTime
except ImportError as l_err:
	print("ImportError: {0}".format(l_err))
	raise l_err

class SitJsonConf(object):

# CONSTANTS

# VARIABLES
	_logger = None
	_config_dir = None #Setted by init
	_config_file = None #File name only
	_config_data = None # Where json.dump are put

# FUNCTIONS DEFINITION

	def __init__(self, a_config_file_name=SitConstants.SIT_JSON_DEFAULT_CONFIG_FILE_NAME):
		"""
			Initialize
		"""
		self._config_dir = SitConstants.DEFAULT_CONF_DIR
		self._config_file = a_config_file_name
		if not os.path.isdir(self._config_dir):
			raise Exception('init->Config dir {} does not exist, sudo mkdir -m 777 {}'.format(self._config_dir, self._config_dir))
		try:
			self._logger = SitLogger().new_logger(__name__)
			if __name__ == '__main__':
				self.init_arg_parse()
			self.read_config(self.configuration_file_path())
		except OSError as l_e:
			self._logger.warning("init-> OSError, probably rollingfileAppender:{}".format(l_e))
			if l_e.errno != errno.ENOENT:
				raise l_e
		except Exception as l_e:
			self._logger.error('Error in init: {}'.format(l_e))
			raise l_e

	def configuration_file_path(self):
		"""
		"""
		l_res = os.path.join(self._config_dir, self._config_file)
		return l_res

	def read_config(self, a_config_file_path=None):
		"""
			puts into self._config_data json data
		"""
		if a_config_file_path is None:
			l_config_file_path = self.configuration_file_path()
		else:
			l_config_file_path = a_config_file_path
		with open(l_config_file_path, "r") as l_file:
			self._config_data = json.load(l_file)

	def item(self, a_key):
		"""
		returns value of given key exception if not found
		"""
		l_res = None
		return l_res

# SCRIPT ARGUMENTS

	def init_arg_parse(self):
		"""
			Parsing arguments
		"""
		self._logger.debug('init_arg_parse-> begin')
		self._parser = argparse.ArgumentParser(description='Actions with sunspec through TCP')
		self._add_arguments()
		l_args = self._parser.parse_args()
		self._args = l_args

	def _add_arguments(self):
		"""
		Add arguments to parser (called by init_arg_parse())
		"""
		self._parser.add_argument('-v', '--verbose', help='increase output verbosity', action="store_true")
		self._parser.add_argument('-u', '--update_leds_status', help='Updates led status according to spec', action="store_true")
		self._parser.add_argument('-t', '--test', help='Runs test method', action="store_true")

		#self._parser.add_argument('-u', '--base_url', help='NOT_IMPLEMENTED:Gives the base URL for requests actions', nargs='?', default=self.DEFAULT_BASE_URL)
		l_required_named = self._parser.add_argument_group('required named arguments')
#		l_required_named.add_argument('-i', '--host_ip', help='Host IP', nargs='?', required=True)
#		l_required_named.add_argument('-u', '--slave_address', help='Slave address of modbus device', nargs='?', required=True)
		l_required_named.add_argument('-m', '--host_mac', help='Host MAC', nargs='?', required=True)
#		l_required_named.add_argument('-l', '--longitude', help='Longitude coordinate (beware timezone is set to Chile)', nargs='?', required=True)
#		l_required_named.add_argument('-a', '--lattitude', help='Lattitude coordinate (beware timezone is set to Chile)', nargs='?', required=True)
#		l_required_named.add_argument('-d', '--device_type', help='Device Type:' + ('|'.join(str(l) for l in self.DEVICE_TYPES_ARRAY)), nargs='?', required=True)

	def execute_corresponding_args( self ):
		"""
			Parsing arguments and calling corresponding functions
		"""
		if self._args.verbose:
			self._logger.setLevel(logging.DEBUG)
		else:
			self._logger.setLevel(logging.INFO)
		if self._args.test:
			self.test()
		#if self._args.store_values:

# TEST

	def test(self):
		"""
			Test function
		"""
		try:
			self._logger.info("################# BEGIN #################")
			self._logger.info("--> ************* device models *************: {}".format(l_d.models))	 #Lists properties to be loaded with l_d.<property>.read() and then access them
		except Exception as l_e:
			self._logger.exception("Exception occured:  {}".format(l_e))
			print('Error: {}'.format(l_e))
			self._logger.error('Error: {}'.format(l_e))
			sys.exit(1)

#################### END CLASS ######################

def main():
	"""
	Main method
	"""
	#logging.basicConfig(level=logging.DEBUG, stream=sys.stdout, filemode="a+", format="%(asctime)-15s %(levelname)-8s %(message)s")
	logger = logging.getLogger(__name__)

	try:
		l_obj = SitJsonConf()
		l_obj.execute_corresponding_args()
#		l_id.test()
	except KeyboardInterrupt:
		logger.exception("Keyboard interruption")
	except Exception as l_e:
		logger.exception("Exception occured:{}".format(l_e))
		raise l_e

#Call main if this script is executed
if __name__ == '__main__':
    main()


import pygame
from sys import exit
import numpy as np
import copy as cp
import math
import random as rd
import time

class GameState:
    def __init__(self, board):
        self.board = board
        self.end=-1
        self.children = []
        self.parent = None
        self.parentPlay = None # (play, movtype)
        self.parentCell = None
        self.numsimulation=0
        self.mctsv=0
        self.mctss=0
        self.uct=0

    def createChildren(self, player_id):
        differentPlayBoards = []
        for i in range(len(self.board)):
            for j in range(len(self.board)):
                if self.board[j][i] == player_id:
                    moves = get_moves(self, (i,j))
                    for mov in moves:
                        if moves[mov][0]:
                            newboard = cp.deepcopy(self.board)
                            play = (i+mov[0], j+mov[1])
                            if moves[mov][1] == 1: #movtype
                                newboard[play[1]][play[0]] = player_id
                            elif moves[mov][1] == 2:
                                newboard[play[1]][play[0]] = player_id
                                newboard[j][i] = 0
                            if newboard not in differentPlayBoards:
                                differentPlayBoards.append(newboard)
                                newboard = get_and_apply_adjacent(play, newboard, player_id)
                                newState = GameState(newboard)
                                newState.parentCell = (i,j)
                                newState.parentPlay = (play, moves[mov][1])
                                newState.parent = self
                                self.children.append(newState)

def evaluatePlay_mcts(game,board,play,cell,player):
    s1=1
    s2=0.4
    s3=0.7
    s4=0.4
    soma=0
    vec=[(1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)]
    if play[1] == 1:
        soma+=s3
        for mov in vec:
            if not (play[0][0]<1 or play[0][0]>len(game.board)-1-1 or play[0][1]<1 or play[0][1]>len(game.board)-1-1):
                if board[play[0][0]+mov[0]][play[0][1]+mov[1]]==3-player:
                    soma+=s1
                if board[play[0][0]+mov[0]][play[0][1]+mov[1]]==player:
                    soma+=s2
    elif play[1] == 2:
        for mov in vec:
            if not (play[0][0]<1 or play[0][0]>len(game.board)-1-1 or play[0][1]<1 or play[0][1]>len(game.board)-1-1):
                if board[play[0][1]+mov[1]][play[0][0]+mov[0]]==3-player:
                    soma+=s1
                if board[play[0][1]+mov[1]][play[0][0]+mov[0]]==player:
                    soma+=s2
            if not (cell[0]<1 or cell[0]>len(game.board)-1-1 or cell[1]<1 or cell[1]>len(game.board)-1-1):
                if board[cell[1]+mov[1]][cell[0]+mov[0]]==player:
                    soma-=s4
    return soma

def final_move(game,board,play,player):     #### função que checka se o estado não tem children
    #print(player,'final')
    gamenp=np.array(board)
    #print(gamenp,'nparray')
    if np.count_nonzero(gamenp==(3-player))==0:
        return (True,player)
    if np.count_nonzero(gamenp==(player))==0:
        return (True,3-player)
    if np.count_nonzero(gamenp==0) != 0:
                return (False,-1)
    if np.count_nonzero(gamenp==0) == 0:
        count_p=np.count_nonzero(gamenp==player)
        count_o=np.count_nonzero(gamenp==(3-player))
        if count_p > count_o:
            return (True,player)
        if count_o > count_p:
            return (True,3-player)
    return (True,0)

def evaluatePlay_minmax(game,board,play,cell,player,values):  #### heurística para o minimax
    s1=values[0]
    s2=values[1]
    s3=values[2]
    s4=values[3]
    soma=0
    vec=[(1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)]
    #print(player,'pre final')
    final=final_move(game,board,play,player)
    #print(final)
    if final[0]:                                        #### ver que tipo de fim é e retornar o valor
        if final[1]==player:
            return (math.inf)
        if final[1]==3-player:
            return (-math.inf)
        if final[1]==0:
            return 0
    if play[1] == 1:
        soma+=s3
        for mov in vec:
            if not (play[0][0]<1 or play[0][0]>len(game.board)-1-1 or play[0][1]<1 or play[0][1]>len(game.board)-1-1):
                if board[play[0][0]+mov[0]][play[0][1]+mov[1]]==3-player:
                    soma+=s1
                if board[play[0][0]+mov[0]][play[0][1]+mov[1]]==player:
                    soma+=s2
    elif play[1] == 2:
        for mov in vec:
            if not (play[0][0]<1 or play[0][0]>len(game.board)-1-1 or play[0][1]<1 or play[0][1]>len(game.board)-1-1):
                if board[play[0][1]+mov[1]][play[0][0]+mov[0]]==3-player:
                    soma+=s1
                if board[play[0][1]+mov[1]][play[0][0]+mov[0]]==player:
                    soma+=s2
            if not (cell[0]<1 or cell[0]>len(game.board)-1-1 or cell[1]<1 or cell[1]>len(game.board)-1-1):
                if board[cell[1]+mov[1]][cell[0]+mov[0]]==player:
                    soma-=s4
    return soma

def randomplay(game, player):
    game.createChildren(player)
    r = rd.randint(0,len(game.children)-1)
    return game.children[r]

def implementar_montecarlos(game,player):
    C=1.5
    game.createChildren(player)
    bestchildren=[]
    Sbasic=100
    for child in game.children:
        childnp=np.array(child.board)
        child.mctss=Sbasic*(1+0.1*(np.count_nonzero(childnp==player)))
        child.mctsv=montecarlots(int(child.mctss),child,player)
        child.numsimulation+=child.mctss
        if len(bestchildren)<=5:
            bestchildren.append(child)
        else:
            for bchild in bestchildren:
                if child.mctsv>bchild.mctsv:
                    bestchildren.remove(bchild)
                    bestchildren.append(child)
    for child in bestchildren:
        child.mctsv+=montecarlots(int(child.mctss),child,player)
        child.numsimulation+=child.mctss
    bestchildren=[]
    for child in game.children:
        child.uct=child.mctsv+C*(math.sqrt(1/(child.numsimulation)))
        if len(bestchildren)<=3:
            bestchildren.append(child)
        else:
            for bchild in bestchildren:
                if child.uct>bchild.uct:
                    bestchildren.remove(bchild)
                    bestchildren.append(child)
    for child in bestchildren:
        child.mctsv+=montecarlots(int((child.mctss)/2),child,player)
    bestchildren=[]
    for child in game.children:
        if len(bestchildren)==0:
            bestchildren.append(child)
        else:
            if child.mctsv>bestchildren[0].mctsv:
                bestchildren.pop(0)
                bestchildren.append(child)
    return bestchildren[0]

def montecarlots(numSimulations, game,player):
    gamenp=np.array(game.board)
    E=np.count_nonzero(gamenp==player)-np.count_nonzero(gamenp==(3-player))
    for i in range(numSimulations):
        player_hid=player
        board=cp.deepcopy(game.board)
        while game.end == -1 and game.end<10:
            if player_hid == 1:
                game.createChildren(player_hid)
                board = randomplay(game,player_hid)  #para testar os algoritmos da AI é só trocar aqui a função pelo algoritmo desejado
                game = GameState(board)
                player_hid = switchPlayer(player_hid)
            elif player_hid == 2:
                game.createChildren(player_hid)
                board = randomplay(game,player_hid)  #igual ao comentario acima
                game = GameState(board)
                player_hid = switchPlayer(player_hid)
            game.end = objective_testmcts(game, player_hid)
        if game.end-10==player_hid:
            E+=500
        elif game.end-10==3-player_hid:
            E-=500
        elif game.end==player_hid:
            E+=50
        elif game.end==3-player_hid:
            E-=50
    return E

def greedy(game,player):
    bestPlay = ([], -math.inf) #random tuple where the 2nd element holds the best play evaluation and the 1st holds its board
    game.createChildren(player)
    for state in game.children: #play[0] -> (i,j) || play][1] -> movType
        board = cp.deepcopy(state.board)
        value=evaluatePlay_mcts(state,board,state.parentPlay,state.parentCell,player)
        if value > bestPlay[1]:
            if state.parentPlay[1] == 1:
                board[state.parentPlay[0][1]][state.parentPlay[0][0]] = player
            elif state.parentPlay[1] == 2:
                board[state.parentCell[1]][state.parentCell[0]] = 0
                board[state.parentPlay[0][1]][state.parentPlay[0][0]] = player
            board = get_and_apply_adjacent((state.parentPlay[0][0], state.parentPlay[0][1]), board, player)
            bestPlay = (board, value)
    return GameState(bestPlay[0])

def implement_minimax(game,player,playerAI):
    max_depth = 5
    absodepth=max_depth
    result=minimaxabc(game,max_depth,absodepth,player,playerAI,-math.inf,math.inf)
    newresult = result[0]
    depth = result[2]
    for _ in range(max_depth-depth-1):
        newresult = newresult.parent
    return newresult

def minimaxabc(game, max_depth,absodepth, player, playerAI, alpha, beta):
    game.createChildren(player)
    if max_depth==0 or game.children == []:
        values = (1.0, 0.4, 0.7, 0.4)
        board = cp.deepcopy(game.board)
        #print(player,'pre evaluate')
        value=(game,evaluatePlay_minmax(game,board,game.parentPlay,game.parentCell,player,values), max_depth)
        #print(value[0].board,' ',value[1],'depth ',max_depth)
        return value

    if player == 3-playerAI:
        value =(GameState([]), math.inf,absodepth)
        for state in game.children:
            evaluation = minimaxabc(state, max_depth - 1,absodepth, 3-player, playerAI, alpha, beta)
            #print(evaluation[0].board,' ',evaluation[1],'minimizer maxdepth %d' % max_depth)
            if evaluation[1]<value[1]:
                value=evaluation
            beta = min(beta, evaluation[1])
            if beta <= alpha:
                break
        return value

    value =(GameState([]), -math.inf,absodepth)
    for state in game.children:
        evaluation = minimaxabc(state, max_depth - 1,absodepth, 3-player, playerAI, alpha, beta)
        #print(evaluation[0].board,' ',evaluation[1], 'maximizer maxdepth %d' % max_depth)
        if evaluation[1]>value[1]:
            value=evaluation
        alpha = max(alpha, evaluation[1])
        if beta <= alpha:
            break
    return value

#i=y and j=x : tuples are (y,x)
def get_moves(game,cell):
    vect = [(1,0),(2,0),(1,1),(2,2),(1,-1),(2,-2),(-1,0),(-2,0),(-1,1),(-2,-2),(0,1),(0,2),(0,-1),(0,-2),(-1,-1),(-2,2)]
    #moves é um dicionario onde a chave de cada elemento é uma lista com a validade do mov (True/False) no indice 0 e o tipo de movimento no indice 1
    moves={}
    for mov in vect:
        play=(cell[0]+mov[0],cell[1]+mov[1])
        if play[0]<0 or play[0]>len(game.board)-1 or play[1]<0 or play[1]>len(game.board)-1 or game.board[play[1]][play[0]]!=0:
            moves[mov]=[False]
        else:
            moves[mov]=[True]

        if 1 in mov or -1 in mov:
            moves[mov].append(1)
        elif 2 in mov or -2 in mov:
            moves[mov].append(2)
    return moves

#draws the board on screen
def drawBoard(game, screen):
    n = len(game.board)
    screen.fill((255,255,255)) #background branco

    #desenha frame do tabuleiro
    pygame.draw.line(screen, (0,0,0), (0,0), (800,0), 2)
    pygame.draw.line(screen, (0,0,0), (0,0), (0,800), 2)
    pygame.draw.line(screen, (0,0,0), (0,798), (800,798), 2)
    pygame.draw.line(screen, (0,0,0), (798, 0), (798,800), 2)

    #desenha linhas do tabuleiro
    for i in range(1,n):
        #linhas verticais
        pygame.draw.line(screen, (0,0,0), (800*i/n,0), (800*i/n,800), 2)
        #linhas horizontais
        pygame.draw.line(screen, (0,0,0), (0,800*i/n), (800,800*i/n), 2)

def drawPieces(game, screen):
    n = len(game.board)
    for i in range(n):
        for j in range(n):
            #desenha peças do jogador 1
            if game.board[j][i] == 1:
                pygame.draw.circle(screen, (0,0,255), ((800*i/n)+800/(2*n), (800*j/n)+800/(2*n)), 800/(3*n))
            #desenha peças do jogador 2
            if game.board[j][i] == 2:
                pygame.draw.circle(screen, (0,150,0), ((800*i/n)+800/(2*n), (800*j/n)+800/(2*n)), 800/(3*n))
            #desenha quadrados onde não se pode jogar
            if game.board[j][i] == 8:
                pygame.draw.rect(screen, (0,0,0), (800*i/n, 800*j/n, 800/n + 1, 800/n + 1))

#mostrar o resultado do jogo graficamente
def drawResult(game, screen):
    if game.end == -1:
        return None
    font = pygame.font.Font('freesansbold.ttf', 32)
    pygame.draw.rect(screen, (0,0,0), (120, 240, 560, 320))
    pygame.draw.rect(screen, (255,255,255), (140, 260, 520, 280))
    if game.end == 0:
        text = font.render("Empate!", True, (0,0,0))
    elif game.end == 1:
        text = font.render("Jogador 1 vence!", True, (0,0,255))
    elif game.end == 2:
        text = font.render("Jogador 2 vence!", True, (0,150,0))
    text_rect = text.get_rect(center=(400, 400))
    screen.blit(text, text_rect)

#return the coordinates of the mouse in the game window
def mousePos(game):
    click = pygame.mouse.get_pos()
    n = len(game.board)
    i = int(click[0]*n/800)
    j = int(click[1]*n/800)
    coord=(i,j)
    return coord

#shows the selected cell on screen
def showSelected(game, screen, coord, player_id):
    n = len(game.board)
    i=coord[0]
    j=coord[1]
    #selectedType é um dicionario onde cada elemento é um dos quadrados onde se pode jogar e cuja chave é o tipo de movimento
    selectedType = {}
    if game.board[j][i] == player_id:
        #desenha as cell possiveis de se jogar do player id
        if player_id == 1:
            selectedCellRGB  = (173,216,230) #azul claro
        elif player_id == 2:
            selectedCellRGB = (144,238,144) #verde claro
        pygame.draw.rect(screen, selectedCellRGB, (800*i/n + 2, 800*j/n + 2, 800/n - 2 , 800/n - 2))
        moves=get_moves(game,coord)
        for mov in moves:
            if moves[mov][0]:
                play=(coord[0]+mov[0],coord[1]+mov[1])
                selectedType[play] = moves[mov][1]
                pygame.draw.rect(screen, selectedCellRGB, (800*play[0]/n + 2, 800*play[1]/n + 2, 800/n - 2 , 800/n - 2))
    return selectedType

def get_and_apply_adjacent(targetCell, newBoard, player_id):
    vectors = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)]
    #adjacent é um dicionario que vai ter como elemento cada cell que esta a volta da targetCell e cujos elementos sao True/False
    #se essa cell tiver/não tiver uma peça do oponente
    adjacent = {}
    for vect in vectors:
        play=(targetCell[0]+vect[0],targetCell[1]+vect[1])
        if play[0]<0 or play[0]>len(newBoard)-1 or play[1]<0 or play[1]>len(newBoard)-1 or newBoard[play[1]][play[0]] != switchPlayer(player_id):
            adjacent[vect] = False
        else:
            adjacent[vect] = True
    for adj in adjacent:
        if adjacent[adj]:
            adjCell = (targetCell[0]+adj[0], targetCell[1]+adj[1])
            newBoard[adjCell[1]][adjCell[0]] = player_id
    return newBoard

def skip(game,player):
    game.createChildren(player)
    if len(game.children) == 0:
        return True
    return False

def objective_testmcts(game,player): #atualizar count
    gamenp=np.array(game.board)
    if np.count_nonzero(gamenp==0)==0:
        if np.count_nonzero(gamenp==player)>np.count_nonzero(gamenp==(3-player)):
            return player
        if np.count_nonzero(gamenp==player)<np.count_nonzero(gamenp==(3-player)):
            return 3-player
        else:
            return 0
    if np.count_nonzero(gamenp==player)==0:
        return (3-player+10)
    for j in range(len(gamenp)):
        for i in range(len(gamenp)):
            if gamenp[j][i]==player:
                if True in get_moves(game,(i,j)):
                    return -1
                else:
                    return (3-player+10)

def objective_test(game,player): #atualizar count
    gamenp=np.array(game.board)
    if np.count_nonzero(gamenp==(3-player))==0:
        return player
    if np.count_nonzero(gamenp==0) != 0:
                return -1
    if np.count_nonzero(gamenp==0) == 0:
        count_p=np.count_nonzero(gamenp==player)
        count_o=np.count_nonzero(gamenp==(3-player))
        if count_p > count_o:
            return player
        if count_o > count_p:
            return (3-player)
    return 0

def executeMov(game, initialCell, targetCell, selectedType, player_id):
    newBoard = cp.deepcopy(game.board)
    if targetCell in selectedType:
        movType = selectedType[targetCell]
        #movimento tipo 1
        if movType == 1:
            newBoard[targetCell[1]][targetCell[0]] = player_id
            newBoard = get_and_apply_adjacent(targetCell, newBoard, player_id)
        #movimento tipo 2
        elif movType == 2:
            newBoard[targetCell[1]][targetCell[0]] = player_id
            newBoard[initialCell[1]][initialCell[0]] = 0
            newBoard = get_and_apply_adjacent(targetCell, newBoard, player_id)
    newGame = GameState(newBoard)
    return newGame

def switchPlayer(player_id):
    return 3-player_id

#game mode Human vs Human
def jogo_Humano_Humano(game, screen):
    player_id = 1
    clickState = False
    while game.end==-1:
        drawPieces(game, screen)
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

            #verificar se o jogador está cercado / não tem jogadas possiveis e tem de passar a jogada
            if not skip(game,player_id):
                #escolher a peca para jogar e as possiveis plays
                if event.type == pygame.MOUSEBUTTONDOWN and clickState == False:
                    drawBoard(game, screen)
                    coord = mousePos(game)
                    selected = showSelected(game, screen, coord, player_id)
                    clickState = True
                    drawPieces(game, screen)

                #fazer o movimento da jogada
                elif event.type == pygame.MOUSEBUTTONDOWN and clickState == True:
                    targetCell = mousePos(game)
                    prevBoard = cp.deepcopy(game.board)
                    game = executeMov(game, coord, targetCell, selected, player_id)
                    if not (np.array_equal(prevBoard,game.board)):
                        player_id = switchPlayer(player_id)
                    clickState=False
                    drawBoard(game, screen)
                    drawPieces(game, screen)
            else:
                player_id = switchPlayer(player_id)
        game.end = objective_test(game,player_id)

        #to display the winner
        while game.end != -1:
            drawResult(game,screen)
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    pygame.quit()
                    exit()
            pygame.display.update()
        pygame.display.update()

def jogo_Humano_AI(game, screen, algorithm):
    player_id = 1
    clickState = False
    while game.end==-1:
        drawPieces(game, screen)
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

            #verificar se o jogador está cercado / não tem jogadas possiveis e tem de passar a jogada
            if not skip(game,player_id):
                if player_id == 1:
                    #escolher a peca para jogar e as possiveis plays
                    if event.type == pygame.MOUSEBUTTONDOWN and clickState == False:
                        drawBoard(game, screen)
                        coord = mousePos(game)
                        selected = showSelected(game, screen, coord, player_id)
                        clickState = True
                        drawPieces(game, screen)

                    #fazer o movimento da jogada
                    elif event.type == pygame.MOUSEBUTTONDOWN and clickState == True:
                        targetCell = mousePos(game)
                        prevBoard = cp.deepcopy(game.board)
                        game = executeMov(game, coord, targetCell, selected, player_id)
                        if not (np.array_equal(prevBoard,game.board)):
                            player_id = switchPlayer(player_id)
                        clickState=False
                        drawBoard(game, screen)
                        drawPieces(game, screen)
                else:
                    if algorithm == 1:
                        game = implement_minimax(game,player_id, player_id)
                    elif algorithm == 2:
                        game = implementar_montecarlos(game,player_id)
                    elif algorithm == 3:
                        game = greedy(game,player_id)
                    elif algorithm == 4:
                        game = randomplay(game, player_id)
                    drawBoard(game, screen)
                    drawPieces(game, screen)
                    player_id = 1
            else:
                player_id = switchPlayer(player_id)
        game.end = objective_test(game,player_id)

        #to display the winner
        while game.end != -1:
            drawResult(game,screen)
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    pygame.quit()
                    exit()
            pygame.display.update()
        pygame.display.update()

#sets the game window
def setScreen():
    width = 800
    height = 800
    screen = pygame.display.set_mode((width, height))
    pygame.display.set_caption("Ataxx")
    return screen

#abre um ficheiro com um mapa do tabuleiro a ser usado no jogo e cria o estado/objeto inicial
def readBoard(ficheiro):
    f = open(ficheiro, "r")
    n = int(f.readline())
    board = []
    for i in range(n):
        board.append(list(map(int, f.readline().split())))
    f.close()
    return GameState(board)

#pede ao user para escolher o tabuleiro que pretende usar
def chooseBoard():
    #todos os ficheiros com tabuleiros devem ter nome do tipo "tabX.txt"
    tableNum = input("Escolha o número do tabuleiro que quer usar para o jogo!\n1) 10x10\n2) 8x8\n3) 6x6\n4) 5x5\n5) 12x12\nTabuleiro: ")
    table = "tab"+tableNum+".txt"
    return table

def chooseMode():
    mode = int(input("Escolha o modo de jogo!\n1) Humano vs Humano\n2) Humano vs AI\nModo: "))
    return mode

def chooseAI():
    algorithm=int(input("Escolha o seu adversário!\n1) Minimax\n2) MonteCarloTreeSearch **VT**\n3) Greedy\n4) Random Play\nModo: "))
    return algorithm

def playMode(game, screen, mode,algorithm):
    if mode == 1:
        jogo_Humano_Humano(game, screen)
    elif mode == 2:
        jogo_Humano_AI(game,screen,algorithm)

def simulacao(numSimulations):
    playerTurns = [1,2,1,1]
    empate = 0
    w1 = 0
    comeutodas1 = 0
    w2 = 0
    comeutodas2 = 0
    for i in range(numSimulations):
        table = "tabSim" + str(i+1) + ".txt"
        #table = "tabSim18.txt"
        game = readBoard(table)
        #player_id = playerTurns[i%4]
        player_id = 1
        while game.end == -1:
            if not skip(game,player_id):
                if player_id == 1:
                    game = greedy(game,player_id)  #para testar os algoritmos da AI é só trocar aqui a função pelo algoritmo desejado
                    player_id = switchPlayer(player_id)
                elif player_id == 2:
                    game = implement_minimax(game, player_id, player_id)  #igual ao comentario acima
                    player_id = switchPlayer(player_id)
            else:
                player_id = switchPlayer(player_id)
            game.end = objective_test(game, player_id)

        print(i+1)
        if game.end == 0:
            empate += 1
        elif game.end == 1:
            w1 += 1
            gamenp = np.array(game.board)
            if np.count_nonzero(gamenp == 2) == 0:
                comeutodas1 += 1
        elif game.end == 2:
            w2 += 1
            gamenp = np.array(game.board)
            if np.count_nonzero(gamenp == 1) == 0:
                comeutodas2 += 1

    with open("data.txt", "a") as data:
        numbers = "%d %d %d %d\n" % (numSimulations, w1, w2, empate)
        data.write(numbers)
    print("Jogos: %d\nAI 1: %d (Jogos com todas as peças do oponente eliminadas: %d)\nAI 2: %d (Jogos com todas as peças do oponente eliminadas: %d)\nEmpate: %d\n" % (numSimulations, w1, comeutodas1, w2, comeutodas2, empate))

def main():
    mode = chooseMode()
    if mode==2:
        algorithm=chooseAI()
    else:
        algorithm=0
    table = chooseBoard()
    pygame.init()
    screen = setScreen()
    game = readBoard(table)
    drawBoard(game, screen)
    playMode(game, screen, mode,algorithm)

start_time = time.time()
main()
#simulacao(100)
print("--- %.5f seconds ---" % (time.time() - start_time))


import sys

sys.stdin = open('input.txt')

def make_number(i, j, depth, ans):
    global visited
    if depth == 6:
        if (depth, i, j, ans) not in visited:
            visited[(depth, i, j, ans)] = 1
            result.append(ans)
        return

    if (depth, i, j, ans) in visited:
        return
    else:
        visited[(depth, i, j, ans)] = 1
        for di, dj in ((0, 1), (0, -1), (1, 0), (-1, 0)):
            ni, nj = i + di, j + dj

            if 0 <= ni < 4 and 0 <= nj < 4:
                make_number(ni, nj, depth+1, ans+data[ni][nj])

T = int(input())

for tc in range(1, 1+T):
    data = [list(map(str, input().split())) for _ in range(4)]
    result = []
    # visited에다가 해당까지 온 값과 i,j값을 넣어준다.
    visited = {}

    # print(visited)
    for i in range(4):
        for j in range(4):
            make_number(i, j, 0, data[i][j])
    result = set(result)
    print(f'#{tc}', len(result))


import math
import sys
from typing import Iterable, Optional

import torch

from timm.data import Mixup
from timm.utils import accuracy

import util.misc as misc
import util.lr_sched as lr_sched
import numpy as np
from scipy.stats import spearmanr, pearsonr

def train_koniq_epoch(model: torch.nn.Module, criterion: torch.nn.Module,
                    data_loader: Iterable, optimizer: torch.optim.Optimizer,
                    device: torch.device, epoch: int, loss_scaler=None, log_writer=None,
                    args=None):
    model.train(True)
    metric_logger = misc.MetricLogger(delimiter="  ")
    metric_logger.add_meter('lr', misc.SmoothedValue(window_size=1, fmt='{value:.6f}'))
    header = 'Epoch: [{}]'.format(epoch)
    print_freq = 20

    accum_iter = args.accum_iter

    optimizer.zero_grad()

    if log_writer is not None:
        print('log_dir: {}'.format(log_writer.log_dir))
    pred_epoch = []
    labels_epoch = []
    for data_iter_step, (samples, targets) in enumerate(metric_logger.log_every(data_loader, print_freq, header)):

        # we use a per iteration (instead of per epoch) lr scheduler
        if data_iter_step % accum_iter == 0:
            lr_sched.adjust_learning_rate(optimizer, data_iter_step / len(data_loader) + epoch, args)

        samples = samples.to(device, non_blocking=True)
        targets = torch.squeeze(targets.type(torch.FloatTensor))
        targets = targets.to(device, non_blocking=True)

        with torch.cuda.amp.autocast():
            outputs = model(samples)
            loss = criterion(torch.squeeze(outputs), targets)

        loss_value = loss.item()

        if not math.isfinite(loss_value):
            print("Loss is {}, stopping training".format(loss_value))
            sys.exit(1)

        loss /= accum_iter
        loss_scaler(loss, optimizer, clip_grad=None,
                    parameters=model.parameters(), create_graph=False,
                    update_grad=(data_iter_step + 1) % accum_iter == 0)
        if (data_iter_step + 1) % accum_iter == 0:
            optimizer.zero_grad()

        torch.cuda.synchronize()

        metric_logger.update(loss=loss_value)
        min_lr = 10.
        max_lr = 0.
        for group in optimizer.param_groups:
            min_lr = min(min_lr, group["lr"])
            max_lr = max(max_lr, group["lr"])

        metric_logger.update(lr=max_lr)
        pred =concat_all_gather(outputs)
        labels =concat_all_gather(targets)
        pred_batch_numpy = pred.data.cpu().numpy()
        labels_batch_numpy = labels.data.cpu().numpy()
        pred_epoch = np.append(pred_epoch, pred_batch_numpy)
        labels_epoch = np.append(labels_epoch, labels_batch_numpy)
        loss_value_reduce = misc.all_reduce_mean(loss_value)
        if log_writer is not None and (data_iter_step + 1) % accum_iter == 0:
            """ We use epoch_1000x as the x-axis in tensorboard.
            This calibrates different curves when batch size changes.
            """
            epoch_1000x = int((data_iter_step / len(data_loader) + epoch) * 1000)
            log_writer.add_scalar('loss', loss_value_reduce, epoch_1000x)
            log_writer.add_scalar('lr', max_lr, epoch_1000x)
    rho_s, _ = spearmanr(np.squeeze(pred_epoch), np.squeeze(labels_epoch))
    rho_p, _ = pearsonr(np.squeeze(pred_epoch), np.squeeze(labels_epoch))

    print('*[train] epoch:%d / SROCC:%4f / PLCC:%4f' % (epoch+1, rho_s, rho_p))

    # gather the stats from all processes
    metric_logger.synchronize_between_processes()
    print("Averaged stats:", metric_logger)
    return {k: meter.global_avg for k, meter in metric_logger.meters.items()}

@torch.no_grad()
def evaluate_koniq(data_loader, model, device):
    criterion = torch.nn.L1Loss()
    metric_logger = misc.MetricLogger(delimiter="  ")
    header = 'Test:'

    # switch to evaluation mode
    model.eval()
    pred_epoch = []
    labels_epoch = []
    for batch in metric_logger.log_every(data_loader, 10, header):
        images = batch[0]
        target = batch[-1]
        images = images.to(device, non_blocking=True)
        targets = torch.squeeze(target.type(torch.FloatTensor))
        targets = targets.to(device, non_blocking=True)

        # compute output
        with torch.cuda.amp.autocast():
            output = model(images)
            loss = criterion(torch.squeeze(output), targets)

        pred =concat_all_gather(output)
        labels =concat_all_gather(targets)
        pred_batch_numpy = pred.data.cpu().numpy()
        labels_batch_numpy = labels.data.cpu().numpy()
        pred_epoch = np.append(pred_epoch, pred_batch_numpy)
        labels_epoch = np.append(labels_epoch, labels_batch_numpy)

        batch_size = images.shape[0]
        metric_logger.update(loss=loss.item())

    # gather the stats from all processes
    metric_logger.synchronize_between_processes()
    rho_s, _ = spearmanr(np.squeeze(pred_epoch), np.squeeze(labels_epoch))
    rho_p, _ = pearsonr(np.squeeze(pred_epoch), np.squeeze(labels_epoch))

    print('*[test] / SROCC:%4f / PLCC:%4f' % ( rho_s, rho_p))

    return {k: meter.global_avg for k, meter in metric_logger.meters.items()}
# utils
@torch.no_grad()
def concat_all_gather(tensor):
    """
    Performs all_gather operation on the provided tensors.
    *** Warning ***: torch.distributed.all_gather has no gradient.
    """
    tensors_gather = [torch.ones_like(tensor)
        for _ in range(torch.distributed.get_world_size())]
    torch.distributed.all_gather(tensors_gather, tensor, async_op=False)

    output = torch.cat(tensors_gather, dim=0)
    return output


from src.Util.GeneralConfig import GeneralConfig
from src.FaceRecognition.FaceRecognition import FaceRecognition
from src.Camera.Camera import Camera
from src.TelegramBot.Bot import Bot
import threading

enviroment = "Development"

#Iniciando Las configuraciones generales
generalConfig = GeneralConfig(enviroment)
bot = Bot(generalConfig)
fr = FaceRecognition(generalConfig)
bot.set_faceRecognition(fr)

def camara():
	cam = Camera(0,generalConfig)
	bot.set_camera(cam)
	cam.init_video()
	while True:
		key = input("t to take Picture:")
		if key == "t": #Simula un boton de la raspberrypi
			path = cam.take_picture()
			bot.send_photo(path)
			result = fr.recognize(path)
			print(result)
			print("_________________________________")
			print("Personas reconocidas en la foto:")
			for r in result:
				if(r['isRecognized']):
					texto = r['person']['name']
					print("|_ {}".format(r['person']['name']))
				else:
					texto = "No reconocible"
					print("|_ No reconocible")
				bot.send_message(texto)
		if key == "c":
			cam.stop()
			#t._stop()
			#b._stop()

def botTest():
	bot.run()
	while True:
		pass

t = threading.Thread(target=camara, name="Test")
b = threading.Thread(target=botTest, name="botTest")

if __name__ == '__main__':
	b.start()
	t.start()


from scipy import sparse
import time

import gradient
import vector_fields

def enforce_boundaries(phi, img_shape, dim):
    # make sure we are inside the image
    phi[:, 1] = phi[:, 1].clip(0, img_shape[1])
    phi[:, 0] = phi[:, 0].clip(0, img_shape[0])
    # 3d case
    if dim == 3:
        phi[:, 2] = phi[:, 2].clip(0, img_shape[2])
    return phi

def integrate(x_0, kernels, alpha, c_sup, dim, steps = 10, compute_gradient = True):
    start = time.time()
    if (compute_gradient):
        S_i = vector_fields.evaluation_matrix_blowup(kernels, x_0, c_sup, dim)
    else:
        S_i = vector_fields.evaluation_matrix(kernels, x_0, c_sup, dim)
    #print("FE -- initial S_i ", (time.time() - start) / 60)
    start = time.time()
    V_i = vector_fields.make_V(S_i, alpha, dim)
    #print("FE -- initial V_i ", (time.time() - start) / 60)
    x_i = x_0
    dphi_dalpha_i = sparse.csc_matrix((S_i.shape[0], S_i.shape[1]))

    for i in range(steps):
        if compute_gradient:
            start = time.time()
            dv_dphit_i = gradient.dv_dphit(x_i, kernels, alpha, c_sup, dim)
            print("FE -- dv_dphi_i ", (time.time() - start) / 60)
            start = time.time()
            dphi_dalpha_i = gradient.next_dphi_dalpha(S_i, dv_dphit_i, dphi_dalpha_i, steps, dim)
            print("FE -- dphi_dalpha_i ", (time.time() - start) / 60)
        start = time.time()
        # Make a step
        x_i = x_i + V_i / steps

        # Compute evaluatation matrix based on updated evaluation points
        if (i < steps - 1):
            if (compute_gradient):
                S_i = vector_fields.evaluation_matrix_blowup(kernels, x_i, c_sup, dim)
            else:
                S_i = vector_fields.evaluation_matrix(kernels, x_i, c_sup, dim)
            V_i = vector_fields.make_V(S_i, alpha, dim)

        print("FE -- Euler step ", (time.time() - start) / 60)
    # Enforce boundary conditions
    img_shape = []
    for d in range(dim):
        img_shape.append(max(x_0[:, d]))
    x_1 = enforce_boundaries(x_i, img_shape, dim)

    if compute_gradient:
        return x_1, dphi_dalpha_i
    else:
        return x_1


"""
Implementation based on:
https://www.kaggle.com/c/quora-question-pairs/discussion/33371
"""
import networkx as nx
import pandas as pd

def magic_feature_3_with_load():
    train = pd.read_csv('../data/train.csv', encoding='utf-8')
    test = pd.read_csv('../data/test.csv', encoding='utf-8')
    return magic_feature_3(train, test)

def magic_feature_3(train_orig, test_orig):
    cores_dict = pd.read_csv("../data/question_max_kcores.csv", index_col="qid").to_dict()["max_kcore"]

    def gen_qid1_max_kcore(x):
        return cores_dict[hash(x)]

    def gen_qid2_max_kcore(x):
        return cores_dict[hash(x)]

    #def gen_max_kcore(row):
    #    return max(row["qid1_max_kcore"], row["qid2_max_kcore"])

    train_orig.loc[:, "m3_qid1_max_kcore"] = train_orig.loc[:, 'question1'].apply(gen_qid1_max_kcore)
    test_orig.loc[:, "m3_qid1_max_kcore"] = test_orig.loc[:, 'question1'].apply(gen_qid1_max_kcore)
    train_orig.loc[:, "m3_qid2_max_kcore"] = train_orig.loc[:, 'question2'].apply(gen_qid2_max_kcore)
    test_orig.loc[:, "m3_qid2_max_kcore"] = test_orig.loc[:, 'question2'].apply(gen_qid2_max_kcore)
    #df_train["max_kcore"] = df_train.apply(gen_max_kcore, axis=1)
    #df_test["max_kcore"] = df_test.apply(gen_max_kcore, axis=1)

    return dict(train=train_orig.loc[:, ['m3_qid1_max_kcore', 'm3_qid2_max_kcore']],
                test=test_orig.loc[:, ['m3_qid1_max_kcore', 'm3_qid2_max_kcore']])

def create_qid_dict(train_orig):
    df_id1 = train_orig.loc[:, ["qid1", "question1"]].drop_duplicates(keep="first").copy().reset_index(drop=True)
    df_id2 = train_orig.loc[:, ["qid2", "question2"]].drop_duplicates(keep="first").copy().reset_index(drop=True)

    df_id1.columns = ["qid", "question"]
    df_id2.columns = ["qid", "question"]

    print(df_id1.shape, df_id2.shape)

    df_id = pd.concat([df_id1, df_id2]).drop_duplicates(keep="first").reset_index(drop=True)
    print(df_id1.shape, df_id2.shape, df_id.shape)

    dict_questions = df_id.set_index('question').to_dict()
    return dict_questions["qid"]

def get_id(question, dict_questions):
    if question in dict_questions:
        return dict_questions[question]
    else:
        new_id = len(dict_questions[question]) + 1
        dict_questions[question] = new_id
        return new_id, new_id

def run_kcore():
    df_train = pd.read_csv("../data/train.csv", encoding='utf-8')
    df_test = pd.read_csv("../data/test.csv", encoding='utf-8')
    df_train.loc[:, 'qid1'] = df_train.loc[:, 'question1'].apply(hash)
    df_train.loc[:, 'qid2'] = df_train.loc[:, 'question2'].apply(hash)
    df_test.loc[:, 'qid1'] = df_test.loc[:, 'question1'].apply(hash)
    df_test.loc[:, 'qid2'] = df_test.loc[:, 'question2'].apply(hash)
    df_all = pd.concat([df_train.loc[:, ["qid1", "qid2"]],
                        df_test.loc[:, ["qid1", "qid2"]]], axis=0).reset_index(drop='index')
    print("df_all.shape:", df_all.shape)  # df_all.shape: (2750086, 2)
    df = df_all
    g = nx.Graph()
    g.add_nodes_from(df.qid1)
    edges = list(df.loc[:, ['qid1', 'qid2']].to_records(index=False))
    g.add_edges_from(edges)
    g.remove_edges_from(g.selfloop_edges())

    print(len(set(df.qid1)), g.number_of_nodes())  # 4789604
    print(len(df), g.number_of_edges())  # 2743365 (after self-edges)

    df_output = pd.DataFrame(data=g.nodes(), columns=["qid"])
    print("df_output.shape:", df_output.shape)

    NB_CORES = 20

    for k in range(2, NB_CORES + 1):
        fieldname = "kcore{}".format(k)
        print("fieldname = ", fieldname)
        ck = nx.k_core(g, k=k).nodes()
        print("len(ck) = ", len(ck))
        df_output[fieldname] = 0
        df_output.ix[df_output.qid.isin(ck), fieldname] = k

    df_output.to_csv("../data/question_kcores.csv", index=None)

def run_kcore_max():
    df_cores = pd.read_csv("../data/question_kcores.csv", index_col="qid")
    df_cores.index.names = ["qid"]
    df_cores.loc[:, 'max_kcore'] = df_cores.apply(lambda row: max(row), axis=1)
    df_cores.loc[:, ['max_kcore']].to_csv("../data/question_max_kcores.csv")  # with index

if __name__ == '__main__':
    run_kcore()
    run_kcore_max()


from Position import Position
from random import randint
from Animal import Animal
from copy import copy

class Turtle(Animal):

    def __init__(self, world, position, strength=2):
        super().__init__(world, position, 'dark green', 'Turtle', 1, strength, -1, 1)

    def action(self):
        chance_to_move = randint(1, 100)
        if chance_to_move > 75:
            super().action()

    def collision(self, position):
        organism_on_position = self.get_organism_on_board(position)
        if organism_on_position is not None:
            if organism_on_position.species == self.species:
                self.multiply(organism_on_position)
            else:
                if not self.is_attack_repelled(organism_on_position):
                    organism_on_position.react_on_collision(self)
                else:
                    message = self.species + ' repels ' + organism_on_position.species + \
                              ' on (' + str(position.x) + ',' + str(position.y) + ')'
                    self.add_message_to_log(message)
        else:
            self.move(position)

    def is_attack_repelled(self, opponent):
        return opponent.strength < 5 and opponent.type == 'Animal'

    def react_on_collision(self, attacker):
        position = copy(self.position)
        if not self.is_attack_repelled(attacker):
            super().react_on_collision(attacker)
        else:
            message = self.species + ' repels ' + attacker.species + \
                      ' in defense on (' + str(position.x) + ',' + str(position.y) + ')'
            self.add_message_to_log(message)


import logging
import random
import asyncio
import websockets
import pandas as pd
import numpy as np
import plotly.express as px
import traits
from alleles import *

pd.options.plotting.backend = "plotly"

#Fix population crash issue

#Work on save function, produce population/world snapshots

#Improve data visualization methods

#Improve color genetics complexity

#Balancing

logging.basicConfig(filename='debug1.txt',level=logging.DEBUG, filemode='w')

def shift_list(list):
    item = None
    if len(list) > 0:
        item = list[0]
        del list[0]
    return item

class World:
    def __init__(self):
        self.resource_increment = 50
        self.resource_cap = 500
        self.reset()
    def get_resources(self):
        return self.resources
    def increment(self):
        logging.debug(f'Incrementing world. Resources: {self.resources} + {self.resource_increment} = {self.resources + self.resource_increment}.')
        self.resources += self.resource_increment
        if self.resources > self.resource_cap:
            self.resources = self.resource_cap
            logging.debug(f'Resource count set to cap: {self.resource_cap}')
    def reset(self):
        self.current_time = 0
        self.resources = 500

class Population:
    def __init__(self):
        self.reset()
    def find_by_id(self, id):
        return self.items[id]
    def filter_mature(self, minAge):
        all_organisms = self.get_all()
        by_age = []
        for org in all_organisms:
            if org.age >= minAge:
                by_age.append(org)
        return by_age
    def addOrganism(self, organism):
        self.items[organism.id] = organism
    def nextId(self):
        self.current_id = self.current_id + 1
        return self.current_id
    def get_all(self):
        return list(self.items.values())
    def reset(self):
        self.items = {}
        self.current_id = 0
        self.info = {}

class Organism:
    def __init__(self, alleles, traits, id):
        self.id = id
        self.alleles = alleles
        self.traits = traits
        self.age = 0
        self.has_fed = True
        self.mature_age = 2
        self.max_age = 5
        self.gender = random.randint(0,1)
        for trait in traits:
            trait.attach(self)

    def __getattr__(self, name):
        # return something when requesting an attribute that doesnt exist on this instance
        return None

    def could_breed(self):
        return self.age >= self.mature_age

class SystemManager:

    def time_advance(self, world):
        world.current_time += 1
        logging.debug(f'Time advanced to {world.current_time}')

    def resource_distribute(self, pop, world):
        fitness_list = sorted(pop.get_all(), key=lambda item: item.fitness, reverse = True)
        for org in fitness_list:
            if world.resources > 0:
                org.has_fed = True
                world.resources -= 1
            else:
                logging.debug(f'Organism {org.id} unfed.')
                org.has_fed = False

    def cull(self, pop):
        for org in pop.get_all():
            if org.age >= org.max_age or org.has_fed == False:
                logging.debug(f'Culling Organism: {org.id}. Fed: {org.has_fed}. Age: {org.age}')
                del pop.items[org.id]

    def logPopulation(self, pop, report, world):
        total_red = 0
        total_green = 0
        total_blue = 0
        for organism in pop.items.values():
            report.append(f'{world.current_time},{organism.id},{organism.age},{organism.r},{organism.g},{organism.b}')
            total_red += organism.r
            total_green += organism.g
            total_blue += organism.b
        pop_count = len(pop.get_all())

        pop.info["average_red"] = 0
        pop.info["average_green"] = 0
        pop.info["average_blue"] = 0

        if pop_count > 0:
            pop.info["average_red"] = total_red/pop_count
            pop.info["average_green"] = total_green/pop_count
            pop.info["average_blue"] = total_blue/pop_count

    def calcBreedScore(self, pop):
        logging.debug("calcBreedScore called")
        for organism in pop.items.values():
            organism.breed_score = 100
            organism.breed_score += organism.redness * -0.5 * 50
            if organism.redness == 255:
                organism.breed_score = 0
                logging.debug("Pure red punished (breedScore)")
            else:
                pass
            organism.breed_score += organism.blueness * 0.5 * 50
            if organism.blueness == 255:
                organism.breed_score = 0
                logging.debug("Pure blue punished (breedScore)")
            else:
                pass
            organism.breed_score += organism.greenness * 0 * 50
            if organism.greenness == 255:
                organism.breed_score = 0
                logging.debug("Pure green punished (breedScore)")
            else:
                pass
            random_num = random.randint(0,10)
            if random_num > 7:
                organism.breed_score += random.randint(0,25)
            elif random_num < 3:
                organism.breed_score -= random.randint(0,25)
            else:
                pass
            #logging.debug(f'Organism {organism.id} breed_score: : {organism.breed_score}\n redness: {redness}, greenness: {greenness}, blueness: {blueness}')

    def calcFitness(self, pop):
        for organism in pop.items.values():
            organism.fitness = 100
            organism.fitness += organism.redness * 0.5 * 50
            if organism.redness == 255:
                organism.fitness = 0
                logging.debug("Pure red punished (fitness)")
            else:
                pass
            organism.fitness += organism.blueness * -0.5 * 50
            if organism.blueness == 255:
                organism.fitness = 0
                logging.debug("Pure blue punished (fitness)")
            else:
                pass
            organism.fitness += organism.greenness * 0 * 50
            if organism.greenness == 255:
                organism.fitness = 0
                logging.debug("Pure green punished (fitness)")
            else:
                pass
            random_num = random.randint(0,10)
            if random_num > 7:
                organism.fitness += random.randint(0,25)
            elif random_num < 3:
                organism.fitness -= random.randint(0,25)
            else:
                pass
            #logging.debug(f'Organism {organism.id} fitness: : {organism.fitness}\n redness: {organism.redness}, greenness: {organism.greenness}, blueness: {organism.blueness}')

    def selectPairs(self, pop):
        logging.debug("selectPairs called")
        males = []
        females = []
        for organism in pop.items.values():
            logging.debug(f"selectPairs: organism could breed? {organism.could_breed()}")
            if organism.could_breed():
                if organism.gender == 0:
                    females.append(organism)
                elif organism.gender == 1:
                    males.append(organism)
                else:
                    logging.debug(f'UNEXPECTED GENDER VALUE: {organism.gender}')
        logging.debug(f"{len(males)} males, {len(females)} females")
        pairs = []
        if len(males) >= 1:
            def organism_to_string(org):
                return str(org.id)
            males = sorted(males, key=lambda item: item.breed_score, reverse = True)
            females = sorted(females, key=lambda item: item.breed_score, reverse = True)
            for male in males:
                female0 = shift_list(females)
                if (female0 is not None):
                    pairs.append([male, female0])
                else:
                    break
                female1 = shift_list(females)
                if (female1 is not None):
                    pairs.append([male, female1])
                else:
                    break
                female2 = shift_list(females)
                if (female2 is not None):
                    pairs.append([male, female2])
                else:
                    break

        return pairs

    def mutate(self, organism):
        global mutation_count
        mutation_target = organism.alleles[random.randint(0, len(organism.alleles)-1)]
        organism.alleles.remove(mutation_target)
        possible_alleles = list(filter(lambda allele: allele.type == mutation_target.type, all_alleles))
        possible_alleles.remove(mutation_target)
        mutant_allele = possible_alleles[random.randint(0, len(possible_alleles)-1)]
        organism.alleles.append(mutant_allele)
        mutation_count += 1
        logging.debug(f"Organism {organism.id} mutated. {mutation_target.name} -> {mutant_allele.name}.")

    def breedPair(self, pair, pop):
        logging.debug("breedPair called")
        a = pair[0]
        b = pair[1]
        children_count = 2
        trait_alleles_a = None
        trait_alleles_b = None
        both_alleles = None
        child_alelles = []
        child_traits = []

        # we want to ensure that both parents have compatible traits and alleles for those traits
        # For loop should take list of relevant alleles for each trait, shuffle them, give output.
        # If either parent has a trait the other lacks, abort the whole function and move to next pair.
        for trait in a.traits:
            if not trait in b.traits:
                logging.debug(f"Pairing rejected: Org {b.id} doesnt have trait {trait}")
                return

        for trait in b.traits:
            if not trait in a.traits:
                logging.debug(f"Pairing rejected: Org {a.id} doesnt have trait {trait}")
                return

        for trait in a.traits:
            trait_alleles_a = list(filter(lambda allele: allele.type == trait.allele_type, a.alleles))
            trait_alleles_b = list(filter(lambda allele: allele.type == trait.allele_type, b.alleles))
            both_alleles = trait_alleles_a + trait_alleles_b

            random.shuffle(both_alleles)

            #logging.debug(f"both_alleles length: {len(both_alleles)}")

            for allele in both_alleles[0:2]:
                child_alelles.append(allele)

            child_traits.append(trait)

        child = Organism(child_alelles, child_traits, pop.nextId())

        if random.randint(0,100) == 100:
            self.mutate(child)

        pop.addOrganism(child)

        logging.debug(f"Org {child.id} created. Redness: {child.redness}, R: {child.r}. Greeness: {child.greenness}, G: {child.g}. Blueness: {child.blueness}, B: {child.b}.")

    def incrementAge(self, pop):
        for organism in pop.items.values():
            organism.age += 1

    def Update(self, pop, world):
        # print("manager.Update called")
        # A new breeding season
        logging.debug(f"Population at start of timestep {world.current_time}: {len(pop.get_all())}")
        self.calcFitness(pop)
        self.resource_distribute(pop, world)
        self.incrementAge(pop)
        self.calcBreedScore(pop)
        pairs = self.selectPairs(pop)
        for pair in pairs:
            self.breedPair(pair, pop)
        self.cull(pop)
        logging.debug(f"Population at end of timestep {world.current_time}: {len(pop.get_all())}")
        world.increment()
        self.time_advance(world)

report = []
population_report = ["time,population,average_red,average_green,average_blue"]
pop = Population()
manager = SystemManager()
world = World()
mutation_count = 0

def runSim(count):
    while count > 0:
        logging.debug(f"runSim, calling manager.Update")
        manager.Update(pop, world)
        manager.logPopulation(pop, report, world)
        pop_count = len(pop.get_all())
        population_report.append(f"{world.current_time},{pop_count}, {pop.info['average_red']},{pop.info['average_green']},{pop.info['average_blue']}")
        output = open("output.csv", "wt")
        for item in report:
            output.write(f"{item}\n")
        output.close()

        output = open("population.csv", "wt")
        for item in population_report:
            output.write(f"{item}\n")
        output.close()
        count -= 1
    return population_report

def resetSim():
    initialize()

def initialize():

    FirstOrg = Organism([Coloration_Green, Coloration_Blue], [traits.ColorationOne], pop.nextId())
    SecondOrg = Organism([Coloration_Red, Coloration_Blue], [trait.ColorationOne], pop.nextId())
    ThirdOrg = Organism([Coloration_Blue, Coloration_Blue], [trait.ColorationOne], pop.nextId())
    FourthOrg = Organism([Coloration_Red, Coloration_Red], [trait.ColorationOne], pop.nextId())
    FifthOrg = Organism([Coloration_Green, Coloration_Blue], [trait.ColorationOne], pop.nextId())
    SixthOrg = Organism([Coloration_Red, Coloration_Green], [trait.ColorationOne], pop.nextId())
    SeventhOrg = Organism([Coloration_Green, Coloration_Green], [traits.Coloration], pop.nextId())

    FirstOrg.gender = 1
    SecondOrg.gender = 0

    initial_generation = [FirstOrg, SecondOrg, ThirdOrg, FourthOrg, FifthOrg, SixthOrg, SeventhOrg]

    pop.reset()
    world.reset()

    report.clear()
    population_report.clear()
    population_report.append("time,population,average_red,average_green,average_blue")
    report.append(f'Time,ID,Age,Red,Green,Blue')

    for org in initial_generation:
        pop.addOrganism(org)

def showColors():
    color_frame = pd.read_csv('population.csv', usecols = ['time', 'average_red', 'average_green', 'average_blue'])

    color_frame.plot(x='time', y=['average_blue','average_red','average_green']).show()

def showPop():
    pop_frame = pd.read_csv('population.csv', usecols = ['time', 'population'])

    pop_frame.plot(x='time', y=['population']).show()

async def main():

    initialize()

    # Start the websocket server and run forever waiting for requests
    async with websockets.serve(handleRequest, "localhost", 8765):
        await asyncio.Future()  # run forever

async def handleRequest(websocket, path):
    #reset command is causing an error, probably getting stuck somewhere in resetSim()
    async for message in websocket:
        parts = message.split(",")
        command_name = parts[0]
        logging.debug(f"Got websocket request")
        if command_name == "getPop":
            print("Population count request recieved")
            await websocket.send(f"Population count: {len(pop.get_all())}")
            print("Population count sent")
        elif command_name == "runSim":
            print(f"Incrementing simulation by t={parts[1]}")
            runSim(int(parts[1]))
            await websocket.send(f"Simulation incremented by t={parts[1]}")
        elif command_name == "reset":
            print("Reset command recieved")
            resetSim()
            print("Simulation reset")
            await websocket.send("Simulation reset")
        elif command_name == "showColors":
            showColors()
            await websocket.send("Ok")
        elif command_name == "showPop":
            showPop()
            await websocket.send("Ok")
        elif command_name == "showAll":
            showPop()
            showColors()
            await websocket.send(f"Final population: {len(pop.get_all())}. Final time: {world.current_time}. Number of mutations: {mutation_count}.")
        else:
            await websocket.send("Unknown Command")
            print(f"{message}")

if __name__ == "__main__":
    asyncio.run(main())