import numpy as np

attributes = ["sky", "air", "humid", "wind", "water", "forecast", "attack"]

weatherData = [["sky", "sunny", "sunny", "rainy", "sunny", "sunny", "rainy"],
                ["air", "warm", "warm", "cold", "warm", "warm", "warm"],
                ["humid", "normal", "high", "high", "high", "normal", "high"],
                ["wind", "strong", "strong", "strong", "strong", "weak", "strong"],
                ["water", "warm", "warm", "warm", "cool", "warm", "warm"],
                ["forecast", "same", "same", "change", "change", "same", "change"],
                ["attack", "+", "+", "-", "+", "-", "-"]]

class Branch:
    def __init__(self, label):
        self.label = label
        self.tree = None

    def __str__(self):
        result = "--" + self.label + "-->"
        if type(self.tree) is Tree:
            result += self.tree.name + "\n"
        result += str(self.tree) + "\n"
        return result

class Tree:
    def __init__(self, name):
        self.name = name
        self.branches = []

    def add_a_branch(self, new_tree, label):
        branch = Branch(label)
        branch.tree = new_tree
        self.branches.append(branch)

    def __str__(self):
        result = ""
        for b in self.branches:
            result += self.name
            result += str(b)
        return result

def dtLearning(examples, attributes, parent_examples):
    if len(examples) == 0:
        return plurality(parent_examples)
    elif is_same_classifications(examples):
        return get_attr_values(get_classification(examples), examples)
    elif len(attributes) == 0:
        return plurality(examples)
    else:
        # find the attribute with the highest information gain
        important_attribute = getImportanceAttributeName(examples, attributes)
        # print("important attribute:", important_attribute)
        tree = Tree(important_attribute)
        attr_value_list = get_attr_values(important_attribute, examples)
        for each_attribute_value in attr_value_list:
            # only datasets of example, where important_attribute has the value of each_attribute_value
            exs = ExampleSetElimination(examples, each_attribute_value, important_attribute)
            subtree = dtLearning(exs, reduce_attr_list(important_attribute, attributes), examples)
            tree.add_a_branch(subtree, each_attribute_value)
        return tree

# returns a copy of the given 2d-array
def copy_2d_array(original_array):
    copy_of_array = []
    for e in original_array:
        column = []
        for a in e:
            column.append(a)
        copy_of_array.append(column)
    return copy_of_array

# returns a copy of attr_list without attr
def reduce_attr_list(attr, attr_list):
    result = []
    for a in attr_list:
        result.append(a)
    result.remove(attr)
    return result

#returns the column of the given attribute
def get_attr_values_complete_list(attribute, data):
    copy_of_examples = copy_2d_array(data)
    attr_values = []
    for column in copy_of_examples:
        if attribute == column[0]:
            for a in column:
                attr_values.append(a)
    return attr_values

# returns only the datasets of examples, where attr has the value of attr_value
def ExampleSetElimination(examples, attr_value, attr):
    newExamples = copy_2d_array(examples)
    attr_value_list = get_attr_values_complete_list(attr, examples) # column of the given attribute
    positionList = find_positions(attr_value, attr_value_list) # list of indices of datasets to remove
    # remove datasets
    for pos in positionList:
        for column in newExamples:
            column.pop(pos)
    #print(newExamples)
    for ne in newExamples:
        if attr == ne[0]:
            newExamples.remove(ne)
    return newExamples

# returns a list which contains all indices of values in column that are not the attr_value (in descending order)
def find_positions(attr_value, column):
    positions = []
    for index, value in enumerate(column):
        if value != attr_value and index != 0: # except label
            positions.append(index)
    return flipList(positions)

# returns the list in reversed order
def flipList(list):
    result = []
    max = len(list) - 1
    for n in range((len(list))):
        result.append(list[max - n])
    return result

# Test for ExampleSetElimination
# print("before: " + "\n")
# print(str(weatherData) + "\n")
# exs_test = ExampleSetElimination(weatherData, "sunny", "sky")
# print("after: " + "\n")
# print(str(exs_test) + "\n")

# returns a list which contains all possible values for the given attribute once
def get_attr_values(attribute, data):
    copy_of_examples = copy_2d_array(data)
    attr_values = []
    for column in copy_of_examples:
        if attribute == column[0]:
            for a in column:
                if a not in attr_values:
                    attr_values.append(a)
    if len(attr_values) != 0:
        attr_values.pop(0) #remove label
    return attr_values

# Test for get_attr_values
# print(get_attr_values("sky", weatherData))

# returns the most common output value
def plurality(examples):
    copy_of_examples = copy_2d_array(examples)
    output_values = copy_of_examples[-1] #output values
    output_values.pop(0) #remove label
    output_values.sort()
    attribute_value_name = output_values[0]
    count = 0
    max_count = 0
    value_with_max_count = attribute_value_name
    for current_value in output_values:
        if current_value == attribute_value_name:
            count += 1
        else:
            if max_count < count: #check max_count
               max_count = count
               value_with_max_count = attribute_value_name
            attribute_value_name = current_value #count next value
            count = 1
    if max_count < count: #check max_count
        max_count = count
        value_with_max_count = attribute_value_name
    return value_with_max_count

# Test for plurality
# data = [['animals', 'duck', 'duck', 'dog', 'dog', 'dog'], ['animals', 'duck', 'duck', 'dog', 'dog', 'dog']]
# print(plurality(data))

# returns the label of the output values
def get_classification(data):
    return data[-1][0]

# returns true iff all examples have same classification
def is_same_classifications(data):
    return len(get_attr_values(get_classification(data), data)) <= 1

# returns the information gain of an attribute, given by the index of its column in the set of examples
def importance(attribute_index, examples):
    attribute = examples[attribute_index] #column of the given attribute
    last_attribute = examples[-1] #column of the output vlaues
    positive_and_negative_count = len(last_attribute) - 1 #except label

    # count the positive output value
    positive_count = 0
    attribute_positive_value_name = last_attribute[1] #first output value
    for index, value in enumerate(last_attribute):
        if index != 0: #except label
            if value == attribute_positive_value_name:
                positive_count += 1

    # probability of the positive output value
    q = positive_count / positive_and_negative_count

    remainder_result = remainder(attribute, examples, attribute_positive_value_name)

    if remainder_result is None:
        result = b(q)
    else:
        result = b(q) - remainder_result
    return result

# B(q) = -(q log2(q) + (1 - q) log2(1 - q)
def b(q):
    if q != 0:
        b = (q * (np.log(q) / np.log(2)))
        if q != 1:
            b += ((1 - q) * (np.log(1 - q) / np.log(2)))
        b = -b
    else:
        b = 0
    return b

#calculates remainder function
def remainder(attribute, examples, attribute_positive_value_name):
    last_attribute = examples[-1]  # column of output values
    e_count = len(attribute) - 1 #except label
    e1_count = 0
    p_e1 = 0
    p_e2 = 0

    attribute_value_name = attribute[1] #first value
    for index, value in enumerate(attribute):
        if index != 0: #except label
            if value == attribute_value_name:
                e1_count += 1 #counts the first value
                if last_attribute[index] == attribute_positive_value_name:
                    p_e1 += 1 #counts the positive output value for the first value of the given attribute
            else:
                if last_attribute[index] == attribute_positive_value_name:
                    p_e2 += 1 #counts the positive output value for the second value of the given attribute

    e2_count = e_count - e1_count #count of the second value

    if e1_count > 0:
        q1 = p_e1 / e1_count
    elif e1_count == 0:
        q1 = 0

    if e2_count > 0:
        q2 = p_e2 / e2_count
    elif e2_count == 0:
        q2 = 0

    result = (e1_count / e_count) * b(q1) + (e2_count / e_count) * b(q2)
    return result

# returns the label of the attribute with the highest information gain
def getImportanceAttributeName(examples, attributes):
    ig_max_attribute_name = None
    ig_max = 0
    for attribute_column_index, attribute_column in enumerate(examples):
        if attribute_column_index != (len(examples) - 1): #except the output value
            ig_current = importance(attribute_column_index, examples)
            if (ig_current > ig_max):
                ig_max = ig_current
                # store the label of the attribute with the current maximum information gain
                ig_max_attribute_name = attributes[attribute_column_index]
    return ig_max_attribute_name

# TEST
end_result_tree = dtLearning(weatherData, attributes, [])
print(end_result_tree)


import PyPDF2
import os

def parse_docs():
    path = "./src/cache/"

    all_text = []

    for i, filename in enumerate(os.listdir(path)):
        file_path = os.path.join(path, filename)
        # checking if it is a file
        if os.path.isfile(file_path):

            text_obj = {}

            reader = PyPDF2.PdfReader(file_path)

            full_txt = ""
            for page in reader.pages:
                full_txt += page.extract_text()

            #For some reason ČSI labels all pdfs differently every year
            pdf_idx = file_path.replace("./src/cache/", "").replace(".pdf", "")[-1]
            if pdf_idx == "0" or pdf_idx == "1":

                #parse txt to get rid of useless parts
                idx = full_txt.find("Závěry")
                top_parse = full_txt[idx:]

                idx = top_parse.find("Seznam dokladů")
                bot_parse = top_parse[:idx]

            elif pdf_idx == "2":

                #parse txt to get rid of useless parts
                idx = full_txt.find("Celkové hodnocení školy")
                top_parse = full_txt[idx:]

                idx = top_parse.find("Seznam písemností,")
                bot_parse = top_parse[:idx]

            elif pdf_idx == "3":

                #parse txt to get rid of useless parts
                idx = full_txt.find("ZÁVĚR")
                top_parse = full_txt[idx:]

                idx = top_parse.find("Razítko")
                bot_parse = top_parse[:idx]

            elif pdf_idx == "4":

                #parse txt to get rid of useless parts
                idx = full_txt.find("ZÁVĚR")
                top_parse = full_txt[idx:]

                idx = top_parse.find("Razítko")
                bot_parse = top_parse[:idx]

            text_obj["label"] = file_path.replace("./src/cache/", "").replace(".pdf", "")[:-2]
            text_obj["text"] = bot_parse

            all_text.append(text_obj)

    return all_text

if __name__ == "__main__":
    print(os.getcwd())
    parse_docs()


import cv2

vid = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier()
face_cascade.load('face_model.xml')

if face_cascade is None:
    print('something fishy')

while True:
    state, frame = vid.read()
    if not state:
        print('cant find any frame in video, exiting')
        break
    # face detection logic
    gray =cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray)
    print("faces",len(faces))
    if len(faces) > 0:
        for x,y,w,h, in faces:
            frame = cv2.rectangle(frame,(x,y),(x+w,y+h),(255,255,0),6)

    cv2.imshow("video",frame)
    if cv2.waitKey(1) == ord('q'):
        break

vid.release()
cv2.destroyAllWindows()


import numpy as np
import scipy as sp
import scipy.optimize
import matplotlib as mpl
import matplotlib.pyplot as plt

R = 1#1.3/2
n = 1.35
shift = 0#-.75 - R
last_x = 5
old = False

def intersect_circle(alpha, x0, y0, R):
    a = 1 + np.tan(alpha)**2
    b = 2*np.tan(alpha)*(y0 - x0*np.tan(alpha))
    c = x0**2 * np.tan(alpha)**2 - 2*x0*y0*np.tan(alpha) + y0**2 - R**2

    discr = b**2 - 4*a*c
    if discr >= 0:
        xa = (-b + np.sqrt(discr))/(2 * a)
        xb = (-b - np.sqrt(discr))/(2 * a)
        return [xa, xb]
    else:
        return None

