# Ex 4.4 - HTTP Server Shell

# TO DO: import modules
import socket
import os

# TO DO: set constants
DEFAULT_URL = "index.html"
REDIRECTION_DICTIONARY = {"imgs\\loading.gif": "/imgs/abstract.jpg", }
FORBIDDEN = ("imgs\\test.jpg",)
IP = "0.0.0.0"
PORT = 80
SOCKET_TIMEOUT = 2
ROOT = "C:\\webroot\\"
HTTP_OK = "HTTP/1.0 200 OK\r\n"
HTTP_ERROR = "HTTP/1.0 500 Internal Server Error\r\n\r\n"
HTTP_NOT_FOUND = "HTTP/1.0 404 Not Found\r\n\r\n"
HTTP_FORBIDDEN = "HTTP/1.0 403 Forbidden\r\n\r\n"
HTTP_REDIRECTION = "HTTP/1.0 302 Found\r\nLocation: "

def get_file_data(filename):
    """ Get data from file """
    file = ROOT + filename

    if os.path.exists(file):
        if filename not in FORBIDDEN:
            read_file = open(file, 'rb')
            data = read_file.read()
            data = ("Content-Length: " + str(len(data)) + "\r\n\r\n").encode() + data
            read_file.close()
            return data
        else:
            return "FORBIDDEN"
    else:
        return "NOT FOUND"

def handle_client_request(resource, client_socket):
    """ Check the required resource, generate proper HTTP response and send to client"""
    # TO DO : add code that given a resource (URL and parameters) generates the proper response
    if resource == '/':
        url = DEFAULT_URL
    else:
        url = resource[1:].replace('/', '\\')

    # TO DO: check if URL had been redirected, not available or other error code. For example:
    if url in REDIRECTION_DICTIONARY:
        # TO DO: send 302 redirection response
        http_header = HTTP_REDIRECTION + REDIRECTION_DICTIONARY.get(url) + "\r\n\r\n"
        client_socket.send(http_header.encode())
        return

    # TO DO: extract requested file type from URL (html, jpg etc)
    request = url.split(".")
    filetype = request[-1]

    if filetype == 'html':
        # TO DO: generate proper HTTP header
        http_header = HTTP_OK + "Content-Type: text/html; charset=utf-8\r\n"
    # TO DO: handle all other headers
    elif filetype == 'css':
        http_header = HTTP_OK + "Content-Type: text/css\r\n"
    elif filetype == 'jpg':
        # TO DO: generate proper jpg header
        http_header = HTTP_OK + "Content-Type: image/jpeg\r\n"
    elif filetype == 'js':
        http_header = HTTP_OK + "Content-Type: text/javascript; charset=UTF-8\r\n"
    elif filetype == 'ico':
        http_header = HTTP_OK + "Content-Type: image/x-icon\r\n"
    else:
        http_header = HTTP_ERROR
        client_socket.send(http_header.encode())
        return
    # TO DO: read the data from the file

    data = get_file_data(url)

    if data == "NOT FOUND":
        http_response = HTTP_NOT_FOUND.encode()
    elif data == "FORBIDDEN":
        http_response = HTTP_FORBIDDEN.encode()
    else:
        http_response = http_header.encode() + data

    client_socket.send(http_response)

def validate_http_request(request):
    """ Check if request is a valid HTTP request and returns TRUE / FALSE and the requested URL """
    # TO DO: write function
    html_request = request.split("\r\n")
    html_request = html_request[0].split(" ")
    if len(html_request) == 3:
        if html_request[0] == "GET" and html_request[2] == "HTTP/1.1":
            return True, html_request[1]
        else:
            return False, ""
    else:
        return False, ""

def handle_client(client_socket):
    """ Handles client requests: verifies client's requests are legal HTTP, calls function to handle the requests """
    print('Client connected')
    while True:
        # TO DO: insert code that receives client request
        client_request = client_socket.recv(1024).decode()
        # ...
        valid_http, resource = validate_http_request(client_request)
        if valid_http:
            print('Got a valid HTTP request')
            handle_client_request(resource, client_socket)
            break
        else:
            print('Error: Not a valid HTTP request')
            http_header = HTTP_ERROR
            client_socket.send(http_header.encode())
            break
    print('Closing connection')
    client_socket.close()

def main():
    # Open a socket and loop forever while waiting for clients
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((IP, PORT))
    server_socket.listen()
    print("Listening for connections on port {}".format(PORT))

    while True:
        client_socket, client_address = server_socket.accept()
        print('New connection received')
        client_socket.settimeout(SOCKET_TIMEOUT)
        try:
            handle_client(client_socket)
        except socket.timeout:
            print("timeout")

if __name__ == "__main__":
    # Call the main handler function
    main()


# Modulos
import scipy.stats as Static
import numpy as np
import tkinter as Tk
import matplotlib.pyplot as plt
from tkinter import *
from tkinter import  ttk
from PIL import Image, ImageTk

########################### DISTRIBUCIONES DISCRETAS ###########################

def Poisson(media):
	# mu: Media
	mu =  float(media.get()) # parametro de forma
	poisson = Static.poisson(mu) # Distribución
	x = np.arange(poisson.ppf(0.01),poisson.ppf(0.99))
	fmp = poisson.pmf(x) # Función de Masa de Probabilidad
	plt.plot(x, fmp, '--')
	plt.vlines(x, 0, fmp, colors='b', lw=5, alpha=0.5)
	plt.title('Distribución Poisson')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show()

def Binomial(proba,num):
	# p: Probabilidad de exito
	# N: Numero de ensayos
	N = int(num.get())
	p = float(proba.get())
	binomial = Static.binom(N, p) # Metodo de scipy.stats que devuelve un probabilidad binomial
	x = np.arange(binomial.ppf(0.01),binomial.ppf(0.99)) #Arreglo del eje de las x desde 0.01 a 0.99
	fmp = binomial.pmf(x) # Función de Masa de Probabilidad sacada desde el arreglo del eje de las x
	plt.plot(x, fmp, '--') # Graficando la distribucion en base a la Funcion de Masa de Probabilidad
	#Personalizacion de la grafica
	plt.vlines(x, 0, fmp, colors='b', lw=5, alpha=0.5)
	plt.title('Distribución Binomial')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show() # Muestra Grafica

def Geometrica(proba):
	# p: Probabilidad de Exito
	p =  float(proba.get()) # parametro de forma
	geometrica = Static.geom(p) # Distribución
	x = np.arange(geometrica.ppf(0.01),geometrica.ppf(0.99))
	fmp = geometrica.pmf(x) # Función de Masa de Probabilidad
	plt.plot(x, fmp, '--')
	plt.vlines(x, 0, fmp, colors='b', lw=5, alpha=0.5)
	plt.title('Distribución Geométrica')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show()

def HiperGeometrica(Me,ne,Ne):
	# n: Conjunto de elementos con exito
	# M: Conjunto Total
	# N: Muestra de N elementos
	n = int(ne.get())
	M = int(Me.get())
	N = int(Ne.get())
	hipergeometrica = Static.hypergeom(M, n, N) # Distribución
	x = np.arange(0, n+1)
	fmp = hipergeometrica.pmf(x) # Función de Masa de Probabilidad
	plt.plot(x, fmp, '--')
	plt.vlines(x, 0, fmp, colors='b', lw=5, alpha=0.5)
	plt.title('Distribución Hipergeométrica')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show()

def Bernoulli():
	# Solo demuestra que hay 50% de exito y 50% de fracaso
	# p: Probabilidad de Exito
	p =  0.5 # parametro de forma
	bernoulli = Static.bernoulli(p)
	x = np.arange(-1, 3)
	fmp = bernoulli.pmf(x) # Función de Masa de Probabilidad
	fig, ax = plt.subplots()
	ax.plot(x, fmp, 'bo')
	ax.vlines(x, 0, fmp, colors='b', lw=5, alpha=0.5)
	ax.set_yticks([0., 0.2, 0.4, 0.6, 0.8, 1])
	plt.title('Distribución Bernoulli')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show()

########################### DISTRIBUCIONES CONTINUAS ###########################

def Normal(media,sig):
	# mu: Media
	# sigma: Desviacion Estandar
	mu = float(media.get())
	sigma = float(sig.get())
	normal = Static.norm(mu, sigma)
	x = np.linspace(normal.ppf(0.01),normal.ppf(0.99), 100)
	fp = normal.pdf(x) # Función de Probabilidad
	plt.plot(x, fp)
	plt.title('Distribución Normal')
	plt.ylabel('Probabilidad')
	plt.xlabel('valores')
	plt.show()

def Uniforme():
	uniforme = Static.uniform()
	x = np.linspace(uniforme.ppf(0.01),uniforme.ppf(0.99), 50)
	fp = uniforme.pdf(x) # Función de Probabilidad
	fig, ax = plt.subplots()
	ax.plot(x, fp, '--')
	ax.vlines(x, 0, fp, colors='b', lw=5, alpha=0.5)
	ax.set_yticks([0., 0.2, 0.4, 0.6, 0.8, 1., 1.2])
	plt.title('Distribución Uniforme')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show()

def Exponencial():
	# No recibe parametros
	exponencial = Static.expon()
	x = np.linspace(exponencial.ppf(0.01),exponencial.ppf(0.99), 100)
	fp = exponencial.pdf(x) # Función de Probabilidad
	plt.plot(x, fp)
	plt.title('Distribución Exponencial')
	plt.ylabel('Probabilidad')
	plt.xlabel('Valores')
	plt.show()

########################### DISTRIBUCIONES INFO ###########################

def InfoPoi():
	Ventana1 = Tk()
	Ventana1.title("Distribución Poisson")
	Ventana1.geometry("980x400")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/poi.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Ventana1.mainloop()

def InfoBi():
	Ventana1 = Tk()
	Ventana1.title("Distribución Binomial")
	Ventana1.geometry("968x282")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/bi.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Ventana1.mainloop()

def InfoGeo():
	Ventana1 = Tk()
	Ventana1.title("Distribución Geométrica")
	Ventana1.geometry("960x310")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/geo.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Ventana1.mainloop()

def InfoHiper():
	Ventana1 = Tk()
	Ventana1.title("Distribución Hipergeométrica")
	Ventana1.geometry("985x535")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/hiper.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Ventana1.mainloop()

def InfoNor():
	Ventana1 = Tk()
	Ventana1.title("Distribución Normal")
	Ventana1.geometry("965x290")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/nor.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Ventana1.mainloop()

def InfoBer():
	Ventana1 = Tk()
	Ventana1.title("Distribución Bernoulli")
	Ventana1.geometry("964x345")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/ber.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Bernoulli()
	Ventana1.mainloop()

def InfoUni():
	Ventana1 = Tk()
	Ventana1.title("Distribución Uniforme")
	Ventana1.geometry("730x445")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/uni.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Uniforme()
	Ventana1.mainloop()

def InfoExp():
	Ventana1 = Tk()
	Ventana1.title("Distribución Exponencial")
	Ventana1.geometry("960x284")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/exp.png")
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=0,y=0)
	Exponencial()
	Ventana1.mainloop()

########################### PESTANAS DE LA GUI ###########################

def Pois(Poi):
	titulo = Label(Poi,text="Distribución Poisson",font=("Arial",24)).place(x=40,y=15)
	consi = Label(Poi,text="Valores para su funcionamiento son números enteros o reales").place(x=40,y=55)
	info = Button(Poi,text="Info",command=InfoPoi).place(x=490,y=20)
	media = StringVar()
	media.set("3.6")
	etiqueta = Label(Poi,text="Media (μ): ").place(x=80,y=110)
	entrada = Entry(Poi,width=10,textvariable= media).place(x=160,y=110)
	#Intento de Atrapar excepcion
	try:
		float(media.get())
	except Exception as e:
		error = Label(Poi,text="Error").place(x=10,y=10)
	else:
		btn = Button(Poi,text="Graficar",command=lambda : Poisson(media)).place(x=300,y=105) #Para pasar argumentos en una funcion

