# -*- coding: utf-8 -*-
"""
Задание 17.4

Создать функцию write_last_log_to_csv.

Аргументы функции:
* source_log - имя файла в формате csv, из которого читаются данные (пример mail_log.csv)
* output - имя файла в формате csv, в который будет записан результат

Функция ничего не возвращает.

Функция write_last_log_to_csv обрабатывает csv файл mail_log.csv.
В файле mail_log.csv находятся логи изменения имени пользователя. При этом, email
пользователь менять не может, только имя.

Функция write_last_log_to_csv должна отбирать из файла mail_log.csv только
самые свежие записи для каждого пользователя и записывать их в другой csv файл.

Для части пользователей запись только одна и тогда в итоговый файл надо записать только ее.
Для некоторых пользователей есть несколько записей с разными именами.
Например пользователь с email c3po@gmail.com несколько раз менял имя:
C=3PO,c3po@gmail.com,16/12/2019 17:10
C3PO,c3po@gmail.com,16/12/2019 17:15
C-3PO,c3po@gmail.com,16/12/2019 17:24

Из этих трех записей, в итоговый файл должна быть записана только одна - самая свежая:
C-3PO,c3po@gmail.com,16/12/2019 17:24

Для сравнения дат удобно использовать объекты datetime из модуля datetime.
Чтобы упростить работу с датами, создана функция convert_datetimestr_to_datetime - она
конвертирует строку с датой в формате 11/10/2019 14:05 в объект datetime.
Полученные объекты datetime можно сравнивать между собой.

Функцию convert_datetimestr_to_datetime использовать не обязательно.

"""

import datetime
import csv
from operator import itemgetter

def convert_datetimestr_to_datetime(datetime_str):
    """
    Конвертирует строку с датой в формате 11/10/2019 14:05 в объект datetime.
    """
    return datetime.datetime.strptime(datetime_str, "%d/%m/%Y %H:%M")