def refract(alpha, x0, y0, ni, nt):
    ray_inc = np.array([1, np.tan(alpha)])
    ray_inc /= np.linalg.norm(ray_inc)
    normal = np.array([x0, y0])
    normal /= np.linalg.norm(normal)
    print(ray_inc)
    print(normal)

    if old:
        theta_i = np.arccos(np.dot(ray_inc, normal))
        if theta_i > np.pi/2:
            theta_i = np.pi - theta_i
        print("theta_i {0}".format(theta_i/np.pi*180))
        theta_t = np.arcsin(ni * np.sin(theta_i) / nt)
        print("theta_t {0}".format(theta_t/np.pi*180))
        print("alpha {0}".format(alpha/np.pi*180))
        vec0 = ni * np.cross(ray_inc, normal)
        print("ray_inc x normal {0}".format(vec0))
        alpha_new1 = theta_t - theta_i + alpha
        vec1a = nt * np.cross([1, np.tan(alpha_new1)]/(1 + np.tan(alpha_new1)**2), normal)
        alpha_new2 = alpha - (theta_t - theta_i)
        vec1b = nt * np.cross([1, np.tan(alpha_new2)]/(1 + np.tan(alpha_new2)**2), normal)
        print("ray_trans x normal {0}, {1}".format(vec1a, vec1b))
        if np.abs(vec1a - vec0) < np.abs(vec1b - vec0):
            alpha_new = alpha_new1
        else:
            alpha_new = alpha_new2
        if np.amin([np.abs(vec1a - vec0),  np.abs(vec1b - vec0)]) > .01:
            print("warning raytracing")

    else:
        ray_inc_3 = np.array([ray_inc[0], ray_inc[1], 0])
        normal_3 = np.array([normal[0], normal[1], 0])
        if np.dot(ray_inc, normal) > 0:
            normal_3 = -normal_3
        kt = ni/nt*np.cross(normal_3, np.cross(-1*normal_3, ray_inc_3)) - normal_3 * np.sqrt(1 - (ni/nt)**2 * np.linalg.norm(np.cross(normal_3, ray_inc_3))**2)
        print("{0} {1} {2}".format(kt, np.arctan2(kt[1], kt[0]), nt*np.cross([kt[0], kt[1]], normal)))
        alpha_new = np.arctan2(kt[1], kt[0])
        print("ni * ki x normal {0}".format(ni * np.cross(ray_inc, normal)))
        print("nt * kt x normal {0}".format(nt*np.cross([kt[0], kt[1]], normal)))
    return (alpha_new, x0, y0)

def plot_segment(x0, y0, x1, y2, alpha, color='b-'):
    beta = np.linspace(0, 1)
    x = beta * x0 + (1 - beta) * x1
    y = np.tan(alpha) * (x - x0) + y0
    plt.plot(x - shift, y, color)

def raytrace(alpha, x0, y0, color='b-'):
    #plot ray 1
    x1 = np.amin(intersect_circle(alpha, x0, y0, R))
    if x1 is None:
        x1 = last_x
        y1 = np.tan(alpha) * (x1 - x0) + y0
        plot_segment(x0, y0, x1, y1, alpha, color)
        return
    y1 = np.tan(alpha) * (x1 - x0) + y0
    plot_segment(x0, y0, x1, y1, alpha, color)

    #plot ray 2
    alpha1, *c = refract(alpha, x1, y1, 1, n)
    print(alpha1)
    x2 = np.amax(intersect_circle(alpha1, x1, y1, R))
    y2 = np.tan(alpha1) * (x2 - x1) + y1
    plot_segment(x1, y1, x2, y2, alpha1, color)

    #plot ray 3
    alpha2, *c = refract(alpha1, x2, y2, n, 1)
    print(alpha2)
    x3 = last_x
    y3 = np.tan(alpha2) * (x3 - x2) + y2
    plot_segment(x2, y2, x3, y3, alpha2, color)

def raytrace_angles(angles, x0, y0, color='b-'):
    for angle in angles:
        raytrace(angle/180*np.pi, x0, y0, color)

x0 = -2 - R
y0 = 0

"""
# Chromatic Aberration
n = 1.33141
raytrace_angles(range(-18, 19, 4), x0, y0, 'r-')
n = 1.34235
raytrace_angles(range(-18, 19, 4), x0, y0, 'b-')
"""

"""Spherical Aberration
raytrace_angles(range(-18, 19, 2), x0, y0, 'b-')
"""

raytrace_angles(range(-4,17,2), x0, y0, 'b-')
#raytrace_angles(range(-10,11,2), x0, y0, 'r-')

"""
old = True
raytrace(3/180*np.pi, x0, y0, 'r-')
raytrace(5/180*np.pi, x0, y0, 'r-')
raytrace(10/180*np.pi, x0, y0, 'r-')
raytrace(18/180*np.pi, x0, y0, 'r-')
"""

y0 = .2
"""
raytrace(-.05, x0, y0, 'g-')
raytrace(-.01, x0, y0, 'g-')
raytrace(-.1, x0, y0, 'g-')
raytrace(-.03, x0, y0, 'g-')
raytrace(.1, x0, y0, 'g-')
raytrace(.05, x0, y0, 'g-')
raytrace(.01, x0, y0, 'g-')
raytrace(.03, x0, y0, 'g-')
raytrace(0, x0, y0, 'g-')
"""

"""
alpha = .03
raytrace(alpha, x0, 0, 'k-')
raytrace(alpha, x0, .1, 'k-')
raytrace(alpha, x0, .2, 'k-')
raytrace(alpha, x0, .3, 'k-')
raytrace(alpha, x0, .4, 'k-')
"""

"""
alpha = 0
raytrace(alpha, x0, 0, 'r-')
raytrace(alpha, x0, .1, 'r-')
raytrace(alpha, x0, .2, 'r-')
raytrace(alpha, x0, .3, 'r-')
raytrace(alpha, x0, .4, 'r-')
raytrace(alpha, x0, -.1, 'r-')
raytrace(alpha, x0, -.2, 'r-')
raytrace(alpha, x0, -.3, 'r-')
raytrace(alpha, x0, -.4, 'r-')
"""

plt.axis([-3,5,-1,1])
#plot lens
phi = np.linspace(0, 2 * np.pi)
plt.plot(R*np.cos(phi) - shift, R*np.sin(phi), 'r-')

plt.grid(b=True, which='major', color='k', linestyle='--')
plt.show()


class Employees:
    def __init__(self, empNum, name, salay):
        self.empNum = empNum
        self.name = name
        self.salary = salay

    def convert(self):
        lst = []
        lst.extend([self.empNum, self.name, self.salary])
        return lst

# Selection Sort

def selectionSort(list1):
    for i in range(0, len(list1)-1):
        minindex = i
        for j in range(i+1, len(list1)):
            if list1[j][2] < list1[minindex][2]:
                minindex = j
        if minindex != i:
            list1[i], list1[minindex] = list1[minindex], list1[i]

lst = []
e1 = Employees(1, "John", 80000)
e2 = Employees(2, "Mike", 50000)
e3 = Employees(3, "Derek", 30000)
e4 = Employees(4, "Raj", 25000)
lst.extend([e1.convert(), e2.convert(), e3.convert(), e4.convert()])
print('\n**********************************Unsorted List**********************************')
print(lst)
print('Sorted List Using Selection Sort: ')
selectionSort(lst)
print(lst)

# Bubble Sort

def bubbleSort(lst):
    n = len(lst)
    for i in range(n):
        for j in range(0, n-i-1):
            if lst[j][2] > lst[j+1][2]:
                lst[j], lst[j+1] = lst[j+1], lst[j]

lst = []
e1 = Employees(1, "John", 80000)
e2 = Employees(2, "Mike", 50000)
e3 = Employees(3, "Derek", 30000)
e4 = Employees(4, "Raj", 25000)
lst.extend([e1.convert(), e2.convert(), e3.convert(), e4.convert()])
print('\n**********************************Unsorted List**********************************')
print(lst)
print('Sorted List Using Bubble Sort: ')
bubbleSort(lst)
print(lst)

# Insertion Sort

def insertionSort(lst):
    for i in range(1, len(lst)):
        temp = lst[i][2]
        j = i-1
        while j >= 0 and temp < lst[j][2]:
            lst[j + 1][2] = lst[j][2]
            j -= 1
        lst[j + 1][2] = temp

lst = []
e1 = Employees(1, "John", 80000)
e2 = Employees(2, "Mike", 50000)
e3 = Employees(3, "Derek", 30000)
e4 = Employees(4, "Raj", 25000)
lst.extend([e1.convert(), e2.convert(), e3.convert(), e4.convert()])
print('\n**********************************Unsorted List**********************************')
print(lst)
print('Sorted List Using Insertion Sort: ')
insertionSort(lst)
print(lst)
print()


from ast import LtE
from heapq import heapify
from http.client import PAYMENT_REQUIRED
from logging import lastResort
from socket import J1939_MAX_UNICAST_ADDR
from tkinter import *
from tkinter.tix import ROW
root = Tk()
frame = Frame()
frame.pack()
root.title("base de datos alumnos")
root.geometry("780x500")

Nombre = Label(frame, text="NOMBRE", justify=LEFT)
Nombre.grid(row= 1 , column= 0, pady=10)
Apellido = Label(frame, text="APELLIDO", justify=LEFT)
Apellido.grid(row= 2 , column= 0, pady=10, padx=2)
Edad = Label (frame, text="EDAD", justify=LEFT)
Edad.grid(row=3, column=0, pady=10)
Fnacimiento = Label(frame, text="FECHA NACIMIENTO", justify=LEFT)
Fnacimiento.grid(row= 4 , column= 0, pady=10)

#area de texto
ltext = Label(frame, text="INFORMACION", justify=LEFT)
ltext.grid(row=2, column=3, padx=5)
binformacion = Button(frame, text="GET-INFORMACION")
binformacion.grid(row=1, column=4, pady=5)
T = Text(frame, width=20, height=10,)
T.grid(row=2, column=4, pady=30)

#creacion de los entrys
eNombre = Entry(frame)
eNombre.grid(row=1 , column= 1) #nombre

eApellido = Entry(frame)
eApellido.grid(row=2 , column= 1) #apellido

eEdad = Entry(frame)
eEdad.grid(row=3 , column= 1) #edad

Efnacimiento = Entry(frame)
Efnacimiento.grid(row=4 , column= 1) #fecha nacimient

ematerias = Entry(frame)
ematerias.grid(row=4, column= 1) #materias

#AREA IFORMACION

#area de botones de crud
C = Button(frame, text="CREAR")
C.grid(row=6, column=1) #crate

R = Button(frame, text="RELOAD")
R.grid(row=6, column=3) #read

U = Button(frame, text="UPDATE")
U.grid(row=6, column=2) #crate

D = Button(frame, text="DELETE")
D.grid(row=6, column=4) #updateCREAR

root.mainloop()


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

# __new__ 생성자를 이용해 구현
# __new__ 생성자는 __init__이 반환값을 가질 수 없는 점을 보완한 생성자
class Singleton(object):
    def __new__(self):
        if not hasattr(self,'instance'): # instance 라는 속성이 없다면
            self.instance = super(Singleton,self).__new__(self)
            return self.instance

def main():
    s = Singleton()
    s2 = Singleton()

    print(s)
    print(s2)

if __name__ == "__main__":
    main()


import tkinter

def check_nul():
    print("match nul")

def print_winner():
    global win

    if win is False:
        win = True
        print("Le joueur", current_player, "a gagné le jeu")

def switch_player():
    global current_player
    if current_player == "X":
        current_player = "O"
    else:
        current_player = "X"

def chek_win(clicked_row, clicked_col):
    # detecter victoire horiaontale
    count = 0
    for i in range(3):
        current_button = buttons[i][clicked_row]
        if current_button["text"] == current_player:
            count += 1
    if count == 3:
        print_winner()

     # detecter victoire verticale
    count = 0
    for i in range(3):
        current_button = buttons[clicked_col][i]
        if current_button["text"] == current_player:
            count += 1
    if count == 3:
        print_winner()

     # detecter victoire en diagonale
    count = 0
    for i in range(3):
        current_button = buttons[i][i]
        if current_button["text"] == current_player:
            count += 1
    if count == 3:
        print_winner()

    # detecter victoire en diagonale inversee
    count = 0
    for i in range(3):
        current_button = buttons[2-i][i]
        if current_button["text"] == current_player:
            count += 1
    if count == 3:
        print_winner()

    if win is False:
        count = 0
        for col in range(3):
            for row in range(3):
                current_button = buttons[col][row]
                if current_button["text"] == "X" or current_button["text"] == "O":
                    count += 1

                if count == 9:
                    print("match nul")