def Bino(Bi):
	titulo = Label(Bi,text="Distribución Binomial",font=("Arial",24)).place(x=40,y=0)
	consi = Label(Bi,text="Valores para su funcionamiento son números: ").place(x=40,y=35)
	co = Label(Bi,text=" -Reales entre 1 y 0 para la probabilidad").place(x=40,y=55)
	c = Label(Bi,text=" -Enteros para el número de ensayos").place(x=40,y=75)
	info = Button(Bi,text="Info",command=InfoBi).place(x=490,y=20)
	proba = StringVar()
	proba.set("0.4")
	etiqueta = Label(Bi,text="Probabilidad de Éxito: ").place(x=60,y=110)
	entrada = Entry(Bi,width=10,textvariable= proba).place(x=210,y=110)
	num = StringVar()
	num.set("30")
	etiqueta2 = Label(Bi,text="Numero de Ensayos: ").place(x=60,y=140)
	entrada2 = Entry(Bi,width=10,textvariable= num).place(x=210,y=140)
	btn = Button(Bi,text="Graficar",command=lambda : Binomial(proba,num)).place(x=360,y=120) #Para pasar argumentos en una funcion

def Geo(Geome):
	titulo = Label(Geome,text="Distribución Geométrica",font=("Arial",24)).place(x=40,y=15)
	consi = Label(Geome,text="Valores para su funcionamiento son números reales entre 1 y 0").place(x=40,y=55)
	info = Button(Geome,text="Info",command=InfoGeo).place(x=490,y=20)
	proba = StringVar()
	proba.set("0.3")
	etiqueta = Label(Geome,text="Probabilidad de Éxito: ").place(x=40,y=100)
	entrada = Entry(Geome,width=10,textvariable= proba).place(x=180,y=100)
	btn = Button(Geome,text="Graficar",command=lambda : Geometrica(proba)).place(x=310,y=95) #Para pasar argumentos en una funcion

def HiperGeo(Hiper):
	#Titulo e info
	titulo = Label(Hiper,text="Distribución Hipergeométrica",font=("Arial",24)).place(x=40,y=15)
	consi = Label(Hiper,text="Valores para su funcionamiento son números enteros").place(x=40,y=55)
	info = Button(Hiper,text="Info",command=InfoHiper).place(x=490,y=20)

	M = StringVar()
	M.set("30")
	etiqueta = Label(Hiper,text="Conjunto Total: ").place(x=60,y=80)
	entrada = Entry(Hiper,width=10,textvariable= M).place(x=210,y=80)
	n = StringVar()
	n.set("12")
	etiqueta2 = Label(Hiper,text="Conjunto de Éxitos: ").place(x=60,y=110)
	entrada2 = Entry(Hiper,width=10,textvariable= n).place(x=210,y=110)
	N = StringVar()
	N.set("10")
	etiqueta3 = Label(Hiper,text="Conjunto Muestra: ").place(x=60,y=140)
	entrada3 = Entry(Hiper,width=10,textvariable= N).place(x=210,y=140)
	btn = Button(Hiper,text="Graficar",command=lambda : HiperGeometrica(M,n,N)).place(x=360,y=105) #Para pasar argumentos en una funcion

def Normalita(No):
	titulo = Label(No,text="Distribución Normal",font=("Arial",24)).place(x=40,y=15)
	consi = Label(No,text="Valores para su funcionamiento son números reales y/o enteros").place(x=40,y=55)
	info = Button(No,text="Info",command=InfoNor).place(x=490,y=20)
	media = StringVar()
	media.set("0")
	etiqueta = Label(No,text="Media (μ): ").place(x=60,y=100)
	entrada = Entry(No,width=10,textvariable= media).place(x=210,y=100)
	sigma = StringVar()
	sigma.set("0.2")
	etiqueta2 = Label(No,text="Desviación Estándar: ").place(x=60,y=130)
	entrada2 = Entry(No,width=10,textvariable= sigma).place(x=210,y=130)
	btn = Button(No,text="Graficar",command=lambda : Normal(media,sigma)).place(x=360,y=110) #Para pasar argumentos en una funcion

def NA_Para(NA):
	titulo = Label(NA,text="Distribuciones",font=("Arial",24)).place(x=190,y=15)
	consi = Label(NA,text="Para ver el comportamiento de las distribuciones pulse el botón correspondiente").place(x=40,y=55)
	Berno = Button(NA,text="Bernoulli",command=InfoBer).place(x=20,y=100)
	Uni = Button(NA,text="Uniforme",command=InfoUni).place(x=245,y=100)
	Exp = Button(NA,text="Exponencial",command=InfoExp).place(x=450,y=100)

########################### CREDITOS ###########################

def Creditos():
	Ventana1 = Tk()
	Ventana1.title("Créditos")
	Ventana1.geometry("500x200")
	Ventana1.resizable(width=False,height=False)
	im = Image.open("Info/proteco.png")
	im = im.resize((100,100),Image.ANTIALIAS)
	ph = ImageTk.PhotoImage(im,master=Ventana1)
	label = Label(Ventana1,image=ph).place(x=20,y=20)
	MARIO = Label(Ventana1,text="Mario Alberto Vásquez Cancino ").place(x=140,y=35)
	MARIO1 = Label(Ventana1,text="Becario PROTECO Generación 37").place(x=160,y=55)
	MARIO2 = Label(Ventana1,text="Unánse al programa está super padre :)").place(x=140,y=75)
	PROTECO = Label(Ventana1,text="Info en Facebook: Proteco").place(x=160,y=95)

	RAUL = Label(Ventana1,text="Agradecimientos especiales a Raul E. Lopez Briega:").place(x=20,y=140)
	RAUL1 = Label(Ventana1,text="-Por tan buen blog, base para poder realizar este programa.").place(x=40,y=160)
	Ventana1.mainloop()

########################### PESTANA DE BIENVENIDA ###########################

def Welcome(Bienvenido):
	titulo = Label(Bienvenido,text="Bienvenido",font=("Arial",24)).place(x=40,y=15)
	consi = Label(Bienvenido,text="Este programa educativo y de licencia libre, te permitirá descubrir el compor-").place(x=40,y=55)
	consi1 = Label(Bienvenido,text="tamiento de algunas de las distribuciones más importantes de probabilidad").place(x=40,y=75)
	consi2 = Label(Bienvenido,text="y estadística.").place(x=40,y=95)
	enjoy = Label(Bienvenido,text="Disfrútalo",font=("Verdana",20)).place(x=40,y=120)
	cre = Button(Bienvenido,text="Créditos",command=Creditos).place(x=470,y=128)

########################### GUI ###########################

Ventana = Tk()
Ventana.title("Distribuciones de Probabilidad")
Ventana.geometry("573x200")
Ventana.resizable(width=False,height=False)
Pestanas = ttk.Notebook(Ventana)
Pestanas.pack(fill="both",expand="yes") #Las ventanas se van a expandir en toda la ventana

#Creando pestanas
Bienvenido = ttk.Frame(Pestanas)
Poi = ttk.Frame(Pestanas)
Bi = ttk.Frame(Pestanas)
Geome = ttk.Frame(Pestanas)
Hiper = ttk.Frame(Pestanas)
No = ttk.Frame(Pestanas)
NA = ttk.Frame(Pestanas)
Pestanas.add(Bienvenido,text="Bienvenido")
Pestanas.add(Poi,text="Poisson")
Pestanas.add(Bi,text="Binomial")
Pestanas.add(Geome,text="Geométrica")
Pestanas.add(Hiper,text="Hipergeométrica")
Pestanas.add(No,text="Normal")
Pestanas.add(NA,text="Sin Parámetros")

Welcome(Bienvenido)
Pois(Poi)
Bino(Bi)
Geo(Geome)
HiperGeo(Hiper)
Normalita(No)
NA_Para(NA)

Ventana.mainloop()


import random

import heapq
from typing import Dict, Tuple, List

import numpy as np

from agents.agent import Agent
from pyrat.definitions import position, MazeGraph
from pyrat.components import State

RouteMap = Dict[position, position]
DistanceMap = Dict[position, int]

MOVE_DOWN = 'D'
MOVE_LEFT = 'L'
MOVE_RIGHT = 'R'
MOVE_UP = 'U'

char_to_index: Dict[str, int] = {
    'R': 0,
    'L': 1,
    'U': 2,
    'D': 3
}

index_to_char: Dict[int, str] = {
    0: 'R',
    1: 'L',
    2: 'U',
    3: 'D'
}

class GreedyAgent(Agent):

    def prepare(self, state: State):
        pass

    def act(self, state: State, exploration_rate: float=0.0) -> str:

        if np.random.rand() < exploration_rate:
            return index_to_char[random.randrange(4)]

        # We use Dijkstra's algorithm from the current location
        (routes, distances) = self.dijkstra(state.maze.graph, state.player_info.current_position)

        # We find the closest pieces of cheese using the distances
        closestPieceOfCheese = self.findClosestPieceOfCheese(distances, state.cheese_list)

        # Using the routes, we find the next move
        resultMoves = self.pathToMoves(self.routesToPath(routes, closestPieceOfCheese))

        return resultMoves[0]

    def locationsToMove(self, location1: position, location2: position) -> str:
        difference = (location2[0] - location1[0], location2[1] - location1[1])
        if difference == (-1, 0):
            return MOVE_LEFT
        elif difference == (1, 0):
            return MOVE_RIGHT
        elif difference == (0, 1):
            return MOVE_UP
        elif difference == (0, -1):
            return MOVE_DOWN
        else:
            raise Exception("Invalid location provided")

    def dijkstra(self, mazeMap: MazeGraph, initialLocation: position) -> Tuple[RouteMap, DistanceMap]:
        minHeap: List[Tuple[int, position, position]] = [(0, initialLocation, None)]
        distances: DistanceMap = {}
        routes: RouteMap = {}

        # Main loop
        while len(minHeap) != 0:
            (distance, location, predecessor) = heapq.heappop(minHeap)
            if location not in distances:
                distances[location] = distance
                routes[location] = predecessor
                for neighbor in mazeMap[location]:
                    newDistanceToNeighbor = distance + mazeMap[location][neighbor]
                    heapq.heappush(minHeap, (newDistanceToNeighbor, neighbor, location))

        # Result
        return (routes, distances)

    def routesToPath(self, routes: RouteMap, targetNode: position) -> List[position]:
        # Recursive reconstruction
        if not targetNode:
            return []
        elif targetNode in routes:
            return self.routesToPath(routes, routes[targetNode]) + [targetNode]
        else:
            raise Exception("Impossible to reach target")

    def pathToMoves(self, path: List[position]) -> List[str]:
        # Recursive reconstruction
        if len(path) <= 1:
            return []
        else:
            return [self.locationsToMove(path[0], path[1])] + self.pathToMoves(path[1:])

    def findClosestPieceOfCheese(self, distances: DistanceMap, piecesOfCheese: List[position]) -> position:
        # We return the cheese associated with the minimum distance
        distancesToCheese = {cheese: distances[cheese] for cheese in piecesOfCheese}
        return min(distancesToCheese, key=distancesToCheese.get)


import requests
from bs4 import BeautifulSoup

# 得到每个offset值
def off_set():
    offset = 18
    # 先取99个ajax，
    for i in range(1,100):
        if i == 1:
            parse_url(offset)
        else:
            offset = limit + offset
            parse_url(offset)

# 将得到的offset传入
def parse_url(offset):
    # 带参传递
    data = {
        'retrieve_type':'by_subject',
        'limit':'20',
        'offset':offset
    }
    # 请求这个ajax地址
    response = requests.get(start_ajax,params=data,headers=headers)
    # 得到的数据是个json格式，所以用requests自带的json函数来解析它
    ajax_data=response.json()
    # 解析得到每篇文章的url，因为ajax是个字典格式，而其中result的值却是个列表，所以要用[0]取出
    lst=ajax_data['result']
    for i in lst:
        url = i['url']
        print(url)
        parse(url)

def parse(url):
    html = requests.get(url,headers=headers)
    html = html.text
    soup = BeautifulSoup(html,'lxml')
    data = soup.find_all('div',class_='content-th')
    for i in data:
        title = i.find_all('a')[0].text
        name = i.find_all('h1')[0].text.split()[0]
        zuoze = i.find_all('div','content-th-info')[0].find_all('a')[0].text
        time = i.find_all('div','content-th-info')[0].find_all('meta')[0]['content']
        print('{}\t\t{}\t\t{}\t\t{}'.format(title,name,zuoze,time))

if __name__ == '__main__':
    start_ajax = 'https://www.guokr.com/apis/minisite/article.json?'
    headers = {
        'User-Agent': 'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)', }
    # 每个offset都是以18为基数，每次叠加20
    limit = 20
    off_set()


# Weight converter 1.0