def write_last_log_to_csv(source_file, output_file):

    email_list = []
    repeated_email_list = []

    with open(source_file, encoding = 'UTF-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            email_list.append(row['Email'])
#       print(sorted(email_list))
        sorted_email_list = sorted(email_list)
        for counter, value in enumerate(sorted_email_list):
            if counter == len(sorted_email_list)-1:
                break
            elif value == sorted_email_list[counter+1]:
                repeated_email_list.append(value)
        uniq_repeated_email_list = list(set(repeated_email_list))
#       print(uniq_repeated_email_list, end = '\n\n')

    with open(source_file, encoding = 'UTF-8') as f, open(output_file, 'w', encoding = 'UTF-8') as ff:
        reader = csv.reader(f)
        writer = csv.writer(ff)
        writer.writerow(next(reader))
        new_list = []
        for row in reader:
            if row[1] in uniq_repeated_email_list:
                new_list.append(row)
            elif row[1] not in uniq_repeated_email_list:
#               row[2] = convert_datetimestr_to_datetime(row[2])
                writer.writerow(row)
#       print(sorted(new_list, key=itemgetter(1)))
        new_list1 = sorted(new_list, key=itemgetter(1))
#       print(new_list1, end = '\n\n')

    with open(output_file, 'a', encoding = 'UTF-8') as ff:
        writer = csv.writer(ff)
        for row in new_list1:
            row[2] = convert_datetimestr_to_datetime(row[2])
        new_list2 = sorted(new_list1, key=itemgetter(1, 2))
#       print(new_list2)

    with open(output_file, 'a', encoding = 'UTF-8') as ff:
        writer = csv.writer(ff)
        for counter, row in enumerate(new_list2, 1):
            if counter == len(new_list2):
                with open(source_file, encoding = 'UTF-8') as f:
                    reader = csv.reader(f)
                    for value in reader:
                        if value[0] == row[0]:
                            writer.writerow(value)
                            break
            elif row[1] != new_list2[counter][1]:
                with open(source_file, encoding = 'UTF-8') as f:
                    reader = csv.reader(f)
                    for value in reader:
                        if value[0] == row[0]:
                            writer.writerow(value)

#testing
write_last_log_to_csv('mail_log.csv', 'task_17_4_result.csv')


from kivy.app import App

from kivy.config import Config
Config.set("graphics", "resizable", False)

from kivy.uix.boxlayout import *
from kivy.uix.gridlayout import *
from kivy.uix.label import *
from kivy.uix.textinput import *
from kivy.uix.button import *
from kivy.uix.widget import Widget
from kivy.uix.camera import *
from kivy.graphics import *
from kivy.graphics.instructions import *
from kivy.uix.image import *
from kivy.uix.dropdown import *
from kivy.uix.floatlayout import *

from kivy.clock import Clock
from kivy.core.window import Window

import time

import random
import cv2 as cv
import numpy as np
from cv2 import line

import matplotlib
import matplotlib.pyplot as plt

class ImageProcessor(object):

    def __init__(self, url):

        self.baseUrl = "C:\\Users\\George\\Pictures\\Hack_tests"

        self.initial = cv.imread(url)
        #cv.imshow('initial', self.initial)

    def label_balls(self, im, tableWidth):
        imcopy = im.copy()

        circles, whiteBall, blackBall = self.extract_circles(im, tableWidth)
        valids = []

        #self.show_image("label", im)
        #cv.imwrite("C:\\Users\\George\\Pictures\\Hack_tests\circle_stuff.jpg", im)

        for i,circle in enumerate(circles[0,:]):
            x,y = (int(circle[0]),int(circle[1]))
            rad = int(circle[2])

            if 0<x-rad//2 and x+rad//2<im.shape[1] and y-rad//2>0 and y+rad//2< im.shape[0]:

                working = True

                for x1 in range(x-rad//2, x+rad//2, rad//10):
                    for y1 in range(y-rad//2,y+rad//2, rad//10):
                        (b,g,r) = im[y1,x1]
                        if (b,g,r) == (0,0,0) or g > max(r,b)*1.2:
                            working = False
                if working:
                    valids.append([x,y,int(circle[2])])

        hList = []
        for i,circle in enumerate(valids):
            x,y = circle[0], circle[1]

            #print(circle)
            hSum = 0
            hCount = 0
            if 0<x-rad//2 and x+rad//2<im.shape[1] and y-rad//2>0 and y+rad//2< im.shape[0]:
                for x1 in range(x-rad//2, x+rad//2, rad//10):
                    for y1 in range(y-rad//2,y+rad//2, rad//10):
                        hCount += 1
                        pix = np.uint8([[imcopy[y,x]]])
                        #print(pix)
                        hsv = cv.cvtColor(pix, cv.COLOR_BGR2HSV)
                        h,s,v = cv.split(hsv)
                        hSum += h[0][0]

                hList.append(hSum/hCount)

        hAverage = sum(hList) / len(hList)
        print(hAverage)

        for i,circle in enumerate(valids):

            if hAverage < 50:
                if hList[i] > hAverage:
                    circle.append('R')
                else:
                    circle.append('Y')
            else:
                if hList[i] < hAverage:
                    circle.append('R')
                else:
                    circle.append('Y')

        whiteBall.append("W")
        blackBall.append("B")
        allBalls = valids + [whiteBall] + [blackBall]
        print(allBalls)

        try:
            for i in allBalls:
                if i[3] == 'Y':
                    col = (255,255,0)
                if i[3] == 'R':
                    col = (0,255,255)
                if i[3] == 'W':
                    col = (0,0,0)
                if i[3] == 'B':
                    col = (255,255,255)
                cv.circle(im,(i[0],i[1]),i[2],col,2)
                cv.circle(im,(i[0],i[1]),2,col,3)
        except:
            pass
        #self.show_image("circle image2", im)
        return allBalls, im

    def get_white_ball(self, im, tableWidth,expected):
        whiteImage = im.copy()
        whiteImage = self.filter_for_white(whiteImage)
        whiteImage = cv.cvtColor(whiteImage, cv.COLOR_BGR2GRAY)
        whiteCircle = cv.HoughCircles(whiteImage,cv.HOUGH_GRADIENT,10,200,
                            param1=60,param2=30,
                            minRadius=int(expected*0.2),maxRadius=int(expected*1.5))

        whiteBall = None

        valids = []
        for i,circle in enumerate(whiteCircle[0,:10]):
            x,y = (int(circle[0]),int(circle[1]))
            rad = int(circle[2])

            if 0<x-rad//2 and x+rad//2<im.shape[1] and y-rad//2>0 and y+rad//2< im.shape[0]:

                working = 0

                for x1 in range(x-rad//2, x+rad//2, rad//10):
                    for y1 in range(y-rad//2,y+rad//2, rad//10):
                        (b,g,r) = im[y1,x1]
                        if (b,g,r) == (0,0,0) or g > max(r,b)*1.2 or int(r)*int(g)*int(b) < 150*150*150:
                            working += 1
                if working == 0 and whiteBall == None:
                    whiteBall = [x,y,int(circle[2])]
                    print("---------------------", whiteBall)
                else:
                    valids.append([working,x,y,int(circle[2])])

        if whiteBall == None:
            v = valids[0]
            v.pop(0)
            whiteBall = v

        return whiteBall

    def get_black_ball(self, im, tableWidth,expected):
        blackImage = im.copy()
        blackImage = self.filter_for_black(blackImage)
        blackImage = cv.cvtColor(blackImage, cv.COLOR_BGR2GRAY)
        #self.show_image("black image for circles", blackImage)
        blackCircle = cv.HoughCircles(blackImage,cv.HOUGH_GRADIENT,10,200,
                            param1=60,param2=30,
                            minRadius=int(expected*0.2),maxRadius=int(expected*1.5))

        blackBall = None

        valids = []
        for i,circle in enumerate(blackCircle[0,:10]):
            x,y = (int(circle[0]),int(circle[1]))
            rad = int(circle[2])

            if 0<x-rad//2 and x+rad//2<im.shape[1] and y-rad//2>0 and y+rad//2< im.shape[0]:

                working = 0

                for x1 in range(x-rad//2, x+rad//2, rad//10):
                    for y1 in range(y-rad//2,y+rad//2, rad//10):
                        (b,g,r) = im[y1,x1]
                        if (b,g,r) == (0,0,0) or g > max(r,b)*1.2 or int(r)*int(g)*int(b) < 150*150*150:
                            working += 1
                if working == 0 and blackBall == None:
                    blackBall = [x,y,int(circle[2])]
                    print("---------------------", blackBall)
                else:
                    valids.append([working,x,y,int(circle[2])])

        if blackBall == None:
            v = valids[0]
            v.pop(0)
            blackBall = v

        print('black ball', blackBall)
        return blackBall

    def extract_circles(self, im, tableWidth):

        #expected = 0.05 * tableWidth
        expected = 75

        whiteBall = self.get_white_ball(im, tableWidth, expected)

        blackBall = self.get_black_ball(im, tableWidth, expected)

        circleImage = im.copy()

        copy = im.copy()
        #im = cv.circle(copy, (whiteBall[0], whiteBall[1]), whiteBall[2], (0,0,0), -1)

        im = self.filter_for_balls(im)
        #self.show_image("filtered", im)
        im = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
        #im = cv.Canny(im, 100, 200)

        #im = cv.bitwise_not(im)
        #kernel = np.ones((10,10),np.float32)/4
        #im = cv.filter2D(im,-1,kernel)
        #self.show_image("blur", blurred)
        #self.show_image("cannied", im)
        circles = cv.HoughCircles(im,cv.HOUGH_GRADIENT,10,100,
                            param1=60,param2=30,
                            minRadius=int(expected*0.2),maxRadius=int(expected*1.5))
        try:
            circles = np.uint16(np.around(circles))
            for i in circles[0,:]:
                cv.circle(circleImage,(i[0],i[1]),i[2],(255,255,0),2)
                cv.circle(circleImage,(i[0],i[1]),2,(255,255,0),3)
        except:
            pass

        #self.show_image("circle image", circleImage)
        return circles, whiteBall, blackBall

    def filter_for_white(self,im):
        #=======================================================================
        # average = im.mean(axis=0).mean(axis=0)
        # print(average)
        #=======================================================================
        lowerFilter = np.array([175, 175,175])
        upperFilter = np.array([255,255,255])

        mask = cv.inRange(im, lowerFilter, upperFilter)
        newIm = cv.bitwise_and(im,im, mask = mask)

        #self.show_image("white image", newIm)

        return newIm

    def filter_for_black(self,im):
        #=======================================================================
        # average = im.mean(axis=0).mean(axis=0)
        # print(average)
        #=======================================================================
        im = cv.bitwise_not(im)

        #self.show_image("negative image", im)

        lowerFilter = np.array([200, 200,200])
        upperFilter = np.array([255,255,255])

        mask = cv.inRange(im, lowerFilter, upperFilter)
        newIm = cv.bitwise_and(im,im, mask = mask)

        #self.show_image("black image", newIm)

        return newIm

    def filter_for_balls(self, im):

        hsv = cv.cvtColor(im, cv.COLOR_BGR2HSV)

        lowerYellow = np.array([0,0,0])
        upperYellow = np.array([35,255,255])

        mask = cv.inRange(hsv, lowerYellow, upperYellow)
        res = cv.bitwise_and(im,im, mask= mask)

        newIm = cv.cvtColor(res, cv.COLOR_HSV2BGR)

        newIm = cv.bitwise_not(newIm)

        lowerFilter = np.array([255,255,255])
        upperFilter = np.array([255,255,255])

        mask = cv.inRange(newIm, lowerFilter, upperFilter)
        newIm = cv.bitwise_and(newIm,newIm, mask = mask)

        newIm = cv.bitwise_not(newIm)
        return newIm

    def cut_board(self, lines):
        im = self.initial.copy()
        (x1,y1), (x2,y2), (x3,y3), (x4,y4) = self.get_corners(lines)

        pts = np.array([[x1,y1], [x2,y2], [x3,y3], [x4,y4]])

        #make bounding rectangle and crop to it
        rect = cv.boundingRect(pts)
        x,y,w,h = rect
        croped = im[y:y+h, x:x+w].copy()

        #make mask
        pts = pts - pts.min(axis=0)
        mask = np.zeros(croped.shape[:2], np.uint8)
        cv.drawContours(mask, [pts], -1, (255, 255, 255), -1, cv.LINE_AA)

        # apply mask
        dst = cv.bitwise_and(croped, croped, mask=mask)

        #print(lines)
        angle = np.arctan(lines[3][0][0]) * (180/np.pi)
        #print(angle)
        #self.show_image('not rotated', dst)
        rows,cols = dst.shape[0], dst.shape[1]

        M = cv.getRotationMatrix2D((cols/2,rows/2),angle,1)
        dst2 = cv.warpAffine(dst,M,(cols,rows))

        #self.show_image('rotated', dst2)

        return dst2

    def get_corners(self, lines):
        coords = []
        ijs = [(0,2), (0,3), (1,3), (1,2)]
        for (i,j) in ijs:
            (m1,c1), (m2,c2) = lines[i][0], lines[j][0]
            x = (c2-c1) / (m1-m2)
            y = m1*x + c1
            coords.append((int(x),int(y)))
        return coords

    def extract_board(self):
        greenIm = self.filter_green(self.initial)

        #smallGreenIm = self.resize(greenIm, 0.2)
        #self.show_image("filtered_green", smallGreenIm)

        whiteFreeIm = self.remove_white(greenIm)
        #self.show_image('white filtered', whiteFreeIm)

        refilteredIm = self.exclude_rb(whiteFreeIm)
        #self.show_image('refiltered', refilteredIm)
        #cv.imwrite(self.baseUrl + "\refiltered.png", refilteredIm)

        edgesIm = self.do_edge_detection(refilteredIm)
        #self.show_image('edges2', edgesIm)

        lineList = self.get_lines(edgesIm)
        #self.display_lines(self.initial, lineList)
        #self.display_xy_lines(self.initial, lineList)

        #print(lineList)
        return lineList

    def show_image(self,label, im):
        #print(im.shape)
        width, height = im.shape[0], im.shape[1]
        #print(width, height)
        if width > 800:
            factor = 800/width
            #print(factor)
            im = self.resize(im, factor)

        cv.imshow(label, im)

    def filter_green(self, im):
        (b,g,r) = cv.split(im)

        m = np.maximum(np.maximum(b,g), r)

        g[g<m] = 0

        newIm = cv.merge([b,g,r])
        return newIm

    def remove_white(self, im):

        lowerFilter = np.array([0, 0,0])
        upperFilter = np.array([200,255,200])

        mask = cv.inRange(im, lowerFilter, upperFilter)
        newIm = cv.bitwise_and(im,im, mask = mask)

        return newIm

    def exclude_rb(self, im):
        # set green value for pixels that have too much red and blue to 0
        # then cut out pixels with 0 green value

        (b,g,r) = cv.split(im)

        m = np.minimum(np.minimum(b,g), r)

        g[g<(1.5*m)] = 0

        newIm = cv.merge([b,g,r])

        # the one here is important
        lowerFilter = np.array([0, 1,0])
        upperFilter = np.array([200,255,200])

        mask = cv.inRange(newIm, lowerFilter, upperFilter)
        newIm = cv.bitwise_and(newIm,newIm, mask = mask)

        return newIm

    def do_edge_detection(self,im):
        newImage = cv.Canny(im, 100, 200)
        return newImage

    def get_lines(self, edgeImage):
        #                     target,   rho, theta, thresh required to identify
        lines = cv.HoughLines(edgeImage,1,np.pi/180,200)
        hLines = []
        vLines = []

        for line in lines:
            for (rho, theta) in line:
                lineLength = 10000
                cT = np.cos(theta)
                sT = np.sin(theta)
                x0 = cT*rho
                y0 = sT*rho
                x1 = int(x0 + lineLength*(-sT))
                y1 = int(y0 + lineLength*(cT))
                x2 = int(x0 - lineLength*(-sT))
                y2 = int(y0 - lineLength*(cT))
                m = (y2-y1) / (x2-x1)
                c = y2 - m*x2
                if 1 < theta < 2:
                    hLines.append([(m, c)])
                else:
                    vLines.append([(m, c)])

        #self.display_lines(self.initial, hLines)
        halfY = edgeImage.shape[1] // 2
        closest = None
        closestX = 10000
        furthest = None
        furthestX = 0
        for line in vLines:
            m,c = line[0]
            x = (halfY - c)/m
            if x < closestX:
                closestX = x
                closest = line
            if x > furthestX:
                furthestX = x
                furthest = line

        newLines = [closest, furthest]

        halfX = edgeImage.shape[0] // 2
        closest = None
        closestY = 10000
        furthest = None
        furthestY = 0
        for line in hLines:
            m,c = line[0]
            y = m*halfX + c
            if y < closestY:
                closestY = y
                closest = line
            if y > furthestY:
                furthestY = y
                furthest = line

        newLines = newLines + [closest, furthest]

        return newLines

    def display_lines(self, im, lineList):
        imCopy = im.copy()
        for line in lineList:
            for (rho,theta) in line:
                lineLength = 10000
                cT = np.cos(theta)
                sT = np.sin(theta)
                x0 = cT*rho
                y0 = sT*rho
                x1 = int(x0 + lineLength*(-sT))
                y1 = int(y0 + lineLength*(cT))
                x2 = int(x0 - lineLength*(-sT))
                y2 = int(y0 - lineLength*(cT))

            cv.line(imCopy,(x1,y1),(x2,y2),(0,0,255),5)

        #self.show_image("line image" + str(random.randint(0,1000)), imCopy)

    def display_xy_lines(self, im, lineList):
        imCopy = im.copy()
        for line in lineList:
            for (m,c) in line:
                x1 = -10000
                y1 = int(m*x1 + c)
                x2 = 10000
                y2 = int(m*x2 + c)

            cv.line(imCopy,(x1,y1),(x2,y2),(0,0,255),5)

        #self.show_image("line image" + str(random.randint(0,1000)), imCopy)

    def resize(self, im, factor):
        return cv.resize(im, (0,0), fx=factor, fy=factor)

class Projector(object):

    def __init__(self, balls, image, url):
        #print(lines)

        #print(angle)

        i = ImageProcessor(url)
        i.initial = image
        lines = i.extract_board()
        angle = np.arctan(lines[3][0][0])

        i.display_xy_lines(image, lines)

        newList = []

        for ball in balls:
            x,y,rad,type = ball
            x1 = (y-lines[0][0][1])/lines[0][0][0]
            x2 = (y-lines[1][0][1])/lines[1][0][0]
            dist = abs (x1-x2)
            xratio = (x-x1) / dist

            yratio = 1 - (y / image.shape[1]) ** 0.5

            #self.project(image, x, y, lines)

            print('x',xratio)
            print('y',yratio)

            newList.append([xratio, yratio*2, type])

        self.newList = newList

        #=======================================================================
        # fig, ax = plt.subplots(figsize=(12,6))
        #
        # plt.plot(yList, xList, marker='x', color='black', linestyle='None', markersize = 5.0)
        #
        # axes = plt.gca()
        # axes.set_xlim([0,1])
        # axes.set_ylim([0,2])
        #
        #
        #
        # plt.show()
        #=======================================================================

    def project(self, image, x, y, lines):
        width, height = image.shape[0], image.shape[1]
        A = (width//2, height)
        B = (x,y)
        C = self.get_halfway(image, lines)
        D = (width//2, 0)

        ac = 1
        BC = self.get_dist(B,C)
        AD = self.get_dist(A,D)
        AC = self.get_dist(A,C)
        ad = 2
        cd = 1
        BD = self.get_dist(B,D)

        bc = cd / ((ad*AC*BD / (ac*BC*AD)) - 1)

        dis = 1- bc

        print('bc is  ', bc)

        return dis

    def get_dist(self, coord1, coord2):
        return abs(coord1[1]-coord2[1])

    def get_halfway(self,image, lines):
        height,width = image.shape[0], image.shape[1]
        #cv.imshow("im", cv.resize(image.copy(), (0,0), fx=0.2, fy=0.2))

        m,c = lines[1][0]
        x1 = -10000
        y1 = int(m*x1 + c)
        x2 = 10000
        y2 = int(m*x2 + c)

        cv.line(image,(x1,y1),(x2,y2),(0,0,255),5)

        holex,holey = [], []

        for y in range(height//6, height//3, 1):
            x = int((y-c)/ m) - 5
            if x > 0 and x < width:
                b,g,r = image[y,x]
                if b<30 and g < 30 and r <30:
                    holex.append(x)
                    holey.append(y)

        if holex != [] and holey != []:
            hole1 = [sum(holex) / len(holex), sum(holey)/ len(holey)]
        else:
            hole1 = None
            raise Exception ("Ahhhh")

        m,c = lines[0][0]
        holex,holey = [], []

        for y in range(height//6, height//3, 1):
            x = int((y-c)/ m) + 5
            if x > 0 and x < width:
                b,g,r = image[y,x]
                if b<30 and g < 30 and r <30:
                    holex.append(x)
                    holey.append(y)

        if holex != [] and holey != []:
            hole2 = [sum(holex) / len(holex), sum(holey)/ len(holey)]
        else:
            hole2 = None
            raise Exception ("Ahhhh")

        halfWayMark = [width//2, int(hole1[1] + hole2[1]+50)//2]
        cv.circle(image, (halfWayMark[0],halfWayMark[1]), 10, (0,255,255), 3 )
        #cv.imshow("im2", cv.resize(image.copy(), (0,0), fx=0.2, fy=0.2))
        return halfWayMark

    def rotate_coords(self, coords, origin, radians):
        x, y = coords
        ox, oy = origin

        qx = ox + np.cos(radians) * (x - ox) + np.sin(radians) * (y - oy)
        qy = oy + -np.sin(radians) * (x - ox) + np.cos(radians) * (y - oy)

        return qx, qy

#----------------------------------------------------------------------------------------------------

def transform_coordinates(pos):
        return (2.2*pos[0]+12, 3.5*pos[1] -180)

def inverse_transform(pos):
    return ((pos[0]-12)/2.2,(pos[1]+180)/3.5)

class PoolTable(Widget):

    def __init__(self):
        super(PoolTable, self).__init__()

        Window.size = (800,600)

        self.radius = 80
        self.balls = []
        self.drawn_balls = []
        self.active_height = Window.size[1]*0.8
        self.active_width = self.active_height/960*562
        self.active_size = (self.active_width,self.active_height)
        print(self.active_size)
        self.lower_pos = (Window.size[0]-self.active_width,Window.size[1]-self.active_height)

        with self.canvas:
            Rectangle(source= "C:\\Users\\George\\Pictures\\Hack_tests\\pool_table.png",pos=self.lower_pos, size=(self.active_width,self.active_height))

    def drawBall(self, ball):
        with self.canvas:
            ball.color
            Ellipse(pos=(self.lower_pos[0]+ball.pos[0]+ball.radius,self.lower_pos[1]+ball.pos[1]+ball.radius), size=(ball.radius, ball.radius))

    def drawBalls(self):
        for ball in self.balls:
            ball.display(self)

    def addBalls(self,manyballs):
        self.canvas.clear()
        with self.canvas:
            Rectangle(source= "C:\\Users\\George\\Pictures\\Hack_tests\\pool_table.png",pos=self.lower_pos, size=(self.active_width,self.active_height))

            self.balls = manyballs
            self.drawBalls()

class Ball():
    def __init__(self, color,position):
        super(Ball, self).__init__()
        self.radius = 2*5.7
        self.color = color
        self.pos = transform_coordinates(position)
        print(self.pos)

    def display(self,a_widget):
        print(self.color)
        with a_widget.canvas:
            Color(self.color[0], self.color[1], self.color[2])
            Ellipse(pos=(a_widget.lower_pos[0]+self.pos[0]+self.radius,a_widget.lower_pos[1]+self.pos[1]+self.radius), size=(self.radius, self.radius))

#===============================================================================
# class MyApp(App):
#
#     def build(self):
#         self.widget = PoolTable(width = Window.size[0]/4, height = Window.size[1]*4/5)
#         return self.widget
#
#     def drawBalls(self):
#         print("lol")
#         self.widget.drawBall()
#
#     def addBalls(self, balls):
#         self.widget.addBalls(balls)
#         print(len(self.widget.balls))
#===============================================================================

#===============================================================================
# if __name__=='__main__':
#     app = MyApp()
#     app.balls = 3
#     app.build()
#
#     ball = Ball()
#     ball.colorize(Color(1,1,0))
#     ball.position((20,30))
#     #ball.display(app.widget)
#
#
#     app.addBalls(ball)
#     app.drawBalls()
#
#
#     app.run()
#===============================================================================

class MainScreen(GridLayout):

    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.cols = 1

        PLAYERS = ["Undecided","Red","Yellow"]
        self.player = "Undecided"

        self.top_row = BoxLayout(orientation = "horizontal", size_hint_y = 0.8)
        self.bottom_row = BoxLayout(orientation = "horizontal", size_hint_y = 0.2)
        self.add_widget(self.top_row)
        self.add_widget(self.bottom_row)
        self.top_widgets = []
        self.bottom_widgets = []

        #self.camera = Camera(play = True, resolution = (960,640), size_hint_x = 1.5)

        url = "C:\\Users\\George\\Pictures\\Hack_tests\\IMG_20191115_191414.jpg" #  "C:\\Users\\George\\Pictures\\Hack_tests\\IMG_20191116_100356.jpg"
        self.camera = Image(source = url)
        self.top_row.add_widget(self.camera)
        self.top_widgets.append(self.camera)

        self.table = PoolTable() #placeholder picture

        self.top_row.add_widget(self.table)
        self.top_widgets.append(self.table)

        self.button_camera = Button(text='Take a pic!', font_size=30)
        self.button_balls = Button(text='Add yellow balls', font_size=20)

        def capture(self):
            '''
            Function to capture the images and give them the names
            according to their captured time and date.
            '''
            timestr = time.strftime("%Y%m%d_%H%M%S")
            self.camera.export_to_png("IMG_{}.png".format(timestr))
            print("Captured")

        def take_pic(instance):
            if self.button_camera.text == "Take a pic!":
                timestr = time.strftime("%Y%m%d_%H%M%S")
                url = "IMG_{}.png".format(timestr)

                #url = "C:\\Users\\George\\Pictures\\Hack_tests\\IMG_20191116_100356.jpg"
                url = "C:\\Users\\George\\Pictures\\Hack_tests\\IMG_20191115_191414.jpg"
                print('changed')
                self.button_camera.text = "Loading..."

                try:
                    i = ImageProcessor(url)

                    lines = i.extract_board()
                    cutBoard = i.cut_board(lines)

                    balls,ballImage = i.label_balls(cutBoard, 2500)
                    cv.imwrite("C:\\Users\\George\\Pictures\\Hack_tests\\processed.jpg", ballImage)
                    #cv.imshow("ball image", ballImage)
                    self.camera = Image(source = "C:\\Users\\George\\Pictures\\Hack_tests\\processed.jpg")

                    proj = Projector(balls, cutBoard, url)
                    self.ballList = proj.newList

                    print(self.ballList)

                    for i in range(len(self.ballList)):
                        x = int(self.ballList[i][0] * 100)
                        y = int(self.ballList[i][1] * 100)
                        col = self.ballList[i][2]
                        if col == 'R':
                            col = [1,1,0]
                        elif col == "Y":
                            col = [1,0,0]
                        elif col == "B":
                            col = [0,0,0]
                        else:
                            col = [1,1,1]

                        self.ballList[i][2] = col

                        self.ballList[i] = Ball(col, (x,y))

                    self.table.addBalls(self.ballList)

                except Exception as e:
                    print(e)
                    self.button_camera.text = "Try again"

                if self.button_camera.text in ["Take a pic!", "Loading..."]:
                    self.button_camera.text = "Retake?"

            else:
                self.button_camera.text = "Take a pic!"
                self.camera.source = "C:\\Users\\George\\Pictures\\Hack_tests\\IMG_20191115_191414.jpg"

            self.camera.reload()
            #self.camera.play = not(self.camera.play)

        def swap_balls(instance):
            if self.button_balls.text == 'Add yellow balls':
                self.button_balls.text = 'Add red balls'
            elif self.button_balls.text == 'Add red balls':
                self.button_balls.text = 'Add white ball'
            elif self.button_balls.text == 'Add white ball':
                self.button_balls.text = 'Add black ball'
            else:
                self.button_balls.text = 'Add yellow balls'

        self.button_camera.bind(on_press = take_pic)
        self.button_balls.bind(on_press = swap_balls)
        self.bottom_row.add_widget(self.button_camera)
        self.bottom_widgets.append(self.button_camera)
        self.bottom_row.add_widget(self.button_balls)
        self.bottom_widgets.append(self.button_balls)

        self.button_calculate = Button(text='Calculate!')
        self.bottom_row.add_widget(self.button_calculate)
        self.bottom_widgets.append(self.button_calculate)

        def null_function(instance):
            return None

        def calculate(instance):
            self.button_calculate.bind(on_press = null_function)
            self.button_calculate.text = "Loading..."
            # give self.ballList to foo()

            for i, ball in enumerate(self.ballList):
                col = ball.color
                if col == [1,1,0]:
                    col = 'red'
                elif col == [1,0,0]:
                    col = 'yellow'
                elif col == [0,0,0]:
                    col = 'black'
                else:
                    col = 'white'

                ballPos = inverse_transform(ball.pos)
                self.ballList[i] = [[ballPos[0], ballPos[1]], col]

            if self.player == 'Undecided':
                colours = ['red', 'yellow']
            else:
                colours = [self.player.lower()]

            dict = turn(colours, self.ballList)

            print(dict)

            cuePoint = dict['cue position']
            whitePoint = dict['collision point']
            pocketPoint = dict['target hole']

            print(cuePoint, whitePoint, pocketPoint)
            cuePoint = [cuePoint[0], cuePoint[1]]
            whitePoint = [whitePoint[0], whitePoint[1]]
            pocketPoint = [pocketPoint[0], pocketPoint[1]]

            cuePoint = transform_coordinates(cuePoint)
            whitePoint = transform_coordinates(whitePoint)
            pocketPoint = transform_coordinates(pocketPoint)

            with self.canvas:
                p1 = [cuePoint[0]+self.table.lower_pos[0]+4*5.7, cuePoint[1]+self.table.lower_pos[1]+4*5.7, whitePoint[0]+self.table.lower_pos[0]+4*5.7, 4*5.7+ whitePoint[1]+self.table.lower_pos[1]]
                print(p1)
                Line(points=p1)
                Line(points=[whitePoint[0]+self.table.lower_pos[0]+4*5.7, whitePoint[1]+self.table.lower_pos[1]+4*5.7, pocketPoint[0]+4*5.7+self.table.lower_pos[0], pocketPoint[1]+self.table.lower_pos[1]+4*5.7])

            self.button_calculate.bind(on_press = calculate)
            self.button_calculate.text = "Calculate!"

        self.button_calculate.bind(on_press = calculate)
        self.button_player = Button(text="Player: " + self.player)
        self.bottom_row.add_widget(self.button_player)
        self.bottom_widgets.append(self.button_player)

        def change_player(instance):
            self.player = PLAYERS[(PLAYERS.index(self.player)+1)%3]
            self.button_player.text = "Player: " + self.player
        self.button_player.bind(on_press = change_player)

#-------------------------------------------------------------------------------

#Input = position of every ball and dimension of table
#Output = optimal shot coordinates

import math

info = {
    "resolution" : 1,
    "dimensions" : [100,200],
    "corner_len" : 8,
    "side_len" : 6,
}

#useful functions for geometry

def euclidean_dist(pos1,pos2):
    return ((pos1[1]-pos2[1])**2 + (pos1[0]-pos2[0])**2)

def slope(pos1,pos2):
    if pos1[0]==pos2[0]:
        return 1000
    else:

        return (pos1[1]-pos2[1])/(pos1[0]-pos2[0])

g = 9.81
mu = 0.6

def affine(m,p,x):
    return (m*x+p)

def in_circle(center,point, radius):
    if euclidean_dist(center,point)<radius**2:
        return True
    else:
        return False

def is_between(m,top_p,bot_p,point):
    x = point[0]
    y = point[1]
    if (affine(m,bot_p,x) < y < affine(m, top_p, x)):
        return True
    else:
        return False

def angle(point1,point2):
    angle = math.atan(slope(point1,point2))
    if point2[0]>point1[0]:
        return angle
    else:
        return (pi-angle)

class Ball2:
    def __init__(self, pos, colour):

        #position is already scaled
        self.pos = pos
        self.colour = colour
        self.r = 2.8
        self.res = info["resolution"]

    def pixels(self):
        # assign the pixels to the ball , radius = 5.7
        r = round(self.res*self.r)
        x = self.pos[0]
        y = self.pos[1]
        pixels = [[x+r,y], [x-r, y], [x, y+r], [x, y-r], [x+round(r/math.sqrt(2)), y + round(r/math.sqrt(2))], [x-round(r/math.sqrt(2)), y + round(r/math.sqrt(2))],[x+round(r/math.sqrt(2)), y - round(r/math.sqrt(2))],[x - round(r/math.sqrt(2)), y - round(r/math.sqrt(2))]]
        return pixels

    def hole_dist(self, hole_pos):
        return math.sqrt(euclidean_dist(self.pos,hole_pos))

    def cue_dist(self, cue_ball):
        return math.sqrt(euclidean_dist(self.pos, cue_ball.pos))

    def get_angle(self, cue_ball, hole_pos):
        m1 = slope(self.pos, cue_ball.pos)
        m2 = slope(hole_pos, self.pos)
        return math.atan(abs((m2-m1)/(1+m1*m2)))

    def initial_force(self, cue_ball, hole_pos):
        angle = self.get_angle(cue_ball, hole_pos)
        initial_force = 2*mu*g*(self.cue_dist(cue_ball)+(2*mu*g*self.hole_dist(hole_pos))/(math.sin(angle/2))**2)
        return initial_force

    def actual_target(self,cue,hole_pos):
        r = self.r*self.res
        angle2 = angle(self.pos,hole_pos)
        target = [self.pos[0]-2*r*math.cos(angle2), self.pos[1]-2*r*math.sin(angle2)] # does this work with signs?
        target = [round(target[0]), round(target[1])]

        return target

    def is_possible(self, cue_ball, hole_pos, balls, hole_bounds): #balls is a list of all balls except the two concerned
        #find actual equation of shot (with adjustment)
        # 1: find adjusted target
        r = self.r*self.res
        angle2 = angle(self.pos,hole_pos)
        target = self.actual_target(cue_ball,hole_pos)

        #find equation
        m = slope(cue_ball.pos, target)
        p = m*target[0] + target[1]

        #find boundaries
        angle1 = angle(cue_ball.pos, target)+0.01
        shift1 = abs(2*r/math.sin(angle1))
        top_p = p + m*shift1
        bot_p = p - m*shift1

        #iterations for checking
        #check cue to ball
        for ball in balls:
            for point in ball.pixels():
                if is_between(m, top_p, bot_p, point) and is_between(0,max(cue_ball.pos[0],ball.pos[0]), min(cue_ball.pos[0],ball.pos[0]), point):
                    return False

        #check ball to hole
        #find new line

        M = slope(self.pos, hole_pos)
        P = M*hole_pos[0] + hole_pos[1]

        shift2 = abs(2*r/math.sin(angle2))
        top_P = P + M*shift2
        bot_P = P - M*shift2

        #check ball to hole
        for ball in balls:
            for point in ball.pixels():
                if is_between(M, top_P, bot_P, point) and is_between(0,max(ball.pos[0],hole_pos[0]), min(ball.pos[0],hole_pos[0]), point):
                    return False

        # narrower boundaries when we check the pocket boundaries
        shift3 = shift2/2
        top_P = P + M*shift3
        bot_P = P - M*shift3
        for hole in hole_bounds:
            for point in hole_bounds[hole]:
                if is_between(M, top_P, bot_P, point) and is_between(0,max(ball.pos[0],hole_pos[0]), min(ball.pos[0],hole_pos[0]), point):
                    return False

        return True

def h_bounds(info):
    s = info["resolution"]*info["corner_len"]
    r = info["resolution"]*info["side_len"]
    [wdt,lth] = info["dimensions"]
    hole_bounds = {
        "1" : [[s,0],[0,s]],
        "2" : [[1,lth//2-r],[1,lth//2+r]],
        "3" : [[s,lth-1],[1,lth-s]],
        "4" : [[wdt-s,lth-1],[wdt-1,lth-s]],
        "5" : [[lth//2-r,wdt-1],[lth//2+r,wdt-1]],
        "6" : [[wdt-s,1],[wdt-1,s]]
    }

    return hole_bounds

#create dic of target points for pocket
def t_points(info):
    s = info["resolution"]*info["corner_len"]
    r = info["resolution"]*info["side_len"]
    res = info["resolution"]

    [wdt,lth] = info["dimensions"]
    target_points = [[0 for i in range(3)] for j in range(6)]
    target_points = {
        "1" : [[s//4,(3*s)//4],[s//2,s//2], [(3*s)//4,s//4]],
        "2" : [[1,lth//2-r//2],[1,lth//2],[1,lth//2+r//2]],
        "3" : [[s//4,lth-(3*s)//4],[s//2,lth-s//2],[(3*s)//4,lth-s//4]],
        "4" : [[wdt-(3*s)//4,lth-s//4],[wdt-s//2,lth-s//2],[wdt-s//4,lth-(3*s)//4]],
        "5" : [[wdt-1,lth//2-r//2],[wdt-1,lth//2],[wdt-1,lth//2+r//2]],
        "6" : [[wdt-(3*s)//4,s//4],[wdt-s//2,s//2], [wdt-s//4,(3*s)//4]],
    }

    return target_points

hole_bounds = h_bounds(info)
target_points = t_points(info)

import scipy.integrate as integrate
import scipy.special as special
from scipy.stats import *
from pynverse import inversefunc
from math import *
import numpy as np
import matplotlib.pyplot as plt

def prob(ball_r,balls_dist,angle_1,angle_2,cue_ball_angle,omega):

    min_in_angle = min(angle_1,angle_2)
    max_in_angle = max(angle_1,angle_2)

    def f(t):
        try:
            return asin(balls_dist*sin(t)/(2*ball_r)) - abs(t) + cue_ball_angle
        except:
            pass

    def pdf(x):
        var = 0.1 #* exp(-(balls_dist-ball_r*2))
        return pow(2*pi*var,-0.5) * exp(-((x-omega)**2)/(2*var))

    try:
        bound = asin(2*ball_r/balls_dist)
    except:
        return 0

    f_image = [min_in_angle,max_in_angle]
    inv_f = inversefunc(f,domain=[-1*bound,bound], image = f_image)

    return integrate.quad(pdf,inv_f(f_image[0]),inv_f(f_image[1]))[0]

#finds the integration bounds
def target_angle_bounds(ball, hole_nb):
    point1, point2 = hole_bounds[hole_nb][0], hole_bounds[hole_nb][1]
    angle1, angle2 = angle(ball.pos,point1), angle(ball.pos, point2)
    return (angle1,angle2)

#For a given cue and colour, iterate the list

def find_optimal_direct(balls,cue,colours):
    shots = []
    radius = balls[0].r*balls[0].res

    for ball in balls:
        if ball.colour in colours:
            for hole in target_points:
                (angle1, angle2) = target_angle_bounds(ball,hole)
                cue_angle = angle(cue.pos,ball.pos)

                for hole_point in target_points[hole]:

                    target = ball.actual_target(cue, hole_point)

                    omega = cue_angle - angle(target,hole_point)
                    if ball.hole_dist(hole_point)<=cue.hole_dist(hole_point):

                        proba = prob(radius, ball.cue_dist(cue), angle1, angle2, cue_angle, omega)
                    else:
                        proba = 0

                    shots.append([ball,hole,hole_point,proba])

    shots.sort(key=lambda x : x[3], reverse=True)

    for shot in shots:
        ball = shot[0]
        hole_point = shot[2]
        if ball.is_possible(cue,hole_point,balls,hole_bounds):
            if shot[3] > 0:
                optimal_shot = {
                    "cue position" : cue.pos,
                    "ball position" : ball.pos,
                    "collision point" : ball.actual_target(cue, hole_point),
                    "target hole" : hole_point,
                    "probability" : shot[3],
                    "bounce" : False
                }

                return optimal_shot

    return "no available shot"

def check_bounce_shot(balls,cue,colours):

    [wdt,lth] = info["dimensions"]

    def Y(x,a):
        return (a*y+b*x)/(a+x)

    def X(y,b):
        return (x*y+a*b)/(b+y)

    for ball in balls:
        if ball.colour in colours:
            [x,y] = cue.pos
            [a,b] = ball.pos
            cue1 = Ball2([1,Y(x, a)],"white")
            cue2 = Ball2([1,Y(wdt - x, wdt - a)],"white")
            cue3 = Ball2([X(y,b),1],"white")
            cue4 = Ball2([X(lth-y, lth-b),1],"white")

            optimals = [find_optimal_direct(balls,cue1,colours), find_optimal(balls,cue2,colours), find_optimal(balls,cue3,colours), find_optimal(balls,cue4,colours),]

            optimals.sort(key = lambda x: x["probability"], reverse=True)
            optimals[0]["bounce"] = True
            return optimals[0]

def find_optimal(balls,cue,colours):
    direct_best = find_optimal_direct(balls,cue,colours)
    if direct_best == "no available shot":
        return check_bounce_shot(balls,cue,colours)
    else:
        return direct_best

#if white ball can be placed
def place_white(balls,colour):
    radius = round(balls[0].r*balls[0].res)
    [wdt,lth] = info["dimensions"]
    optimals = []
    for delta_x in range(radius,wdt-radius,4*radius):
        for delta_y in range(radius,lth//4-radius,4*radius):
            cue = Ball2([delta_x,delta_y],"white")
            optimals.append(find_optimal(balls,cue,colour))
    optimals.sort(key = lambda x: x["probability"], reverse=True)
    return optimals[0]

#===============================================================================
#
# #For each turn
# colour = input() # can be ["red","yellow"] if table is open
# white_on_table = bool(input())
#===============================================================================
def turn(colours, ball_coords):
    balls = []
    cue = None
    for ball in ball_coords:
        balls.append(Ball2(ball[0],ball[1]))
        print(ball[1])
        if ball[1] == 'white':
            cue = Ball2(ball[0],ball[1])
            print('executed')
    #balls is a list of elements of the class ball
    print(list(ball.pos for ball in balls))
    if cue != None:
        return find_optimal(balls,cue,colours)
    else:
        return place_white(balls,colours)

#-------------------------------------------------------------------------------

class MyApp(App):

    def build(self):
        return MainScreen()

if __name__ == '__main__':
    MyApp().run()


import logging

config = {
    'log_config': {
        'version': 1,
        'disable_existing_loggers': True,
        'formatters': {
            'default': {
                '()': 'uvicorn.logging.DefaultFormatter',
                'fmt': '%(levelprefix)s %(message)s',
                'use_colors': None
            },
            'access': {
                '()': 'uvicorn.logging.AccessFormatter',
                'fmt': '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s'}
        },
        'handlers': {
            'default': {
                'formatter': 'default',
                'class': 'logging.StreamHandler',
                'stream': 'ext://sys.stderr'
            },
            'access': {
                'formatter': 'access',
                'class': 'logging.StreamHandler',
                'stream': 'ext://sys.stdout'
            }
        },
        'loggers': {
            'uvicorn': {
                'handlers': ['default'],
                'level': 'INFO'
            },
            'uvicorn.error': {
                'level': 'INFO',
                'handlers': ['default'],
                'propagate': True
            },
            'uvicorn.access': {
                'handlers': ['access'],
                'level': 'INFO',
                'propagate': False
            },
        },
    }
}

log_format = f"[%(asctime)s] %(levelname)s, %(process)s-%(thread)d, %(filename)s, line %(lineno)d, %(message)s"
formatter = logging.Formatter(log_format, '%Y/%m/%d %H:%M:%S')

def _init_logger(handler_name=None):
    if handler_name is None:
        log = logging.getLogger()
    else:
        log = logging.getLogger(handler_name)

    log.setLevel(logging.INFO)
    log.propagate = False

    log.handlers.clear()
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)
    log.addHandler(stream_handler)

def init():
    _init_logger()
    _init_logger('uvicorn')
    _init_logger('uvicorn.error')
    _init_logger('uvicorn.access')

    # print(dir(logging.Logger.manager.loggerDict))
    # print(logging.Logger.manager.loggerDict)


import sys
from Tkinter import *
from numero_a_letras import *

def holamundo():
    n = int(var_campo.get())
    texto = to_word(n)
    etiqueta2 = Label(raiz, text=texto, fg="blue", font=("Helvetica", 16))
    etiqueta2.place(x = 250, y = 75, anchor = CENTER)

def salir():
    #m_salir = messagebox.askokcancel(titel="Salir", message="Esta seguro que desea salir.")
    #if m_salir > 0:
    #    raiz.destroy()
    #    return
    raiz.destroy()

raiz = Tk()
var_campo = StringVar()
raiz.geometry('500x200+200+200')
raiz.title("Convertir Numero a Letra")
etiqueta = Label(raiz, text="Escriba un numero")
boton = Button(raiz, text="Convetir a letra", command = holamundo)
campo = Entry(raiz, textvariable=var_campo)
b_salir = Button(raiz, text="Salir", command = salir)

etiqueta.place(x = 130, y= 12.5)
campo.place(x = 250, y= 10)
boton.place(x = 15, y= 150)
b_salir.place(x = 430, y= 150)
raiz.mainloop()


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

ts = pd.Series(np.random.randn(1000),
               index=pd.date_range('2019-01-01', periods=1000))

ts = ts.cumsum()
ts.plot()

# %%

ts = ts.cummin()
ts.plot()

# %%

ts = ts.cummax()
ts.plot()

# %%

df = pd.DataFrame(np.random.randn(1000, 5),
               index=pd.date_range('2019-01-01', periods=1000),
               columns=list('ABCDE'))

# %%

df = df.cumsum()
df.plot()

# %%

df['B'].plot()

# %%

abs(df.iloc[5]).plot(kind='bar', title='bar chart')


import sys
from tkinter import *
import time
import random

root = Tk()
root.title('2020 Countdown')
root.iconbitmap('C:\\Program Files\\Python39\\DLLs\\pyc.ico')
root.geometry('200x150')
root.config(background='orange')

l1 = Label(root, font='times 20', fg='blue')
l1.grid(row=1, column=2)

times = StringVar()
e1 = Entry(root, textvariable=times)
e1.grid(row=3, column=2)

t = 0

def set_timer():
    global t
    t += int(e1.get())
    return t

def countdown():
    global t
    if t > 0:
        # print(t)
        m, s = divmod(t, 60)
        h, m = divmod(m, 60)
        l1.config(text=str(h).zfill(2) + ':' + str(m).zfill(2) + ':' + str(s).zfill(2))
        t -= 1
        l1.after(1000, countdown)
    elif t == 0:
        print('end')
        l1.config(text='GO')

button1 = Button(root, text='SET', width=21, pady=5, bd=2, command=set_timer, fg='red')
button1.grid(row=4, column=2, padx=21)

button2 = Button(root, text='START', width=21, pady=5, bd=2, command=countdown, fg='red')
button2.grid(row=6, column=2, padx=21)

root.mainloop()


"""
Input: (well_height, snail_speed, snail_slide_speed, fatigue factor)
Output: success on day n
"""
import sys

def main():

	for line in sys.stdin:
		well_height, snail_speed, snail_slide_speed, fatigue_factor = map(float, line.split())

		if well_height == 0:
			break

		current_day = 0
		snail_height = 0
		#print("Speed: {}".format(snail_speed))
		#print("Fatigue: {}".format(fatigue_factor))

		speed_decrease_per_day = snail_speed * (fatigue_factor/100)

		#print("Speed Decrease Per Day: {}".format(speed_decrease_per_day))
		#Failing 56 3 1 5
		while(snail_height >= 0):
			current_day += 1
			snail_height += snail_speed

			if(snail_height > well_height):
				break

			snail_height -= snail_slide_speed

			snail_speed -= speed_decrease_per_day

			snail_speed = max(0, snail_speed)

			#print('============\nDay: {}\nHeight {}\nSnail Speed: {}\n=============\n'.format(current_day, snail_height, snail_speed))

		if(snail_height > well_height):
			print("success on day %d" % current_day)
		else:
			print("failure on day %d" % current_day)

main()


# coding: utf-8

import json
from pprint import pprint
from kubernetes import client, config

from apis.t3q_config import CLUSTER
import apis.t3q_serving as t3q_serving
import apis.t3q_patch as t3q_patch

def get_autoscaling_body(Resource):
    autoscaling = {}
    if Resource['autoscale_class'] == 'hpa':
        autoscaling.update({"autoscaling.knative.dev/class": "hpa.autoscaling.knative.dev"})
    else:
        autoscaling.update({"autoscaling.knative.dev/class": "kpa.autoscaling.knative.dev"})
    if Resource['minscale']:
        autoscaling.update({"autoscaling.knative.dev/minScale": Resource['minscale']})
    if Resource['maxscale']:
        autoscaling.update({"autoscaling.knative.dev/maxScale": Resource['maxscale']})
    return autoscaling

def create(Resource):
    revision = Resource['name'] + '-first'
    t3q_serving.create_service(
            name = Resource['name'],
            image = Resource['image'],
            env = Resource['env'],
            revision = revision,
            autoscaling = get_autoscaling_body(Resource),
            traffic = [
                {"tag": "first", "revisionName": revision, "percent": 100},
                {"tag": "latest", "latestRevision": True, "percent": 0}
            ])

def patch(Resource):
    t3q_patch.patch_service(
            name = Resource['name'],
            revision = Resource['revision'],
            image = Resource['image'],
            env = Resource['env'],
            autoscaling = get_autoscaling_body(Resource),
            traffic = Resource['traffic']
            )

def delete(Resource):
    t3q_serving.delete_service(Resource['name'])

def list():
    service = t3q_serving.list_service()
    res = []
    for v in service:
        status = v['status']
        template = v['spec']['template']
        container = template['spec']['containers'][0]

        reason = ''
        ready = ''
        for st in status['conditions']:
            if('type' in st and st['type'] == 'Ready'):
                ready = st['status']
                if 'reason' in st:
                    reason = st['reason']

        annotations = {}
        if 'metadata' in template and 'annotations' in template['metadata']:
            annotations = template['metadata']['annotations']

        autoscale_class = 'kpa'
        minscale = ''
        maxscale = ''
        for key in annotations:
            if key.endswith('class') and annotations[key].startswith('hpa'):
                autoscale_class = 'hpa'
            if key.endswith('minScale'):
                minscale = annotations[key]
            if key.endswith('maxScale'):
                maxscale = annotations[key]

        res.append({
            'name': v['metadata']['name'],
            'url': status['url'],
            'latestcreated': status['latestCreatedRevisionName'],
            'latestready': status['latestReadyRevisionName'],
            'traffic': status['traffic'],
            'ready': ready,
            'reason': reason,
            'env': container['env'],
            'image': container['image'],
            'autoscale_class': autoscale_class,
            'minscale': minscale,
            'maxscale': maxscale
        })
    return res


def data_type(data):
    """ Compares and returns results based on the data type
    of the argument supplied"""
    if type(data) is str:
        return len(data)
    elif data == None:
        return 'no value'
    elif data == True or data == False:
        return data
    elif type(data) is int:
        if data < 100:
            return 'less than 100'
        elif data == 100:
            return 'equal to 100'
        else:
            return 'more than 100'
    elif type(data) is list:
        for i in range(len(data)):
            if i == 2:
                return data[i]
        else:
            return None


import numpy as np
import matplotlib.pyplot as plt

class Perceptron(object):
    """
    感知机对象
    """
    def __init__(self, learning_rate=0.7, n_iter=100):
        self.learning_rate = learning_rate
        self.iterations = n_iter
        self.weights = np.nan

    def fit(self, x, y):
        self.weights = np.random.rand(x.shape[1])
        for i in range(self.iterations):
            y_hat = 1 * (np.dot(x, self.weights) >= 0)
            self.weights -= self.learning_rate * np.dot(x.T, (y_hat - y).T)
        return self

    def predict(self, x):
        return 1 * (np.dot(x, self.weights) >= 0)

if __name__ == '__main__':
    x = np.array([[0.3, 0.7],
                  [-0.6, 0.3],
                  [-0.1, -0.8],
                  [0.1, -0.45]])
    y = np.array([1, 0, 0, 1])
    p = Perceptron()
    p.fit(x, y)
    print(p.predict(x))
    print(p.weights)
    plt.scatter(x[y == 0][:, 0], x[y == 0][:, 1], marker='o')
    plt.scatter(x[y == 1][:, 0], x[y == 1][:, 1], marker='^')
    plt.plot(np.linspace(x[:, 0].min(), x[:, 0].max(), 100),
             -p.weights[0] / p.weights[1] * np.linspace(x[:, 0].min(), x[:, 0].max(), 100))
    plt.show()


BASE_OPTION = {
    'experience': 'spade',  # 实验的名称
    'gpu_ids': '-1',  # 使用的GPU，0 0,1,2, 0,2. CPU为-1
    'checkpoints_dir': 'spade/checkpoints',  # 模型保存的位置
    'images_dir': 'images',  # 图像保存的位置
    'model': 'spade',  # 使用的模型的名称
    'is_train': False,  # 是否是训练
    'continue_train': False,  # 继续训练，是则加载数据
    'current_epoch': 100,  # 如果是继续训练，从哪个epoch开始
    'save_log': True,  # 是否保存损失值的变化情况
    'dataset': 'natural',  # 数据集的名称, "_"之后的是备注
}

MODEL_OPTION = {
    'use_vae': True,  # 使用image encoder参与训练
    'D_model_num': 2,  # 用于multiscale的discriminator的数量
    'lambda_kld': 0.05,  # kld loss的权重
    'lambda_vgg': 10.0,  # perceptual loss的权重
    'lambda_feature': 10.0,  # GAN Feature matching Loss的权重
    'z_dim': 256,  # 输入噪声的维度
    'init_variance': 0.02,  # 网络初始化的方差
}

ADE20K_DATASET_OPTION = {
    # 和数据输入部分相关
    'dataset_dir': 'dataset/ADEChallengeData2016/',  # 数据集所在的根目录
    'shuffle': True,  # 是否打乱数据集
    'flip': True,  # is_train=True & flip=True时，训练集中的图像有一半概率翻转，数据增强
    'thread_num': 0,  # dataloader用来读取数据集时的线程数，默认值为0
    'no_instance': True,  # 有无instance_map
    'pairing_check': True,  # 检查输入图像和label是否匹配
    'img_mean': 0.5,  # 输入的图像各个像素点的均值
    'img_var': 0.5,  # 输入的图像各个像素点的方差

    # 和训练相关
    'batch_size': 16,  # 'input batch size'
    'preprocess_mode': 'scale_and_crop',  # 图像预处理，"resize"（直接resize会变形）/"scale_and_crop"（把图像缩放到比loadsize大后裁剪）
    'load_size': (256, 256),  # 预处理后图像的目标size
    'n_label': 150,  # 标签数，包括无法识别的标签. 参见contain_dontcare_label.'
    'contain_dontcare_label': True,  # 无法识别的标签，对应255
    'output_nc': 3,  # 输出图像的通道数
    'total_epochs': 200,  # 总共有多少个epoch（包括learning rate decay的周期）
    'decay_epochs': 100,  # learning rate decay的周期数，10表示最后10个周期内发生decay
    'learning_rate': 0.0001,  # 初始的学习率
    'TTUR': True,  # Two Time-Scale Update Rule
    'beta1': 0,  # adam中的动量参数
    'beta2': 0.999,  # adam中的动量参数
}

NATURAL_DATASET_OPTION = {
    # 和数据输入部分相关
    'dataset_dir': 'dataset/refinedcoco/',  # 数据集所在的根目录
    'shuffle': True,  # 是否打乱数据集
    'flip': True,  # is_train=True & flip=True时，训练集中的图像有一半概率翻转，数据增强
    'thread_num': 0,  # dataloader用来读取数据集时的线程数，默认值为0
    'no_instance': True,  # 有无instance_map
    'pairing_check': True,  # 检查输入图像和label是否匹配
    'img_mean': 0.5,  # 输入的图像各个像素点的均值
    'img_var': 0.5,  # 输入的图像各个像素点的方差

    # 和训练相关
    'batch_size': 4,  # 'input batch size'
    'preprocess_mode': 'scale_and_crop',  # 图像预处理，"resize"（直接resize会变形）/"scale_and_crop"（把图像缩放到比loadsize大后裁剪）
    'load_size': (512, 512),  # 预处理后图像的目标size
    'n_label': 12,  # 标签数，包括无法识别的标签. 参见contain_dontcare_label.'
    'contain_dontcare_label': True,  # 无法识别的标签，对应255
    'output_nc': 3,  # 输出图像的通道数
    'total_epochs': 100,  # 总共有多少个epoch（包括learning rate decay的周期）
    'decay_epochs': 40,  # learning rate decay的周期数，10表示最后10个周期内发生decay
    'learning_rate': 0.0002,  # 初始的学习率
    'TTUR': True,  # Two Time-Scale Update Rule
    'beta1': 0,  # adam中的动量参数
    'beta2': 0.999,  # adam中的动量参数
}


from math import sqrt
from utils import round_off

def ema(ohlc_arr, n=3, seed='sma'):
    '''
    ohlc_arr is any list of dicts with length > 3
    dict must have following keys - 'open', 'high', 'low', 'close', 'timestamp'
    '''
    if len(ohlc_arr) < n + 1:
        return None

    sorted_arr = sorted(ohlc_arr, key=lambda k: k['timestamp'])
    c = 2 / float(n + 1)
    arr = sorted_arr[-n:]
    if seed == 'sma':
        ema_prev = sma(sorted_arr[:-n])
    else:
        ema_prev = float(sorted_arr[-n - 1]['close'])

    ema = 0.0
    for ohlc in arr:
        close = float(ohlc['close'])
        ema = (close * c) + (ema_prev * (1 - c))
    return ema

def sma(ohlc_arr):
    total = 0
    if not ohlc_arr:
        return total
    for ohlc in ohlc_arr:
        total += float(ohlc['close'])
    return float(total / len(ohlc_arr))

def gann(price=0, direction='up'):
    angles = (0.02, 0.04, 0.08, 0.1, 0.15, 0.25, 0.35,
              0.40, 0.42, 0.46, 0.48, 0.5, 0.67, 1.0)
    if direction == 'up':
        return [round_off((sqrt(price) + a) ** 2) for a in angles]
    elif direction == 'down':
        return [round_off((sqrt(price) - a) ** 2) for a in angles]
    else:
        return None


import json
import os
import requests

file_path = '/home/ilia/Documents/MaxinAI/clean_product.json'
save_path = '/home/ilia/Documents/MaxinAI/my_data'

def download_images(element, directory):
    for i, image_url in enumerate(element['image_urls']):
        response = requests.get(image_url, allow_redirects=True)
        with open(f'{directory}/{i}.jpg', 'wb') as img:
            img.write(response.content)

def save_json(element, directory, i):
    with open(f'{directory}/{i}.json', 'w') as fl:
        json.dump(element, fl, indent=4, sort_keys=True)

def download_and_save_images_and_desctiptions(data):
    for i, element in enumerate(data):
        directory = f'{save_path}/{i}'
        if not os.path.isdir(directory):
            os.makedirs(directory)
        save_json(element, directory, i)
        download_images(element, directory)

def main():
    with open(file_path, 'r') as fl:
        data = json.load(fl)

    download_and_save_images_and_desctiptions(data)

if __name__ == '__main__':
    main()


# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from progressbar import progressbar
from random import shuffle, seed

from .sequence import Sequence

class Decoy(Sequence):
    decoy_counter = 0

    def __init__(self, amino_acids):
        Decoy.decoy_counter += 1
        name = "Decoy-%d" % (Decoy.decoy_counter,)
        Sequence.__init__(
            self,
            name=name,
            amino_acids=amino_acids,
            attributes={"source": "decoy"})

def generate_decoys(
        sequences,
        n_decoys=None,
        max_scrambling_attempts_per_decoy=3,
        random_seed=0):
    """
    Parameters
    ----------
    sequences : list of objects derived from Sequence

    n_decoys : int
        Number of decoys to generate, if None then make one for each hit.

    max_scrambling_attempts_per_decoy : int
        Number of times to try to scramble a sequence before giving up if all
        scrambled results were already in the hit sequences.

    random_seed : int
        Initial random seed to make scrambling determinstic

    Returns list of Decoy
    -------

    """
    if n_decoys <= 0:
        return []

    seed(random_seed)
    real_peptide_set = {s.amino_acids for s in sequences}
    real_peptide_list = list(real_peptide_set)
    shuffle(real_peptide_list)
    n_hits = len(real_peptide_list)
    decoys = []
    print("Generating decoy sequences by scrambling...")
    if n_decoys is None:
        n_decoys = len(real_peptide_list)

    outer_iter = 0
    while len(decoys) < n_decoys:
        outer_iter += 1
        expected_iters = n_decoys / n_hits

        if outer_iter > 100 * expected_iters:
            print("Warning: failed to generate sufficient decoys")

        for peptide in progressbar(real_peptide_list):
            if len(decoys) >= n_decoys:
                break
            list_of_amino_acids = list(peptide)
            for attempt in range(max_scrambling_attempts_per_decoy):
                shuffle(list_of_amino_acids)
                scrambled = "".join(list_of_amino_acids)
                if scrambled not in real_peptide_set:
                    decoys.append(Decoy(amino_acids=scrambled))
                    break

    print("Generated %d decoy sequences" % len(decoys))

    return decoys


from .launchers import launcher  # pylint: disable=E0402
from .datasets import dataset  # pylint: disable=E0402

class test:
    def __init__(self, data):
        MODEL_NAME_TAG = 'name'
        LAUNCHERS_TAG = 'launchers'
        DATATSETS_TAG = 'datasets'

        self.model_name = data[MODEL_NAME_TAG]
        self.launchers = [launcher(launcher_data) for launcher_data in data[LAUNCHERS_TAG]]
        self.datasets = [dataset(dataset_data) for dataset_data in data[DATATSETS_TAG]]


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import re

# PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
train = pd.read_csv("train.csv", dtype={"Age": np.float64},)

# survived
n_total = len(train.values)
n_dead = len(train.loc[train['Survived'] == 0]) # dead
n_alive = len(train.loc[train['Survived'] == 1]) # alive

############################################################################
# Missing Data Check
############################################################################
headers = 'PassengerId,Survived,Pclass,Name,Sex,Age,\
SibSp,Parch,Ticket,Fare,Cabin,Embarked'.split(',')
missing_dict = {}
for h in headers:
    missing_dict[h] = (n_total - len(train[h].dropna().values))

names = ['total']+headers
values = [n_total] + list(missing_dict.values())
plt.figure(figsize=(12,8))
plt.bar(names, values)
plt.title('Missing data')
for i in range(len(names)):
    plt.text(i, values[i], str(values[i]))

plt.tight_layout()
plt.show()

############################################################################
# Age - Survived
############################################################################
age_dead = train.loc[train['Survived'] == 0]['Age'].dropna() # dead
age_alive = train.loc[train['Survived'] == 1]['Age'].dropna()# alive

# Visualization
fig = plt.figure()
ax = fig.add_subplot(121)
ax.boxplot(age_dead.values)
ax.set_xticklabels(np.repeat('dead', 2), rotation=0, fontsize=8)
_ = np.random.normal(1.0, 0.04, size=len(age_dead.values))
plt.scatter(_, age_dead.values, alpha=0.5)

ax = fig.add_subplot(122)
plt.boxplot(age_alive.values)
ax.set_xticklabels(np.repeat('alive', 2), rotation=0, fontsize=8)
_ = np.random.normal(1.0, 0.04, size=len(age_alive.values))
plt.scatter(_, age_alive.values, alpha=0.5)

# 결측값을 어떻게 처리? -> median 값으로 처리함
age_median = np.median(train['Age'].dropna())
train['Age'] = train['Age'].fillna(age_median)

plt.show()

############################################################################
# Sex - Survived
############################################################################
# Change male -> 0 ,female -> 1

sex_alive = train.loc[train['Survived'] == 1]['Sex']
n_man_alive = len(sex_alive.loc[sex_alive == 'male'].values)
n_woman_alive = len(sex_alive.loc[sex_alive == 'female'].values)

sex_dead= train.loc[train['Survived'] == 0]['Sex']
n_man_dead = len(sex_dead.loc[sex_dead == 'male'].values)
n_woman_dead = len(sex_dead.loc[sex_dead == 'female'].values)

names = ['alive man', 'alive woman', 'dead man', 'dead woman']
values = [n_man_alive, n_woman_alive, n_man_dead, n_woman_dead]
plt.bar(names, values, color='y', alpha = 0.5)
for i in range(len(names)):
    plt.text(i, values[i], str(values[i]))

plt.show()

############################################################################
# Pclass - Survied
############################################################################
# Change male -> 0 ,female -> 1
# 순서대로 1st , 2nd , 3rd

pclass_survived = train.loc[train['Survived'] == 1]['Pclass']
pclass_dead = train.loc[train['Survived'] == 0]['Pclass']

dead_ns = []
for i in range(3):
    dead_ns.append(len(pclass_dead.loc[pclass_dead == i+1]))
survivied_ns = []
for i in range(3):
    survivied_ns.append(len(pclass_survived.loc[pclass_survived == i+1]))

print('dead 1st : {}\t2nd : {}\t3rd {}'.format(*dead_ns))
print('survivied 1st : {}\t2nd : {}\t3rd {}'.format(*survivied_ns))

names = ['survived 1st', 'dead 1st', 'survived 2nd', 'dead 2nd','survived 3rd', 'dead 3rd']
values = [survivied_ns[0], dead_ns[0], survivied_ns[1] , dead_ns[1], survivied_ns[2], dead_ns[2]]
plt.bar(names, values, color=['b','b','y','y','r','r'], alpha = 0.5 )
for i in range(len(names)):
    plt.text(i, values[i], str(values[i]))
plt.tight_layout()
plt.show()

############################################################################
# SibSP - Survied
# Number of Siblings/Spouses Aboard
############################################################################

sibsp_survived = train.loc[train['Survived'] == 1]['SibSp']
sibsp_dead = train.loc[train['Survived'] == 0]['SibSp']

print(len(sibsp_survived))
print(len(sibsp_dead))
print(set(sibsp_survived.values))

sibsp_dict = {}
name_ns = []
for i in range(5):
    sibsp_dict['survived_\n{}'.format(i)] = len(sibsp_survived.loc[sibsp_survived==i])
    sibsp_dict['dead_\n{}'.format(i)] = len(sibsp_dead.loc[sibsp_dead == i])

names = list(sibsp_dict.keys())
values = list(sibsp_dict.values())
colors = ['b','b','y','y','r','r','c','c','g','g']
plt.bar(names, values, color=colors, alpha=0.5)
for i in range(len(sibsp_dict.keys())):
    plt.text(i, values[i], str(values[i]))
plt.tight_layout(w_pad=1000)
plt.xlabel('# Sib')
plt.ylabel('# people')
plt.title('Sib - Survived')
plt.show()

############################################################################
# parch - Survied
# Number of Parents/Children Aboard
############################################################################
# get Unique from parch
parch_unique = set(train['Parch'].values)

# get # values except Missing data
parch_survived = train.loc[train['Survived'] == 1]['Parch']
parch_dead = train.loc[train['Survived'] == 0]['Parch']

# Checking Unique
print('Unique from parch : {}'.format(parch_unique))

# Checking Missing Data
n_valid = len(train['Survived'].dropna().values)
print('# Missing Data : {}'.format(n_total - n_valid))

# get # people , each index
parch_dict={}
for i in list(parch_unique):
    # i th : survivied
    parch_dict['survived\n{}'.format(i)] = \
        len(parch_survived.loc[parch_survived == i].values)

    # i th : dead
    parch_dict['dead\n{}'.format(i)] = \
        len(parch_dead.loc[parch_dead == i].values)

colors = ['b','b','y','y','r','r','c','c','g','g','m','m']
values = list(parch_dict.values())
names = list(parch_dict.keys())
plt.figure(figsize=(10,6))
plt.bar(names, values, color = colors, alpha =0.5)
for i in range(len(parch_dict.keys())):
    plt.text(i, values[i], str(values[i]))
plt.tight_layout(w_pad=1000)
plt.title('Parch - Survived')
plt.xlabel('# child or parents')
plt.ylabel('# people')
plt.show()

############################################################################
# parch - Survied
# Number of Parents/Children Aboard
############################################################################

# Change text data to numberic data
train = pd.read_csv("train.csv", dtype={"Age": np.float64},)
train ["Name"] = train ["Name"].apply(lambda x: re.search(' ([A-Za-z]+)\.',x).group(1))
name_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Dr": 5, "Rev": 6, "Major": 7, "Col": 7, "Mlle": 2, "Mme": 3,"Don": 9,"Dona": 9, "Lady": 10, "Countess": 10, "Jonkheer": 10, "Sir": 9, "Capt": 7, "Ms": 2}
train["Name"] = train.loc[:,'Name'].map(name_mapping )

# Count Missing Data
n_title = len(train["Name"].dropna().values)
print(n_total - n_title)

# Unique
unique = set(train["Name"].values)

survived = train.loc[train['Survived'] == 1]['Name']
dead = train.loc[train['Survived'] == 0]['Name']
name_dict={}
for i in list(unique):
    # get # values except Missing data

    print('Unique from Name : {}'.format(i))
    # i th : survivied
    name_dict['survived\n{}'.format(i)] = len(survived.loc[survived == i].values)
    # i th : dead
    name_dict['dead\n{}'.format(i)] = len(dead.loc[dead == i].values)

# Colors
colors = []
for i in range(10):
    color = ['C{}'.format(i)] * 2
    colors.extend(color)
values = list(name_dict.values())
names = list(name_dict.keys())

# Msg
msg = ''
for i in range(len(name_mapping.keys())):
    key = list(name_mapping.keys())[i]
    value = list(name_mapping.values())[i]
    msg += '{} : {}\n'.format(key, value)

# Set Figure size
plt.figure(figsize=(10,6))

# Plot bar
plt.bar(names, values, color=colors, alpha=0.5, )
plt.text(15, 200, msg, fontsize=8, label='a')
plt.legend()

#
for i in range(len(name_dict.keys())):
    plt.text(i, values[i], str(values[i]))
plt.tight_layout(w_pad=1000)
plt.title('Name - Survived')
plt.xlabel('Name')
plt.ylabel('# people')
plt.show()

############################################################################
# Embarked - Survied
# Port of Embarkation (C = Cherbourg; Q = Queenstown; S = Southampton)
############################################################################

# get Unique from parch
unique= set(train['Embarked'].dropna().values)

# get # values except Missing data
survived = train.loc[train['Survived'] == 1]['Embarked']
dead = train.loc[train['Survived'] == 0]['Embarked']

# Checking Unique
print('Unique from parch : {}'.format(unique))

# Checking Missing Data
n_valid = len(train['Embarked'].dropna().values)
print('# Missing Data : {}'.format(n_total - n_valid))

# get # people , each index
embarked_dict={}
for i in list(unique):
    # i th : survivied
    embarked_dict['survived\n{}'.format(i)] = \
        len(survived.loc[survived == i].values)

    # i th : dead
    embarked_dict['dead\n{}'.format(i)] = \
        len(dead.loc[dead == i].values)

# Colors
colors = []
for i in range(10):
    color = ['C{}'.format(i)] * 2
    colors.extend(color)
values = list(embarked_dict.values())
names = list(embarked_dict.keys())

plt.bar(names, values, color = colors, alpha =0.5)
for i in range(len(embarked_dict.keys())):
    plt.text(i, values[i], str(values[i]))
plt.tight_layout()
plt.title('Embarked - Survived', fontsize= 7)
plt.xlabel('# child or parents', fontsize= 7)
plt.ylabel('# people', fontsize= 7)
plt.show()


# Program Name: What's the Weather?
# Author: Maya Name
# Creation Date: 06/16/2019
# Description: Weather app that gets current weather information from
# Open Weather Maps. Location entry option include city name, zip code (US),
# and latitude/longitude coordinates.
#

import _config
import requests
import tkinter as tk
from datetime import datetime
from tkinter import font
from tkinter import messagebox
from tkinter import ttk
from PIL import Image
from PIL import ImageTk

root = tk.Tk()
root.title("Wolf's Weather")
root.geometry('500x500')
tk.Tk.iconbitmap(root, default='./img/wolftrack.ico')

# Set default values for temperature scale and location selectors
temp_scale = tk.StringVar(value='F')
req_mode = tk.StringVar(value='C')

# Open Weather Map constants
API_KEY = _config.weather_key  # Get key
API_URL = 'api.openweathermap.org/data/2.5/weather?'

def get_temp_scale():
    """
    :Description: Allows selection of either imperial (F) or metric (C) temperature scales
    :params: none
    :returns: string value for units variable
    """
    if temp_scale.get() == 'F':
        return 'imperial'
    else:
        return 'metric'

def get_time(ts):
    """
    :Description: Converts Int timestamp to time str
    :params: ts - timestamp as Int
    :returns: formatted (HH:MM:SS) time string (24hr)
    """
    return datetime.fromtimestamp(ts).strftime('%H:%M:%S')

def format_json(weather):
    """
    :Description: Formats weather data for display
    :params: weather - weather data dictionary
    :returns: formatted weather string
    """
    # Parsing the JSON data
    name = weather['name']
    desc = weather['weather'][0]['description']
    temp = weather['main']['temp']
    temp_min = weather['main']['temp_min']
    temp_max = weather['main']['temp_max']
    hum = weather['main']['humidity']
    pres = weather['main']['pressure']
    wind = weather['wind']['speed']
    s_rise = get_time(weather['sys']['sunrise'])
    s_set = get_time(weather['sys']['sunset'])

    # Convert pressure hPa to inHg
    if temp_scale.get() == 'F':
        pres = round(pres * 0.02953, 2)
        pres_uom = 'inHg'
    else:
        pres_uom = 'hPa'

    # Weather data string
    display = f'City: {name} \nCurrent Condition: {desc}'
    main = f' \nTemperature ({temp_scale.get()}): {temp}° \nHumidity: {hum}% \nPressure: {pres} {pres_uom}'
    sun = f'\nSunrise: {s_rise} \nSunset: {s_set}'
    return  display + main + sun

def get_weather_image(weather):
    icon_filename = f".\img\{weather['weather'][0]['icon']}.png"
    return tk.PhotoImage(file = icon_filename)

def get_weather(loc):
    """
    :Description: Retrieves weather data from Open Weather Maps using either
                city or zip code as locator
    :params: city - locator string
    :returns: none
    """
    # units are imperial for F and meteric fo C degrees
    units = get_temp_scale()

    # Set url based on locator selection
    if req_mode.get() == 'C':
        if loc.isalpha():
            loc_ok = True
            url = f'https://{API_URL}q={loc}&units={units}&appid={API_KEY}'
        else:
            loc_ok = False
            messagebox.showerror('Location Entry Error', 'City name must only contain letters.')
    elif req_mode.get() == 'Z':
        url = f'https://{API_URL}zip={loc}&units={units}&appid={API_KEY}'
    elif req_mode.get() =='G':
        geo = loc.split(',')
        print(geo[0])
        print(geo[1].strip())
        url = f'https://{API_URL}lat={geo[0].strip()}&lon={geo[1].strip()}&units={units}&appid={API_KEY}'

    # Get weather data
    try:
        response = requests.get(url)
        received_OK = True
    except requests.RequestException:
        received_OK = False
        messagebox.showerror('Communication Error', 'Failed to establish a connection')

    if received_OK:
        weather = response.json()

        if int(weather['cod']) // 100 == 2:  # Received valid response
            print(weather)

            # Update weather conditions display with formatted data
            label['text'] = format_json(weather)

            # Display weather icon
            icon_filename = f".\img\{weather['weather'][0]['icon']}.png"
            weather_icon = ImageTk.PhotoImage(Image.open(icon_filename).resize((50, 50)))
            icon_canvas.delete('all')
            icon_canvas.create_image(0, 0, anchor = tk.NW, image = weather_icon)
            icon_canvas.image = weather_icon
        elif weather['cod'] == '404':  # Invalid city name or city not found
            messagebox.showerror('Request Error', 'City not found')
        else:
            messagebox.showerror('Request Error', 'Error with response')

# Set up background image
background_image = tk.PhotoImage(file = '.\img\\landscape.png')
background_label = tk.Label(root, image = background_image)
background_label.place(relheight = 1, relwidth = 1)

# Lay out window
# Use to display location and temperature scale radio buttons
top_frame = tk.Frame(root, bg = '#80c1ff', bd = 5)
top_frame.place(anchor = tk.N, relx = 0.5, rely = 0.1, relheight = 0.1, relwidth =  0.82)

city_rbt = tk.Radiobutton(top_frame, text="City", padx = 10, pady=5, bg = '#e6f2ff',
    variable=req_mode, value='C')
city_rbt.grid(row=0, column=1, sticky=tk.W)
zip_rbt = tk.Radiobutton(top_frame, text="Zip (US)", padx = 10, pady=5, bg = '#e6f2ff',
    variable=req_mode, value='Z')
zip_rbt.grid(row=0, column=2, sticky=tk.W)
# Not yet implemented
geo_rbt = tk.Radiobutton(top_frame, text="Lat/Lon", padx = 10, pady=5, bg = '#e6f2ff',
    variable=req_mode, value='G')
geo_rbt.grid(row=0, column=3, sticky=tk.W)

f_rbt = tk.Radiobutton(top_frame, text="F °", padx = 10, pady=5, bg = '#e6f2ff',
    variable=temp_scale, value='F')
f_rbt.grid(row=0, column=4, sticky=tk.E)
c_rbt = tk.Radiobutton(top_frame, text="C °", padx = 10, pady=5, bg = '#e6f2ff',
    variable=temp_scale, value='C')
c_rbt.grid(row=0, column=5, sticky=tk.E)

# Display for entry textbox and button
mid_frame = tk.Frame(root, bg = '#80c1ff', bd = 5)
mid_frame.place(anchor = tk.N, relx = 0.5, rely = 0.25, relheight = 0.1, relwidth =  0.75)

button = ttk.Button(mid_frame, text = 'Get Weather', command = lambda: get_weather(entry.get()))
button.place(relx = 0.7, relheight = 1, relwidth = 0.3)

entry = ttk.Entry(mid_frame )
entry.place(relheight = 1, relwidth = 0.65)

bottom_frame = tk.Frame(root, bg = '#80c1ff', bd = 7)
bottom_frame.place(anchor = tk.N, relx = 0.5, rely = 0.4, relheight = 0.5, relwidth =  0.75)

# Display weather information
label = tk.Label(bottom_frame, anchor = tk.NW, justify = tk.LEFT, bg = '#ffffff', bd = 5)
label.place(relheight = 1, relwidth = 1)

# Use canvas object to display weather icon
icon_canvas = tk.Canvas(bottom_frame, height = 50, width = 50, bg = '#ffffff', bd = 0, highlightthickness=0)
icon_canvas.place(x = 280, y = 10)
weather_icon = ImageTk.PhotoImage(Image.open('.\img\\01d.png').resize((50, 50)))

root.mainloop()


import numpy as np
import matplotlib.pyplot as plt
from mirnylib import genome
#HELPER FUNCTIONS AND VARS

hg19Genome = genome.Genome("~/libraries//hg19", readChrms=["#", "X"])

colors = [(255,0,0),(50,53,204),(254,0, 234),(255,200,0),(50,205,50),(0,128,0),(0,100,0),(194,225,5),(255,255,0),(102,205,170),
              (138,145,208),(205,92,92),(233,150,122),(189,183,107),(128,128,128),(192,192,192),(255,200,255)]

def chrNumToStr(chrNum):
    if 0<=chrNum<22:
        return "chr"+str(chrNum+1)
    elif chrNum==22:
        return "chrX"
    else:
        raise ValueError('Chromosome index out of range: ',chrNum)

def chrStrToNum(chrStr):
    if(chrStr=='chrX'):
        return 22
    chrNum=int(chrStr.split('r')[1])-1
    if 0<=chrNum<22:
        return chrNum
    else:
        raise ValueError('Chromosome number out of range: ',chrStr)

def plotAdjusted(statePlot, color, plotLabel="",lw=2):
    plt.plot(statePlot/np.mean(statePlot),label=plotLabel,color=color,linewidth=lw)

def makeUnique(positions,CUTOFF=5000): #helper function that removes locations that are near each other
    positions=sorted(positions)
    i=0
    while i<len(positions)-1:
        if positions[i+1]-positions[i]<CUTOFF:
            positions.remove(positions[i+1])
            i-=1
        i+=1


from tkinter import Tk,Label

for i in range(2):
    root=Tk()

    root.geometry("1024x600")

    root.minsize("800","600")

    root.maxsize("1280","720")
    Label(text="Ali is a good boy").pack()
    root.mainloop()


def readPestArray(gridClass, fieldType, fieldName, fileName):
    import arcpy
    import numpy
    from numpy import loadtxt

    getI=[]
    getJ=[]
    getVal=[]
    fcount=0
    mycurs = arcpy.UpdateCursor(gridClass)
    for feat in mycurs:
        fcount += 1
        getI.append(feat.getValue("I"))
        getJ.append(feat.getValue("J"))
        getVal.append(feat.getValue(fieldName))
    del feat
    maxI=0
    maxJ=0
    for i in range(fcount):
        if getI[i] > maxI:
            maxI = getI[i]
    for i in range(fcount):
        if getJ[i] > maxJ:
            maxJ = getJ[i]

    parray = numpy.empty((maxI,maxJ))
    parray.fill(float(0.0001))

    tmparray = []
    with open(fileName, 'r') as f:
        data = f.readlines()
        for line in data:
            words = line.split()
            for word in words:
                tmparray.append(float(word))

    acount = 0
    for bbb in range(maxI):
        for ccc in range(maxJ):
            parray[[bbb], ccc] = float(tmparray[acount])
            acount += 1

    acount=0
    mycurs = arcpy.UpdateCursor(gridClass)
    for feat in mycurs:
        acount += 1
        tmpI = feat.getValue("I")
        tmpJ = feat.getValue("J")
        if fieldType != 'INTEGER':
            feat.setValue(fieldName, float(parray[[tmpI-1],tmpJ-1]))
        else:
            feat.setValue(fieldName, int(parray[[tmpI-1],tmpJ-1]))
        if (acount%1000 == 0):
            print(acount)
        mycurs.updateRow(feat)
    del feat
    del mycurs
    del parray
    del tmparray
    del data
    del words
    del word


#!/usr/bin/env python3

import os
import time

import numpy as np
import pandas as pd
from tensorflow.keras.models import load_model

# MacOS Fix
os.environ["KMP_DUPLICATE_LIB_OK"] = "True"

# Start total file time
file_time = time.time()

# Load Data
print("Loading data...", end="\r")
start_time = time.time()
user = pd.read_json("../data/user.json", lines=True)
business = pd.read_json("../data/business.json", lines=True)
end_time = np.round(time.time() - start_time, 2)
print(f"Loading data...DONE! [{end_time} seconds]")

# Load model
model = load_model("weights/model.h5")

# Get user and business index
business["business_index"] = business.index
user["user_index"] = user.index

# Get random user
user_sample_index = user["user_index"][
    user["user_id"] == np.random.choice(user["user_id"], size=1)[0]
].iloc[0]

# Print user
user_sample = user[user['user_index'] == user_sample_index]
print(f"\n{user_sample['user_id'].iloc[0]}:: {user_sample['name'].iloc[0]}")

# Make index arrays for model
X = business
X["user_index"] = user_sample_index
X_user_sample = X["user_index"].values
X_business_sample = X["business_index"].values

# Predict Stars
X["ratings_bar"] = model.predict([X_user_sample, X_business_sample])

# Get top 25 reviews and print
X = X.sort_values(by=["ratings_bar"], ascending=False).iloc[:10]

for i, (index, row) in enumerate(X.iterrows()):
    print(
        f"{i+1}:: {row['name']} - {np.round(row['ratings_bar'], 2)}"  # noqa
    )


# -*- coding: utf-8 -*-#
'''
# Name:         t2
# Description:
# Author:       super
# Date:         2019-07-09
'''

import numpy as np

points = np.arange(-5,5,0.01)
xs, ys = np.meshgrid(points, points)
print(ys)
z = np.sqrt(xs ** 2+ ys **2)
print(z)


# in GB File: raw (Original), id (ACCESSION), description (DEFINITION), sequence (ORIGIN), neues Feld features,
# alle gene einträge in eine Sequenz aus Dicts mit den Keys: position, name, description, id

def parse_def(file_hanlde, firstline):
    definition = firstline.replace("DEFINITION", "")
    definition = definition.strip()

    for i in file_hanlde:
        if i.startswith(" "):
            definition += i.strip()
        else:
            return definition,i

def parse_origin(file_handle):
    origin = ""
    for i in file_handle:
        if i.startswith(" "):
            i = i.strip()
            first = 1
            for j in i.split(" "):
                if not first:
                    origin += j
                else:
                    first = 0
        else:
            return origin,i

def parse_gene(file_handle, firstline):
    geneDict = {}
    position = firstline.replace("     gene", "")
    position = position.strip()
    geneDict["position"] = position
    #print(position)
    for i in file_handle:
        if i.startswith("      "):
            i = i.strip()
            if i.startswith("/gene"):
                i = i.replace("/gene=", "")
                i = i.replace("\"", "")
                geneDict["name"] = i
            if i.startswith("/note"):
                i = i.replace("/note=", "")
                notes = i
                if not i.endswith("\""):
                    for i in file_handle:
                        i = i.strip()
                        notes += i
                        if i.endswith("\""):
                            break
                notes = notes.replace("\"", "")
                geneDict["description"] = notes
            if i.startswith("/db_xref="):
                i = i.replace("/db_xref=", "")
                i = i.replace("\"", "")
                geneDict["id"] = i
        else:
            return geneDict,i

def parse_features(file_handle):
    features = []
    for i in file_handle:
        if i.startswith(" "):
            if i.startswith("     gene"):
                one_feature = parse_gene(file_handle, i)
                features.append(one_feature)
        else:
            return features,i

def parse_gb(file):
    file_handle = open(file, 'r')
    gbList = []
    gbDict = {}
#    raw = ""

    for i in file_handle:
#        raw += i
        if i.startswith("DEFINITION"):
            description,i = parse_def(file_handle, i)
            gbDict["description"] = description

        if i.startswith("ACCESSION"):
            id = i.replace("ACCESSION", "")
            id = id.strip()
            gbDict["id"] = id

        if i.startswith("FEATURES"):
            features,i = parse_features(file_handle)
            gbDict["features"] = features

        if i.startswith("ORIGIN"):
            origin,i = parse_origin(file_handle)
            gbDict["sequence"] = origin

        if i.startswith("//"):
            gbDict["raw"] = ""
            gbList.append(gbDict)
#            raw = ""

    #print(gbList)

    file_handle.close()
    file_handle = open(file, 'r')
    pos = 0
    raw = ""
    for i in file_handle:
        if (pos >= len(gbList)):
            break
        raw += i
        if i.startswith("//"):
            #print(pos)
            #print(len(raw))
            gbList[pos]["raw"] = raw
            raw = ""
            pos += 1
    file_handle.close()
    return gbList

def get_raw(data_object, index):
    return data_object[index]["raw"]

def get_id(data_object, index):
    #print(data_object[index])
    return data_object[index]["id"]

def get_description(data_object, index):
    return data_object[index]["description"]

def get_sequence(data_object, index):
    return data_object[index]["sequence"]

def get_fasta(dataobject, index):
    fasta = get_id(data_object,index) + get_description(data_object, index) + "\n"
    sequence = get_sequence(data_object, index)
    for i in range(0, len(sequence), 80):
        fasta += sequence[i:i+80] + "\n"
    return fasta

def get_feature(data_object, index, feature):
    return data_object[index]["features"][0][0][feature]

def add_feature(data_object, index, feature, value):
    data_object[index]["features"][0][0][feature] = value

def add_sequence_object(data_object, id, descritption, sequence, features):
    new_seq = {"id": id, "description": descritption, "sequence": sequence, "features": features}
    data_object.append(new_seq)

def get_gc_content(data_object, index):
    seq = get_sequence(data_object, index)
    count = seq.count("c") + seq.count("g")
    gc_content = count/len(seq)
    return gc_content

data_object = parse_gb("sequence.gb")

#raw = get_raw(data_object, 1)
#print(raw)

#id =get_id(data_object, 1)
#print(id)

#description = get_description(data_object, 1)
#print(description)

#sequence = get_sequence(data_object, 1)
#print(sequence)

#fasta = get_fasta(data_object, 1)
#print(fasta)

#feature = get_feature(data_object, 0, "position")
#print(feature)

#add_feature(data_object, 0, "A", 11)
#print(data_object[0])

#add_sequence_object(data_object, "TEST", "123: descritption", "agtgtgtgtgtgt", [{"name": "TEST"}])
#print(data_object[len(data_object)-1])

#gc_content = get_gc_content(data_object, 0)
#print(gc_content)


# -*- coding: utf-8 -*-********************
from bs4 import BeautifulSoup

import traceback

class XbrlParser:
    """
    Clase que implementa la funcionalidad de parseado de ficheros XBRL
    """
    def __init__(self, xbrlPath):
        """ Constructor de la clase, recibe como parámetro la ruta del fichero xbrl a parsear.

        El constructor se encarga de realizar la lectura y carga del fichero xbrl, dejando el
        objeto listo para recibir solicitudes de consulta sobre los elementos presentes en el
        xbrl.

        Parameters
        ----------
        xbrlPath: str, mandatory
            Ruta fichero XBRL sobre el que se desea realizar el pareo.

        """
        try:
            # leer el fichero xbrl, usando encoding 'utf-8'
            self.xbrl_string = open(xbrlPath, encoding='utf-8').read()
            # Inializar el contenedor BeautifulSoup
            self.soup = BeautifulSoup(self.xbrl_string, "lxml-xml")
        except Exception:
            traceback.print_exc()
            raise Exception('Error en XbrlParser.__init__')

    def get(self,tag_name, contextRef):
        """Recupera el elemento cuyo nombre de tag y contexto coincidan con los suministrados
           como parámetro.
        Parameters
        ----------
        tag_name: str, mandatory
            Nombre de tag del elemento/s que se desea recuperar
        contextRef: str, mandatory
            Nombre de contexto al que ha de pertenecer el/los elementos a recuperar
        """
        try:
            # recupera el conjunto completo de elementos
            tag_list = self.soup.find_all()
            for tag in tag_list:
                if(tag.name == tag_name and tag['contextRef'] == contextRef):
                    value = tag.text
                    return value
        except Exception:
            traceback.print_exc()
            raise Exception('Error en XbrlParser.get')


import uuid
from typing import Tuple, Optional

import graphene
from django.contrib.auth import get_user_model
from graphene_django import DjangoObjectType

from organisations.models import Address as AddressModel
from organisations.models import \
    ASICOrganisationDetails as ASICOrganisationDetailsModel
from organisations.models import \
    OrganisationModules as OrganisationModulesModel
from organisations.models import Organisation as OrganisationModel
from organisations.schemadoc import Docs
from web.utils import ESGraphQLException, heyyouthere

User = get_user_model()

class AddressInput(graphene.InputObjectType):
    care_of = graphene.String()
    line2 = graphene.String(required=True)
    street = graphene.String(required=True)
    locality = graphene.String(required=True)
    state = graphene.String(required=True)
    postcode = graphene.String(required=True)
    country = graphene.String(required=True)

def address_from_input(address: AddressInput) -> AddressModel:
    addr = AddressModel(
        care_of=address.care_of,
        line2=address.line2,
        street=address.street,
        locality=address.locality,
        state=address.state,
        postcode=address.postcode,
        country=address.country
    )
    addr.save()
    return addr

class ASICOrganisationDetailsInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    acn = graphene.String()
    abn = graphene.String()
    registration_status = graphene.String(required=True)
    registration_location = graphene.String(required=True)
    registration_date = graphene.Date(required=True)
    next_review_date = graphene.Date(required=True)
    name_start_date = graphene.Date(required=True)
    company_type = graphene.String(required=True)
    company_class = graphene.String(required=True)
    company_subclass = graphene.String(required=True)
    principle_place_of_business_address = graphene.InputField(
        AddressInput, required=True)
    principle_place_of_business_address_start_date = graphene.Date(
        required=True)
    contact_address = graphene.InputField(AddressInput)
    contact_address_start_date = graphene.Date(required=True)
    registered_address = graphene.InputField(
        AddressInput, required=True)
    registered_address_start_date = graphene.Date(required=True)

class Address(DjangoObjectType, description=Docs.Address):

    class Meta:
        model = AddressModel

class ASICOrganisationDetails(
    DjangoObjectType,
    description=Docs.ASICOrganisationDetails
):

    class Meta:
        model = ASICOrganisationDetailsModel

class OrganisationModules(
    DjangoObjectType
):

    class Meta:
        model = OrganisationModulesModel

class Organisation(DjangoObjectType, description=Docs.Organisation):

    class Meta:
        model = OrganisationModel

class CreateOrganisationInput(graphene.InputObjectType):
    name = graphene.String(required=True)
    acn_abn = graphene.String(required=False)
    asic_details = graphene.InputField(
        ASICOrganisationDetailsInput, required=False)

class CreateOrganisation(
        graphene.Mutation, description=Docs.CreateOrganisation):
    class Arguments:
        create_organisation_data = CreateOrganisationInput(required=True)

    organisation = graphene.Field(Organisation)

    @staticmethod
    @heyyouthere(throw="You must be authenticated to create orgs.")
    def mutate(root, info, create_organisation_data=None):
        partner_accounts = list(info.context.user.partneraccount_set.all())
        if len(partner_accounts) >= 2:
            # right now we only support one partner account
            raise ESGraphQLException("Not implemented yet.")
        org, asic_deets = create_org_from_inputs(
            create_organisation_data, info.context.user.id)

        if partner_accounts:
            partner_accounts[0].partnerorganisation_set\
                .create(organisation=org)
        return CreateOrganisation(organisation=org)

class Mutation(graphene.ObjectType):
    create_organisation = CreateOrganisation.Field()

def create_org_from_inputs(
    create_organisation_data: CreateOrganisationInput,
    created_by_user_id: uuid.UUID
) -> Tuple[Organisation, Optional[ASICOrganisationDetails]]:
    d: Optional[ASICOrganisationDetails] = \
        create_organisation_data.asic_details
    organisation = OrganisationModel.objects.create(
        name=create_organisation_data.name,
        created_by_id=created_by_user_id,
    )
    if d:
        asic_deets = ASICOrganisationDetailsModel.objects.create(
            organisation=organisation,
            name=d.name,
            acn=d.acn,
            abn=d.abn,
            registration_status=d.registration_status,
            registration_location=d.registration_location,
            registration_date=d.registration_date,
            next_review_date=d.next_review_date,
            name_start_date=d.name_start_date,
            company_type=d.company_type,
            company_class=d.company_class,
            company_subclass=d.company_subclass,
            principle_place_of_business=address_from_input(
                d.principle_place_of_business_address)
            if d.principle_place_of_business_address else None,
            principle_place_of_business_start_date=d.
            principle_place_of_business_address_start_date,
            contact_address=address_from_input(d.contact_address)
            if d.contact_address else None,
            contact_address_start_date=d.contact_address_start_date,
            registered_address=address_from_input(d.registered_address)
            if d.registered_address else None,
            registered_address_start_date=d.registered_address_start_date
        )
    else:
        asic_deets = None
    return (organisation, asic_deets)


from django.conf.urls import url
from . import views
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
    url(r'^snippets/$',views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$',views.SnippetDetail.as_view()),
    url(r'^model/$',views.ModelList.as_view()),
    url(r'^delete/(?P<pk>[0-9]+)/$',views.ModelDelete.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)