def place_symbol(row, column):
    print("click", row, column)

    clicked_button = buttons[column][row]
    clicked_button.config(text=current_player)

    chek_win(row, column)
    switch_player()

#permet de créer une grille a l'aide de button
def draw_grid():
    for column in range(3):
        buttons_in_cols = []
        for row in range(3):
            button = tkinter.Button(
                root, font=("Arial", 50),
                width=5, height=3,
                command=lambda r=row, c=column:place_symbol(r, c)
                )
            button.grid(row=row, column=column)
            buttons_in_cols.append(button)
        buttons.append(buttons_in_cols)

#stockage
buttons = []
current_player = "X"
win = False

#creer la fenetre du jeux
root = tkinter.Tk()

#personnalisation de la fenetre
root.title("TicTacToe")
root.minsize(500, 500)

draw_grid()
root.mainloop()


"""Test pycog.graph"""

import sys
import os.path as op

# Need this so we pick up the code base for which this is a test, not an
# installed version.

package_dir = op.abspath(op.join('..', 'packages'))
if package_dir not in sys.path:
    sys.path.insert(0, package_dir)

import unittest

from pycog.graph import *

class TestGraph(unittest.TestCase):
    def setUp(self):
        self.graph = Graph()

    def test_vertices(self):
        """Test adding and removing vertices"""

        self.assertEqual(self.graph.num_vertices(), 0)

        self.graph.add("a")
        self.graph.add("b")
        self.graph.add("c")
        self.graph.add("d")
        self.graph.add("e")

        self.assertEqual(self.graph.num_vertices(), 5)

        self.graph.remove("b")
        self.graph.remove("e")
        self.assertEqual(self.graph.num_vertices(), 3)

        self.graph.clear()
        self.assertEqual(self.graph.num_vertices(), 0)

    def test_connect(self):
        for i in range(10): self.graph.add(i)

        # Connect each integer to its successors in the graph
        for v in range(9):
            for s in range(v+1, 10):
                self.graph.connect(v, s)

        # Test degree
        for v in range(10):
            self.assertEqual(self.graph.in_degree(v), v)
            self.assertEqual(self.graph.out_degree(v), 9-v)

        # Test succ
        for v in range(10):
            expected = set(range(v + 1, 10))
            for s in self.graph.succ(v):
                expected.remove(s)
            self.assertEqual(len(expected), 0)

        # Test pred
        for v in range(10):
            expected = set(range(v))
            for s in self.graph.pred(v):
                expected.remove(s)
            self.assertEqual(len(expected), 0)

    def test_double_add(self):
        self.graph.clear()
        self.graph.add('a')
        self.graph.add('b')
        self.graph.connect('a', 'b')
        self.graph.add('c')
        self.graph.add('b') # double add -- should keep connection to a.
        self.graph.connect('c', 'b')
        self.assertTrue('a' in self.graph.pred('b'))

class TestGraphWrapper(TestGraph):
    def setUp(self):
        self.graph = GraphWrapper(Graph())

class MinGraph:
    """
    Graph class with only required protcol methods.
    """

    def __init__(self):
        self._vertices = set()
        self._succ = dict()

    def vertices(self):
        """Return an iterator over the vertices."""

        return self._vertices.__iter__()

    def succ(self, v):
        """
        Get the successors of a vertex.

        Args:
            v: Vertex for which successors are desired.

        Returns:
            An iterator over the successor vertices.

        Raises:
            KeyError if the vertex is not in the graph.
        """
        return self._succ[v].__iter__()

    def add(self, v):
        """
        Add a vertex to the graph.

        Args:
            v: Vertex to add.
        """
        self._vertices.add(v)
        self._succ[v] = set()

    def remove(self, v):
        """
        Remove a vertex from the graph.

        Args:
            v: Vertex to remove.
        """
        for s in self.succ(v):
            self.disconnect(v, s)
        self._vertices.remove(v)
        del self._succ[v]

    def connect(self, pred, succ):
        """
        Create a directed edge between two vertices.

        Args:
            pred: predecessor vertex.  The edge is traversed from this vertex.
            succ: successor vertex.  The edge is traversed to this vertex.

        Raises:
            KeyError if either vertex is not in the graph.
        """
        self._succ[pred].add(succ)

    def disconnect(self, pred, succ):
        """
        Removed a directed edge between two vertices.

        Args:
            pred: predecessor vertex.  The edge is traversed from this vertex.
            succ: successor vertex.  The edge is traversed to this vertex.

        Raises:
            KeyError if either vertex is not in the graph.
        """
        self._succ[pred].remove(succ)

    #
    # Graph protocol definitions
    #

    # Required
    gp_vertices = vertices
    gp_succ = succ
    gp_add = add
    gp_remove = remove
    gp_connect = connect
    gp_disconnect = disconnect

class TestGraphWrapperMin(TestGraph):
    def setUp(self):
        self.graph = GraphWrapper(MinGraph())

class OrderRecorder:
    """
    Class to record visit order.
    """

    def __init__(self, **kw_args):
        super().__init__(**kw_args)
        self.order = []

    def on_visit(self, vertex):
        self.order.append(vertex)

class BFSOrderRecorder(OrderRecorder, BreadthFirstSearch):
    """
    Collects the visitor order of a BreadthFirstSearch
    """
    def __init__(self, **kw_args):
        super().__init__(**kw_args)

class DFSOrderRecorder(OrderRecorder, DepthFirstSearch):
    """
    Collects the visitor order of a DepthFirstSearch
    """
    def __init__(self, **kw_args):
        super().__init__(**kw_args)

class TestBFS(unittest.TestCase):

    def setUp(self):

        # Cycle and an isolated vertex.  This graph might look like a tree
        # because every vertex except the isolated vertex has one predecessor,
        # (the isolated vertex has no predecessors).
        self.isolated = Graph()
        self.isolated.add('isolated')
        for x in range(5):
            self.isolated.add(x)
        for x in range(4):
            self.isolated.connect(x, x+1)
        self.isolated.connect(4, 0)

        self.singleton = Graph()
        self.singleton.add(0)

        self.ring = Graph()
        for x in range(6):
            self.ring.add(x)
        for x in range(5):
            self.ring.connect(x, x+1)
        self.ring.connect(5, 0)

        self.tree = Graph()
        self.tree.add(0)
        for x in range(1, 31):
            self.tree.add(x)
            self.tree.connect((x-1) >> 1, x)

    def test_is_tree(self):
        self.assertEqual(is_tree(self.tree), 0)
        self.assertEqual(is_tree(self.singleton), 0)
        self.assertFalse(is_tree(self.isolated))
        self.assertFalse(is_tree(self.ring))

    def test_visit_order(self):
        orderRecorder = BFSOrderRecorder(graph=self.tree, start_vertex=0)
        orderRecorder.run()
        self.assertEqual(orderRecorder.order, [x for x in range(31)])

class TestDFS(unittest.TestCase):
    def setUp(self):
        self.tree = Graph()
        self.tree.add(0)
        for x in range(1, 31):
            self.tree.add(x)
            self.tree.connect((x-1) >> 1, x)

    def test_visit_order(self):
        expectedOrder = [0, 1, 3, 7, 15, 16, 8, 17, 18, 4, 9, 19, 20, 10, 21,
                         22, 2, 5, 11, 23, 24, 12, 25, 26, 6, 13, 27, 28, 14,
                         29, 30]
        orderRecorder = DFSOrderRecorder(graph=self.tree, start_vertex=0)
        orderRecorder.run()
        self.assertEqual(orderRecorder.order, expectedOrder)

if __name__ == '__main__':
    unittest.main()


from termcolor import colored

print(colored('{txt:*^119}'.format(txt='*'), 'red'))
print(colored("""
                                                         |--__
                                                         |
                                                         X
                                                |-___   / \       |--__
                                                |      =====      |
                                                X      | .:|      X
                                               / \     | O |     / \\
                                              =====   |:  . |   =====
                                              |.: |__| .   : |__| :.|
                                              |  :|. :  ...   : |.  |
                                      __   __W| .    .  ||| .      :|W__  --
                                    -- __  W  WWWW______"_"______WWWW   W -----  --
                                -  -     ___  ---    ____     ____----       --__  -
                                    --__    --    --__     -___        __-   _
""", 'red'))
print(colored('{txt:*^119}'.format(txt='*'), 'red'))
print(colored('{txt:*^119}'.format(txt='*'), 'blue'))
print(colored("""
                                                     Привет!

                    Это приложение по созданию листа персонажа для игры Dungeons & Dragons.
                    Ниже будут появляться инструкции, следуй им и у тебя будет самый топовый персонаж
""", 'blue'))
print(colored('{txt:*^119}'.format(txt='*'), 'blue'))
print('{txt:*^119}\n'.format(txt='*'))
name_player = input('Шаг 1: Для начала давай познакомимся! Введите ваше имя: ')  # имя игрока
print()

def input_gender():
    print('Шаг 2: За персонажа какого пола вы будете играть: ')
    gender = {
        1: ['Мужчина (Man)'],
        2: ['Женщина (Woman)']
    }
    for number, gender_name in gender.items():
        print(' {num:^5} |    {name} '.format(num=number, name=gender_name[0]))
    user_input_gender = int(input('Введите номер пола: '))

    while user_input_gender not in gender:
        print('Такого пола нет')
        user_input_gender = int(input("Введите номер пола: "))
    else:
        print('Вы выбрали пол', gender[user_input_gender][0], '\n')
        name_gender = gender[user_input_gender][0]
        return name_gender

def input_level():
    print('Шаг 3: За персонажа какого уровня вы будете играть: ')
    user_input_level = int(input('Введите номер уровня от 1 до 20: '))
    lvl = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

    while user_input_level not in lvl:
        print('Такого уровня нет')
        user_input_level = int(input("Введите номер уровня от 1 до 20: "))
    else:
        print('Вы выбрали уровень', user_input_level, '\n')
        name_level = user_input_level
        return name_level

name = ''  # имя персонажа
game_gender = input_gender()  # пол персонажа
age = ''  # возраст персонажа
height = ''  # рост персонажа
weight = ''  # вес персонажа

race = ''  # раса
game_class = ''  # класс
background = ''  # предыстория
alignment = ''  # мировоззрение

like_mechanics = ''  # призвание/гильдия/судьбоносное происшествие
personality_traits = ''  # черты характера
ideals = ''  # идеалы
bonds = ''  # привязанности
flaws = ''  # слабости

level = input_level()  # уровень
experience_point = 0  # опыт
proficiency_bonus = 0  # бонус мастерства

if level == 1:
    experience_point = 0
    proficiency_bonus = 2
elif level == 2:
    experience_point = 300
    proficiency_bonus = 2
elif level == 3:
    experience_point = 900
    proficiency_bonus = 2
elif level == 4:
    experience_point = 2700
    proficiency_bonus = 2
elif level == 5:
    experience_point = 6500
    proficiency_bonus = 3
elif level == 6:
    experience_point = 14000
    proficiency_bonus = 3
elif level == 7:
    experience_point = 23000
    proficiency_bonus = 3
elif level == 8:
    experience_point = 34000
    proficiency_bonus = 3
elif level == 9:
    experience_point = 48000
    proficiency_bonus = 4
elif level == 10:
    experience_point = 64000
    proficiency_bonus = 4
elif level == 11:
    experience_point = 85000
    proficiency_bonus = 4
elif level == 12:
    experience_point = 100000
    proficiency_bonus = 4
elif level == 13:
    experience_point = 120000
    proficiency_bonus = 5
elif level == 14:
    experience_point = 140000
    proficiency_bonus = 5
elif level == 15:
    experience_point = 165000
    proficiency_bonus = 5
elif level == 16:
    experience_point = 195000
    proficiency_bonus = 5