def weight_converter(x, cha):
    if cha == "K":
        converted = float(x) * 2.205
        print(f"Your weight is: {str(converted)} lbs")
    elif cha == "L":
        converted = float(x) / 2.205
        print(f"Your weight is: {str(converted)} kg")
    else:
        print("Please enter 'l' for lbs or 'k' for kg")

def emoji_converter(text):
    words = text.split(" ")
    emojis = {
        ":)": "ЪЎѓ",
        ":(": "Рў╣№ИЈ",
        "(:": "ЪЎЃ",
        ";)": "ЪўЅ",
        "┬»\_(сЃё)_/┬»": "Ъци"
    }
    output = ""
    for word in words:
        output += emojis.get(word, word) + " "
    return output

user_weight = input("Please enter your weight:\n> ")
unit = input("lbs (l) or kg (k)?\n> ")
upper_unit = unit.upper()
weight_converter(user_weight, upper_unit)
print("*" * 36)
comment = input("Enter your text here\n> ")
print(emoji_converter(comment))
print("*" * 36)


import torch
import numpy as np
import pytorch_lightning as pl
from torch import nn
from sklearn.metrics import r2_score

class SequentialAutoencoder(pl.LightningModule):
    def __init__(self,
                 input_size=29,
                 hidden_size=50,
                 learning_rate=1e-3,
                 weight_decay=1e-4,
                 rate_conversion_factor=0.05,
                 dropout=0.1):
        super().__init__()
        self.save_hyperparameters()
        # Instantiate bidirectional GRU encoder
        self.encoder = nn.GRU(
            input_size=input_size,
            hidden_size=hidden_size,
            batch_first=True,
            bidirectional=True,
        )
        # Instantiate linear mapping to initial conditions
        self.ic_linear = nn.Linear(2*hidden_size, hidden_size)
        # Instantiate autonomous GRU decoder
        self.decoder = nn.GRU(
            input_size=1, # Not used
            hidden_size=hidden_size,
            batch_first=True,
        )
        # Instantiate linear readout
        self.readout = nn.Linear(
            in_features=hidden_size,
            out_features=input_size,
        )
        # Instantiate dropout
        self.dropout = nn.Dropout(p=dropout)

    def forward(self, x):
        # Interpolate NaNs with zeros
        x = torch.nan_to_num(x, nan=0.0)
        # Pass data through the model
        _, h_n = self.encoder(x)
        # Combine output from fwd and bwd encoders
        h_n = torch.cat([*h_n], -1)
        # Compute initial condition
        h_n_drop = self.dropout(h_n)
        ic = self.ic_linear(h_n_drop)
        # Create an empty input tensor
        input_placeholder = torch.zeros_like(x)[:, :, :1]
        # Unroll the decoder
        ic_drop = self.dropout(ic)
        latents, _ = self.decoder(input_placeholder, torch.unsqueeze(ic_drop, 0))
        # Map decoder state to logrates
        logrates = self.readout(latents)
        return logrates

    def configure_optimizers(self):
        optimizer = torch.optim.Adam(
            self.parameters(),
            lr=self.hparams.learning_rate,
            weight_decay=self.hparams.weight_decay,
        )
        return optimizer

    def training_step(self, batch, batch_ix):
        x, truth = batch
        # Keep track of location of observed data
        mask = ~torch.isnan(x)
        # Pass data through the model
        logrates = self.forward(x)
        # Mask unobserved steps
        x_obs = torch.masked_select(x, mask)
        logrates_obs = torch.masked_select(logrates, mask)
        # Compute Poisson log-likelihood
        loss = nn.functional.poisson_nll_loss(logrates_obs, x_obs)
        self.log('train_loss', loss, on_epoch=True)
        self.log('train_nll', loss, on_epoch=True)
        # Compute match to true rates
        truth = truth.detach().cpu().numpy()
        rates = torch.exp(logrates).detach().cpu().numpy()
        rates *= self.hparams.rate_conversion_factor
        truth = np.concatenate([*truth])
        rates = np.concatenate([*rates])
        r2 = r2_score(truth, rates)
        self.log('train_r2', r2, on_epoch=True)
        return loss

    def validation_step(self, batch, batch_ix):
        x, truth = batch
        # Keep track of location of observed data
        mask = ~torch.isnan(x)
        # Pass data through the model
        logrates = self.forward(x)
        # Mask unobserved steps
        x_obs = torch.masked_select(x, mask)
        logrates_obs = torch.masked_select(logrates, mask)
        # Compute Poisson log-likelihood
        loss = nn.functional.poisson_nll_loss(logrates_obs, x_obs)
        self.log('valid_loss', loss, on_epoch=True)
        self.log('valid_nll', loss, on_epoch=True)
        truth = truth.detach().cpu().numpy()
        rates = torch.exp(logrates).detach().cpu().numpy()
        rates *= self.hparams.rate_conversion_factor
        truth = np.concatenate([*truth])
        rates = np.concatenate([*rates])
        r2 = r2_score(truth, rates)
        self.log('valid_r2', r2, on_epoch=True)
        return loss


import warnings
import random
from typing import List

import numpy as np
from scipy.stats import beta

from src.operators_utils.Operator import Operator
from src.statistics_utils.Statistics import Statistics
from src.strategies_utils.AdaptiveStrategy import AdaptiveStrategy
from src.strategies_utils.StatisticalStrategy import StatisticalStrategy

class EpsilonGreedy(AdaptiveStrategy):
    def __init__(self, arms: List[Operator], epsilon: float):
        assert 0 <= epsilon <= 1, 'Error: the epsilon parameter for EpsilonGreedy class has to be in [0, 1]'
        super(EpsilonGreedy, self).__init__('eps-greedy-' + str(epsilon), arms)

        self.epsilon = epsilon

    def with_probability_epsilon(self):
        return random.random() < self.epsilon

    def choose_operator_id(self):
        self.probabilities = [self.epsilon for _ in range(self.arms_num)]
        self.probabilities[np.argmax(self.rewards)] = 1 - self.epsilon

        if self.with_probability_epsilon():
            return np.random.randint(0, self.arms_num)
        else:
            return np.argmax(self.rewards)

class UCB1(AdaptiveStrategy):
    def __init__(self, arms: List[Operator]):
        super(UCB1, self).__init__('UCB1', arms)

    def choose_operator_id(self):
        if self.t < self.arms_num:
            return self.t

        arm_id = np.argmax([
            mu_i + np.sqrt(2 * np.log(self.t) / self.pulls[i])
            for i, mu_i in enumerate(self.rewards)
        ])

        self.probabilities = [0 for _ in range(self.arms_num)]
        self.probabilities[arm_id] = 1

        return arm_id

class Softmax(AdaptiveStrategy):
    def __init__(self, arms: List[Operator], tau: float):
        assert tau >= 0, 'Error: the tau parameter for Softmax class has to be in [0, inf]'
        super(Softmax, self).__init__('softmax-' + str(tau), arms)

        self.tau = tau

    def choose_operator_id(self):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")

            normalization_factor = np.sum([np.exp(mu_j / self.tau) for mu_j in self.rewards])

            probabilities = np.array([
                np.exp(mu_i / self.tau) / normalization_factor
                for mu_i in self.rewards
            ])

            self.probabilities = list(probabilities)

            arm_id = np.random.choice(
                a=[i for i in range(self.arms_num)],
                p=self.probabilities
            )

            return arm_id

class Thompson(AdaptiveStrategy):
    def __init__(self, arms: List[Operator]):
        super(Thompson, self).__init__('thompson', arms)

    def choose_operator_id(self):
        beta_params = zip(self.rewards, self.losses)

        all_draws = [beta.rvs(i[0], i[1], size=1) for i in beta_params]

        self.probabilities = [0 for _ in range(self.arms_num)]
        self.probabilities[all_draws.index(max(all_draws))] = 1

        return all_draws.index(max(all_draws))

class S_n(StatisticalStrategy):
    def __init__(self, operators: List[Operator]):
        super(S_n, self).__init__('s_n', operators, [0.25, 0.25, 0.25, 0.25])

class Random(StatisticalStrategy):
    def __init__(self, operators: List[Operator]):
        super(Random, self).__init__('random', operators, [1 / len(operators) for _ in operators])

class S_fn(StatisticalStrategy):
    def __init__(self, operators: List[Operator]):
        super(S_fn, self).__init__('s_fn', operators, [0.4435, 0.1233, 0.2152, 0.218])

def normalize(raw):
    return [float(i)/sum(raw) for i in raw]

class S_v(StatisticalStrategy):
    def __init__(self, operators: List[Operator], statistics: Statistics):
        super(S_v, self).__init__('s_v', operators,
                                  normalize([statistics.operator_statistics(operator_id)['v'] /
                                             statistics.operator_statistics(operator_id)['t']
                                             for operator_id, _ in enumerate(operators)]))

class S_f(StatisticalStrategy):
    def __init__(self, operators: List[Operator], statistics: Statistics):
        super(S_f, self).__init__('s_f', operators,
                                  normalize([statistics.operator_statistics(operator_id)['f']
                                             for operator_id, _ in enumerate(operators)]))

class S_pool(StatisticalStrategy):
    def __init__(self, operators: List[Operator], statistics: Statistics):
        super(S_pool, self).__init__('s_pool', operators,
                                     normalize([statistics.operator_statistics(operator_id)['is_in_pool']
                                                for operator_id, _ in enumerate(operators)]))

class S_best(StatisticalStrategy):
    def __init__(self, operators: List[Operator], statistics: Statistics):
        super(S_best, self).__init__('s_best', operators,
                                     normalize([statistics.operator_statistics(operator_id)['was_best']
                                                for operator_id, _ in enumerate(operators)]))

class Pure(StatisticalStrategy):
    def __init__(self, operator: Operator):
        super(Pure, self).__init__('pure-' + str(operator.short_name), [operator], [1])


# makedata.py  Make a file of simulated behavioural data

import numpy as np
import scipy.stats

# set parameters
ntrials = 200
stimlevels = np.linspace(-1.0, 1.0, 10)
sigma = 0.5

# make simulated data
trialnum = np.arange(ntrials)
stim = np.random.choice(stimlevels, size=ntrials)
pcorrect = scipy.stats.norm.cdf(stim, loc=0.0, scale=sigma)
correct = np.random.binomial(1,pcorrect)
rt = 0.100 + (np.random.normal(size=ntrials) ** 2)

# write simulated data to a text file
data = np.column_stack((trialnum,stim,correct,rt))
np.savetxt('data.txt',data,fmt=('%3d,%7.4f,%d,%6.4f'))


from distutils.command.config import config
import json
from pathlib import Path
from typing import Any, List

import pytest
from unitunes.matcher import DefaultMatcherStrategy
from unitunes.searcher import DefaultSearcherStrategy
from unitunes.services.services import Pushable, cache
from unitunes.services.beatsaber import (
    BeatsaberConfig,
    BeatsaberService,
    BeatsaverAPIWrapper,
)

from tests.conftest import cache_path
from unitunes.track import AliasedString, Track
from unitunes.uri import BeatsaberPlaylistURI, BeatsaberTrackURI

@pytest.fixture
def beatsaver_api_wrapper() -> BeatsaverAPIWrapper:
    return BeatsaverAPIWrapper(cache_path)

def test_get_map(beatsaver_api_wrapper: BeatsaverAPIWrapper):
    map = beatsaver_api_wrapper.map("27b65")
    assert map["id"] == "27b65"

    expected = {
        "id": "27b65",
        "name": "My Hero (TV Size) [Inuyashiki Opening] - MAN WITH A MISSION",
        "description": "Thanks to https://twitter.com/kitsunesoba1 for the special request!\n\nGameplay preview:\nhttps://youtu.be/uLcGgJEOGuQ\n\nMy Hero is the opening theme song of the Inuyashiki anime series, performed by the Japanese rock band Man with a Mission.\n\nKeep up to date on my maps: https://twitter.com/Joetastic_\nMy mapper's profile: https://bsaber.com/members/joetastic/\nContact me on discord: @Joetastic#2501\n\nEDIT:  Fixed a small inconsistency on E+",
        "uploader": {
            "id": 58338,
            "name": "Joetastic",
            "hash": "5cff0b7498cc5a672c85050e",
            "avatar": "https://cdn.beatsaver.com/avatar/227767566402191360.png",
            "type": "DISCORD",
            "curator": True,
            "verifiedMapper": True,
        },
        "metadata": {
            "bpm": 180,
            "duration": 92,
            "songName": "My Hero (TV Size)",
            "songSubName": "",
            "songAuthorName": "MAN WITH A MISSION",
            "levelAuthorName": "Joetastic",
        },
        "stats": {
            "plays": 0,
            "downloads": 0,
            "upvotes": 32,
            "downvotes": 1,
            "score": 0.8072,
        },
        "uploaded": "2022-07-12T18:40:15.270804Z",
        "automapper": False,
        "ranked": False,
        "qualified": False,
        "createdAt": "2022-07-12T18:40:04.134607Z",
        "updatedAt": "2022-07-12T19:14:09.477843Z",
        "lastPublishedAt": "2022-07-12T19:14:09.477843Z",
        "tags": ["j-rock", "anime", "balanced"],
    }
    assert expected.items() <= map.items()