elif level == 17:
    experience_point = 225000
    proficiency_bonus = 6
elif level == 18:
    experience_point = 265000
    proficiency_bonus = 6
elif level == 19:
    experience_point = 305000
    proficiency_bonus = 6
elif level == 20:
    experience_point = 355000
    proficiency_bonus = 6

strength = 0  # сила
dexterity = 0  # ловкость
constitution = 0  # телосложение
intelligence = 0  # интеллект
wisdom = 0  # мудрость
charisma = 0  # харизма

mod_strength = 0  # модификатор сила
mod_dexterity = 0  # модификатор ловкость
mod_constitution = 0  # модификатор телосложение
mod_intelligence = 0  # модификатор интеллект
mod_wisdom = 0  # модификатор мудрость
mod_charisma = 0  # модификатор харизма

check_saving_throws_strength = False  # знание спас бросок сила
check_saving_throws_dexterity = False  # знание  спас бросок ловкость
check_saving_throws_constitution = False  # знание  спас бросок телосложение
check_saving_throws_intelligence = False  # знание  спас бросок интеллект
check_saving_throws_wisdom = False  # знание  спас бросок мудрость
check_saving_throws_charisma = False  # знание  спас бросок харизма

saving_throws_strength = mod_strength  # спас бросок сила
saving_throws_dexterity = mod_dexterity  # спас бросок ловкость
saving_throws_constitution = mod_constitution  # спас бросок телосложение
saving_throws_intelligence = mod_intelligence  # спас бросок интеллект
saving_throws_wisdom = mod_wisdom  # спас бросок мудрость
saving_throws_charisma = mod_charisma  # спас бросок харизма

check_acrobatics = False  # знание акробатика
check_perception = False  # знание анализ
check_athletics = False  # знание атлетика
check_investigation = False  # знание внимательность
check_survival = False  # знание выживание
check_performance = False  # знание выступление
check_intimidation = False  # знание запугивание
check_history = False  # знание история
check_sleight_of_hand = False  # знание ловкость рук
check_arcana = False  # знание магия
check_medicine = False  # знание медицина
check_deception = False  # знание обман
check_nature = False  # знание природа
check_insight = False  # знание проницательность
check_religion = False  # знание религия
check_stealth = False  # знание скрытность
check_persuasion = False  # знание убеждение
check_animal_handling = False  # знание уход за животными

acrobatics = mod_dexterity  # акробатика
perception = mod_intelligence  # анализ
athletics = mod_strength  # атлетика
investigation = mod_wisdom  # внимательность
survival = mod_wisdom  # выживание
performance = mod_charisma  # выступление
intimidation = mod_charisma  # запугивание
history = mod_intelligence  # история
sleight_of_hand = mod_dexterity  # ловкость рук
arcana = mod_intelligence  # магия
medicine = mod_wisdom  # медицина
deception = mod_charisma  # обман
nature = mod_intelligence  # природа
insight = mod_wisdom  # проницательность
religion = mod_intelligence  # религия
stealth = mod_dexterity  # скрытность
persuasion = mod_charisma  # убеждение
animal_handling = mod_wisdom  # уход за животными

passive_wisdom = 10 + mod_wisdom  # пассивная мудрость (внимательность)

armor_class = 0  # КД (класс доспеха)
initiative = dexterity  # инициатива
speed = 0  # скорость

hit_point_maximum = 0  # максимальное кол-во очков жизни
hit_dise = ''  # кубик жизни

dark_vision = ''  # темное зрение
language = ''  # языки
other = ''  # другие умения
skills = ''  # навыки
equipment = ''  # снаряжение


from unittest.mock import call, patch

import pytest

from gicg_sim.die import DieState, _create_die_state_by_array
from gicg_sim.state import PlayerID, RoundPhase, State
from gicg_sim.userboard import UserBoard

def roll_n_dies_patch(die_count: int) -> DieState:
    if die_count == 8:
        return _create_die_state_by_array([1, 1, 1, 1, 1, 1, 1, 1])
    else:
        return _create_die_state_by_array(
            [(die_count if i == 0 else 0) for i in range(8)]
        )

@pytest.fixture
def setup_state():
    state = State()
    player_1 = PlayerID.Player_1
    player_2 = PlayerID.Player_2
    userboard_1 = UserBoard(state, player_1)
    userboard_2 = UserBoard(state, player_2)

    userboard_1.add_character("Diluc")
    userboard_2.add_character("Diluc")

    return state, userboard_1, userboard_2

@pytest.fixture
def setup_mock_roll_n_dies():
    with patch(
        "gicg_sim.state.roll_n_dies", side_effect=roll_n_dies_patch
    ) as mock_func:
        yield mock_func

class TestReroll:
    def test_reroll_action(self, setup_state, setup_mock_roll_n_dies):
        state, userboard_1, userboard_2 = setup_state
        mock_func = setup_mock_roll_n_dies

        assert state.round_phase == RoundPhase.END

        state.new_turn()
        assert state.round_phase == RoundPhase.ROLL

        keepdies_1 = _create_die_state_by_array([1, 1, 0, 0, 0, 0, 0, 0])
        keepdies_2 = _create_die_state_by_array([1, 0, 0, 0, 0, 0, 0, 0])

        userboard_1.reroll_dies(keepdies_1)
        userboard_2.reroll_dies(keepdies_2)

        assert state.round_phase == RoundPhase.ACTION

        assert userboard_1.die_state.Omni == 7
        assert userboard_1.die_state.Pyro == 1

        assert userboard_2.die_state.Omni == 8

        assert userboard_1.die_state.die_count == 8
        assert userboard_2.die_state.die_count == 8

        mock_func.assert_has_calls([call(8), call(8), call(6), call(7)])

    def test_reroll_exception(self, setup_state, setup_mock_roll_n_dies):
        state, userboard_1, _ = setup_state
        mock_func = setup_mock_roll_n_dies

        state.new_turn()
        mock_func.assert_has_calls([call(8), call(8)])

        keepdies_1 = _create_die_state_by_array([2, 1, 0, 0, 0, 0, 0, 0])

        with pytest.raises(AssertionError):
            userboard_1.reroll_dies(keepdies_1)


class SlimProtoVolume:
    """Represents a sound volume. This is an awful lot more complex than it sounds."""

    minimum = 0
    maximum = 100
    step = 1

    # this map is taken from Slim::Player::Squeezebox2 in the squeezecenter source
    # i don't know how much magic it contains, or any way I can test it
    old_map = [
        0,
        1,
        1,
        1,
        2,
        2,
        2,
        3,
        3,
        4,
        5,
        5,
        6,
        6,
        7,
        8,
        9,
        9,
        10,
        11,
        12,
        13,
        14,
        15,
        16,
        16,
        17,
        18,
        19,
        20,
        22,
        23,
        24,
        25,
        26,
        27,
        28,
        29,
        30,
        32,
        33,
        34,
        35,
        37,
        38,
        39,
        40,
        42,
        43,
        44,
        46,
        47,
        48,
        50,
        51,
        53,
        54,
        56,
        57,
        59,
        60,
        61,
        63,
        65,
        66,
        68,
        69,
        71,
        72,
        74,
        75,
        77,
        79,
        80,
        82,
        84,
        85,
        87,
        89,
        90,
        92,
        94,
        96,
        97,
        99,
        101,
        103,
        104,
        106,
        108,
        110,
        112,
        113,
        115,
        117,
        119,
        121,
        123,
        125,
        127,
        128,
    ]

    # new gain parameters, from the same place
    total_volume_range = -50  # dB
    step_point = -1  # Number of steps, up from the bottom, where a 2nd volume ramp kicks in.
    step_fraction = 1  # fraction of totalVolumeRange where alternate volume ramp kicks in.

    def __init__(self):
        """Initialize class."""
        self.volume = 50

    def increment(self):
        """Increment the volume."""
        self.volume += self.step
        if self.volume > self.maximum:
            self.volume = self.maximum

    def decrement(self):
        """Decrement the volume."""
        self.volume -= self.step
        if self.volume < self.minimum:
            self.volume = self.minimum

    def old_gain(self):
        """Return the "Old" gain value as required by the squeezebox."""
        return self.old_map[self.volume]

    def decibels(self):
        """Return the "new" gain value."""
        # pylint: disable=invalid-name

        step_db = self.total_volume_range * self.step_fraction
        max_volume_db = 0  # different on the boom?

        # Equation for a line:
        # y = mx+b
        # y1 = mx1+b, y2 = mx2+b.
        # y2-y1 = m(x2 - x1)
        # y2 = m(x2 - x1) + y1
        slope_high = max_volume_db - step_db / (100.0 - self.step_point)
        slope_low = step_db - self.total_volume_range / (self.step_point - 0.0)
        x2 = self.volume
        if x2 > self.step_point:
            m = slope_high
            x1 = 100
            y1 = max_volume_db
        else:
            m = slope_low
            x1 = 0
            y1 = self.total_volume_range
        return m * (x2 - x1) + y1

    def new_gain(self):
        """Return new gainvalue of the volume control."""
        decibel = self.decibels()
        floatmult = 10 ** (decibel / 20.0)
        # avoid rounding errors somehow
        if -30 <= decibel <= 0:
            return int(floatmult * (1 << 8) + 0.5) * (1 << 8)
        return int((floatmult * (1 << 16)) + 0.5)


"""
Exercise: Numbers in python
You have a football field that is 92 meter long and 48.8 meter wide. Find out total area using python and print it.
You bought 9 packets of potato chips from a store. Each packet costs 1.49 dollar and you gave shopkeeper 20 dollar. Find out using python, how many dollars is the shopkeeper going to give you back?
You want to replace tiles in your bathroom which is exactly square and 5.5 feet is its length. If tiles cost 500 rs per square feet, how much will be the total cost to replace all tiles. Calculate and print the cost using python (Hint: Use power operator ** to find area of a square)
Print binary representation of number 17
"""
# 1. solution
length =  92
width = 48.8
total_area = length * width
print('toal area', total_area)

# 2. solution
item_bought = 9
each_cost = 1.49
give_money = 20
receive = give_money - (item_bought * each_cost)
print('The shopkeeper is going to give you', receive, 'dollars.')

# 3. solution
length = 5.5
area = length**2
cost_per_sqft = 500
cost_bathroom = area * cost_per_sqft
print('The cost of the bathroom tiles :', cost_bathroom, 'Rs.')

# 4. solution
number = 17
print('The binary representation of number', number, 'is', bin(number)+'.')
print('Binary representation of number 17 =', format(number, 'b'))

print('done')


# 점수계산

n = int(input())
chk = list(map(int, input().split()))
score = 0
result = 0
for i in range(n):
    if chk[i] == 1:
        score += 1
        result += score
    else:
        score = 0
print(result)


import sys
import numpy
from gptwosample.data.dataIO import get_data_from_csv
import os

__PREFIX__ = "GPTwoSample"

def message(s):
    form = lambda p,s: "{} {}".format(p,s)
    lines = s.split('\n')
    outstrings = [form(__PREFIX__+":",lines[0])]
    p = " "*(len(__PREFIX__) + 1)
    for s in lines[1:]:
        outstrings.append(form(p,s))

    return "\n".join(outstrings)

def started(s, verbose=1):
    sys.stdout.write(message(s))
    sys.stdout.flush()
    sys.stdout.write("            \r")

def finished(s, verbose=1):
    try:
        sys.stdout.write(message(s) + " " + '\033[92m' + u"\u2713" + '\033[0m' + '              \n')
    except:
        sys.stdout.write(message(s) + " done              \n")
    sys.stdout.flush()

def get_header_for_covar(CovFun, CovFunInd=None):
    if CovFunInd is None:
        CovFunInd = CovFun
    ret = map(lambda x:"Common " + x, CovFun.get_hyperparameter_names())
    ret.extend(map(lambda x:"Individual " + x, \
                   CovFunInd.get_hyperparameter_names()))
    return ret