def test_search_wrapper(beatsaver_api_wrapper: BeatsaverAPIWrapper):
    results = beatsaver_api_wrapper.search("my hero MAN WITH A MISSION", 0)
    first = results[0]
    assert len(results) > 1
    assert first["name"] == "My Hero - MAN WITH A MISSION ( Inuyashiki OP )"

    results = beatsaver_api_wrapper.search(
        "my hero MAN WITH A MISSION", 0, search_config={"minNps": 10}
    )
    # print(results)
    assert len(results) == 0

@pytest.fixture
def empty_dir():
    dir = Path("tests") / "test_bplists"
    dir.mkdir(exist_ok=True)
    assert dir.exists()

    yield dir

    dir.rmdir()

@pytest.fixture
def populated_dir(empty_dir: Path):
    raw = {
        "playlistTitle": "Bass House Music Pack",
        "playlistAuthor": "alphabeat",
        "playlistDescription": "A description",
        "image": "truncated47318904732189047201",
        "customData": {
            "syncURL": "https://api.beatsaver.com/playlists/id/7015/download"
        },
        "songs": [
            {
                "key": "27bfe",
                "hash": "24800f88b15041713940163bebaf344df0775471",
                "songName": "[Alphabeat - Bass House Pack] Cheyenne Giles - Jump Around",
            },
            {
                "key": "27ca1",
                "hash": "c07dfcec4114f36cd686273e8cd99f94651009d8",
                "songName": "[Alphabeat - Bass House Pack] Rootkit - Levitate",
            },
        ],
    }
    file = empty_dir / "bass_house_music_pack.bplist"
    file.write_text(json.dumps(raw, indent=4))

    yield empty_dir

    file.unlink()

@pytest.fixture
def Beatsaber(populated_dir: Path):
    config = BeatsaberConfig(dir=populated_dir.absolute())
    return BeatsaberService("beatsaber", config, cache_path)

def test_pull_track(Beatsaber: BeatsaberService):
    track = Beatsaber.pull_track(BeatsaberTrackURI.from_uri("27b65"))
    assert track.name.value == "My Hero (TV Size)"
    assert track.artists[0].value == "MAN WITH A MISSION"

def test_search(Beatsaber: BeatsaberService):
    searcher = DefaultSearcherStrategy(DefaultMatcherStrategy())
    query_track = Track(
        name=AliasedString("My Hero"), artists=[AliasedString("MAN WITH A MISSION")]
    )
    results = searcher.search(Beatsaber, query_track, 3)
    assert len(results) > 0
    assert results[0].artists[0].value == "MAN WITH A MISSION"
    assert "My Hero" in results[0].name.value

def test_get_playlist_metadatas(Beatsaber: BeatsaberService):
    metas = Beatsaber.get_playlist_metadatas()
    assert len(metas) == 1
    assert metas[0].name == "Bass House Music Pack"
    assert metas[0].description == "A description"
    assert metas[0].uri.uri == "bass_house_music_pack.bplist"

def test_pull_tracks(Beatsaber: BeatsaberService):
    tracks = Beatsaber.pull_tracks(
        BeatsaberPlaylistURI.from_uri("bass_house_music_pack.bplist")
    )
    assert len(tracks) == 2
    assert tracks[0].name.value == "Jump Around"
    assert tracks[1].name.value == "Levitate"

def test_add_remove_tracks(Beatsaber: BeatsaberService):
    playlist = BeatsaberPlaylistURI.from_uri("bass_house_music_pack.bplist")
    track = Track(
        name=AliasedString("My Hero"),
        artists=[AliasedString("MAN WITH A MISSION")],
        uris=[BeatsaberTrackURI.from_uri("27b65")],
    )
    Beatsaber.add_tracks(playlist, [track])
    assert len(Beatsaber.pull_tracks(playlist)) == 3

    Beatsaber.remove_tracks(playlist, [track])
    assert len(Beatsaber.pull_tracks(playlist)) == 2

def test_protocols(Beatsaber: BeatsaberService):
    assert isinstance(Beatsaber, Pushable)


import gamelib
import random
import math
import warnings
from sys import maxsize
import json

"""
Most of the algo code you write will be in this file unless you create new
modules yourself. Start by modifying the 'on_turn' function.

Advanced strategy tips:

  - You can analyze action frames by modifying on_action_frame function

  - The GameState.map object can be manually manipulated to create hypothetical
  board states. Though, we recommended making a copy of the map to preserve
  the actual current map state.
"""