def twosampledata(cond1, cond2, fil=None):
    T1 = numpy.array(cond1.pop("input"))[:, None]
    T2 = numpy.array(cond2.pop("input"))[:, None]

    Y1 = numpy.array(cond1.values()).T.swapaxes(0, 1)
    Y2 = numpy.array(cond2.values()).T.swapaxes(0, 1)
    Y = numpy.array([Y1, Y2])

    _, r, _, _ = Y.shape

    T1 = numpy.tile(T1, r).T
    T2 = numpy.tile(T2, r).T

    T = numpy.array([T1, T2])

    gene_names = cond1.keys()

    assert T.shape == Y.shape[:3]
    assert gene_names == cond2.keys()

    del T1, T2, Y1, Y2, cond1, cond2

    Ynorm = Y.mean(1).mean(1)[:, None, None, :]
    Y -= Ynorm
    return T,Y, gene_names, Ynorm

def loaddata(cond1file, cond2file, verbose=0, fil=None):
    s = "loading data..."
    started(s)
    #if verbose: sys.stdout.write(os.linesep)
    cond1 = get_data_from_csv(cond1file, verbose=verbose, message=message(s), fil=fil)
    s += " " + os.path.basename(cond1file)
    cond2 = get_data_from_csv(cond2file, verbose=verbose, message=message(s), fil=fil)
    s += " " + os.path.basename(cond2file)
    T,Y,gene_names, Ynorm = twosampledata(cond1, cond2)
    finished(s)
    return T,Y,gene_names,Ynorm


#!/bin/python3
# -*- coding: UTF-8 -*-

class Bag:

	def __init__(self, color):
		self.color = color
		self.contain = []

	def addContain(self, bag, quantite):
		self.contain.append([bag,quantite])

	def getColor(self):
		return self.color

	def __str__(self):
		s = "["+self.color+"]:"
		for c in self.contain:
			s+= c[1] +" "+ c[0].getColor() + ", "
		return s

	def isContainShiny(self):
		for c in self.contain:
			bag = c[0]
			if bag.getColor() == "shiny gold":
				return True
			elif bag.isContainShiny():
				return True
		return False

	def countBagsInside(self):
		res = 0
		for c in self.contain:
			bag = c[0]
			nbBag = c[1]
			res += int(nbBag)
			res += bag.countBagsInside() * int(nbBag)
		return res

input = open("input","r")
lines = input.readlines()

bags = []

for l in lines:
	l = l[:-2]
	l = l.split("bags contain")
	l[0] = l[0][:-1]
	b = Bag(l[0])
	bags.append(b)

input.seek(0,0)

for l in lines:
	l = l[:-2]
	l = l.split("bags contain")
	color1 = l[0]
	color1 = color1[:-1]
	l = l[1].split(",")

	for bag in bags:
		if bag.getColor() == color1:
			b1 = bag

	for b in l:
		b = b[1:].split(" ")
		color2 = b[1]+" "+b[2]

		find = False
		for bag in bags:
			if bag.getColor() == color2:
				b2 = bag
				find = True
		if find:
			b1.addContain(b2,b[0])

part1 = 0
part2 = 0

for bag in bags:
	shiny =  bag.isContainShiny()
	if shiny:
		part1 += 1
	if bag.getColor() == "shiny gold":
		part2 = bag.countBagsInside()

print("Part1: "+str(part1))
print("Part2: "+str(part2))


import easyocr
import time
import pandas as pd
from PIL import Image
import cv2
import numpy as np
import shutil
import os
import tensorflow as tf
from PIL import Image
from matplotlib.pyplot import imshow
import matplotlib.pyplot as plt
import time
import keras_ocr
start_time = time.time()
assert tf.test.is_gpu_available(), 'No GPU is available.'

#####################################################################################################
# FRAME CREATION AND THEIR EHANCEMENTS

def create_frames(path):
    """Creates frames from the given input video
    Args:path of the video"""
    frame_counter = 0
    reduced_frames = 0
    capture = cv2.VideoCapture(path)
    name = path.split("/")[-1]
    directory = f'./images/{name}'
    if (os.path.isdir(directory)):
        shutil.rmtree(directory)

    os.makedirs(directory)
    while True:
        success, frame = capture.read()
        if success:
            # Deleting low resolution frame
            if np.mean(frame) < 15:
                print("Removed the frame")
                continue
            if frame_counter % 400 == 0:
                resized_frame = cv2.resize(frame, (960, 540))
                cv2.imwrite(
                    f'./images/{name}/frame_{frame_counter}.jpg', resized_frame)
                reduced_frames += 1
        else:
            break
        frame_counter += 1
    print(f'There were {frame_counter} frames in this video')
    print(f'After reducing frames there are {reduced_frames} in this video. ')
    capture.release()
    return

def enhance_powerlaw(path, file_name, gamma):
    image = cv2.imread(path)
    normalized_image = image / 255.0
    result = cv2.pow(normalized_image, gamma)
    frame_normed = 255 * (result - result.min()) / \
        (result.max() - result.min())
    frame_normed = np.array(frame_normed, np.int64)

    cv2.imwrite(
        f'./enhanced_images/{dataset}/{file_name}.jpg', frame_normed)
    return

def enhance_inverse(path, file_name, file):
    image = Image.open(path)
    image_array = np.asarray(image)
    image_inverse = 255 - image_array
    fm = './enhanced_images/inverse_law/'+dataset+'/'+file_name
    # print(fm)
    file.write(fm+'\n')
    cv2.imwrite(fm, image_inverse)
    return

def enhance_frames(path, opt, file):
    dirs = os.listdir(path)
    # print("runnnnel")
    if (opt == 0):
        # Applying Power Law
        directory = f'./enhanced_images/power_law/'+dataset
        if (os.path.isdir(directory)):
            shutil.rmtree(directory)

        os.makedirs(directory)
        for file_name in dirs:
            enhance_powerlaw(path + '/' + file_name, file_name, 1.6)
    else:
        # Applying Inverse law
        directory = f'./enhanced_images/inverse_law/'+dataset
        if (os.path.isdir(directory)):
            shutil.rmtree(directory)

        os.makedirs(directory)
        for file_name in dirs:
            enhance_inverse(path + '/' + file_name, file_name, file)

#####################################################################################################
# OPTICAL CHARACTER RECOGNITION (OCR) ON ROI
d = {}
reader = easyocr.Reader(['en'], recog_network='iter_30000', gpu=True)

def OCR(imgs, mode):
    if mode == 2:
        for img in imgs:
            image = img[1]
            result = reader.readtext(image)
            if img[0] not in d:
                d[img[0]] = []
                if (len(result) > 0 and len(result[0]) >= 2):
                    d[img[0]].append(result[0][-2])
                else:
                    d[img[0]].append(None)
            else:
                if (len(result) > 0 and len(result[0]) >= 2):
                    d[img[0]].append(result[0][-2])
                else:
                    d[img[0]].append(None)

#####################################################################################################
####################################################################################################
# for kocr_detection_orientation_check

def order_points(pts):
    # initialzie a list of coordinates that will be ordered
    # such that the first entry in the list is the top-left,
    # the second entry is the top-right, the third is the
    # bottom-right, and the fourth is the bottom-left
    rect = np.zeros((4, 2), dtype="float32")
    # the top-left point will have the smallest sum, whereas
    # the bottom-right point will have the largest sum
    s = pts.sum(axis=1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    # now, compute the difference between the points, the
    # top-right point will have the smallest difference,
    # whereas the bottom-left will have the largest difference
    diff = np.diff(pts, axis=1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    # return the ordered coordinates
    return rect

def four_point_transform(image, pts):
    # obtain a consistent order of the points and unpack them
    # individually
    rect = order_points(pts)
    (tl, tr, br, bl) = rect
    # compute the width of the new image, which will be the
    # maximum distance between bottom-right and bottom-left
    # x-coordiates or the top-right and top-left x-coordinates
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    # compute the height of the new image, which will be the
    # maximum distance between the top-right and bottom-right
    # y-coordinates or the top-left and bottom-left y-coordinates
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    # now that we have the dimensions of the new image, construct
    # the set of destination points to obtain a "birds eye view",
    # (i.e. top-down view) of the image, again specifying points
    # in the top-left, top-right, bottom-right, and bottom-left
    # order
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")
    # compute the perspective transform matrix and then apply it
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    # return the warped image
    return warped

#####################################################################################################

def showROIS(ROIs, img_raw):
    # counter to save image with different name
    crop_number = 0
    imgs = []
    # loop over every bounding box save in array "ROIs"
    for rect in ROIs:
        if rect[1].shape == (4,):
            x1 = rect[1][0]
            y1 = rect[1][1]
            x2 = rect[1][2]
            y2 = rect[1][3]
            # crop roi from original image
            img_crop = img_raw[y1:y1+y2, x1:x1+x2]
            # save cropped image
            imgs.append((rect[0], "crop"+str(crop_number)+".jpeg"))
            cv2.imwrite("crop"+str(crop_number)+".jpeg", img_crop)
            crop_number += 1
            # hold window
            cv2.waitKey(0)
        else:
            warped = four_point_transform(img_raw, rect[1])
            imgs.append((rect[0], "crop"+str(crop_number)+".jpeg"))
            cv2.imwrite("crop"+str(crop_number)+".jpeg", warped)
            crop_number += 1

    OCR(imgs, 2)
    # closing all open windows
    cv2.destroyAllWindows()
####################################################################################################
# REGION OF INTEREST (ROI) SELECTION

det = keras_ocr.detection.Detector()
det.model.load_weights('./detector_icdar2013.h5')

def createROIS(image_folder, mode):
    files = os.listdir(image_folder)
    print(files)
    lst = []
    for file in files:
        lst.append(image_folder + "/" + file)
    print(lst)

    if mode == 1:
        for path in image_folder:
            img_raw = cv2.imread(image_folder + "/" + path)
            # select ROIs function
            ROIs = cv2.selectROIs(
                "Select ROIs and press Enter to move further, Press Esc to exit, Press c to clear selection", img_raw)
            # print rectangle points of selected roi
            print(ROIs)
            showROIS(ROIs, img_raw)
    elif mode == 2:
        path = files[0]
        p = image_folder + "/" + path
        img_raw = cv2.imread(p)
        image = keras_ocr.tools.read(p)
        img_det = det.detect([image])
        img_tup = []
        for i in range(len(img_det[0])):
            st = 'roi'+str(i+1)
            img_tup.append((st, img_det[0][i]))
        img = keras_ocr.tools.drawBoxes(image, img_det[0], color=(
            36, 255, 12), thickness=1, boxes_format='boxes')
        for i in img_tup:
            x = int(i[1][0][0])
            y = int(i[1][0][1])
            cv2.putText(img, i[0], (x, y-5),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 20, 147), 2)

        cv2.imshow('window_name', img)
        cv2.waitKey(0)
        r = input(
            "Please select the ROIs on which you want OCR to be done by entering them with comma as a separator:")
        rl = r.split(",")
        rm = list(map(lambda x: "roi"+x, rl))
        rf = tuple(filter(lambda x: x[0] in rm, img_tup))
        print(rf)
        ROIs = cv2.selectROIs(
            "Select ROIs and press Enter to move further, Press Esc to exit, Press c to clear selection", img)
        # print rectangle points of selected roi
        print(ROIs)
        ROI_tup = []
        for i in ROIs:
            name = input(
                'Please enter the attribute name for the selected ROIS:')
            ROI_tup.append((name, i))
        ROI_tup.extend(rf)
        for name, coords in ROI_tup:
            print(f'{name} --- {coords}  {type(coords)} {coords.shape}')
        showROIS(ROI_tup, img_raw)
        del files[0]
        for path in files:
            img_raw = cv2.imread(image_folder + "/" + path)
            showROIS(ROI_tup, img_raw)
    else:
        for path in files:
            print(image_folder + "/" + path)

            abcd = reader.readtext(image_folder + "/" + path)
            for line in abcd:
                print(f"{line[0]}      {line[1]}")
            print("*****************************************************************")

#####################################################################################################
# MAIN DRIVER FUNCTIONS

file = open('images.txt', 'w')
dataset = "Stable_Video_1.mp4"
create_frames("./dataset/"+dataset)
enhance_frames("./images/"+dataset, 1, file)
createROIS("./enhanced_images/inverse_law/"+dataset, mode=2)
formated_output = pd.DataFrame(d)
print(formated_output)
file.close()
print("Execution time: ", time.time() - start_time)


'''
정수를 입력 받아 1 ~ 입력 받은 정수까지
짝수 합과 홀수 합을 구하시오.

'''
l = int(input("정수 입력"))
ev = 0 #짝수
od = 0 #홀수

for i in range(1 , l) :
    if i % 2 == 0 :
        #짝수
        #print("짝 :",i)
        ev += i
    else :
        #홀수
        #print("홀 :",i)
        od += i
print("짝수 총합 :",ev)
print("홀수 총합 :",od)

'''선생님 답안'''

data = int(input("정수 입력 : "))
data += 1
odd_total = 0
even_total = 0
for i in range(1,data) :
    if i % 2 == 0 :
        even_total += i
    else :
        odd_total += i
print("짝수 합계 : {}".format(even_total))
print("홀수 합계 : {}".format(odd_total))


import numpy as np
import pandas as pd
import pickle
import matplotlib.pyplot as plt
from PIL import Image
import sys
import cv2

from keras import  backend as K
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from tensorflow.keras.utils import to_categorical

(x_train, y_train),(x_test, y_test) = mnist.load_data()
unique, counts = np.unique(y_train, return_counts=True)
print("Train labels: ", dict(zip(unique, counts)))

unique, counts = np.unique(y_test, return_counts=True)
print("\nTest labels: ", dict(zip(unique, counts)))

num_labels = len(np.unique(y_train))
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

image_size = x_train.shape[1]
input_size = image_size * image_size

x_train = np.reshape(x_train, [-1, input_size])
x_train = x_train.astype('float32') / 255
x_test = np.reshape(x_test, [-1, input_size])
x_test = x_test.astype('float32') / 255

batch_size = 128
hidden_units = 256
dropout = 0.45

model = Sequential()
model.add(Dense(hidden_units, input_dim=input_size))
model.add(Activation('relu'))
model.add(Dropout(dropout))
model.add(Dense(hidden_units))
model.add(Activation('relu'))
model.add(Dropout(dropout))
model.add(Dense(num_labels))
model.add(Activation('softmax'))

#model.summary()

model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=20, batch_size=batch_size)

loss, acc = model.evaluate(x_test, y_test, batch_size=batch_size)
print("\nTest accuracy: %.1f%%" % (100.0 * acc))
filename = 'finalized_model'
model.save(filename)
#pickle.dump(model, open(filename, 'wb'))


"""
A Transportation Problem (TRNSPORT)

This problem finds a least cost shipping schedule that meets
requirements at markets and supplies at factories.

Dantzig, G B, Chapter 3.3. In Linear Programming and Extensions.
Princeton University Press, Princeton, New Jersey, 1963.

This formulation is described in detail in:
Rosenthal, R E, Chapter 2: A GAMS Tutorial. In GAMS: A User's Guide.
The Scientific Press, Redwood City, California, 1988.

The line numbers will not match those in the book because of these
comments.

Keywords: linear programming, transportation problem, scheduling
"""

from gamspy import Set, Parameter, Variable, Equation, Model, Container
from gamspy import Sum, Sense
import sys

def main():
    m = Container()

    # Prepare data
    distances = [
        ["seattle", "new-york", 2.5],
        ["seattle", "chicago", 1.7],
        ["seattle", "topeka", 1.8],
        ["san-diego", "new-york", 2.5],
        ["san-diego", "chicago", 1.8],
        ["san-diego", "topeka", 1.4],
    ]

    capacities = [["seattle", 350], ["san-diego", 600]]
    demands = [["new-york", 325], ["chicago", 300], ["topeka", 275]]

    # Set
    i = Set(m, name="i", records=["seattle", "san-diego"])
    j = Set(m, name="j", records=["new-york", "chicago", "topeka"])

    # Data
    a = Parameter(m, name="a", domain=[i], records=capacities)
    b = Parameter(m, name="b", domain=[j], records=demands)
    d = Parameter(m, name="d", domain=[i, j], records=distances)
    c = Parameter(m, name="c", domain=[i, j])
    c[i, j] = 90 * d[i, j] / 1000

    # Variable
    x = Variable(m, name="x", domain=[i, j], type="Positive")

    # Equation
    supply = Equation(m, name="supply", domain=[i])
    demand = Equation(m, name="demand", domain=[j])

    supply[i] = Sum(j, x[i, j]) <= a[i]
    demand[j] = Sum(i, x[i, j]) >= b[j]

    transport = Model(
        m,
        name="transport",
        equations=m.getEquations(),
        problem="LP",
        sense=Sense.MIN,
        objective=Sum((i, j), c[i, j] * x[i, j]),
    )
    transport.solve(output=sys.stdout)

    print(x.records)
    print(transport.objective_value)
    print(transport.status)

if __name__ == "__main__":
    main()


import autograd.numpy as np
from autograd.scipy.special import logsumexp
import autograd.numpy.random as npr
from autograd import grad
from autograd.misc.optimizers import adam
import os
import sys
import matplotlib.pyplot as plt

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# path to data
sys.path.append(os.path.join(os.getcwd(), "../../../data"))
from data.data_utils import load_dataset

# from typing import list, Tuple

def init_randn(m, n, rs=npr.RandomState(0)):
    """ init mxn matrix using small random normal
    """
    return 0.1 * rs.randn(m, n)

def init_xavier(m, n, rs=npr.RandomState(0)):
    return rs.randn(m, n) / np.sqrt(m)

def init_net_params(layer_sizes, init_fcn, rs=npr.RandomState(0)):
    """ inits a (weights, biases) tuples for all layers using the intialize function (init_fcn)"""
    return [
        (init_fcn(m, n), np.zeros(n))  # weight matrix  # bias vector
        for m, n in zip(layer_sizes[:-1], layer_sizes[1:])
    ]

def relu(x):
    return np.maximum(0, x)

def neural_net_predict(params, inputs):
    for W, b in params:
        outputs = np.dot(inputs, W) + b # general formula for transformation of a layer in neural net
        inputs = relu(outputs)
    return outputs - logsumexp(outputs, axis=1, keepdims=True)

def mean_log_like(params, inputs, targets):
    # raise NotImplementedError("mean_log_like function not completed (see Q3).")
    # print('computing mean-log-like')
    return np.mean(neural_net_predict(params, inputs) * targets) * 10

def mean_log_like2(params, inputs, targets):
    N = len(inputs)
    for W, b in params:
        outputs = np.dot(inputs, W) + b # general formula for transformation of a layer in neural net
        inputs = relu(outputs)
    # outputs = relu(outputs - logsumexp(outputs, axis=1, keepdims=True))
    log_p = 0
    for i, f_hat in enumerate(outputs):
        for j, val in enumerate(f_hat):
            if targets[i][j]:
                if (val > 0):
                    continue
                else:
                    outputs[i][j] = 0
    return log_p / N

def accuracy(params, inputs, targets):
    """ return the accuracy of the neural network defined by params
    """
    target_class = np.argmax(targets, axis=1)
    predicted_class = np.argmax(neural_net_predict(params, inputs), axis=1)
    return np.mean(predicted_class == target_class)