class AlgoStrategy(gamelib.AlgoCore):
    def __init__(self):
        super().__init__()
        seed = random.randrange(maxsize)
        random.seed(seed)
        gamelib.debug_write('Random seed: {}'.format(seed))

    def on_game_start(self, config):
        """
        Read in config and perform any initial setup here
        """
        gamelib.debug_write('Configuring your custom algo strategy...')
        self.config = config
        global WALL, SUPPORT, TURRET, SCOUT, DEMOLISHER, INTERCEPTOR, MP, SP
        WALL = config["unitInformation"][0]["shorthand"]
        SUPPORT = config["unitInformation"][1]["shorthand"]
        TURRET = config["unitInformation"][2]["shorthand"]
        SCOUT = config["unitInformation"][3]["shorthand"]
        DEMOLISHER = config["unitInformation"][4]["shorthand"]
        INTERCEPTOR = config["unitInformation"][5]["shorthand"]
        MP = 1
        SP = 0
        # This is a good place to do initial setup
        self.scored_on_locations = []

    def on_turn(self, turn_state):
        """
        This function is called every turn with the game state wrapper as
        an argument. The wrapper stores the state of the arena and has methods
        for querying its state, allocating your current resources as planned
        unit deployments, and transmitting your intended deployments to the
        game engine.
        """
        game_state = gamelib.GameState(self.config, turn_state)

        gamelib.debug_write('Performing turn {} of your custom algo strategy'.format(game_state.turn_number))
        game_state.suppress_warnings(True)  #Comment or remove this line to enable warnings.

        self.starter_strategy(game_state)

        game_state.submit_turn()

    """
    NOTE: All the methods after this point are part of the sample starter-algo
    strategy and can safely be replaced for your custom algo.
    """

    def starter_strategy(self, game_state):
        """
        For defense we will use a spread out layout and some interceptors early on.
        We will place turrets near locations the opponent managed to score on.
        For offense we will use long range demolishers if they place stationary units near the enemy's front.
        If there are no stationary units to attack in the front, we will send Scouts to try and score quickly.
        """
        # First, place basic defenses
        self.build_defences(game_state)
        # TODO hoard or attack
        self.attack(game_state)

    def build_defences(self, game_state):
        # how to use the first 12 SP
        starting_turrets = [[3, 12], [8, 12], [13, 12], [18, 12], [24, 12]]
        starting_walls = [[2, 13], [3, 13], [24, 13], [25, 13], [26, 13], [27, 13]]
        starting_supports = [[13,2]]

        # urgent defenses
        urgent_supports = [[13, 2], [14, 2]]
        urgent_turrets = [[3, 12], [8, 12], [13, 12], [18, 12], [24, 12], [6, 10], [10, 10], [16, 10], [21, 10]]
        urgent_walls = [[2, 13], [3, 13], [4, 13], [7, 13], [8, 13], [9, 13], [12, 13], [13, 13], [14, 13], [17, 13], [18, 13], [19, 13], [23, 13], [24, 13], [25, 13], [26, 13], [27, 13]]

        # high defenses
        high_supports = [[5, 10], [6, 9], [7, 8], [8, 7], [9, 6], [10, 5], [11, 4], [12, 3], [15, 3], [16, 3], [13, 2], [14, 2]]
        high_turrets = [[3, 12], [4, 12], [8, 12], [13, 12], [18, 12], [21, 12], [24, 12], [25, 12], [4, 11], [6, 10], [10, 10], [16, 10], [21, 10], [12, 8]]
        high_walls = [[2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [7, 13], [8, 13], [9, 13], [12, 13], [13, 13], [14, 13], [17, 13], [18, 13], [19, 13], [20, 13], [21, 13], [22, 13], [23, 13], [24, 13], [25, 13], [26, 13], [27, 13], [16, 11]]

        # normal defenses
        normal_supports = [[5, 10], [6, 9], [7, 9], [7, 8], [8, 8], [8, 7], [9, 7], [9, 6], [10, 6], [10, 5], [11, 5], [11, 4], [12, 4], [12, 3], [13, 3], [14, 3], [15, 3], [16, 3], [13, 2], [14, 2],[5,11],[4, 11]]
        normal_turrets = [[3, 12], [4, 12], [5, 12], [8, 12], [10, 12], [12, 12], [13, 12], [18, 12], [21, 12], [22, 12], [24, 12], [25, 12], [17, 11], [6, 10], [11, 10], [16, 10], [21, 10], [16, 9], [12, 8], [14, 6]]
        normal_walls = [[2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [7, 13], [8, 13], [9, 13], [10, 13], [11, 13], [12, 13], [13, 13], [14, 13], [17, 13], [18, 13], [19, 13], [20, 13], [21, 13], [22, 13], [23, 13], [24, 13], [25, 13], [26, 13], [27, 13], [14, 12], [17, 12], [12, 11], [13, 11], [16, 11], [15, 10], [15, 9]]

        # low defenses
        low_supports = [[5, 10], [6, 9], [7, 9], [7, 8], [8, 8], [8, 7], [9, 7], [9, 6], [10, 6], [10, 5], [11, 5], [11, 4], [12, 4], [12, 3], [13, 3], [14, 3], [15, 3], [16, 3], [13, 2], [14, 2],[13,4],[12,5],[11,6],[10,7],[9,8],[8,9],[7,10],[6,11]]
        low_turrets = [[3, 12], [4, 12], [5, 12], [8, 12], [10, 12], [12, 12], [13, 12], [18, 12], [21, 12], [22, 12], [24, 12], [25, 12], [4, 11], [17, 11], [6, 10], [11, 10], [16, 10], [21, 10], [16, 9], [12, 8], [14, 6], [18,8],[19,12], [20,12],[23,12],[6,12],[7,12]]
        low_walls = [[2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [7, 13], [8, 13], [9, 13], [10, 13], [11, 13], [12, 13], [13, 13], [14, 13], [17, 13], [18, 13], [19, 13], [20, 13], [21, 13], [22, 13], [23, 13], [24, 13], [25, 13], [26, 13], [27, 13], [14, 12], [17, 12], [12, 11], [13, 11], [16, 11], [15, 10], [15, 9]]

        if game_state.turn_number == 0:
            game_state.attempt_spawn(TURRET, starting_turrets)
            game_state.attempt_spawn(WALL, starting_walls)
            game_state.attempt_spawn(SUPPORT, starting_supports)

        # attempt_spawn will try to spawn units if we have resources, and will check if a blocking unit is already there
        else:
            # urgent defenses: turrets are most important
            game_state.attempt_spawn(TURRET, urgent_turrets)
            game_state.attempt_spawn(SUPPORT, urgent_supports)
            game_state.attempt_spawn(WALL, urgent_walls)
            # high defenses: channel is most important
            game_state.attempt_spawn(SUPPORT, high_supports)
            game_state.attempt_spawn(TURRET, high_turrets)
            game_state.attempt_spawn(WALL, high_walls)
            if game_state.get_resource(0) >= 1:
                # normal defenses: attempt to upgrade turret in corner first
                # TODO hoard until upgrade is possible
                game_state.attempt_upgrade([3,12])
                game_state.attempt_spawn(TURRET, normal_turrets)
                game_state.attempt_spawn(WALL, normal_walls)
                game_state.attempt_spawn(SUPPORT, normal_supports)
                # secondary upgrades
                game_state.attempt_upgrade([18,12])
                game_state.attempt_upgrade([4,12])
                game_state.attempt_upgrade([13,12])
                game_state.attempt_upgrade([24,12])
                game_state.attempt_upgrade([2,13])
                # low defenses
                game_state.attempt_spawn(TURRET, low_turrets)
                #game_state.attempt_spawn(WALL, low_walls)
                game_state.attempt_spawn(SUPPORT, low_supports)
                game_state.attempt_upgrade([4,11])
                game_state.attempt_upgrade([5,11])

    def attack(self,game_state):
        mp = game_state.get_resource(1)
        if mp >= 6:
            game_state.attempt_spawn(SCOUT, [15,1], 4)
            game_state.attempt_spawn(SCOUT, [16,2], 1000)
        else:
            game_state.attempt_spawn(SCOUT, [14,0], 1000)

if __name__ == "__main__":
    algo = AlgoStrategy()
    algo.start()


import socket
import collections
import sys
import os
from sys import stdout
import time

#   ====================    FUNCTIONS    ====================    #
#   check for a message from the server
def checkForNewMessageFromServer( socketToServer ):
    bytesFromServer = None
    try:
        bytesFromServer = socketToServer.recv( 1024 )
        while bytesFromServer:
            stdout.buffer.write( bytesFromServer )
            stdout.flush()
            bytesFromServer = socketToServer.recv( 1024 )
    except socket.timeout:
        pass
    except BrokenPipeError:
        global serverOpen
        serverOpen = False
        print( "Alert:\tBrokenPipeError" )
        sys.exit()
    except socket.error:
        print( "Alert:\t Disconnected from server." )
        sys.exit()

#   see if the server is still connected
def pingServer( socketToServer ):
    #print( " pinging speakers " )
    try:
        socketToServer.send( "PING".encode() )
    except socket.timeout:
        pass
    except socket.error:
        print( "Server failed PING." )
        sys.exit()
        pass

#   keep track of time
def tic( lastTime, oneSecondTracker, socketToServer ):
    deltaTime = time.time() - lastTime
    oneSecondTracker += deltaTime

    if oneSecondTracker > 1:
        oneSecondTracker = 0
        pingServer( socketToServer )

    lastTime = time.time()

    return lastTime, oneSecondTracker

#   ====================    MAIN    ====================    #
#   -----   setup   -----   #
socketToServer = socket.socket( )
#socketToServer.setblocking(0)
host = "76.30.234.227"
port = 1337

#   time keepers
lastTime = time.time()
oneSecondTracker = 0

#   -----   connect to server   -----   #
socketToServer.settimeout(5)
socketToServer.connect( (host, port) )
clientType = "LSTN"
socketToServer.send( clientType.encode() )
bytesFromServer = socketToServer.recv( 1024 )
serverGreeting = bytesFromServer.decode()
stdout.write( serverGreeting )
stdout.flush()

#   -----   be a client -----   #
userMessage = None
bytesFromServer = None
socketToServer.settimeout( 0.001 )
serverOpen = True
while serverOpen:
    checkForNewMessageFromServer( socketToServer )
    lastTime, oneSecondTracker = tic( lastTime, oneSecondTracker, socketToServer )


from threading import Thread
import time

'''
decolando = 0
pousando = 0
esperandoPousar = []
esperandoDecolar = []

def decolar(aviao):
    decolandoAviao = 0
    while(decolandoAviao <= 100):
        print('Decolando aviao: ', aviao)
        decolandoAviao += 1
    decolando = 0
    print('Finalizou decolagem aviao: ',aviao)

def pousar(aviao):
    pousandoAviao = 0
    while(pousandoAviao <= 100):
        print('Decolando aviao: ', aviao)
        pousandoAviao += 1
    pousando = 0
    print('Finalizou pouso aviao: ',aviao)

def aviao(id, acao):
    executando = 0
    liberar = decolando == 0 and pousando == 0 and esperandoDecolar == 0 and esperandoPousar == 0
    if(acao == "decolar"):
        if(liberar):
            decolar(id)
            time.sleep(0.5)
        else:
            print('Esperando decolar: ',id)
            esperandoDecolar.append(id)
    elif(acao == "pousar"):
        if(liberar):
            pousar(id)
        else:
            print('Esperando pousar: ',id);
            esperandoPousar.append(id)
'''
#def carrinho(velocidade,nome):
    #distancia = 0
    #while distancia <= 1000:
        #print("Carrinho :",nome,distancia)
        #distancia += velocidade
        #time.sleep(0.3)

class Aviao():
    def __init__(self):
        self.__decolou = 0
        self.__pousou = 0
        self.__decolando = 0
        self.___pousando = 0
        self.__esperando_pousar = []
        self.__esperando_decolar = []
        self.__excedente_pousar = []
        self.__excedente_decolar = []

    def decolar(self, aviao):
        print('Decolaram: ',self.__decolou)
        if(self.__decolando == 0 and self.___pousando == 0):
            self.__decolando = 1
            print('decolagem Ok. Aviao: ', aviao)
            self.__decolou += 1
            time.sleep(5)
            if(aviao in self.__esperando_decolar):
                self.__esperando_decolar.remove(aviao)
            self.__decolando = 0
        else:
            print('\n\n -- Lista esperando decolar: ',self.__esperando_decolar)

            if len(self.__esperando_decolar) <= 5 and (aviao in self.__esperando_decolar) == False:
                self.__esperando_decolar.append(aviao)

            if len(self.__esperando_decolar) >= 6 and (aviao in self.__excedente_decolar) == False:
                print('\n -- Excendente de decolagem --. Aviao: ', aviao,'\n')
                self.__excedente_decolar.append(aviao)
            if len(self.__esperando_decolar) == 0 and len(self.__excedente_decolar) != 0:
                self.__esperando_decolar = self.__excedente_decolar[:6]
                self.__excedente_decolar = self.__excedente_decolar[6:]

            print('Aguardando decolar. Aviao: ', aviao)
            time.sleep(2)
            self.decolar(aviao)

    def pousar(self, aviao):
        print('Pousaram: ', self.__pousou)
        if(self.__decolando == 0 and self.___pousando == 0):
            self.___pousando = 1
            print('pouso ok. Aviao: ',aviao)
            self.__pousou += 1
            time.sleep(5)
            if (aviao in self.__esperando_pousar):
                self.__esperando_pousar.remove(aviao)
            self.___pousando = 0
        else:
            print('\n\n -- Lista esperando pousar: ',self.__esperando_pousar)

            if len(self.__esperando_pousar) <= 2 and (aviao in self.__esperando_pousar) == False:
                self.__esperando_pousar.append(aviao)

            if len(self.__esperando_pousar) >= 3 and (aviao in self.__excedente_pousar) == False:
                print('\n -- Excendente de pouso --. Aviao: ', aviao,'\n')
                self.__excedente_pousar.append(aviao)
            if len(self.__esperando_pousar) == 0 and len(self.__excedente_pousar) != 0:
                self.__esperando_pousar = self.__excedente_pousar[:3]
                self.__excedente_pousar = self.__excedente_pousar[3:]

            print('Aguardando pousar. Aviao: ', aviao)
            time.sleep(2)
            self.pousar(aviao)

pista = Aviao()

for i in range(10):
    aviao_id = i + 1
    aviaoD = Thread(target=pista.decolar, args=[aviao_id])
    aviaoD.start()

for i in range(10):
    aviao_id = i + 1
    aviaoP = Thread(target=pista.pousar, args=[aviao_id])
    aviaoP.start()

#aviao1 = Thread(target=pista.decolar,args=[1])
#aviao2 = Thread(target=pista.pousar,args=[2])

#aviao1.start()
#aviao2.start()


#!/usr/bin/env python
# -*- coding:utf-8 -*-
#虽然同时记录索引path和数据path是不太方便,
# 但是可以用一个临时变量保存当前index_path（存索引）的相邻左兄弟节点（num_path）[此处能够只用相邻兄弟节点保存的重要前提就是数组是有序的，如果无序的话就得保存先前所有左兄弟节点进行对比了]
# , 通过对比当前num_path和左兄弟节点的num_path是否一致来决定要不要对当前path进行剪枝,
# leetcode网站上没通过[1,2]这个用例，但是本地跑是没问题的
from typing import List

class Solution:
    temp = []
    def permuteUnique(self, nums):
        self.res = []
        # 重要前提是排序后的
        nums.sort()
        def dfs(nums, path, num_index):
            path.append(num_index)
            if Solution.temp == [nums[i] for i in path]:
                return
            if len(path) == len(nums):
                self.res.append([nums[i] for i in path])
                return
            for index in range(len(nums)):
                if index in path:
                    continue
                dfs(nums,path[:],index)
            Solution.temp = [nums[i] for i in path]
        for index,i in enumerate(nums):
            dfs(nums,[],index)
        return self.res

# 别人的，有空记得看
# from typing import List
#
#
# class Solution:
#
#     def permuteUnique(self, nums: List[int]) -> List[List[int]]:
#
#         def dfs(nums, size, depth, path, used, res):
#             if depth == size:
#                 res.append(path.copy())
#                 return
#             for i in range(size):
#                 if not used[i]:
#
#                     if i > 0 and nums[i] == nums[i - 1] and not used[i - 1]:
#                         continue
#
#                     used[i] = True
#                     path.append(nums[i])
#                     dfs(nums, size, depth + 1, path, used, res)
#                     used[i] = False
#                     path.pop()
#
#         size = len(nums)
#         if size == 0:
#             return []
#
#         nums.sort()
#
#         used = [False] * len(nums)
#         res = []
#         dfs(nums, size, 0, [], used, res)
#         return res

# 二刷 没用缓存时间是1600ms,缓存只加载叶节点能到800ms,缓存所有节点能到76ms
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        self.res = []
        self.mem = {}
        def dfs(index_path,n_path, cur_index, cur_n):
            n_path.append(cur_n)
            index_path.append(cur_index)

            if str(n_path) in self.mem:
                return
            self.mem[str(n_path)] = 1

            if len(n_path) == len(nums):
                self.res.append(n_path)
                return
            for index, n in enumerate(nums):
                if index not in index_path:
                    dfs(index_path[:], n_path[:], index,n)
        for index,i in enumerate(nums):
            dfs([],[],index, i)
        return self.res

a=Solution().permuteUnique([1,1,2])
print(a)


import trace_test_expectations
import page_sets

from telemetry import benchmark
from telemetry.page import page_test
from telemetry.core.platform import tracing_category_filter
from telemetry.core.platform import tracing_options
from telemetry.timeline import model

TOPLEVEL_GL_CATEGORY = 'gpu_toplevel'
TOPLEVEL_CATEGORIES = ['disabled-by-default-gpu.device',
                       'disabled-by-default-gpu.service']

test_harness_script = r"""
  var domAutomationController = {};

  domAutomationController._finished = false;

  domAutomationController.setAutomationId = function(id) {}

  domAutomationController.send = function(msg) {
    domAutomationController._finished = true;
  }

  window.domAutomationController = domAutomationController;
"""

class _TraceValidator(page_test.PageTest):
  def ValidateAndMeasurePage(self, page, tab, results):
    timeline_data = tab.browser.platform.tracing_controller.Stop()
    timeline_model = model.TimelineModel(timeline_data)

    categories_set = set(TOPLEVEL_CATEGORIES)
    for event in timeline_model.IterAllEvents():
      if event.args.get('gl_category', None) == TOPLEVEL_GL_CATEGORY:
        categories_set.discard(event.category)
      if not categories_set:
        break
    else:
      raise page_test.Failure(self._FormatException(sorted(categories_set)))

  def CustomizeBrowserOptions(self, options):
    options.AppendExtraBrowserArgs('--enable-logging')

  def WillNavigateToPage(self, page, tab):
    cat_string = ','.join(TOPLEVEL_CATEGORIES)
    cat_filter = tracing_category_filter.TracingCategoryFilter(cat_string)
    options = tracing_options.TracingOptions()
    options.enable_chrome_trace = True
    tab.browser.platform.tracing_controller.Start(options, cat_filter, 60)

  def _FormatException(self, categories):
    return 'Trace markers for GPU categories were not found: %s' % categories

class TraceTest(benchmark.Benchmark):
  """Tests GPU traces"""
  test = _TraceValidator

  def CreateExpectations(self):
    return trace_test_expectations.TraceTestExpectations()

  def CreatePageSet(self, options):
    # Utilize pixel tests page set as a set of simple pages to load.
    page_set = page_sets.PixelTestsPageSet()
    for page in page_set.pages:
      page.script_to_evaluate_on_commit = test_harness_script
    return page_set


import wx
import wx.adv

from GimelStudio.datafiles.splash import SPLASH_GIMEL_STUDIO

class StartupSplashScreen(wx.adv.SplashScreen):
    def __init__(self):
        _bmp = SPLASH_GIMEL_STUDIO.GetBitmap()
        bmp = wx.Image.ConvertToBitmap(
            wx.Bitmap.ConvertToImage(_bmp).Scale(
                _bmp.GetWidth() / 2,
                _bmp.GetHeight() / 2,
                wx.IMAGE_QUALITY_HIGH
            )
        )
        wx.adv.SplashScreen.__init__(self, bmp,
                                     wx.adv.SPLASH_CENTRE_ON_SCREEN
                                     | wx.adv.SPLASH_NO_TIMEOUT,
                                     5000, None, -1)

        self.Bind(wx.EVT_CLOSE, self.OnClose)

    def OnClose(self, event):
        # Make sure the default handler runs too
        # so this window gets destroyed.
        event.Skip()
        self.Hide()


from spack import *
import os

class BlasrLibcpp(Package):
    """Blasr_libcpp is a library used by blasr
    and other executables such as samtoh5,
    loadPulses for analyzing PacBio sequences."""

    homepage = "https://github.com/PacificBiosciences/blasr_libcpp"
    url      = "https://github.com/PacificBiosciences/blasr_libcpp/archive/5.3.1.tar.gz"

    version('5.3.1', 'ca770042cbca508d5ff12dff0d645045')

    depends_on('pbbam')
    depends_on('hdf5+cxx@1.8.12:1.8.99')
    # maximum version is 1.8.20 currently. There doesn't appear to be a
    # major version 1.9 and the 1.10.1 version doesn't build correctly.
    # https://github.com/PacificBiosciences/blasr/issues/355

    depends_on('python', type='build')

    phases = ['configure', 'build', 'install']

    def configure(self, spec, prefix):
        configure_args = [
            'PBBAM_INC={0}'.format(self.spec['pbbam'].prefix.include),
            'PBBAM_LIB={0}'.format(self.spec['pbbam'].prefix.lib),
            'HDF5_INC={0}'.format(self.spec['hdf5'].prefix.include),
            'HDF5_LIB={0}'.format(self.spec['hdf5'].prefix.lib)
        ]
        python('configure.py', *configure_args)

    def build(self, spec, prefix):
        os.environ['CPLUS_INCLUDE_PATH'] = self.stage.source_path
        make()

    def install(self, spec, prefix):
        install_tree('alignment', prefix.alignment)
        install_tree('hdf', prefix.hdf)
        install_tree('pbdata', prefix.pbdata)

    def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
        spack_env.prepend_path('LD_LIBRARY_PATH',
                               self.spec.prefix.hdf)
        spack_env.prepend_path('LD_LIBRARY_PATH',
                               self.spec.prefix.alignment)
        spack_env.prepend_path('LD_LIBRARY_PATH',
                               self.spec.prefix.pbdata)


from .utils import CONFIG_PATH
import json

def set_config(update, strategy_name: str = '', interval: str = '', verbose: bool = False):
    config = None
    try:
        file = open(CONFIG_PATH, 'r')
        config = json.loads(file.read())
        file.close()
    except:
        if verbose: print('\033[91m\033[1mConfig file not found.\033[00m')
        return
    if strategy_name:
        if not strategy_name in config:
            config[strategy_name] = {}
        if interval:
            config[strategy_name][interval] = update
        else: config[strategy_name] = update
    else:
        config = update
    try:
        file = open(CONFIG_PATH, 'w')
        file.write(json.dumps(config, indent=2))
        file.close()
    except:
        if verbose: print('\033[91m\033[1mConfig file not found.\033[00m')
        return


import pytest
import brownie

@pytest.fixture(autouse=True)
def isolation(fn_isolation):
    """make each function being isolated by common fixtures"""
    pass

def test_success__burn_dao_token(dao_deployment):
    # Arrange
    dao_token = dao_deployment['dao_token']
    owner = dao_deployment['owner']

    total_supply = dao_token.totalSupply()
    burn_amount = 100

    # Action
    dao_token.burn(burn_amount, {"from": owner})

    # Assert
    assert dao_token.totalSupply() == total_supply - burn_amount
    assert dao_token.balanceOf(owner) == total_supply - burn_amount

def test_burn_exceed_amount_dao_token(dao_deployment):
    # Arrange
    dao_token = dao_deployment['dao_token']
    owner = dao_deployment['owner']

    burn_amount = dao_token.balanceOf(owner) + 1

    # Action

    # Assert
    with brownie.reverts("ERC20: burn amount exceeds balance"):
        dao_token.burn(burn_amount, {"from": owner})

def test_burn_dao_token_from_zero_address(dao_deployment, zero_address):
    # Arrange
    dao_token = dao_deployment['dao_token']
    owner = dao_deployment['owner']

    burn_amount = dao_token.balanceOf(owner) + 1

    # Action

    # Assert
    with brownie.reverts("ERC20: burn from the zero address"):
        dao_token.burn(burn_amount,
                       {"from": zero_address})


from lib.db.models.model import Model

WAITING = 'waiting'
EXECUTING = 'executing'
FINISHED = 'finished'
FAILED = 'failed'

class JobInfo(Model):
    @classmethod
    def _get_collection_name(cls):
        return 'job_infos'

    @classmethod
    def _get_fields(cls):
        return [
            'name',
            'info',
            'status',
            'error',
            'start_timestamp',
            'end_timestamp',
            'progress',
            'output'
        ]


import datetime as dt

def process_date_time(execution_date, times):
    # 19:58:57 -> 2021-10-13 19:58:57
    for time in times:
        ti = time["start_time"]
        time["start_time"] = execution_date + " " + ti

        tf = time["end_time"]
        time["end_time"] = execution_date + " " + tf

    return times

def diff_hours(start, end):
    format = "%H:%M:%S"

    diff = dt.datetime.strptime(end, format) - dt.datetime.strptime(start, format)

    return diff.total_seconds()


def bin_search(A,n,i,j):  # A is the search array, n is the string/number to be searched, i,j is the positions between the array to be searched
    if j<=i:
        if A[i]==n:
            return True
        return False
    mid=A[i+(j-i)//2]
    #print(mid,i,j,n)
    if mid <= n:
        if mid == n:
            return True
        return bin_search(A,n,i+((j-i)//2)+1,j)
    elif mid >= n:
        if mid ==n:
            return True
        return bin_search(A,n,i,i+((j-i)//2)-1)


receiver = input("check if your code has qwerty or not!")
list = receiver.split()
empt = ""
for i in list:
    for j in i:
       empt = empt + j #added this to account for spaces
print(empt)
if "qwerty" in empt:
    print("qwerty detected!")
else:
    print("qwerty not detected")


import logging

# Configuración básica de logging
logging.basicConfig(filename='example.log',         # Nombre de archivo para guardar los registros
                    level=logging.DEBUG,            # Nivel de registro mínimo para registrar
                    format='%(asctime)s:%(levelname)s:%(name)s: %(message)s',  # Formato del mensaje
                    filemode='w',                    # Modo de apertura de archivo ('w' sobrescribe, 'a' agrega)
                    datefmt='%Y-%m-%d %H:%M:%S')     # Formato de la fecha en el mensaje

# Registrar mensajes con diferentes niveles de severidad
logging.debug("Este es un mensaje de nivel DEBUG")
logging.info("Este es un mensaje de nivel INFO")
logging.warning("Este es un mensaje de nivel WARNING")
logging.error("Este es un mensaje de nivel ERROR")
logging.critical("Este es un mensaje de nivel CRITICAL")

# Crear un logger personalizado
logger = logging.getLogger("MiLoggerPersonalizado")

# Configurar el nivel de logging para este logger
logger.setLevel(logging.WARNING)

# Crear un manejador de archivo para el logger
file_handler = logging.FileHandler('mi_logger.log')
file_handler.setLevel(logging.WARNING)

# Crear un manejador de consola
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.ERROR)

# Definir un formato para los manejadores
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

# Agregar los manejadores al logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)

# Registrar mensajes con el logger personalizado
logger.debug("Este mensaje no se registrará, el nivel es demasiado bajo")
logger.warning("Este mensaje se registrará en el archivo pero no se mostrará en la consola")
logger.error("Este mensaje se registrará en el archivo y se mostrará en la consola")


# 使用melt()函数来转换数据的行列
# pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)
import pandas as pd

data = pd.read_csv("../Pokemon.csv")

pd.set_option('display.max_columns', None)  # 给最大列设置为10列
pd.set_option('display.max_rows', None)  # 设置最大可见100行
pd.set_option('display.width', 1000)

# 从Pokemon数据中创建一组新的数据
data_new = data[10:15]
print(data_new)
# 使用melt()函数
# frame:要处理的数据集
# id_vars: 不需要被转换的列名
# value_vars ：需要转换的列名
melted = pd.melt(frame=data_new, id_vars='Name', value_vars=['Attack', 'Defense'])
print(melted)
print(melted.pivot(index='Name', columns='variable', values='value'))

数据清洗/重塑数据.py


def repeatedNTimes(A: [int]) -> int:
    counts = {}
    halflength = int(len(A) / 2 + 1)
    for i in range(halflength):
        if (A[i] in counts):
            return A[i]
        else:
            counts[A[i]] = 1
    return A[halflength]

print(repeatedNTimes([1, 2, 3, 3]))
print(repeatedNTimes([2, 6, 2, 1]))
print(repeatedNTimes([5, 1, 5, 2, 5, 3, 5, 4]))


import sys
from collections import deque

N, M = map(int, sys.stdin.readline().split())
D = [[0, 1], [1, 0], [0, -1], [-1, 0]]
queue = deque()
a = []
year = 0
check = False

def bfs(start):
    global melt
    queue.append(start)

    while queue:
        r, c = queue.popleft()

        for d in D:
            nr, nc = r + d[0], c + d[1]

            if 0 <= nr < N and 0 <= nc < M:
                if not visited[nr][nc] and a[nr][nc]:
                    queue.append([nr, nc])
                    visited[nr][nc] = 1

                elif a[nr][nc] == 0:
                    melt[r][c] -= 1

for _ in range(N):
    a.append(list(map(int, sys.stdin.readline().split())))

while True:
    visited = [[0] * M for _ in range(N)]
    melt = [[0] * M for _ in range(N)]
    cnt = 0

    for i in range(N):
        for j in range(M):
            if a[i][j] and not visited[i][j]:
                bfs([i, j])
                cnt += 1

    for i in range(N):
        for j in range(M):
            val = a[i][j] + melt[i][j]
            a[i][j] = val if val > 0 else 0

    if cnt >= 2:
        check = True
        break

    if cnt == 0:
        break
    year += 1

if check:
    print(year)
else:
    print(0)


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

from yuantacat.spider.operating_revenue_spider import OperatingRevenueSpider

import unittest

class OperatingRevenueSpiderTest(unittest.TestCase):
    def test_crawl_2498(self):
        spider = OperatingRevenueSpider()
        param = { 'stock_symbol' : '2498' }
        spider.crawl(param)
        self.assertTrue(spider.is_crawled(param))


# By submitting this assignment, I agree to the following:
#   "Aggies do not lie, cheat, or steal, or tolerate those who do."
#   "I have not given or received any unauthorized aid on this assignment."
#
# Name:         Bobby Hao
# Section:      525
# Assignment:   THE ASSIGNMENT NUMBER Lab 7.25.1
# Date:         10/10/2022
vowel = ['a','e','i','o','u','A','E','I','O','U','y','Y']
words = str(input(("Enter word(s) to convert to Pig Latin:")))

letter = words.split(" ")
convert = ''

for everyword in range(len(letter)):#if the first letter of the user input is a vowel, add yay to the end of "words"
   convert = ''
   if letter[everyword][0] in vowel:

      letter[everyword] = letter[everyword] + "yay"
      continue

   for pig in letter[everyword]:
        if pig not in vowel:
             convert = convert + pig
        else:#if not a vowel, add the first letter of "words" and ay to the end of words
            letter[everyword] = letter[everyword].replace(convert,'',1) + convert + "ay"

            break

print(f"In Pig Latin,\"{words}\" is: {' '.join(letter)}" )#go through for loop and print out each indi word


import math
import re
import string
from typing import Iterable, Mapping, Optional, Sequence, Union

import numpy as np
import pandas as pd
import scipy.interpolate

from .. import config, helper

class _FlexMul:
    """Helper class to evaluate "?" in flexible sequences

    In excitation sequences containing multiplication with "?", the "?" is
    replaced by a number so that the excitation sequence length matches
    a given number of frames.
    """
    n_flex_frames: int
    """Number of frames to be filled by repeating sequence part"""

    def __init__(self, n_flex_frames: int):
        """Parameters
        ----------
        n_flex_frames
            Set :py:attr:`n_flex_frames` attribute
        """
        self.n_flex_frames = n_flex_frames

    def __mul__(self, rep_seq: str) -> str:
        """Perform expansion

        `rep_seq` will be repeated until the length of the result is equal to
        :py:attr:`n_flex_frames`.

        Paramters
        ---------
        rep_seq
            Sequence part to be repeated

        Returns
        -------
        Expanded `rep_seq`
        """
        reps, rem = divmod(self.n_flex_frames, len(rep_seq))
        if rem:
            raise ValueError("Number of flexible frames is not divisible by "
                             "length of repeated sequence.")
        return rep_seq * reps

    def __rmul__(self, rep_seq: str) -> str:
        """Same as :py:meth:`__mul__`"""
        return self.__mul__(rep_seq)

class FrameSelector:
    """Select images and datapoints of a certain excitation type

    For instance, if employing alternating excitation for a FRET experiment,
    this can be used to select only the donor or only the acceptor frames.
    For details on how the excitation sequence is specified, see
    :py:attr:`excitation_seq`.

    Examples
    --------
    >>> # Sequence of 8 "images"
    >>> img_seq = numpy.array([numpy.full((3, 3), i) for i in range(8)])
    >>> sel = FrameSelector("odda")
    >>> sel.select(img_seq, "o")
    array([[[0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]],
    <BLANKLINE>
           [[4, 4, 4],
            [4, 4, 4],
            [4, 4, 4]]])
    >>> sel.select(img_seq, "d")
    array([[[1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]],
    <BLANKLINE>
           [[2, 2, 2],
            [2, 2, 2],
            [2, 2, 2]],
    <BLANKLINE>
           [[5, 5, 5],
            [5, 5, 5],
            [5, 5, 5]],
    <BLANKLINE>
           [[6, 6, 6],
            [6, 6, 6],
            [6, 6, 6]]])

    A flexible sequence specification uses ``?`` as a multiplicator. This
    causes repetition of a subsequence such that the excitation sequence
    length matches the image sequence length. In the following example,
    ``"da"`` is repeated three times.

    >>> sel = FrameSelector("o + da * ? + c")
    >>> sel.select(img_seq, "d")
    array([[[1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]],
    <BLANKLINE>
           [[3, 3, 3],
            [3, 3, 3],
            [3, 3, 3]],
    <BLANKLINE>
           [[5, 5, 5],
            [5, 5, 5],
            [5, 5, 5]]])
    """
    excitation_seq: str
    """Excitation sequence. Use different letters to describe different
    excitation types, e.g., "d" for donor excitation, "a" for acceptor,
    etc.

    One needs only specify the shortest sequence that is repeated,
    i. e. ``"ddddaddddadddda"`` is equivalent to ``"dddda"``. It is
    possible to specifiy repetition via the multiplication operator.
    ``"c + da * 3 + c"`` is equivalent to ``"cdadadac"``. Also, flexible
    sequences can be specified using ``?`` as a multiplicator. In ``"c +
    da * ? + c"``, ``"da"`` is repeated an appropriate number of times
    to generate a sequence of given length. This length is either derived
    from the image sequence the class instance is applied to or given
    explicitly (see :py:meth:`select`).

    If the sequence is empty, the FrameSelector does nothing. E.g.,
    :py:meth:`select` and :py:meth:`renumber_frames` just return their
    argument unaltered.
    """

    _rm_whitespace_trans = str.maketrans("", "", string.whitespace)
    """To be used with ``str.translate`` to remove whitespace"""
    _letter_re = re.compile(r"([A-Za-z]+)")
    """Regular expression grouping upper- and lowercase letters"""

    def __init__(self, excitation_seq: str):
        """Parameters
        ----------
        excitation_seq
            Set :py:attr:`excitation_seq`
        """
        self.excitation_seq = excitation_seq

    def _eval_simple(self, seq: str, glob: Mapping = {}, loc: Mapping = {}
                     ) -> str:
        """Evaluate non-flexible sequence

        Parameters
        seq
            Sequence to evaluate
        glob
            Global variables to pass to :py:func:`eval`
        loc
            Local variables to pass to :py:func:`eval`

        Returns
        -------
        Evaluated sequence string
        """
        re_seq = self._letter_re.sub(r'"\1"', seq)
        if not re_seq:
            return ""
        return eval(re_seq, glob, loc)

    def eval_seq(self, n_frames: Optional[int] = None) -> np.ndarray:
        """Evaluate excitation sequence

        Parameters
        ----------
        n_frames
            Number of frames. This needs to be given if sequence is flexible,
            i.e., contains multiplication by ``?``. In this case, ``?``
            evaluates to a number such that the total sequence length is
            `n_frames`. If `n_frames` is equal to -1, ``?`` is replaced by
            1. This is useful for testing and finding e.g. the first occurence
            of a frame without depending on actual data.

        Returns
        -------
        Array of characters representing evaluated sequence
        """
        seq = self.excitation_seq.translate(self._rm_whitespace_trans)
        q_pos = seq.find("?")
        if q_pos < 0:
            eseq = self._eval_simple(seq)
            return np.fromiter(eseq, "U1", len(eseq))
        if n_frames is None:
            raise ValueError("`n_frames` must be given for sequences "
                             "containing '?'")

        pre_pos = seq.rfind("+", 0, q_pos)
        post_pos = seq.find("+", q_pos)

        n_fixed = 0
        if pre_pos >= 0:
            n_fixed += len(self._eval_simple(seq[:pre_pos]))
        if post_pos >= 0:
            n_fixed += len(self._eval_simple(seq[post_pos+1:]))

        if n_frames < 0:
            mul = 1
        else:
            mul = _FlexMul(n_frames - n_fixed)
        eseq = self._eval_simple(seq.replace("?", "_", 1), loc={"_": mul})
        return np.fromiter(eseq, "U1", len(eseq))

    @staticmethod
    def _find_mask(eval_seq: np.ndarray, frame_nos: np.ndarray,
                   which: Union[str, Iterable[str]]) -> np.ndarray:
        """Find frames of certain type in list of frames, return boolean mask

        Parameters
        ----------
        eval_seq
            Evaluated excitation sequence (array of characters).
            See :py:meth:`eval_seq`.
        frame_nos
            Array of frame numbers from which frames should be selected
        which
            Excitation type(s), one or multiple characters out of
            :py:attr:`excitation_seq`.

        Returns
        -------
        Boolean array indicating whether elements of `frame_nos` are of an
        excitation type given by `which`.
        """
        good_frame_mask = np.isin(eval_seq, list(which))
        good_frames = np.nonzero(good_frame_mask)[0]
        mask = np.isin(frame_nos % len(eval_seq), good_frames)
        return mask

    @staticmethod
    def _find_numbers(eval_seq: np.ndarray, frame_nos: np.ndarray,
                      which: Union[str, Iterable[str]]) -> np.ndarray:
        """Find frames of certain type in list of frames, return numbers

        Parameters
        ----------
        eval_seq
            Evaluated excitation sequence (array of characters).
            See :py:meth:`eval_seq`.
        frame_nos
            Array of frame numbers from which frames should be selected
        which
            Excitation type(s), one or multiple characters out of
            :py:attr:`excitation_seq`.

        Returns
        -------
        Elements of `frame_nos` that are of an excitation type given by
        `which`.
        """
        return frame_nos[__class__._find_mask(eval_seq, frame_nos, which)]

    @staticmethod
    def _get_subseq(data: Sequence, index: Sequence[int]) -> Sequence:
        """Get a subsequence of `data`

        Parameters
        ----------
        data
            Sequence to get subsequence from
        index
            Indices of `data` present in subsequence

        Returns
        -------
        If possible, directly index `data` with `index` (works e.g. for numpy
        arrays). If not, create a :py:class:`helper.Slicerator` instance and
        use `index` on that.
        """
        try:
            return data[index]
        except TypeError:
            # This can happen if e.g. data is a list
            s = helper.Slicerator(data)
            return s[index]

    @staticmethod
    def _renumber(eval_seq: np.ndarray, frame_nos: np.ndarray,
                  which: Union[str, Iterable[str]], restore: bool
                  ) -> np.ndarray:
        """Do the actual frame renumbering

        for :py:meth:`select`, :py:meth:`renumber_frames`, and
        :py:meth:`restore_frame_numbers`. If ``restore=False``, any frames that
        don't belong to the excitation type given by `which` are mapped to -1.

        Parameters
        ----------
        eval_seq
            Evaluated excitation sequence (array of characters).
            See :py:meth:`eval_seq`.
        frame_nos
            Array of frame numbers to be mapped
        which
            Excitation type(s), one or multiple characters out of
            :py:attr:`excitation_seq`.
        restore
            If `False`, renumber the frames (as in :py:meth:`select`).
            If `True`, restore original frame numbers (as in
            :py:meth:`restore_frame_numbers`).

        Returns
        -------
        New frame numbers
        """
        if len(eval_seq) == 0 or len(frame_nos) == 0:
            return frame_nos
        frame_nos = np.asanyarray(frame_nos, dtype=int)
        good_frame_mask = np.isin(eval_seq, list(which))
        n_good = np.sum(good_frame_mask)
        max_frame = np.max(frame_nos)
        if restore:
            if not n_good:
                # None of `which` are in excitation seq. There is nothing we
                # can do.
                raise ValueError(f"excitation sequence '{''.join(eval_seq)}' "
                                 f"does not contain types '{''.join(which)}'")
            # f_map_inv needs at least max_frame + 1 entries (the domain of
            # the restoring map is {0, 1, …, max_frame}), meaning
            # good_frame_mask has to be chained (max_frame + 1) / n_good
            # times, where n_good is the number of True entries in
            # good_frame_mask
            n_repeats = math.ceil((max_frame + 1) / n_good)
        else:
            if not n_good:
                # All are invalid and thus mapped to -1
                return np.full(frame_nos.size, -1, dtype=int)
            # f_map needs at least max_frame + 1 entries (the domain of
            # the frame number map is {0, 1, …, max_frame}). f_map_inv's values
            # (which form the codomain of the map) need to go up to at least
            # max_frame.
            n_repeats = math.ceil((max_frame + 1) / len(eval_seq))
        # Calculate the restoring map
        f_map_inv = np.nonzero(np.tile(good_frame_mask, n_repeats))[0]
        if restore:
            return f_map_inv[frame_nos]
        # Invert the restoring map
        f_map = np.full(f_map_inv[-1] + 1, -1, dtype=int)
        f_map[f_map_inv] = np.arange(f_map_inv.size)
        return f_map[frame_nos]

    def renumber_frames(self, frame_nos: np.ndarray,
                        which: Union[str, Iterable[str]],
                        restore: bool = False, n_frames: Optional[int] = None
                        ) -> np.ndarray:
        """Renumber a sequence of frame numbers

        The numbers can be with respect to the original image sequence. In this
        case, set ``restore=False`` and this function will return frame numbers
        with respect to an image sequence which was returned by
        :py:meth:`select`.  Any frames that don't belong to the excitation type
        given by `which` are mapped to -1.
        If ``restore=True`` is set, this works the opposite other way.

        Parameters
        ----------
        frame_nos
            Array of frame numbers to be mapped
        which
            Excitation type(s), one or multiple characters out of
            :py:attr:`excitation_seq`.
        restore
            If `False`, renumber the frames (as in :py:meth:`select`).
            If `True`, restore original frame numbers (as in
            :py:meth:`restore_frame_numbers`).

        Returns
        -------
        New frame numbers
        """
        eval_seq = self.eval_seq(n_frames)
        return self._renumber(eval_seq, frame_nos, which, restore)

    def find_other_frames(self, data: Union[int, Sequence],
                          which: Union[str, Iterable[str]],
                          other: Union[str, Iterable[str]],
                          how: str = "nearest-up") -> Sequence:
        """For given excitation type, find frames of other type

        Typically, this is used to find the closest frame of a certain type,
        e.g., find the next acceptor excitation frame for donor excitation
        frames in FRET ALEX experiments.

        Examples
        --------
        >>> fs = FrameSelector("dddda")
        >>> d_img = fs.select(image_sequence, "d")
        >>> a_img = fs.find_other_frames(image_sequence, "d", "a)
        >>> for di, ai in zip(d_img, a_img):
        ...    # `ai` is the frame of type "a" closest to `di`
        ...    pass

        Parameters
        ----------
        data
            If this is a sequence, return a subsequence of the same length as
            ``select(data, which)``. Each entry of the returned sequence is
            the corresponding entry to what ``select(data, which)`` returns.
            Passing an int is equivalent to using ``numpy.arange(data)``.
        which
            Excitation types for which to find other excitation type's frames
        other
            Other frames' excitation type(s)
        how
            How to do the interpolation. "nearest-up" will return the nearest
            frame. In case of a tie, the “other” frame after the current one
            is used. "nearest" will return the “other” frame before the current
            one in case of a tie. "previous” and "next" return the “other”
            frame before and after the current one, respectively.

        Returns
        -------
        Subsequence of `data` with entries being the “other” entries to
        ``select(data, which)``.
        """
        if isinstance(data, int):
            n_frames = data
            data = None
        else:
            n_frames = len(data)

        eval_seq = self.eval_seq(n_frames)
        idx = np.arange(n_frames)
        source_idx = self._find_numbers(eval_seq, idx, which)
        target_idx = self._find_numbers(eval_seq, idx, other)
        if len(target_idx) == 0:
            raise ValueError("excitation sequence does not contain types any "
                             "of the types in `other`.")
        if len(target_idx) == 1:
            # scipy.interpolate.interp1d needs at least two points, so deal
            # with this case here
            return np.full(len(source_idx), target_idx[0], dtype=int)
        interp_idx = scipy.interpolate.interp1d(
            target_idx, target_idx, how, bounds_error=False,
            fill_value=(target_idx[0], target_idx[-1])
            )(source_idx)
        interp_idx = interp_idx.astype(int)

        if data is not None:
            return self._get_subseq(data, interp_idx)
        return interp_idx

    @config.set_columns
    def select(self, data: Union[pd.DataFrame, Iterable[np.ndarray]],
               which: Union[str, Iterable[str]], renumber: bool = False,
               n_frames: Optional[int] = None, columns: Mapping = {}
               ) -> Union[pd.DataFrame, np.ndarray, helper.Slicerator]:
        """Get only data corresponding to a certain excitation type

        Parameters
        ----------
        data
            Localization data or sequence of images
        which
            Excitation type(s), one or multiple characters out of
            :py:attr:`excitation_seq`.
        renumber
            Renumber frames so that only frames for excitation types
            corresponding to `which` are counted.

            After selecting only data corresponding to an excitation type (e.g.
            "a") in a :py:class:`pandas.DataFrame`, all other types are
            missing and frame number are not consecutive any more. This can be
            a problem for tracking or diffusion analysis. Setting
            ``renumber=True`` will work around this.

            Only applicable if `data` is a :py:class:`pandas.DataFrame`.
        n_frames
            Number of frames. This needs to be given if sequence is flexible,
            i.e., contains multiplication by ``?``. In this case, ``?``
            evaluates to a number such that the total sequence length is
            `n_frames`. If `data` is an image sequence, `n_frames` can be
            inferred from ``len(data)``.

        Returns
        -------
        Selected frames. If `data` is a DataFrame, return only lines
        corresponding to excitation types given by `which`. If
        ``renumber=True``, a modified copy of `data` is returned.

        If `data` is an image sequence, first an attempt is made at
        indexing the images  directly. If `data` supports this (e.g. if it
        is a :py:class:`numpy.ndarray`), the indexed version is returned.
        Otherwise, `img_seq` is converted to
        :py:class:`helper.Slicerator`, indexed, and returned.

        Other parameters
        ----------------
        columns
            Override default column names in case `data` is a
            :py:class:`pandas.DataFrame`. The only relevant name is `time`.
            That means, if the DataFrame has frame number columns "frame2",
            set ``columns={"time": "frame2"}``.
        """
        if not self.excitation_seq:
            return data
        if not isinstance(data, pd.DataFrame) and n_frames is None:
            # Use length of image sequence
            n_frames = len(data)
        eval_seq = self.eval_seq(n_frames)

        if isinstance(data, pd.DataFrame):
            ret = data[
                self._find_mask(
                    eval_seq, data[columns["time"]].to_numpy(), which)]
            if renumber and not ret.empty:
                ret = ret.copy()
                ret[columns["time"]] = self._renumber(
                    eval_seq, ret[columns["time"]].to_numpy(), which, False)
            return ret

        # Deal with image data
        sel_idx = self._find_numbers(eval_seq, np.arange(len(data)), which)
        return self._get_subseq(data, sel_idx)

    @config.set_columns
    def restore_frame_numbers(self, data: pd.DataFrame,
                              which: Union[str, Iterable[str]],
                              n_frames: Optional[int] = None,
                              columns: Mapping = {}):
        """Undo frame renumbering from :py:meth:`select`

        `data` is modified in place for this purpose.

        Parameters
        ----------
        data
            Localization data
        which
            Excitation type(s), one or multiple characters out of
            :py:attr:`excitation_seq`.
        n_frames
            Number of frames. This needs to be given if sequence is flexible,
            i.e., contains multiplication by ``?``. In this case, ``?``
            evaluates to a number such that the total sequence length is
            `n_frames`.

        Other parameters
        ----------------
        columns
            Override default column names in case `data` is a
            :py:class:`pandas.DataFrame`. The only relevant name is `time`.
            That means, if the DataFrame has frame number columns "frame2",
            set ``columns={"time": "frame2"}``.
        """
        if not self.excitation_seq or data.empty:
            return
        data[columns["time"]] = self.renumber_frames(
            data[columns["time"]].to_numpy(), which, True, n_frames)

    def __eq__(self, other: "FrameSelector"):
        return self.excitation_seq == other.excitation_seq


import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
from service.crwaling import lotto_win_history_crawling
from service.compare import data_compare
from service.save import jdbc_config
from datetime import datetime
from dto import util

class WinHistoryImpl:
    def __init__(self, winObject:lotto_win_history_crawling.WinHistoryByArea):
        self.winObject = winObject
        self.jdbcConfig = jdbc_config.JDBCConfig()
        self.utils = util.Utils()

    def compareAndSaveData(self, fristList, secondList):
        lotto645 = data_compare.Lotto645WinInfoCompare()
        others = data_compare.OtherWinInfoCompare()
        l, unknown = lotto645.compareHistoryToStoreInfo(1, fristList["lotto645"])
        l2, unknown2 = lotto645.compareHistoryToStoreInfo(2, secondList["lotto645"])
        self._save_log_win_history(unknown)
        self._save_log_win_history(unknown2)
        ol, unknownOther = others.compareHistoryToStoreInfo(1, fristList)
        ol2, unknownOther2 = others.compareHistoryToStoreInfo(2, secondList)
        self._save_log_win_history(unknownOther)
        self._save_log_win_history(unknownOther2)
        self.utils.write_log_to_file("./log.log", f"l : {len(l)}, {len(unknown)}, l2: {len(l2)}, {len(unknown2)}")
        self.utils.write_log_to_file("./log.log", f"ol : {len(ol)}, {len(unknownOther)}, ol2: {len(ol2)}, {len(unknownOther2)}")
        # self.jdbcConfig.save_win_history_data(l)
        # self.jdbcConfig.save_win_history_data(l2)

        # self.jdbcConfig.save_win_history_data(ol)
        # self.jdbcConfig.save_win_history_data(ol2)

    def getData(self):
        winUtil = lotto_win_history_crawling.WinInfoUtil()
        queryParam = {}
        firstResult = {}
        secondResult = {}
        firstSido = {}
        secondSido = {}
        headers = winUtil.get_win_history_header()
        url = "https://dhlottery.co.kr/store.do"
        session = winUtil.get_session()
        queryParam["method"] = "topStore"

        for key, value in winUtil.lottoTypes.items():
            queryParam["pageGubun"] = value
            firstResult[key] = {}
            secondResult[key] = {}
            for sido in winUtil.address_map.keys():
                firstSigugun, secondSigugun = \
                        self._parseData(session, url, sido, headers, queryParam)
                firstSido[sido] = firstSigugun.copy()
                secondSido[sido] = secondSigugun.copy()
                firstSigugun.clear()
                secondSigugun.clear()
            firstResult[key] = firstSido.copy()
            secondResult[key] = secondSido.copy()
            firstSido.clear()
            secondSido.clear()
        return firstResult, secondResult

    def _parseData(self, session, url, sido, headers, queryParam):
        return self.winObject.parseWinHistory(session, url, sido, headers, queryParam)

    def _save_log_win_history(self, winhistory_data):
        current = datetime.now()
        for item in winhistory_data:
            with open("./error_win_history.txt", "a") as f:
                f.write(f"[{current.strftime('%H:%M:%S')}] ")
                for k,v in item.items():
                    f.write(f"{k}:{str(v)}, ")
                f.write("\n")


import random

def choose_option():
    options = ('piedra', 'papel','tijera')
    user_option=input('piedra, paptel o tijera =>')
    user_option= user_option.lower()

    #verificar si la opcion elegida por el usuario esta dentro de las opciones
    if not user_option in options:
        print('esa opcion no es valida')
        return None, None

    computer_opcion = random.choice(options)

    print('User Option =>',user_option)
    print('Computer Option =>',computer_opcion)
    return user_option, computer_opcion

def check_rules(user_option, computer_option, user_wins, computer_wins):
    if user_option == computer_option:
        print('Empate!')
    elif user_option=='piedra':
        if computer_option == 'tijera':
            print('Piedra gana a tijera \n user gano!')
            user_wins +=1
        else:
            print('Papel gana a piedra \n computer gano!')
            computer_wins +=1
    elif user_option == 'papel':
        if computer_option == 'piedra':
            print('papel gana a piedra \n user gano!')
            user_wins +=1
        else:
            print('tijera gana a papel \n computer gano!')
            computer_wins +=1
    elif user_option == 'tijera':
        if computer_option == 'papel':
            print('tijera gana a papel \n user gano!')
            user_wins +=1
        else:
            print('piedra gana a tijera \n computer gano!')
            computer_wins +=1
    return user_wins, computer_wins

#INICIO DEL JUEGO
def run_game():
    computer_wins = 0
    user_wins = 0
    rounds = 1
    while True:
        print('*' * 10)
        print('ROUND',rounds)
        print('*' * 10)

        user_option, computer_option = choose_option()
        user_wins, computer_wins = check_rules(user_option,computer_option, user_wins, computer_wins)

        if computer_wins == 2:
            print('El ganador es la computadora')
            break
        elif user_wins == 2:
            print('El ganador es el usuario!')
            break

run_game()


import flet as ft
import flet_fastapi
import os
from components.page_header.page_header import PageHeader
from components.search_bar.search_bar import SearchBar
from components.bookmarks.bookmarks import Bookmarks
from components.socials.socials import Socials
from utils import *

async def main(page: ft.Page):
    page.title = "Subhradeep's Custom Homepage"
    page.fonts = fonts
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    ref_search_field = ft.Ref[ft.TextField]()

    async def on_keyboard(e: ft.KeyboardEvent):
        if e.key == "/":
            ref_search_field.current.focus()
        await page.update_async()

    content = ft.Column(
        [
            PageHeader(),
            ft.Container(
                SearchBar(
                    page,
                    ref_search_field
                ),
                padding=5
            ),
            Socials(),
            Bookmarks(),
        ],
        spacing=35,
        expand=True,
        scroll=ft.ScrollMode.HIDDEN,
        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
    )

    page.on_keyboard_event = on_keyboard

    await page.add_async(
        content
    )

app = flet_fastapi.app(main, assets_dir=os.path.abspath("assets"))