if __name__ == "__main__":
    ''' best so far: roughly 57% with 100 0.0004 10000 [784, 512, 10] (peaks at 50 iterations)
    some ideas:
        - two hidden layers? how many units in each?
        - probably best to tune the layer count first, then worry about getting good grad desc params
    '''
    # ----------------------------------------------------------------------------------
    # EXAMPLE OF HOW TO USE STARTER CODE BELOW
    # ----------------------------------------------------------------------------------

    # loading data
    x_train, x_valid, x_test, y_train, y_valid, y_test = load_dataset("mnist_small")
    # print(len(x_train))
    # initializing parameters
    layer_sizes = [784, 392,10]
    params = init_net_params(layer_sizes, init_randn)

    # setting up training parameters
    num_epochs = 30
    learning_rate = 2e-3
    batch_size = 1000 # total of 10000 datapoints

    # Constants for batching
    num_batches = int(np.ceil(len(x_train) / batch_size))
    rind = np.arange(len(x_train))
    npr.shuffle(rind)

    def batch_indices(iter):
        idx = iter % num_batches
        return rind[slice(idx * batch_size, (idx + 1) * batch_size)]

    # Define training objective
    def objective(params, iter):
        # get indices of data in batch
        idx = batch_indices(iter)
        # print(x_train[idx][0])
        return -mean_log_like(params, x_train[idx], y_train[idx])

    # Get gradient of objective using autograd.
    objective_grad = grad(objective)
    print(num_epochs, learning_rate, batch_size, layer_sizes)
    print("     Epoch     |    Train accuracy  |       Test accuracy  ")

    # Dictionary to store train/val history
    opt_history = {
        "train_nll": [],
        "val_nll": [],
    }
    global g_params
    g_params = None

    def callback(params, iter, gradient):
        if iter % num_batches == 0:
            # record training & val. accuracy every epoch
            opt_history["train_nll"].append(-mean_log_like(params, x_train, y_train))
            opt_history["val_nll"].append(-mean_log_like(params, x_valid, y_valid))
            train_acc = accuracy(params, x_train, y_train)
            val_acc = accuracy(params, x_valid, y_valid)
            print("{:15}|{:20}|{:20}".format(iter // num_batches, train_acc, val_acc))
            global g_params
            g_params = params

    # We will optimize using Adam (a variant of SGD that makes better use of
    # gradient information).
    opt_params = adam(
        objective_grad,
        params,
        step_size=learning_rate,
        num_iters=num_epochs * num_batches,
        callback=callback,
    )
    # Plotting the train and validation negative log-likelihood
    plt.plot(opt_history["train_nll"], label='training')
    plt.plot(opt_history["val_nll"], label = 'validation')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend()
    # plt.show()
    plt.cla()
    target_class = np.argmax(y_test, axis=1)
    predicted_class = np.argmax(neural_net_predict(g_params, x_test), axis=1)
    cm = confusion_matrix(predicted_class, target_class)
    disp = ConfusionMatrixDisplay(cm)
    disp.plot()
    plt.show()


# ! /usr/bin/env python
# - * - coding:utf-8 - * -
# __author__ : KingWolf
# createtime : 2018/11/29 1:25

import time
import threading

#为了更好的封装，采用继承类的方式写
class CodingThread(threading.Thread):

    def run(self):
        for x in range(3):
            # 查看当前线程的名字
            print('正在coding：%s' % x, threading.current_thread())
            time.sleep(1)

class DrawingThread(threading.Thread):
    def run(self):
        for x in range(3):
            # 查看当前线程的名字
            print('正在drawing：%s' % x, threading.current_thread())
            time.sleep(1)

def main():
    #创建线程对象
    t1 = CodingThread()
    t2 = DrawingThread()

    #启动线程
    t1.start()
    t2.start()

if __name__ == '__main__':
    main()


class Solution:
    """
    Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
        Symbol       Value
        I             1
        V             5
        X             10
        L             50
        C             100
        D             500
        M             1000
    For example, 2 is written as II in Roman numeral, just two ones added together. 12 is written
    as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

    Roman numerals are usually written largest to smallest from left to right. However, the numeral
    for four is not IIII. Instead, the number four is written as IV. Because the one is before the
    five we subtract it making four. The same principle applies to the number nine, which is written
    as IX. There are six instances where subtraction is used:
        I can be placed before V (5) and X (10) to make 4 and 9.
        X can be placed before L (50) and C (100) to make 40 and 90.
        C can be placed before D (500) and M (1000) to make 400 and 900.
    Given a roman numeral, convert it to an integer.
    Constraints:
        1 <= s.length <= 15
        s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
        It is guaranteed that s is a valid roman numeral in the range [1, 3999]
    """

    def romanToInt(self, s: str) -> int:
        numerals = {
            'I': 1,
            'V': 5,
            'X': 10,
            'L': 50,
            'C': 100,
            'D': 500,
            'M': 1000
        }

        # highest valued numeral so far
        highest_so_far = 0

        # result variable
        res = 0

        # go though s in reversed order, if a numeral appears that is smaller than the largest one
        # seen so far, subtract it from the result, otherwise add it
        for c in reversed(s):
            val = numerals[c]
            if val >= highest_so_far:
                res += val
                highest_so_far = val
            else:
                res -= val

        return res


"""GraphLoader.py"""

import sys
import csv
import pandas as pd
import numpy as np
from scipy.sparse import coo_matrix
import networkx as nx
from .graph import Graph

def custom_read_edgelist(path, comments='#', delimiter=' ', \
                         create_using=None, \
                         nodetype=np.int64, data=True, \
                         edgetype=np.int64, encoding='utf-8'):
    """
    DESC: Customized read_edgelist() to construct graph adjacency matrix
          in the form of scipy csr matrix directly from input file.
    PARAMS:    Same as in networkx.read_edgelist().
               nodetype, data, edgetype, encoding are not used.
    """
    # checking number of columns in input file
    fstr = open(path, 'r')
    reader = csv.reader(fstr, delimiter=delimiter)
    sample = next(reader)
    while sample[0][0] == comments: #skipping comments
        sample = next(reader)
    fstr.close()

    ncol = len(sample)
    if ncol == 2:
        names = ['src', 'dst']
    elif ncol == 3:
        names = ['src', 'dst', 'wgt']
    else:
        msg = "read_edgelist: Expected 2 or 3 columns in input file!\n"
        msg = msg + str(ncol) + " column detected in first row: " + str(sample)
        msg = msg + "\nPlease ensure if the specified delimiter '"
        msg = msg + delimiter + "' is correct!"
        raise ValueError(msg)

    # loading data by excluding duplicate rows
    df = pd.read_csv(path, sep=delimiter, comment=comments, \
                     names = names, dtype = edgetype)

    # converting to numpy array
    mat = df.drop_duplicates().values
    num_edges = mat.shape[0]

    # checking whether data is 0-based or 1-based
    tarr = mat[:, :2].flatten()
    if sys.version_info[0] < 3:
        min_id = long(tarr.min()) #'long' should be replaced with 'int',
        max_id = long(tarr.max()) #'int' gives same behaviour as 'long' in py3.
    else:
        min_id = int(tarr.min())
        max_id = int(tarr.max())

    if min_id == 0:
        rowid = mat[:, 0]
        colid = mat[:, 1]
        num_vertices = max_id + 1
    else:
        rowid = mat[:, 0] - 1
        colid = mat[:, 1] - 1
        num_vertices = max_id

    # extracting edge weight information (if available)
    if ncol == 3:
        data = mat[:, 2]
    else:
        data = np.ones(num_edges)

    # constructing sparse matrix structure
    data = np.asarray(data, dtype = edgetype)
    rowid = np.asarray(rowid, dtype = nodetype)
    colid = np.asarray(colid, dtype = nodetype)
    shape = (num_vertices, num_vertices)
    if isinstance(create_using, nx.classes.digraph.DiGraph):
        coo = coo_matrix((data, (rowid, colid)), shape=shape)
    else:
        data_ = np.concatenate((data, data))
        rowid_ = np.concatenate((rowid, colid))
        colid_ = np.concatenate((colid, rowid))
        coo = coo_matrix((data_, (rowid_, colid_)), shape=shape)
    return coo.tocsr()

def read_edgelist(path, comments='#', delimiter=' ', \
                  create_using=None,\
                  nodetype=np.int64, data=True, \
                  edgetype=np.int64, encoding='utf-8'):
    """
    DESC: Reads edgelist data from persistent storage.
    PARAMS:    path : file or string
                      File or filename to read. If a file is
                      provided, it must be opened in 'rb' mode. Filenames
                      ending in .gz or .bz2 will be uncompressed.
               comments : string, optional
                      The character used to indicate the start of a comment.
               delimiter : string, optional
                      The string used to separate values.  The default is
                      whitespace.
               create_using : NetworkX graph constructor, optional
                              (default=nx.Graph)
                      Graph type to create. If graph instance, then cleared
                      before populated.
               nodetype : int, float, str, Python type, optional
                      Convert node data from strings to specified type
               data : bool or list of (label,type) tuples
                      Tuples specifying dictionary key names and types for
                      edge data
               edgetype : int, float, str, Python type, optional OBSOLETE
                      Convert edge data from strings to specified type and
                      use as 'weight'
               encoding: string, optional
                      Specify which encoding to use when reading file.
    """
    #nx_graph = nx.read_edgelist(path, comments, delimiter, create_using, \
    #                            nodetype, data, edgetype, encoding)
    #return Graph(nx_graph=nx_graph)
    smat = custom_read_edgelist(path, comments, delimiter, create_using, \
                                nodetype, data, edgetype, encoding)
    return Graph(nx_graph=smat)


"""
Strokes gained analyses.
"""
from pga_analysis.putting import *
from pga_analysis.par_5_tee_shots import *
import warnings
from scipy.stats import wilcoxon
import logging

warnings.simplefilter(action='ignore', category=FutureWarning)

def prepare_tournament_data(tournament, pga_data_added):
    """
    Returns pga_data for a given tournament, for players that made the cut (played 4 rounds).
    """
    tournament_data = pga_data_added[pga_data_added.tournament == tournament]

    players_made_the_cut = tournament_data.groupby('player')['round_number'].max() == 4
    players_made_the_cut = pd.Series(players_made_the_cut[players_made_the_cut].index)
    tournament_data = tournament_data.merge(players_made_the_cut, how='inner', on='player')

    return tournament_data

def compute_total_putting_strokes_gained_by_player(tournament_data, putting_data):
    """
    Computes total putting strokes gained for each player in the data.
    """
    _, first_shot_on_green = prepare_putting_data(tournament_data)
    putting_strokes_gained = compute_putting_strokes_gained(putting_data, first_shot_on_green, by_player=True,
                                                            aggregation='sum')
    return putting_strokes_gained

def compute_total_par_5_strokes_gained_by_player(tournament_data, strokes_model, par_5_tee_shot_features, pga_data_added):
    """
    Computes total strokes gained from the tee shot on a Par 5 for each player in the data.
    """
    par_5_analysis_data = get_par_5_analysis_data(tournament_data, common_shot_end_locations(pga_data_added))
    par_5_model_features = par_5_analysis_data.drop(['player', 'strokes_from_here', 'strokes_to_finish'], axis=1)

    # Gets columns in the same order as when the model was trained
    orig_model_columns = \
        par_5_tee_shot_features.drop(['player', 'strokes_to_finish', 'strokes_from_here'], axis=1).columns
    for column in orig_model_columns:
        if column not in par_5_analysis_data.columns:
            par_5_model_features[column] = [0] * len(par_5_model_features)
    par_5_model_features = par_5_model_features[orig_model_columns]

    par_5_strokes_gained = strokes_model.predict(par_5_model_features)
    strokes_left = pd.DataFrame({'player': par_5_analysis_data.player,
                                 'strokes_to_finish': par_5_analysis_data.strokes_to_finish,
                                 'predicted_strokes_to_finish': par_5_strokes_gained})
    strokes_left['strokes_gained'] = strokes_left.predicted_strokes_to_finish - strokes_left.strokes_to_finish
    cum_strokes_gained = strokes_left.groupby('player')['strokes_gained'].sum()

    return cum_strokes_gained

def plot_strokes_gained_driving_vs_putting_by_winnings(putting_data, strokes_model,
                                                       par_5_tee_shot_features, pga_data_added,
                                                       winnings_rank_min=0, winnings_rank_max=5,
                                                       over_all_tournaments=False):
    """
    Strokes gained violin plot for driving (left half) vs putting (right half).

    winnings_rank_{min / max}: Min/max rank of tournament maximum winnings to plot.
    """
    most_winnings_tournaments = \
        pga_data_added.groupby('tournament').winnings.max().sort_values(ascending=False)[winnings_rank_min:winnings_rank_max].index

    if not over_all_tournaments:
        fig, ax = plt.subplots(figsize=(17, 6))

        putting_strokes_gained_list = []
        tee_shot_strokes_gained_list = []

        for tournament in most_winnings_tournaments:
            tournament_data = prepare_tournament_data(tournament, pga_data_added)
            putting_strokes_gained = compute_total_putting_strokes_gained_by_player(tournament_data, putting_data).iloc[:, 0]
            tee_shot_strokes_gained = compute_total_par_5_strokes_gained_by_player(tournament_data, strokes_model,
                                                                                par_5_tee_shot_features, pga_data_added)

            putting_strokes_gained_list.append(putting_strokes_gained)
            tee_shot_strokes_gained_list.append(tee_shot_strokes_gained)

    else:
        fig, ax = plt.subplots(figsize=(7, 6))

        putting_strokes_gained_list = [compute_total_putting_strokes_gained_by_player(pga_data_added, putting_data).iloc[:, 0]]
        tee_shot_strokes_gained_list = [compute_total_par_5_strokes_gained_by_player(pga_data_added, strokes_model,
                                                                                par_5_tee_shot_features, pga_data_added)]

    def violin_plot(data, half, width_factor=1.0):
        violin_plot = ax.violinplot(data, positions=np.arange(0, len(data)),
                                    showmeans=False, showextrema=False, showmedians=False, widths=0.5 * width_factor)
        for b in violin_plot['bodies']:
            m = np.mean(b.get_paths()[0].vertices[:, 0])
            if half == 'left':
                b.get_paths()[0].vertices[:, 0] = np.clip(b.get_paths()[0].vertices[:, 0], -np.inf, m)
                b.set_color('b')
            elif half == 'right':
                b.get_paths()[0].vertices[:, 0] = np.clip(b.get_paths()[0].vertices[:, 0], m, np.inf)
                b.set_color('r')
        return violin_plot

    violin_left = violin_plot(tee_shot_strokes_gained_list, half='left')
    width_factor = 0.7 if not over_all_tournaments else 0.85
    violin_right = violin_plot(putting_strokes_gained_list, half='right', width_factor=width_factor)

    ax.legend([violin_left['bodies'][0],violin_right['bodies'][0]],['DRIVING', 'PUTTING'])
    if not over_all_tournaments:
        ax.set_xticklabels(
            ['', 'THE PLAYERS CHAMPIONSHIP 2021\n$2.7M', 'PGA CHAMPIONSHIP 2020\n$2M', 'WGC CONCESSION 2021\n$1.8M'
                , 'WGC FEDEX ST JUDE INVITATIONAL 2020\n$1.8M', 'BMW CHAMPIONSHIP 2020\n$1.7M']
        )
    else:
        ax.set_xticks([])
    plt.ylabel('Strokes Gained')
    plt.title('Total Strokes Gained (Player)')

def plot_putting_strokes_gained_distribution(first_shot_to_green):
    """
    Plot distribution of average putting strokes gained per round, by player
    """
    putting_strokes_gained_by_player = first_shot_to_green.groupby(['player', 'tournament', 'round_number']) \
        ['strokes_gained'].sum().reset_index().groupby(['player']).strokes_gained.mean()
    grid = sns.kdeplot(putting_strokes_gained_by_player, shade=True)
    plt.xlim([-3, 3])
    plt.ylabel('')
    grid.set(yticks=[])
    set_size(10, 2)
    plt.title('Putting: Average Strokes Gained per Round, by Player')
    plt.xlabel('Strokes Gained')

def plot_strokes_gained_above_or_below_15_feet(putting_data, first_shot_to_green):
    """
    Scatter plot of each player's strokes gained for putts below or above 15 feet.
    """
    sg_below_15_feet_by_player = compute_putting_strokes_gained(putting_data, first_shot_to_green[
        first_shot_to_green.shot_start_distance_feet < 15], by_player=True)
    sg_above_15_feet_by_player = compute_putting_strokes_gained(putting_data, first_shot_to_green[
        first_shot_to_green.shot_start_distance_feet >= 15], by_player=True)
    sg_15_feet_putts_threshold = sg_below_15_feet_by_player.merge(sg_above_15_feet_by_player, on='player', how='inner')
    sg_15_feet_putts_threshold.columns = ['below_15_feet', 'above_15_feet']
    grid = sns.lmplot(x='below_15_feet', y='above_15_feet', data=sg_15_feet_putts_threshold)
    plt.xlabel('Avg SG BELOW 15-feet')
    plt.ylabel('Avg SG ABOVE 15-feet')
    plt.title('Small correlation between good SHORT vs LONG putters\n')
    plt.xlim([-0.2, 0.2])
    plt.ylim([-0.2, 0.2])
    set_size(5,4)
    grid.set(xticks=[-0.2, 0, 0.2], yticks=[-0.2, 0, 0.2])
    plt.tight_layout()

def drive_or_putt_for_dough(pga_data_added, putting_data, strokes_model, par_5_tee_shot_features):
    """
    Wilcoxon Signed Rank test to test whether players gained more strokes from putting vs driving.
    Unused due to insignificant result.
    """
    putting_sg = compute_total_putting_strokes_gained_by_player(pga_data_added, putting_data).iloc[:,0]
    driving_sg = compute_total_par_5_strokes_gained_by_player(pga_data_added, strokes_model, par_5_tee_shot_features, pga_data_added)

    statistic, p_value = wilcoxon(x=driving_sg, y=putting_sg, alternative='greater')

    logger = logging.getLogger()
    logger.info(f'For each player, PUTTING contributed more SG than PAR 5 TEE SHOTS.\n'
                f'p-value = {round(p_value,3)}')


"""empty message

Revision ID: d8d772eb526f
Revises: dd61148aa0eb
Create Date: 2023-03-31 17:58:32.322215

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'd8d772eb526f'
down_revision = 'dd61148aa0eb'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('posts',
    sa.Column('title', sa.String(length=255), nullable=False),
    sa.Column('slug', sa.String(length=255), nullable=False),
    sa.Column('content', sa.Text(), nullable=False),
    sa.Column('date', sa.DateTime(), nullable=True),
    sa.Column('is_published', sa.Boolean(), nullable=True),
    sa.Column('users_id', sa.Integer(), nullable=False),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.ForeignKeyConstraint(['users_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('slug'),
    sa.UniqueConstraint('title')
    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('posts')
    # ### end Alembic commands ###


# from sklearn import svm as sksvm
from models.libsvm import svmutil as libsvm, _svm as libsvm_low

import os
import numpy as np
from datetime import datetime
from pprint import pformat

try:
    import cPickle as pickle
except:
    import pickle

from models.model_base import ModelBase
from utilities import linux_path, profile

class SVM(ModelBase):
    """
    :type _params: SVM.Params
    :type _weights: libsvm.svm_train
    :type _problem: libsvm.svm_problem
    :type _libsvm_params: libsvm.svm_parameter
    :type _train_features: np.ndarray
    :type _train_labels: np.ndarray
    :type labels: np.ndarray
    :type probabilities: np.ndarray
    """

    class Params(ModelBase.Params):
        """
        :ivar implementation: SVM implementation to use: 0: libsvm (high level)
        1: libsvm (low level) 2: sklearn.svm 3: lasvm

        :ivar verbose: Show detailed diagnostic messages, if any, from the underlying
        library

        """

        def __init__(self):
            ModelBase.Params.__init__(self)

            self.implementation = 0
            self.verbose = 0

    def __init__(self, params, logger, feature_shape, name):
        """
        :type params: SVM.Params
        :type logger: logging.RootLogger
        :rtype: None
        """
        ModelBase.__init__(self, params, logger, feature_shape, name, 'SVM', n_classes=2)

        self._params = params

        self._weights = None
        self._problem = None
        self._libsvm_params = None

        self._train_opts = '-c 1 -g 1 -b 1 -h 0'
        self._predict_opts = '-b 1'

        if not self._params.verbose:
            # self._train_opts += ' -q'
            self._predict_opts += ' -q'

        self._labels = None
        # self.accuracies = None
        self._probabilities = None
        self.accuracies = None

        if self._params.implementation == 0:
            self._logger.info('Using high level implementation')
            self._problem_fn = libsvm.svm_problem
        elif self._params.implementation == 1:
            self._logger.info('Using low level implementation')
            self._problem_fn = libsvm_low.svm_problem
        else:
            raise IOError('Invalid implementation type: {}'.format(self._params.implementation))

        if not self._params.accumulative:
            self._logger.warning('accumulative training is disabled')

        self._params.min_samples = int(self._params.min_samples)

        if self._params.min_samples > 0:
            self._logger.info('skipping training with less than {:d} samples'.format(self._params.min_samples))

        if self._params.min_samples_ratio > 0:
            self._logger.info(
                'skipping training with ratio of new samples less than {:.3f}'.format(self._params.min_samples_ratio))

        self._params.max_samples = int(self._params.max_samples)

        if self._params.max_samples > 0:
            self._logger.info('limiting the maximum number of training samples to {:d}'.format(self._params.max_samples))

    def train(self, labels, features):
        """
        :type labels: np.ndarray
        :type features: np.ndarray
        :rtype: None
        """

        if not self._check_train(labels, features):
            return

        n_samples = self._train_labels.size

        _train_labels, _train_labels = self._train_labels, self._train_labels

        max_samples = int(self._params.max_samples)

        if max_samples > 0 and max_samples < n_samples:
            self._logger.info('randomly selecting {} / {} training samples'.format(
                max_samples, n_samples))

            all_idx = list(range(n_samples))
            random_idx = list(np.random.permutation(all_idx))
            random_sampled_idx = random_idx[:max_samples]

            _train_features = self._train_features[random_sampled_idx, ...]
            _train_labels = self._train_labels[random_sampled_idx]

            n_samples = max_samples
        else:
            _train_features, _train_labels = self._train_features, self._train_labels

        features_list = list(map(list, _train_features))
        labels_list = list(_train_labels)

        # params = libsvm.svm_parameter('-c 1 -q')
        # prob = libsvm.svm_problem([1,-1], [{1:1, 3:1}, {1:-1,3:-1}])

        start_time = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
        self._logger.info(f'{start_time} :: training on {n_samples} samples')

        times = {}
        with profile('svm_train', times, show=1):
            self._problem = self._problem_fn(labels_list, features_list)
            self._libsvm_params = libsvm.svm_parameter(self._train_opts)
            self._weights = libsvm.svm_train(self._problem, self._libsvm_params)

        self._logger.info('time taken: {}'.format(times['svm_train']))

        self.is_trained = True
        self.is_loaded = False

        # self.logger.debug('Done')

    def predict(self, features, gt_labels=None, vis=None):
        """
        :type features: np.ndarray
        :type gt_labels: np.ndarray | None
        :type vis bool | int | None
        :rtype: None
        """
        n_samples = features.shape[0]
        if self._params.verbose:
            self._logger.info('predicting for {} samples'.format(n_samples))

        features_list = list(map(list, features))
        labels = -np.ones((n_samples,))
        labels_list = list(labels)

        _labels, _accuracies, _probabilities = libsvm.svm_predict(
            labels_list, features_list, self._weights, self._predict_opts)

        self._labels = np.array(_labels)
        self._probabilities = np.array(_probabilities)
        self.accuracies = np.array(_accuracies)
        return self._labels, self._probabilities

    def batch_train(self):
        """

        :return: str
        """
        _batch_params = self._params.batch  # type: ModelBase.Params.BatchTrain

        self._load_samples_recursive(_batch_params.db_path, non_negative_labels=False)

        self._split_samples(_batch_params)

        save_path = _batch_params.save_dir
        load_path = _batch_params.load_dir
        if not load_path:
            load_path = save_path

        if _batch_params.load_weights:
            self.load(load_path)

        # self.train(self._all_labels, self._all_features)

        n_samples = self._all_labels.size
        start_time = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
        self._logger.info(f'{start_time} :: batch training on {n_samples} samples')

        times = {}
        with profile('svm_train', times, show=1):
            features_list = list(map(list, self._all_features))
            labels_list = list(self._all_labels)

            self._problem = self._problem_fn(labels_list, features_list)
            self._libsvm_params = libsvm.svm_parameter(self._train_opts)
            self._weights = libsvm.svm_train(self._problem, self._libsvm_params)

        self._logger.info('time taken: {}'.format(times['svm_train']))

        self.is_trained = True
        self.is_loaded = False

        if not save_path:
            save_root_dir = os.path.dirname(self._db_path[0])
            timestamp = datetime.now().strftime("%y%m%d_%H%M%S")
            save_path = linux_path(save_root_dir, f'svm_batch_{timestamp}')

        os.makedirs(save_path, exist_ok=True)

        model_save_path = self.save(save_path, save_samples=False)

        model_dict = {
            'model_save_path': model_save_path,
            'n_samples': n_samples,
            'timestamp': datetime.now().strftime("%Y/%m/%d %H:%M:%S"),
        }
        pickle.dump(model_dict, open('{:s}/model_info.bin'.format(save_path), "wb"))

        return model_save_path

    def save(self, save_dir, save_samples=True):
        """
        :type save_path: str
        :type save_samples: bool | int
        :rtype: None
        """
        save_dir = self._check_save(save_dir)
        if save_dir is None:
            return

        model_save_path = linux_path(save_dir, 'model.bin')

        self._logger.info(f'Saving weights to {model_save_path}')
        libsvm.svm_save_model(model_save_path, self._weights)

        assert os.path.isfile(model_save_path), "model saving failed"

        if save_samples and self._params.accumulative:
            samples_save_dir = linux_path(save_dir, 'train_samples')
            self._save_train_samples(samples_save_dir, reset=not self._params.accumulative)

        return model_save_path

    def load(self, load_dir):
        """
        :type load_dir: str
        :type load_samples: bool | int
        :rtype: None
        """

        if self._params.batch.load_samples:
            self._load_train_samples(load_dir)
            return True
        """
        hack to allow custom load_path for the model independently of the target
        """
        if self._params.batch.load_dir:
            load_dir = self._params.batch.load_dir

        if os.path.isdir(load_dir):
            model_load_path = linux_path(load_dir, 'model.bin')
        else:
            model_load_path = load_dir

        if not os.path.exists(model_load_path):
            msg = 'weights file does not exist: {}'.format(model_load_path)
            raise IOError(msg)

        self._logger.info('Loading weights from: {}'.format(model_load_path))
        self._weights = libsvm.svm_load_model(model_load_path)

        assert self._weights is not None, "Model loading failed"

        model_info_path = linux_path(load_dir, 'model_info.bin')

        if os.path.isfile(model_info_path):
            model_info = pickle.load(open(model_info_path, "rb"))
            self._logger.info('Loaded model with train info: {}'.format(pformat(model_info)))

        # if load_samples and self._params.accumulative:
        #     samples_load_path = linux_path(load_dir, 'train_samples')
        #     self._load_train_samples(samples_load_path)

        self.is_trained = True
        self.is_loaded = True

        return True


import aioredis

from gloop.channels import Channel

class RedisChannel(Channel):

    def __init__(self, topic: str, address: str):
        super(RedisChannel, self).__init__()
        self._topic: str = topic
        self._address: str = address
        self._redis: aioredis.Redis = None

    async def connect(self):
        self._redis = await aioredis.create_redis(self._address)

    async def send(self, message: str):
        # XADD self._topic * message {message}
        if self._redis is None:
            await self.connect()
        await self._redis.xadd(
            self._topic,
            dict(
                message=message
            )
        )

    async def receive(self) -> str:
        if self._redis is None:
            await self.connect()
        messages = await self._redis.xread([self._topic])
        message = messages[0]
        topic, message_hash, body = message
        content = list(body.values())[0]
        return content.decode()

    async def close(self):
        self._redis.close()
        await self._redis.wait_closed()