# All of our imports
import time
import math
import bottle

# 'route' is for the anotation (@route), request there so we can get the json, run is there so we can run this thing
from bottle import route, run, request

# This lets us connect to the db
import pymongo
from pymongo import Connection

# this says that the path to make a HTTP POST request to is /trapreport
@route('/trapreport', method='POST')
def trapreport():
    # ---------------------------------- All of this should go into a celery worker function --------------------------------------------------- #

    # as long as the person (application) making the post request has the header: "Content-Type: application/json", we can get the json info directly from the request.
    # This trap variable is a python dict object. We can access stuff like this: trap['bearing']. We should definitly do some data validation here.
    trap = request.json

    # get a connection to mongod which must be running
    connection = Connection()

    # get a handle on our database
    db = connection.radar

    # get a handle on our collection
    collection = db.rawTrapData

    # insert our new data
    collection.insert(trap)

    # Log the client/user's location into the :last known location" database so we can notify them in real time if
    # they are heading towards a trap that is reported in the near future near them

    # Maybe the two next things should be in a celery function?

    # Now we should process the new data and adjust the weights and locations of the aggregated trap database.

    # Then notify all users that might be affected, Figure this out by using the info in "last known location database"

    # -------------------------------------------End what should go in a celery worker function-------------------------------------------------------------- #

    # return something?
    return str("OK")

# Haversine formula example in Python, gives distance in km
# Author: Wayne Dyck
# Works awesomely
def distance(origin, destination):
    lat1, lon1 = origin
    lat2, lon2 = destination
    radius = 6371 # km

    dlat = math.radians(lat2 - lat1)
    dlon = math.radians(lon2 - lon1)
    a = math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1))\
                                                  * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(
        dlon / 2)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    d = radius * c

    return d

def bearingBetweenTwoPoints(end, start):
    distanceFromOldPointToRightTrianglePoint = distance([start[0], start[1]], [start[0], end[1]])
    distanceFromOldPointToCurrentPoint = distance([start[0], start[1]], [end[0], end[1]])

    rawAngle = math.acos(distanceFromOldPointToRightTrianglePoint / distanceFromOldPointToCurrentPoint)
    rawAngle = math.degrees(rawAngle)

    quadrant = 0

    if start[0] < end[0]:
        if start[1] < end[1]:
            quadrant = 1
        else:
            quadrant = 2
    else:
        if start[1] > end[1]:
            quadrant = 3
        else:
            quadrant = 4

    bearing = 361

    if quadrant == 1:
        bearing = rawAngle
    elif quadrant == 2:
        bearing = 180 - rawAngle
    elif quadrant == 3:
        bearing = 180 + rawAngle
    elif quadrant == 4:
        bearing = 360 - rawAngle

    return bearing

# The max number of traps to give to the client
TRAP_LIMIT = 100

SECONDS_IN_HOUR = 3600

# tolerance level for how similar the direction the new client must be
# going in comparison to the client that reported the trap
VALID_REPORTED_BEARING_RANGE = 120

# the search range in which to consider points to send clients (in degrees)
VALID_LOCATION_BEARING_RANGE = 120

# get a connection to mongod which must be running
connection = Connection()

# get a handle on our database
db = connection.radar

@route('/gettraps', method='POST')
def gettraps_handler():
    if request:
        gettraps(request.json)

def gettraps(clientInfo, collection=db.rawTrapData):

    clientLocation = clientInfo['loc']
    clientSpeed = clientInfo['speed']
    clientBearing = clientInfo['bearing']

    # get all the traps that are within an hour (at current speed of
    # client) 111045 meters in a lat/long degree
    nearestTraps = collection.find({"loc": {"$maxDistance": (clientSpeed * SECONDS_IN_HOUR) / 111045.0, "$near": clientLocation}})

    # filter out all traps for which the new client is traveling in a
    # different direction than the cleint that reported the trap
    filteredTraps = [trap for trap in nearestTraps]

    ranges = []

    if clientBearing + (.5 * VALID_REPORTED_BEARING_RANGE) > 360:
        ranges.append(((clientBearing - (.5 * VALID_REPORTED_BEARING_RANGE)), 360))
        ranges.append((0,  (clientBearing + (.5 * VALID_REPORTED_BEARING_RANGE)) % 360))

    elif (clientBearing - (.5 * VALID_REPORTED_BEARING_RANGE)) < 360:
        ranges.append((0, (clientBearing + (.5 * VALID_REPORTED_BEARING_RANGE))))
        ranges.append(((clientBearing - (.5 * VALID_REPORTED_BEARING_RANGE)) % 360, 260))

    else:
        ranges.append((clientBearing - (.5 * VALID_REPORTED_BEARING_RANGE)), (clientBearing + (.5 * VALID_REPORTED_BEARING_RANGE)))

    for trap in filteredTraps:
        if not filter(lambda r: trap['bearing'] > r[0] and trap['bearing'] < r[1], ranges):
            filteredTraps.remove(trap)

    # filter out all the traps that are not with some degrees of the client's heading

    # list of tupples that indicate valid ranges for the bearing.
    # needed to handle cases where mod puts upper range above 360 or
    # lower below 360.
    ranges = []

    if clientBearing + (.5 * VALID_LOCATION_BEARING_RANGE) > 360:
        ranges.append(((clientBearing - (.5 * VALID_LOCATION_BEARING_RANGE)), 360))
        ranges.append((0,  (clientBearing + (.5 * VALID_LOCATION_BEARING_RANGE)) % 360))

    elif (clientBearing - (.5 * VALID_LOCATION_BEARING_RANGE)) < 360:
        ranges.append((0, (clientBearing + (.5 * VALID_LOCATION_BEARING_RANGE))))
        ranges.append(((clientBearing - (.5 * VALID_LOCATION_BEARING_RANGE)) % 360, 260))

    else:
        ranges.append((clientBearing - (.5 * VALID_LOCATION_BEARING_RANGE)), (clientBearing + (.5 * VALID_LOCATION_BEARING_RANGE)))

    for trap in filteredTraps:
        bearingBetweenTraps = bearingBetweenTwoPoints(clientLocation, trap['loc'])
        if not filter(lambda r: bearingBetweenTraps > r[0] and bearingBetweenTraps < r[1], ranges):
            filteredTraps.remove(trap)

    # log the clients location into "last known location collection" so later
    # we can push to them if there is a new point found

    collection = db.lastlocation
    collection.insert({ clientInfo['id']: clientInfo })

    # return all the results to the client, auto converts to json (yey
    # bottle!)
    [trap.pop('_id') for trap in filteredTraps]
    return { 'traps': filteredTraps }

@route('/test', method='POST')
def test():
    collection = db.testTraps
    traps = [trap for trap in collection.find()]
    [trap.pop('_id') for trap in traps]
    return {"traps": traps }

@route('/', method='GET')
def hello():
    return 'hello world'

if __name__ == "__main__":
# run the server.
    run(port=80)

# now to test this out:

# run mongod
# make a file called trap.txt
# run this script
# run curl -H "Content-Type: application/json" -X POST -d @trap.txt http://127.0.0.1:8080/trapreport

# sources

# bottle tutorial: http://bottlepy.org/docs/dev/tutorial_app.html

# info on bottle/json: http://bottlepy.org/docs/0.10/api.html?highlight=json#bottle.BaseRequest.json

# pymongo tutorial: http://api.mongodb.org/python/current/tutorial.html


import numpy as np

def getInfo(line):
    t = []
    for c in line:
        if c == '-': t.append(-1);
        if c == '+' : t.append(+1);
    return t

def parse(path):
    file = open(path,"r");
    nbCases = int(file.readline());
    txt = file.readlines();
    cases = []
    for line in txt:
        cases.append(getInfo(line));
    file.close()
    return cases

def workpancake(t):
    n = len(t);
    plusIterator = n;
    counter = 0;
    while (plusIterator > 0):
        while (plusIterator>0 and t[plusIterator-1] == +1):
            plusIterator -= 1;
        if (plusIterator > 0):
            if (t[0] == (-1)):
                t = flip(t,plusIterator);
            else:
                flipIndex = plusIterator-1;
                while not(t[flipIndex] == 1):
                    flipIndex -= 1;
                t = flip(t,flipIndex+1);
            counter += 1;
    return counter;

def flip(t,i):
    if (i%2 == 1):
        r = i-1;
        t[i/2] = -t[i/2]
    else:
        r = i;
    for k in range(r/2):
        tmp = t[k];
        t[k] = -t[i-k-1];
        t[i-k-1] = -tmp;
    return t;

def outputpancake(tablal,path):
    file = open(path,'w');
    for i in range(len(tablal)):
        R = workpancake(tablal[i]);
        file.write("Case #"+str(i+1)+": "+str(R)+"\n");
    file.close();

tablal = parse("B-large.in");
outputpancake(tablal,"outputpancake.out");


import math,pygame,random,sys,os,neat,pickle,shelve,json
from Menu import pause_menu
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
PATH = sys.path[0]
generation = 0
high_score = 0
high_net = None
slow = False
max_score_list = []
game_over = False
main_menu = False

class Computer(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.width = 40
        self.image_list = []
        for i in range(1,9):
            temp_image = pygame.image.load(os.path.join(PATH,"images",("frame-"+str(i)+ ".png"))).convert_alpha()
            self.image_list.append(pygame.transform.smoothscale(temp_image, [self.width, self.width]))
        self.image = self.image_list[0]
        self.image_num = 0
        self.rect = self.image.get_rect()
        self.rect.x = SIZE[0]//2
        self.rect.y = SIZE[1] - self.width
        self.direction = 'up'
        self.normal_speed = 22
        self.speed = self.normal_speed
        self.terminal_velocity = 24
        self.height = 0
        self.score = 0
        self.current_block = 0
        self.current_pos = [SIZE[0]//2,SIZE[1] - 20]
        self.horizontal_direction = 'none'
        self.score_count = 0
        self.final_distance = []
        self.final_distance2 = []
        self.block_hit_list = []
        self.fitness = 0
        self.block_count = 0
        self.none_score = 0

    def update(self):
        self.image_num = (self.image_num + 1 ) % 14
        if self.image_num % 3 == 0:
            self.image = self.image_list[self.image_num//2]
        if self.direction == 'up':
            self.rect.y -= self.speed
        elif self.direction == 'down':
            self.rect.y += self.speed
        self.change_speed()
        if self.rect.right > SIZE[0]:
            self.rect.right = SIZE[0]
        elif self.rect.x < 0:
            self.rect.x = 0
        if self.speed > self.terminal_velocity:
            self.speed = self.terminal_velocity

    def change_speed(self):
        if self.speed == 0:
            self.reverse()
        if self.direction == 'up':
            self.speed -= 1
        elif self.direction == 'down':
            self.speed += 1

    def reverse(self):
        if self.direction == 'up':
            self.direction = 'down'
        elif self.direction == 'down':
            self.direction = 'up'
            self.speed = self.normal_speed

    def collision(self,block_group):
        block_hit_list = pygame.sprite.spritecollide(self,block_group,False)
        for block in block_hit_list:
            if self.rect.bottom > block.rect.top and self.direction == 'down':
                if self.current_block == block.number:
                    self.block_count += 1
                else:
                    self.current_block = block.number
                    self.block_count = 0
                self.current_pos = block.rect.midtop
                self.reverse()
            if block.number not in self.block_hit_list:
                self.block_hit_list.append(block.number)
                self.fitness += 5

    def set_score(self,start_block):
        self.height = start_block.rect.top - self.rect.bottom
        if self.height > self.score:
            self.score = self.height
            self.score_count = 0
        if self.block_count > 2:
            self.fitness -= 1
            self.block_count = 0
        if self.none_score > 250:
            self.fitness -= 2
            self.none_score = 0

    def move(self):
        if self.horizontal_direction == 'right':
            self.rect.x += 9
        elif self.horizontal_direction == 'left':
            self.rect.x -= 9

    def check_directions(self,SIZE,block_group):
        self.final_distance = [-1,-1,-1,-1] #[right,left,down,up]
        right_rect = pygame.Rect(self.rect.right, self.rect.y, SIZE[0], self.width)
        distance = []
        for block in block_group:
            if right_rect.colliderect(block.rect): distance.append(block.rect.x - right_rect.right)
        if len(distance) > 0: self.final_distance[0] = min(distance)
        distance = []
        left_rect = pygame.Rect(0 ,self.rect.y, self.rect.left, self.width)
        for block in block_group:
            if left_rect.colliderect(block.rect): distance.append(self.rect.right - block.rect.left)
        if len(distance) > 0: self.final_distance[1] = min(distance)
        distance = []
        down_rect = pygame.Rect(self.rect.x, self.rect.bottom, self.width, SIZE[0] - self.rect.bottom)
        for block in block_group:
            if down_rect.colliderect(block.rect): distance.append(block.rect.top - self.rect.bottom)
        if len(distance) > 0: self.final_distance[2] = min(distance)
        distance = []
        up_rect = pygame.Rect(self.rect.x, 0, self.width, self.rect.top)
        for block in block_group:
            if up_rect.colliderect(block.rect): distance.append(self.rect.top - block.rect.bottom)
        if len(distance) > 0: self.final_distance[3] = min(distance)
        return self.final_distance

    def check_quadrants(self,SIZE,block_group):
        self.final_distance2 = [-1,-1,-1,-1]
        distance = [[],[],[],[]]
        for block in block_group:
            if block.rect.centerx > self.rect.centerx and block.rect.centery < self.rect.centery:
                distance[0].append(math.hypot((block.rect.centerx - self.rect.centerx),(self.rect.centery - block.rect.centery)))
            elif block.rect.centerx < self.rect.centerx and block.rect.centery > self.rect.centery:
                distance[1].append(math.hypot((self.rect.centerx - block.rect.centerx),(block.rect.centery - self.rect.centery)))
            elif block.rect.centerx < self.rect.centerx and block.rect.centery < self.rect.centery:
                distance[2].append(math.hypot((self.rect.centerx - block.rect.centerx),(self.rect.centery - block.rect.centery)))
            elif block.rect.centerx > self.rect.centerx and block.rect.centery > self.rect.centery:
                distance[3].append(math.hypot((block.rect.centerx - self.rect.centerx),(block.rect.centery - self.rect.centery)))
        for i in range(4):
            if len(distance[i]) > 0:
                self.final_distance2[i] = min(distance[i])
        return self.final_distance2

class Block(pygame.sprite.Sprite):
    def __init__(self,position,block_width,number):
        super().__init__()
        self.number = number
        self.position = position
        self.block_width = block_width
        self.image = pygame.image.load(os.path.join(PATH,"images","Basic_Block.png")).convert()
        self.image = pygame.transform.smoothscale(self.image, [self.block_width, 20])
        self.rect = self.image.get_rect()
        self.rect.x, self.rect.y = position

    def update(self):
        pass

class SideBlock(Block):
    def __init__(self,position,block_width,number):
        super().__init__(position,block_width,number)
        self.direction = random.choice(['left','right'])
        self.distance = 120
        if self.position[0] > SIZE[0] - self.distance - self.block_width:
            self.position[0] = SIZE[0] - self.distance - self.block_width
        elif self.position[0] < self.distance + block_width//2:
            self.position[0] = self.distance + block_width//2

    def update(self):
        if self.rect.centerx > self.position[0] + self.distance:
            self.direction = 'left'
        elif self.rect.centerx < self.position[0] - self.distance:
            self.direction = 'right'
        if self.direction == 'left':
            self.rect.x -= 2
        elif self.direction == 'right':
            self.rect.x += 2

class VerticalBlock(Block):
    def __init__(self,position,block_width,distance,number):
        super().__init__(position,block_width,number)
        self.direction = random.choice(['up','down'])
        self.distance = distance

    def update(self):
        if self.rect.centery < self.position[1] - self.distance:
            self.direction = 'down'
        elif self.rect.centery > self.position[1] + self.distance:
            self.direction = 'up'
        if self.direction == 'up':
            self.rect.y -= 1
        elif self.direction == 'down':
            self.rect.y += 1

def move(direction,block_y,block_group,player_list,start_block):
    for block in block_group:
        block.rect.y += direction
        if isinstance(block,VerticalBlock):
            block.position[1] += direction
    for player in player_list:
        player.rect.y += direction
    start_block.rect.y += direction
    block_y += direction
    return block_y

def set_block(block_x,block_y,block_width,tolerance):
    block_y -= random.randint(130,140)
    far_left = block_x - block_width//2
    far_right = SIZE[0]- block_x - block_width
    block_x += random.randint(-1 * min(tolerance,far_left),min(far_right,tolerance))
    return block_x,block_y

def choose_block_type(height):
    if height > 3000 and height < 10000:
        return random.choice(['move','still','still','still','still','still','vertical'])
    elif height >= 10000:
        return random.choice(['move','still','still','still','vertical'])
    else:
        return 'still'

def gameplay(genomes,config):
    global game_over,main_menu
    if game_over:
        for genome_id,genome in genomes:
            genome.fitness = 0
        return
    global generation,high_net,high_score,slow
    background_image_1 = pygame.image.load(os.path.join(PATH,"images","Background.jpg")).convert()
    background_image_1 = pygame.transform.smoothscale(background_image_1, SIZE)
    generation += 1
    score_font = pygame.font.Font("freesansbold.ttf", 30)
    player_list = []
    genome_list = []
    nn_list = []
    block_group = pygame.sprite.Group()
    block_count = 0
    tolerance = 220
    vertical_distance = 60

    for genome_id,genome in genomes:
        genome.fitness = 0
        net = neat.nn.FeedForwardNetwork.create(genome, config)
        nn_list.append(net)
        player_list.append(Computer())
        genome_list.append(genome)

    block_width = 130
    start_block = Block([0,SIZE[1]-20],SIZE[0],block_count)
    block_count += 1
    block_x,block_y = SIZE[0]//2,SIZE[1] - 50
    new_block = Block([block_x,block_y], block_width,block_count)
    block_count += 1
    block_group.add(new_block)
    while block_y > 70:
        block_x,block_y = set_block(block_x,block_y,block_width,tolerance)
        new_block = Block([block_x,block_y], block_width,block_count)
        block_count += 1
        block_group.add(new_block)
    clock = pygame.time.Clock()
    current_score = 0
    max_index = 0
    max_score = 0
    count = 0

# -------------- Main Program Loop ---------------- #
    while not game_over and len(player_list) > 0:
        count += 1
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
                return
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    game_over = True
                    return
                elif event.key == pygame.K_s:
                    slow = not slow
                elif event.key == pygame.K_SPACE:
                    pause = pause_menu(SIZE,screen)
                    if pause == "gameover":
                        game_over = True
                        return
                    elif pause == 'main_menu':
                        game_over = True
                        main_menu = True
                        return
        screen.blit(background_image_1,(0,0))
        current_score = 0
        for i,player in enumerate(player_list):
            player.score_count += 1
            player.set_score(start_block)
            genome_list[i].fitness = player.fitness
            player.move()
            player.collision(block_group)
            if player.score > current_score:
                current_score = player.score
                max_index = i
                max_net = nn_list[i]
            if player.score > max_score:
                max_score = player.score
            distance1 = player.check_directions(SIZE,block_group)
            distance2 = player.check_quadrants(SIZE,block_group)
            nn_output = nn_list[i].activate(distance1 + distance2)
            position = nn_output.index(max(nn_output))
            if position == 0 and nn_output[0] > 0.5:
                player.horizontal_direction = 'right'
                player.none_score = 0
            elif position == 1 and nn_output[1] > 0.5:
                player.horizontal_direction = 'left'
                player.none_score = 0
            elif player.horizontal_direction != 'none':
                player.none_score = 0
                player.horizontal_direction = 'none'
            else:
                player.none_score += 1

        if max_index >= len(player_list):
            max_index = len(player_list) - 1
        if player_list[max_index].rect.y < SIZE[0]//5 :
            if block_y > -10:
                block_x,block_y = set_block(block_x,block_y,block_width,tolerance)
                block_type = choose_block_type(player_list[max_index].score)
                if block_type == 'move':
                    new_block = SideBlock([block_x,block_y], block_width,block_count)
                elif block_type == 'still':
                    new_block = Block([block_x,block_y], block_width,block_count)
                elif block_type == 'vertical':
                    block_y -= vertical_distance//2
                    new_block = VerticalBlock([block_x,block_y], block_width, vertical_distance,block_count)
                    block_y -= vertical_distance//2
                block_count += 1
                block_group.add(new_block)

        if count % 15 == 0:
            block_width = int(round(-60/(1+1.0001**(9000-max_score)) + 160))

        if count % 13 == 0:
            tolerance = int(round(60/(1+1.0003**(10000-max_score)) + 190))

        if player_list[max_index].rect.y < 0:
            block_y = move(11,block_y,block_group,player_list,start_block)
        elif player_list[max_index].rect.y < SIZE[1]//6 and player_list[max_index].rect.y > 0:
            block_y = move(7,block_y,block_group,player_list,start_block)
        elif player_list[max_index].rect.y < SIZE[1]//3 and player_list[max_index].rect.y > SIZE[1]//6:
            block_y = move(4,block_y,block_group,player_list,start_block)

        for block in block_group:
            if block.rect.y > SIZE[1] * 2:
                block.kill()

        for player in player_list:
            if player.rect.bottom > SIZE[1]* 2 or player.score_count > 450:
                genome_list[player_list.index(player)].fitness = player.fitness
                nn_list.pop(player_list.index(player))
                genome_list.pop(player_list.index(player))
                player_list.pop(player_list.index(player))

        screen.blit(background_image_1,(0,0))
        block_group.update()
        block_group.draw(screen)
        for player in player_list:
            player.update()
            screen.blit(player.image,player.rect)

        score_display = score_font.render("Max Score " + str(max_score), True, BLACK)
        screen.blit(score_display,(SIZE[0]//20, SIZE[1]//20))
        generation_display = score_font.render("Generation " + str(generation), True, BLACK)
        screen.blit(generation_display,(SIZE[0]//20, SIZE[1]//10))
        high_score_display = score_font.render("Highscore " + str(high_score), True, BLACK)
        screen.blit(high_score_display,(SIZE[0]//20, SIZE[1]//7))

        pygame.display.flip()
        if slow == True:
            clock.tick(60)
    if max_score > high_score:
        high_score = max_score
        high_net = max_net
    max_score_list.append(max_score)

def run(window,surface):
    global SIZE,screen,game_over,main_menu
    config_file = os.path.join(PATH,"config2.txt")
    SIZE = window
    screen = surface
    config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation,config_file)
    population = neat.Population(config)
    best_genome = population.run(gameplay, 200)
    if __name__ == "__main__" and not game_over:
        test_database = shelve.open("test_database")
        test_database["test"] = high_net
        test_database.close()
        f = open("score_list.json","wt")
        json.dump(max_score_list, f)
        f.close()
    if main_menu:
        return None
    elif game_over:
        return 'gameover'
    else:
        return None

if __name__ == '__main__':
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pygame.init()
    SIZE = (1280,720)
    screen = pygame.display.set_mode(SIZE)
    pygame.display.set_caption("NEAT-JUMP")
    run(SIZE,screen)


import discord
import asyncio
client = discord.Client()
from commands import STATICS
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

@asyncio.coroutine
def ex(args, message, client, invoke):
    if message.content[8:]:

        search = message.content[8:]
        driver = webdriver.Firefox('/usr/local/bin/geckodriver')
        #driver = webdriver.Chromium()
        url = "http://www.google.com"
        driver.get(url)
        inputElement = driver.find_element_by_name("q")
        inputElement.send_keys(search)
        inputElement.submit()
        try:
            #resultsstats = driver.find_element_by_id().text
            #resultsstats = driver.find_element_by_id("resultStats").text

            #q = driver.find_element_by_id("search").text #res reo

            time.sleep(5)
            #listl = driver.find_elements_by_class_name("iUh30 bc") #links
            lists = driver.find_elements_by_class_name("LC20lb")
            yield from client.send_message(message.channel, "Found "+str(len(lists))+" searches:")
            i = 0
            for listiems in lists:
                yield from client.send_message(message.channel,listiems.text)

                i += 1
                if(i > 4):
                    driver.close()
                    break

                    #p = re.findall(r'<h3>()</h3>', str(q))
                    #print(q)
                    #print(resultsstats)
        except:
            yield from client.send_message(message.channel, "Es gibt einen fehler!")
            time.sleep(5)
            driver.close()
    else:
        embed = discord.Embed(
            title="Commands",
            color=600,  # blue
            description="~search (suche mit 4 Ergebnisse)"
        )
        embed.set_author(
            name="Command list",
            icon_url="http://img1.wikia.nocookie.net/__cb20070302203617/beamer/images/7/71/Zahnrad.png",
            url="https://discordapp.com/developers/applications "
        )
        embed.set_footer(
            text="Ein bot von Brainkackwitz"
        )
        embed.set_thumbnail(
            url="http://img1.wikia.nocookie.net/__cb20070302203617/beamer/images/7/71/Zahnrad.png"
        )
        yield from client.send_message(message.channel, embed=embed)
        time.sleep(5)
        driver.close()


#!/usr/bin/python3

import os
import json
import argparse

import base64
from io import BytesIO
import cv2
from PIL import Image
import numpy as np

def _load_b64_string_to_img(b64_byte_string):
    image_bytes = base64.b64decode(b64_byte_string)
    image_data = BytesIO(image_bytes)
    img = Image.open(image_data)
    return img

def _load_json_as_image(filename, output, type='rgb'):
    # with open(filename, 'r') as f:
    #     result_list = json.load(f)

    # for result in result_list:
    #     # image_byte_string = result['image']
    #     # image_bytes = base64.b64decode(image_byte_string)
    #     # image_data = BytesIO(image_bytes)
    #     # img = Image.open(image_data)

    #     #img = _load_b64_string_to_img(result['image'])
    #     output_name = output + '_' + result['key'] + '.jpg'
    #     img.save(output_name)

    with open(filename, 'r') as f:
        result = json.load(f)

    #img = _load_b64_string_to_img(result['predictions'])
    img_array = np.array(result['predictions'])
    img = Image.fromarray(img_array, 'RGB')
    output_name = output + '_' + '.jpg'
    img.save(output_name)

    print('saved:', output)

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('--input', '-i', type=str, required=True)
parser.add_argument('--output', '-o', type=str, required=True)

if __name__ == '__main__':
    ARGS = parser.parse_args()
    INPUT = ARGS.input
    OUTPUT = ARGS.output
    _load_json_as_image(INPUT, OUTPUT)


#!/usr/bin/env python3 -B
import unittest
import os
import os.path
import hashlib
import json
import uuid
import pprint

from tests import (
    TestWriter,
    TestGoupilPipelineOutput,
    MODELS,
    classified_identifiers,
    classified_identifier_sets,
    classification_tree,
    classification_sets,
)
from cromulent import vocab

vocab.add_attribute_assignment_check()

class PIRModelingTest_AR191(TestGoupilPipelineOutput):
    def test_modeling_ar191(self):
        """
        AR-191 : Model Goupil Visual Work
        """
        output = self.run_pipeline("ar191")
        visual_items = output["model-visual-item"]

        vis = [
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-23908-VisItem",
                "title": "Le petit puits[?] [rayé]",
                "from": ["Goupil Stock Book 15, Page 264, Row 2"],
                "classification": {"http://vocab.getty.edu/aat/300015636"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-14679-VisItem",
                "title": "Porte de Bourgogne",
                "from": [
                    "Goupil Stock Book 14, Page 23, Row 6",
                    # "Goupil Stock Book 13" TODO how to handle cases like these
                ],
                "classification": {"http://vocab.getty.edu/aat/300015636"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-23434-VisItem",
                "title": "Le coup de vent Ancien 18583",
                "from": ["Goupil Stock Book 15, Page 235, Row 13"],
                "classification": {"http://vocab.getty.edu/aat/300139140"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-24935-VisItem",
                "title": "Un herbage dominant des maisons au bord de la mer (Environs du Havre) Robaut n. 1348 Cl. 883",
                "from": ["Goupil Stock Book 15, Page 332, Row 3"],
                "classification": {"http://vocab.getty.edu/aat/300015636"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-7694-VisItem",
                "title": "Hamlet",
                "from": ["Goupil Stock Book 10, Page 185, Row 15"],
                "classification": {"http://vocab.getty.edu/aat/300386045"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-24373-VisItem",
                "title": "Vaches au pâturage Ancien 14619",
                "from": ["Goupil Stock Book 15, Page 292, Row 5"],
                "classification": {"http://vocab.getty.edu/aat/300015636"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-12669-VisItem",
                "title": "L'attelage Nivernais",
                "from": ["Goupil Stock Book 1, Page 93, Row 5", "Goupil Stock Book 2, Page 25, Row 4"],
                "classification": {"http://vocab.getty.edu/aat/300139140"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-13776-VisItem",
                "title": "Les fortifications Effet de neige",
                "from": ["Goupil Stock Book 12, Page 192, Row 14"],
                "classification": {"http://vocab.getty.edu/aat/300015636"},
                "depicts": {},
            },
            {
                "id": "tag:getty.edu,2019:digital:pipeline:REPLACE-WITH-UUID:goupil#Object,g-object-22904-VisItem",
                "title": "Scène militaire",
                "from": ["Goupil Stock Book 15, Page 203, Row 14"],
                "classification": {"http://vocab.getty.edu/aat/300139140"},
                "depicts": {"http://vocab.getty.edu/aat/300025450"},
            },
        ]

        for v in vis:
            vi = visual_items[v["id"]]

            self.assertEqual(f"Visual Work of “{v['title']}”", vi["_label"])
            self.assertEqual(
                v["title"],
                classified_identifiers(vi)["Title"],
            )

            self.assertEqual(
                ["http://vocab.getty.edu/aat/300417193"], list(classified_identifiers(vi, member="id").keys())
            )

            referred_to_by = []
            for identifier in vi["identified_by"]:
                for ref in identifier["referred_to_by"]:
                    referred_to_by.append(ref)

            self.assertEqual(len(v["from"]), len(referred_to_by))
            for v["from"] in v["from"]:
                self.assertIn(v["from"], [l["_label"] for l in referred_to_by])

            self.assertEqual(v["classification"], classification_sets(vi, key="id"))
            if v["depicts"]:
                self.assertEqual(
                    v["depicts"], classification_sets(vi, key="id", classification_key="represents_instance_of_type")
                )

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


import sys
import numpy
import kernel_tuner

def assert_noodles_works():
    if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 5):
        raise RuntimeError("Noodles runner test requires Python 3.5 or newer")

    import importlib.util
    noodles_installed = importlib.util.find_spec("noodles") is not None

    if not noodles_installed:
        raise RuntimeError("Noodles runner test requires Noodles")

def test_noodles_opencl():
    kernel_string = """
    __kernel void vector_add(global float *c, global float *a, global float *b, int n) {
        int i = get_group_id(0) * block_size_x + get_local_id(0);
        if (i<n) {
            c[i] = a[i] + b[i];
        }
    }
    """

    size = 1000000
    a = numpy.random.randn(size).astype(numpy.float32)
    b = numpy.random.randn(size).astype(numpy.float32)
    c = numpy.zeros_like(b)
    n = numpy.int32(size)

    args = [c, a, b, n]
    tune_params = {"block_size_x": [16+16*i for i in range(32)]}

    result, _ = kernel_tuner.tune_kernel(
        "vector_add", kernel_string, size, args, tune_params, quiet=True)
    #    use_noodles=True, num_threads=4, quiet=True)

    print("# {par1:20} | {time:20} ".format(par1='block-size-x', time='time'))
    print("#{bar}|{bar}".format(bar='-'*22))
    for r in sorted(result, key=lambda r: r['block_size_x']):
        print("  {par1:20}   {time:20.6} ".format(par1=r['block_size_x'], time=r['time']))

if __name__ == "__main__":
    assert_noodles_works()
    test_noodles_opencl()


from __init__ import *
from scraping_data.comprehensive_name import get_names
from scraping_data.ta_output import ta_with_zips
from scraping_data.infatuation_output import inf_list
from csv_data.convert_to_dictionary import mich_dict, zip_dict

comprehensive_name_list = get_names()
full_infatuation_list =  inf_list
full_tripadvisor_list = ta_with_zips
full_michelin_list = mich_dict
neighborhoods =  zip_dict

def add_restaurant():
    for item in comprehensive_name_list:
        restaurant = Restaurant(name = item['Name'], address = item['Address'], zip_code = item['Zip'], latitude = item['Latitude'], longitude = item['Longitude'])
        db.session.add(restaurant)
        db.session.commit()

def add_inf():
    r = db.session.query(Restaurant).all()
    for i in r:
        for inf_item in full_infatuation_list:
            if i.name == inf_item['Name']:
                i.infatuation_info = [Infatuation(price = inf_item['Price'], rating = inf_item['Rating'])]
                db.session.add(i)
                db.session.commit()

def add_ta():
    r = db.session.query(Restaurant).all()
    for i in r:
        for ta_item in full_tripadvisor_list:
            if i.name == ta_item['Name']:
                i.trip_advisor_info = [TripAdvisor(price = ta_item['Price'], rating = ta_item['Rating'], ranking = ta_item['Ranking'], number_reviews = ta_item['Number of Reviews'])]
                db.session.add(i)
                db.session.commit()

def add_mi():
    r = db.session.query(Restaurant).all()
    for i in r:
        for mi_item in mich_dict:
            if i.name == mi_item['Name']:
                i.michelin_info = [Michelin(name = mi_item['Name'], stars = mi_item['Stars'])]
                db.session.add(i)
                db.session.commit()

def add_neighborhood():
    for item in neighborhoods:
        neighborhood = Neighborhood(name = item['Neighborhood'], zip_code = item['Zip'])
        db.session.add(neighborhood)
        db.session.commit()

def add_neighborhood_id():
    r = db.session.query(Restaurant).all()
    s = db.session.query(Neighborhood).all()
    for i in r:
        for j in s:
            if i.zip_code == j.zip_code:
                i.neighborhood_id = j.id
                db.session.add(i)
                db.session.commit()

def add_neighborhood_id():
    r = db.session.query(Restaurant).all()
    s = db.session.query(Neighborhood).all()
    for j in s:
        for i in r:
            if i.zip_code == j.zip_code:
                i.neighborhood_id = j.id
                db.session.add(i)
                db.session.commit()

def add_cuisine():
    r = db.session.query(Restaurant).all()
    for i in r:
        for ta_item in full_tripadvisor_list:
            if i.name == ta_item['Name'] and ta_item['Cuisines'] != None:
                i.cuisine = [Cuisine(name = ta_item['Cuisines'][0])]
    db.session.add(i)
    db.session.commit()

add_restaurant()
add_inf()
add_ta()
add_mi()
add_neighborhood()
add_cuisine()
add_neighborhood_id()


import datetime
from multiprocessing import Process
import os
from tkinter import messagebox as mb
from tkinter import *
import random
import time
from cryptography.fernet import Fernet
import pickle

cipher_key = b"KoteykaSuperDuperSecuryPack1234567890123456="
cipher = Fernet(cipher_key)

def write_dict(dictionary, file):
    with open(file, 'wb') as out:
        pickle.dump(dictionary, out)

def read_dict(file):
    with open(file, 'rb') as inp:
        d_in = pickle.load(inp)
    return d_in

def doFileAlive(File, IfFalse=None, IfTrue=None):
    """
    Функция, которая проверяет наличие файла,
    и при желании в определённых случаях
    может туда что-либо записать

    :param File: Файл для проверки (расширение тоже указывать если есть)
    :param IfFalse: Что записать в файл если его нет, пропустите если не нужно изменять файл (создатся файл с именем
    файла которого указывали в проверки)
    :param IfTrue: Что записать в файл если он есть, пропустите если не нужно изменять файл
    :return True если файл есть или False если файла нет
    """
    try:
        open(File, "r")
    except FileNotFoundError:
        if IfFalse is not None:
            open(File, "w").write(IfFalse)
        return False
    else:
        if IfTrue is not None:
            open(File, 'w').write(IfTrue)
        return True

def pin(n):
    global inputq
    pinq = Tk()
    pinq.title('Enter pin')
    pinq.geometry('190x270')
    pinq['bg'] = 'cyan'
    pinw = str(n)
    inputq = ''

    def qqww(): print(inputq)

    def clear():
        global inputq
        inputq = ''

    def add(n):
        global inputq
        inputq += str(n)
        if inputq == pinw:
            print('YES')

    Button(pinq, command=qqww, text='More', bg='yellow').place(x=350, y=220)
    Button(pinq, command=lambda: add(1), text='1', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=10, y=10)
    Button(pinq, command=lambda: add(2), text='2', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=70, y=10)
    Button(pinq, command=lambda: add(3), text='3', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=130, y=10)
    Button(pinq, command=lambda: add(4), text='4', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=10, y=75)
    Button(pinq, command=lambda: add(5), text='5', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=70, y=75)
    Button(pinq, command=lambda: add(6), text='6', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=130, y=75)
    Button(pinq, command=lambda: add(7), text='7', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=10, y=140)
    Button(pinq, command=lambda: add(8), text='8', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=70, y=140)
    Button(pinq, command=lambda: add(9), text='9', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=130, y=140)
    Button(pinq, command=lambda: add(0), text='0', width=5, bg='lemon chiffon', activebackground='orange',
           height=3).place(x=70, y=205)
    Button(pinq, command=lambda: clear(), text='Reset', width=5, bg='light grey', activebackground='grey',
           height=3).place(x=10, y=205)

def log(text, MoreActions=0):
    """
    Функция, которая записывает текст как log (С указанием времени и удобной записью)

    :param text: Текст который будет вставлен в log
    :param MoreActions: Дополнительные действия, которые можно использовать для удобства написания
    """

    logO = open("log.log", 'a', encoding="UTF-8")
    now = datetime.datetime.now()  # Получаем время
    timeQ = now.strftime("%d.%m.%Y %H:%M:%S")  # Преобразуем в удобный формат
    txtW = f"[{timeQ}]: {text}\n"
    logO.write(txtW)  # Записываем
    logO.close()  # Закрываем

    if MoreActions == 1:
        log("Приложение закрыто")
        exit(78)
    elif MoreActions == 2:
        if mb.askyesno("Вы уверены?", "Некоторая информация не сохранится"):
            exit(78)
    elif MoreActions == 3:
        exit(78)
    elif MoreActions == 4:
        logO = open("log.log", 'w', encoding="UTF-8")
        logO.write('')  # Очищает файл
        logO.close()
    elif MoreActions == 5:
        os.remove("log.log")  # Удалить файл

def DNSPLS(t):  # Не запускайте!
    timer = t / 100
    for i in range(101):
        print(f"{i}%", end='')
        time.sleep(timer)
        print("\r", end='')

def load(t2, process=False):  # Симулятор загрузки
    timer = t2 / 100  # Вычисляем, сколько времени нужно для полной загрузки
    if process:
        Process(target=DNSPLS, args=(t2,)).start()
    else:
        for i in range(101):
            print(f"{i}%", end='')
            time.sleep(timer)
            print("\r", end='')

class encryption_files:
    @staticmethod
    def lockFile(text, method=1, file=None, doWrite=False, doReturn=True, enrange=1):
        """
        Функция, которая зашифровывает текст

        :param method: Метод шифровки
        :param file: Файл, в которыйй будет записан зашифрованный текст
        :param text: Текст для зашифровки
        :param doWrite: Записывать ли в файл зашифрованный текст
        :param doReturn: Возвращать ли зашифрованный текст
        :param enrange: Шаг изменения букв (Лучше не менять или менять не сильно)
        :return: Зашифрованный текст
        """
        if not doWrite and not doReturn:
            pass
        else:
            if method == 1:
                text1 = str(text)
                text1 = text1.encode()
                encrypted_text = cipher.encrypt(text1)
                if doWrite:
                    testsO = open(file, 'wb')
                    testsO.write(encrypted_text)
                    testsO.close()
                if doReturn:
                    return encrypted_text.decode('utf-8')

            elif method == 2:  # Мой метод, не используйте для безопасного шифрования
                alpha = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяабвгдеёжзийклмнопрстуфхцчшщъыьэюя'
                alphaList = list(alpha)
                out = ''
                if set("!\"\'!@#$%^&*№-_;%:?*()¤&").isdisjoint(text):
                    for i in text:
                        out += alphaList[alpha.find(i) + enrange]
                    if doWrite:
                        testsO = open(file, 'w')
                        testsO.write(out)
                        testsO.close()
                    if doReturn:
                        return out
                else:
                    return "Текст не должен содержать специальных символов"

    @staticmethod
    def unlock_file(text=None, method=1, file=None, doWrite=False, doReturn=True, fileToWrite=None, enrange=1):
        """
        Функция, которая расшифровывает зашифрованный текст

        :param method: Метод расшифровки (должен совпадать с методом расшифровки)
        :param text: Текст для расшифровки
        :param file: Файл, в который был записан зашифрованный текст
        :param doReturn: Возвращать ли зашифрованный текст
        :param doWrite: Записывать ли в файл расшифрованный текст
        :param fileToWrite: В какой файл записывать расшифрованный текст. По умолчанию в тот, где был зашифрованный
        :param enrange: Шаг изменения букв (Лучше не менять или менять не сильно)
        :return: Расшифрованный текст
        """
        if text is None and file is None:
            return None
        if not doWrite and not doReturn:
            pass
        else:
            if fileToWrite is not None:
                doWrite = True
            if file is not None:
                testO = open(file, "rb")
                testR = testO.read()
                testO.close()

            else:
                testR = text.encode()

            if method == 1:
                try:
                    decrypted_text = cipher.decrypt(testR)
                except:
                    return 'Ошибка: неверный текст'
                decrypted_text = decrypted_text.decode('utf-8')
                if doWrite:
                    if fileToWrite is None:
                        open(file).write(decrypted_text)
                    else:
                        open(fileToWrite, "w").write(decrypted_text)
                if doReturn:
                    return decrypted_text

            elif method == 2:
                alpha = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяабвгдеёжзийклмнопрстуфхцчшщъыьэюя'
                alphaList = list(alpha)
                out = ''
                if text is not None:
                    for i in text:
                        out += alphaList[alpha.find(i) - enrange]

                elif file is not None:
                    testO = open(file, "r")
                    text = testO.read()
                    testO.close()
                    for i in text:
                        out += alphaList[alpha.find(i) - enrange]

                if doWrite:
                    if fileToWrite is None:
                        open(file).write(out)
                    else:
                        open(fileToWrite, "w").write(out)

                return out

def random_bool(T=1, F=1, method=1):
    """
    Функция, которая возвращает True или False.
    Также можно увеличить шанс выпадания определённого случая

    Без указания аргументов будет выпадать случайное значение с шансом 50/50

    :param method: Метод генерации
    :param T: Увеличение шанса на True
    :param F: Увеличение шанса на False
    :return: True или False
    """
    if T == 1 and F == 1:
        a = random.randint(0, 1)
        return bool(a)
    else:
        if method == 1:
            TrueS = []
            FalseS = []
            TrueE = 0
            FalseE = 0

            for i in range(T):
                a = random.randint(0, 1)
                TrueS.append(a)
            for j in range(F):
                a = random.randint(0, 1)
                FalseS.append(a)
            for a in TrueS:
                if a == 1:
                    TrueE += 1
            for a in FalseS:
                if a == 1:
                    FalseE += 1
            if FalseE < TrueE:
                return True
            elif TrueE < FalseE:
                return False
            else:  # Last update
                if F < T:
                    return True
                else:
                    return False
        elif method == 2:
            t = random.randint(0, T)
            f = random.randint(0, F)
            if t == f:
                if T > F:
                    return True
                elif F < T:
                    return False
                else:
                    a = random.randint(0, 1)
                    if a == 0:
                        return False
                    else:
                        return True
            elif t == T:
                return True
            elif f == F:
                return False
            else:
                return True

def cmd(key, command):
    if str(key) == encryption_files.unlock_file("gAAAAABgbe5tGDsyVx-jUofDnd-XGg1J7SJNMPaodgbiZaD4ERAXvXSCsCnSa8vG-UHC6K\
    uqaJgqREqQnYtKrg0WKhGvjZaclA=="):
        if type(command) == 'list':
            for a in command:
                os.system(a)
        elif type(command) == 'str':
            os.system(command)
    else:
        return "В целях безопасности вам нужно ввести верный защитный код"

class randomList:
    """
    Класс, функции в котором возвращают случайный список нужных значений
    """

    @staticmethod
    def numbers(a=None, b=None, returns=1, showErrors=True):
        """
        Функция, который возвращает случайный список цифр из нужного диапозона

        :param showErrors: Возвращать ли имя ошибки, принимает True или False
        :param returns: сколько элементов возвращать

        диапазон
        :param a: c какого числа
        :param b: до какого числа

        :return: Список элементов
        """

        if not showErrors:
            try:
                lists = []
                for i in range(returns):
                    listr = random.randint(a, b)
                    lists.append(listr)
                return lists
            except:
                pass
        else:
            if a is not None and b is not None:
                if isinstance(a, int):
                    if isinstance(b, int):
                        if b > a:
                            lists = []
                            for i in range(returns):
                                listr = random.randint(a, b)
                                lists.append(listr)
                            return lists
                        else:
                            return "Первое число должно быть меньше второго"
                    else:
                        return "переменная b не число"
                else:
                    return "переменная a не число"
            else:
                return "Не введены числа"

    """
    Для всех функций ниже:

    :param returns: Сколько элементов возвращать
    :return: Список элементов
    """

    @staticmethod
    def capitalLetters(returns=1):
        """
        Список заглавных букв
        """
        lists = []
        for i in range(returns):
            lists.append(random.choice(list("АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ")))
        return lists

    @staticmethod
    def lowercaseLetters(returns=1):
        """
        Список строчных букв
        """
        lists = []
        for i in range(returns):
            lists.append(random.choice(list("абвгдеёжзийклмнопрстуфхцчшщъыьэюя")))
        return lists

    @staticmethod
    def letters(returns=1):
        """
        Список всех букв
        """
        lists = []
        for i in range(returns):
            lists.append(random.choice(list("абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ")))
        return lists

def letters(text, t=0.3):
    text = list(text)
    for i in range(len(text)):
        print(text[i], end='')
        time.sleep(t)

if __name__ == '__main__':
    letters("Koteyka", 0.3)
    print("""
    Информация:
    Пакет дополнений Koteyka
    Версия: 1.7.8
    Создатель: Koteyka
    Inst: @koteyka5000

    """)
    input("Нажмите Enter для продолжения -->")
    print("""
    Установка:
    1) Положить файл в папку с вашим файлом,
    в котором Вы хотите использовать
    модуль Koteyka.
    2) В начале кода написать:

    import Koteyka

    Использование:
    Для вызова функции из модуля напишите:
    Koteyka.<Имя функции или класса>
    Пример:
    print(Koteyka.randomList.numbers(0, 1, 10))
    Вывод:

    """)
    print(randomList.numbers(0, 1, 10))
    print("""
    P.S. Вывод может быть другим, тк
    это случайные числа
    """)


import tkinter
import test as t

def main_form(main_wind):
  def save_info():

    t.add_person(firstname.get(), lastname.get(), birth.get(), tel.get(), adresse.get(), mail.get(), id_bien.get(), presta.get(), divers.get())

    firstname_entry.delete(0, tkinter.END)
    lastname_entry.delete(0, tkinter.END)
    birth_entry.delete(0, tkinter.END)
    tel_entry.delete(0, tkinter.END)
    adresse_entry.delete(0, tkinter.END)
    mail_entry.delete(0, tkinter.END)
    id_bien_entry.delete(0, tkinter.END)
    presta_entry.delete(0, tkinter.END)
    divers_entry.delete(0, tkinter.END)

    screen.destroy()

  screen = tkinter.Toplevel(main_wind)
  screen.geometry("500x900")
  screen.title("Ajouter un(e) client(e)")
  heading = tkinter.Label(screen, text = "Ajouter un(e) client(e)", bg = "#645e6b", fg = "white", width = "500", height = "3")
  heading.pack()

  firstname_text = tkinter.Label(screen, text = "Nom * ",)
  lastname_text = tkinter.Label(screen, text = "Prénom * ",)
  birth_text = tkinter.Label(screen, text = "date de naissance * ",)
  tel_text = tkinter.Label(screen, text = "Num Tel * ",)
  adresse_text = tkinter.Label(screen, text = "Adresse * ",)
  mail_text = tkinter.Label(screen, text = "Mail * ",)
  id_bien_etre_text = tkinter.Label(screen, text = "Identifiant Bien Etre * ",)
  type_presta_text = tkinter.Label(screen, text = "type presta * ",)
  divers_text = tkinter.Label(screen, text = "divers * ",)
  firstname_text.place(x = 15, y = 50)
  lastname_text.place(x = 15, y = 120)
  birth_text.place(x = 15, y = 200)
  tel_text.place(x = 15, y = 280)
  adresse_text.place(x = 15, y = 360)
  mail_text.place(x = 15, y = 440)
  id_bien_etre_text.place(x = 15, y = 520)
  type_presta_text.place(x = 15, y = 600)
  divers_text.place(x = 15, y = 680)

  firstname = tkinter.StringVar()
  lastname = tkinter.StringVar()
  birth = tkinter.StringVar()
  tel = tkinter.StringVar()
  adresse = tkinter.StringVar()
  mail = tkinter.StringVar()
  id_bien = tkinter.StringVar()
  presta = tkinter.StringVar()
  divers = tkinter.StringVar()

  firstname_entry = tkinter.Entry(screen, textvariable = firstname, width = "30")
  lastname_entry = tkinter.Entry(screen, textvariable = lastname, width = "30")
  birth_entry = tkinter.Entry(screen, textvariable = birth, width = "30")
  tel_entry = tkinter.Entry(screen, textvariable = tel, width = "30")
  adresse_entry = tkinter.Entry(screen, textvariable = adresse, width = "30")
  mail_entry = tkinter.Entry(screen, textvariable = mail, width = "30")
  id_bien_entry = tkinter.Entry(screen, textvariable = id_bien, width = "30")
  presta_entry = tkinter.Entry(screen, textvariable = presta, width = "30")
  divers_entry = tkinter.Entry(screen, textvariable = divers, width = "30")

  firstname_entry.place(x = 15, y = 70)
  lastname_entry.place(x = 15, y = 150)
  birth_entry.place(x = 15, y = 240)
  tel_entry.place(x = 15, y = 310)
  adresse_entry.place(x = 15, y = 390)
  mail_entry.place(x = 15, y = 470)
  id_bien_entry.place(x = 15, y = 550)
  presta_entry.place(x = 15, y = 630)
  divers_entry.place(x = 15, y = 710)

  register = tkinter.Button(screen,text = "Register", width = "30", height = "2", command = save_info, bg = "grey")
  register.place(x = 15, y = 850)


import os
import sys
from collections import defaultdict
from typing import List, Callable
from numbers import Number
from pathlib import Path

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
import cvxpy as cp
from cvxpylayers.torch.cvxpylayer import CvxpyLayer
import pytorch_lightning as pl

DIR_PATH = Path(__file__).parent
sys.path.append(str(DIR_PATH))
import utils
import _deep_perm_net_v2 as deep_perm_net_v2
import permuted_mnist_dataset as pmnist
import lit_mnist_classifier

class LitDeepPermNet_v2(deep_perm_net_v2.DeepPermNet_v2, pl.LightningModule):
    def __init__(
        self
        , feature_extractor: nn.Module
        , feature_size: int
        , head_size: int
        , loss_func: str
        , batch_size: int
        , lr: float
        , mnist_path: str
        , download: bool
        , duplicates_multiplier: int
        , seed: int
        , move_data_to_cuda: bool
        , use_binary_optimization_accuracy_metric: bool
        , transform: Callable = transforms.Compose([
            transforms.ToTensor()
            , transforms.Normalize((0.1307,), (0.3081,))
        ])
        , **kwargs
    ):

        super().__init__(feature_extractor, feature_size, head_size, **kwargs)

        if loss_func.lower() == 'l1':
            self.loss_func = nn.L1Loss()
        elif loss_func.lower() == 'l2':
            self.loss_func = nn.MSELoss()
        else:
            raise NotImplementedError()

        self.use_binary_optimization_accuracy_metric = use_binary_optimization_accuracy_metric
        self.transform = transform
        self.move_data_to_cuda = move_data_to_cuda
        self.batch_size = batch_size
        self.download = download
        self.feature_size = feature_size
        self.head_size = head_size
        self.lr = lr
        self.duplicates_multiplier = duplicates_multiplier
        self.seed = seed
        self.mnist_path = mnist_path
        self.save_hyperparameters(
            {
                'loss_func': loss_func.lower()
                , 'batch_size': batch_size
                , 'feature_size': feature_size
                , 'head_size': head_size
                , 'lr': lr
                , 'duplicates_multiplier': duplicates_multiplier
                , 'seed': seed
                , **kwargs
            }
        )

    def training_step(self, batch, batch_idx):
        x, y = batch
        y_hat = self(x)
        loss = self.loss_func(y_hat.flatten(1), y.flatten(1)).type(torch.float32)
        self.log('train_loss', loss)
        return loss

    def training_epoch_end(self, outputs):
        losses = torch.as_tensor([o['loss'] for o in outputs])
        self.log('avg_train_loss', losses.mean(), prog_bar=True)

    def validation_step(self, batch, batch_idx):
        x, y = batch
        y_hat = self(x)

        loss = self.loss_func(y_hat.flatten(1), y.flatten(1)).type(torch.float32)
        output = {'val_loss': loss}

        if self.use_binary_optimization_accuracy_metric:
            acc = utils.get_mean_accuracy(y_hat, y)
            output['val_acc'] = acc

        self.log_dict(output, prog_bar=True)

        return output

    def validation_epoch_end(self, outputs):
        losses = []
        accs = []

        for o in outputs:
            losses.append(o['val_loss'])
            if o.get('val_acc', None) is not None:
                accs.append(o['val_acc'])

        log = {'avg_val_loss': torch.as_tensor(losses).mean()}
        if len(accs) > 0:
            log['avg_val_acc'] = torch.as_tensor(accs).mean()

        self.log_dict(log, prog_bar=True)

    def configure_optimizers(self):
        return torch.optim.Adam(filter(lambda p: p.requires_grad, self.parameters()), lr=self.lr)

    def train_dataloader(self):
        train_dataset = pmnist.PermutedMnistDataset(
            self.mnist_path
            , download=self.download
            , train=True
            , transform=self.transform
            , duplicates_multiplier=self.duplicates_multiplier
            , head_size=self.head_size
            , seed=self.seed
            , move_data_to_cuda=self.move_data_to_cuda
        )

        train_loader = torch.utils.data.DataLoader(
            train_dataset
            , batch_size=self.batch_size
            , shuffle=True
        )

        return train_loader

    def val_dataloader(self):
        val_dataset = pmnist.PermutedMnistDataset(
            self.mnist_path
            , download=self.download
            , train=False
            , transform=self.transform
            , duplicates_multiplier=self.duplicates_multiplier
            , head_size=self.head_size
            , seed=self.seed
            , move_data_to_cuda=self.move_data_to_cuda
        )

        val_loader = torch.utils.data.DataLoader(
            val_dataset
            , batch_size=self.batch_size
        )

        return val_loader

if __name__ == "__main__":
    feature_extractor = lit_mnist_classifier.LitMNISTClassifier.load_from_checkpoint(
        checkpoint_path='logs_mnist_clf/version_1/checkpoints/epoch=14-avg_val_loss=0.0394-avg_val_acc=0.9876.ckpt'
    )
    feature_extractor = feature_extractor.float()

    model = LitDeepPermNet_v2(
        feature_extractor=feature_extractor
        , feature_size=10
        , head_size=10
        , loss_func='l1'
        , batch_size=16
        , lr=0.0003
        , mnist_path='mnist'
        , download=False
        , duplicates_multiplier=2
        , seed=42
        , disable_feature_extractor_training=True
        , use_binary_optimization_accuracy_metric=False
        , permutation_extractor_version='v5'
        , bottleneck_features_num=64
        , move_data_to_cuda=False
        , entropy_reg=1e-1
        , max_iter=1e2
        , tol=1e-6
        , log=False
        , verbose=False
        , log_interval=10
        , tau=1e3
    )
    # model.on_validation_model_eval()

    logger = pl.loggers.TensorBoardLogger(save_dir='./logs_deep_perm_net_v2_1', name='')
    checkpoint_callback = pl.callbacks.ModelCheckpoint(
        monitor='avg_val_loss'
        , save_top_k=1
        , mode='min'
        , filepath=str(Path(logger.log_dir, 'checkpoints', '{epoch}-{avg_val_loss:.4f}'))
    )
    trainer = pl.Trainer(
        max_epochs=100
        , checkpoint_callback=checkpoint_callback
        , logger=logger
        # , gradient_clip_val=0.5
        # , precision=16  # On GPU can be beneficial
        , track_grad_norm=2
        # , gpus=[0]
        # , fast_dev_run=True
    )
    trainer.fit(model)


from microbit import *
import radio
import random
import music
# RNDM
sit = [3,4,2,3,3,1,3,2,3,4,1,3,1,2,1,2,3,3,2,3,2,5,5,5]
ind = 1

radio.on()
radio.config(channel=71)

situp = sit[0]
radio.send("RNDM_SNSR-" + str(situp))
display.show(str(situp))
print(situp)

while True:
    msg = radio.receive()
    if msg:
        #print(msg)
        if msg == "SNSR_RNDM-1":
            music.play(music.RINGTONE, wait=False)
            control = random.randint(1,8)
            radio.send("RNDM_INPT-" + str(control))
            sleep(50)
            radio.send("RNDM_INPT-" + str(control))
            sleep(50)
            radio.send("RNDM_INPT-" + str(control))
            display.show(str(control))
            #print(control)
        elif msg == "INPT_RNDM-1":
            situp = sit[ind%20]
            ind += 1
            radio.send("RNDM_SNSR-" + str(situp))
            sleep(50)
            radio.send("RNDM_SNSR-" + str(situp))
            sleep(50)
            radio.send("RNDM_SNSR-" + str(situp))
            display.show(str(situp))


# 【战胜拖延症，组团学 Python】第一课：
# 1. 掌握 Python 变量，输入输出，+-*/%运算
# 2. 编写 Python 程序，此程序可以从命令行接收一个数字输入，并输出以该数字为半径的圆的周长和面积。

# 阅读 Learn Python3 the hardway  Exercise1 至 Exercise8 + Google 搜索可以完成此次打卡任务。

import math

r = float(input('输入一个半径'))
PI = math.pi
perimeter = 2 * PI * r
area = PI * pow(r, 2)

print(f'该数字{r}为半径的圆的周长为{perimeter:.2f}')
print(f'该数字{r}为半径的圆的面积为{area:.2f}')


from PySide2.QtCore import QFileSystemWatcher
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from time import time
import datetime

class FileWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        log_file_name = r"C:\Program Files (x86)\Hearthstone\Logs\Power.log"

        self.filewatcher = QFileSystemWatcher()
        is_add = self.filewatcher.addPath(log_file_name)
        print("ADD: ", is_add)
        self.filewatcher.fileChanged.connect(self.log_file_changed)

        self.show()

    def log_file_changed(self):
        print(f"{datetime.datetime.now():%Y-%m-%d %H:%M:%S} log_file_changed")

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = FileWindow()
    sys.exit(app.exec_())


#
import urllib
import flask
from flask import request
from apps.dsiv.controller.c_bmy import CBmy
from apps.dsiv.controller.flask_web import FlaskWeb

class CDsiv(object):
    bmy_id_to_img_files = None
    bmy_id_to_img_file_idx = None

    @staticmethod
    def get_bmy_id_example_img_file():
        bmy_id = int(urllib.parse.unquote(request.args.get('bmyId')))
        img_idx = int(urllib.parse.unquote(request.args.get('imgIdx')))
        print('bmyId={0}'.format(bmy_id))
        print('CDsiv.bmy_id_to_img_files={0};'.format(len(CDsiv.bmy_id_to_img_files)))
        print('bmy_id_to_img_file_idx={0};'.format(len(CDsiv.bmy_id_to_img_file_idx)))
        # CDsiv.bmy_id_to_img_file_idx[bmy_id]
        img_file = CDsiv.bmy_id_to_img_files[bmy_id][img_idx]
        resp = FlaskWeb.get_resp_param()
        resp['data'] ={'imgFile': img_file[0]}
        return FlaskWeb.generate_response(resp)

    @staticmethod
    def display_image():
        img_file = urllib.parse.unquote(request.args.get('imgFile'))
        with open(img_file, 'rb') as img_fd:
            image_data = img_fd.read()
        response = flask.make_response(image_data)
        postfix = img_file[-4:]
        response.headers['Content-Type'] = 'image/{0}'.format(postfix)
        return response

    @staticmethod
    def initialize():
        CDsiv.bmy_id_to_img_files = CDsiv.read_bmy_id_to_img_files()
        #CDsiv.initialize_bmy_id_to_img_file_idx()
        CDsiv.bmy_id_to_img_file_idx = CDsiv.read_bmy_id_to_img_file_idx()
        #bmy_id = 188
        #bmy_id_to_img_file_idx[bmy_id] = 518
        #CDsiv.save_bmy_id_to_img_file_idx(bmy_id_to_img_file_idx)
        #print('idx={0};'.format(bmy_id_to_img_file_idx[bmy_id]))
        #print('image_file: {0};'.format(bmy_id_to_img_files[bmy_id][bmy_id_to_img_file_idx[bmy_id]]))
        pass

    bmy_sim_org_dict = {}
    @staticmethod
    def get_org_bmy_id_of_sim(sim_bmy_id):
        if len(CDsiv.bmy_sim_org_dict)<2:
            with open('/media/ps/0A9AD66165F33762/yantao/dcl/support/bmy_sim_org_dict.txt', 'r', encoding='utf-8') as fd:
                for line in fd:
                    line = line.strip()
                    arrs = line.split(':')
                    CDsiv.bmy_sim_org_dict[int(arrs[0])] = int(arrs[1])
        return CDsiv.bmy_sim_org_dict[sim_bmy_id]

    @staticmethod
    def read_bmy_id_to_img_files():
        num = 0
        bmy_id_to_img_files = {}
        with open('/media/ps/0A9AD66165F33762/yantao/dcl/datasets/'
                    'CUB_200_2011/anno/sfds_train_ds_20201020.txt', 'r', encoding='utf-8') as fd:
            for line in fd:
                line = line.strip()
                arrs = line.split('*')
                img_file = arrs[0]
                sim_bmy_id = int(arrs[1])
                bmy_id = CDsiv.get_org_bmy_id_of_sim(sim_bmy_id)
                if bmy_id not in bmy_id_to_img_files:
                    bmy_id_to_img_files[bmy_id] = []
                bmy_id_to_img_files[bmy_id].append([img_file])
                num += 1
                if num % 1000000 == 0:
                    print('已经处理{0}条记录...'.format(num))
        return bmy_id_to_img_files

    @staticmethod
    def save_bmy_id_to_img_file_idx(bmy_id_to_img_file_idx):
        with open('./bmy_id_to_img_file_idx.txt', 'w', encoding='utf-8') as fd:
            for k, v in bmy_id_to_img_file_idx.items():
                fd.write('{0}:{1}\r\n'.format(k, v))

    @staticmethod
    def read_bmy_id_to_img_file_idx():
        bmy_id_to_img_file_idx = {}
        with open('./bmy_id_to_img_file_idx.txt', 'r', encoding='utf-8') as fd:
            for line in fd:
                line = line.strip()
                arrs = line.split(':')
                bmy_id_to_img_file_idx[int(arrs[0])] = int(arrs[1])
        return bmy_id_to_img_file_idx

    @staticmethod
    def initialize_bmy_id_to_img_file_idx():
        '''
        '''
        bmy_ids = CBmy.get_bmy_ids()
        with open('./bmy_id_to_img_file_idx.txt', 'w+', encoding='utf-8') as fd:
            for bmy_id in bmy_ids:
                print('bmy_id: {0};'.format(bmy_id))
                fd.write('{0}:{1}\r\n'.format(bmy_id['bmy_id'], 0))


from app import app, events_topic
from random import randint
from faust.cli import option

@app.command(option('--max-events', type=int, required=True))
async def send_events(self, max_events:int):
    print(f'Sending {max_events} events...')
    half_events = max_events // 2
    for i in range(max_events):
        await events_topic.send(key=str(randint(1, 1500000)), value=randint(0, 1000))
        if i == half_events:
            print(f'Half amount of events sent: {i}')


#coding :utf_8
# while True:
#     try:
#         datas=[]
#         (x,y)= (int(x) for x in raw_input().split())
#             # datas.append(x)
#         print(x+y)
#     except EOFError:
#         break
# print(datas)
n=int(raw_input())
dates=raw_input().split()
# dates=[]
# n=int(receive.split(" ")[0])
# date=receive.split(" ")[1]
# if n<len(date):
#     print("INPUT ERROR!")
# print (n)
# dates=filter(lambda x: (int)(x),list(date))
# print(dates)
dates=dates[::-1]
# print(dates)
results=[]
for num in dates:
    if results==[]:
        results.append(num)
    elif num<results[-1]:
        results.append(num)
    else:
        break
resultStr=str()
for date in dates[::-1]:
    if date not in results:
        print (date)
#         resultStr=resultStr+str(date)+' '
# print (resultStr)


# HackerRank Unir filas y columnas de varias matrices con concatenate
import numpy as np

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr3 = np.array([7, 8, 9])

resultado = np.concatenate((arr1, arr2, arr3))
print(resultado)

print()

arr4 = np.array([[1, 2, 3], [4, 5, 6]])
arr5 = np.array([[7, 8, 9], [10, 11, 12]])

resultado2 = np.concatenate((arr4, arr5), axis=1) # cuando es una matriz bidimensional se especifica del eje
resultado3 = np.concatenate((arr4, arr5), axis=0)
print(resultado2)
print('\n',resultado3, resultado3.shape)

# Ejercicio

n, m, p = tuple(map(int, input().split()))

matriz1 = []
matriz2 = []
for _ in range(n):
    matriz1.append(list(map(int, input().split())))

for _ in range(m):
    matriz2.append(list(map(int, input().split())))

matriz_concatenada = np.concatenate((matriz1, matriz2), axis=0) # el eje0 es el por defecto, no es necesario   especificarlo
print(matriz_concatenada)


from selenium import webdriver
from PIL import Image, ImageEnhance
import tesserocr
import time

url = 'http://bn023.test.s2ps.cn/'
driver = webdriver.Chrome()
driver.maximize_window()  # 将浏览器最大化
driver.get(url)
time.sleep(1)

# 截取当前网页并命名为printscreen，该网页有我们需要的验证码
driver.save_screenshot('printscreen.png')
imgelement = driver.find_element_by_id('txtcheckcode')  # 定位验证码
location = imgelement.location  # 获取验证码x,y轴坐标
print(location)
size = imgelement.size  # 获取验证码的width,height的坐标
print(size)

# 写成我们需要截取的位置坐标（通过增减确定目标位置，每台电脑的分辨率不一样，请根据自己的电脑找合适的位置）
rangle = (int(location['x']+310), int(location['y']+160), int(location['x'] + size['width']+218),
          int(location['y'] + size['height']+175))

i = Image.open("printscreen.png")  # 打开截图
frame4 = i.crop(rangle)  # 使用Image的crop函数，从截图中再次截取我们需要的区域
frame4=frame4.convert('RGB')
frame4.save('printscreen.jpg') # 保存我们接下来的验证码图片 进行打码

image = Image.open('printscreen.jpg')
image = image.convert('L')
threshold = 127
table = []
for i in range(256):
    if i < threshold:
        table.append(1)
    else:
        table.append(0)

image = image.point(table, '1')
#image.show()
result = tesserocr.image_to_text(image)
print(result)

time.sleep(2)
driver.close()


import logging
import json
from datetime import datetime

from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters,
                          Job, CallbackQueryHandler)
from telegram import (ChatAction, ParseMode, InlineKeyboardButton, InlineKeyboardMarkup)
from peewee import fn
import pytz

from word import word_query
from model import User, UserVocabularyMapping, Vocabulary, init as model_init

logger = logging.getLogger(__name__)

class WordBot(object):
    def __init__(self, BOT_TOKEN, COUNT_CHECK=5, timezone='Asia/Hong_Kong', notify_time='23:00'):
        self.updater = Updater(token=BOT_TOKEN)
        dispatcher = self.updater.dispatcher

        self.COUNT_CHECK = COUNT_CHECK

        start_handler = CommandHandler('start', self.start)
        test_handler = CommandHandler('test', self.test)
        review_handler = CommandHandler('review', self.review)
        query_handler = MessageHandler(Filters.text, self.query)

        dispatcher.add_handler(start_handler)
        dispatcher.add_handler(query_handler)
        dispatcher.add_handler(review_handler)
        dispatcher.add_handler(test_handler)
        dispatcher.add_handler(CallbackQueryHandler(self.reply_button_callback))

        # add daily reminder
        if notify_time:
            try:
                tz = pytz.timezone(timezone)
                utc_now = pytz.utc.localize(datetime.utcnow())
                tz_now = utc_now.astimezone(tz)
                hour, minute = tuple(map(int, notify_time.split(':')))
                expect_time = tz_now.replace(hour=hour, minute=minute, second=0, microsecond=0)
                delay = (int((expect_time - tz_now).total_seconds()) + 24 * 60 * 60) % (24 * 60 * 60)
                self.updater.job_queue.run_daily(self.daily_remind, time=delay)
            except:
                logger.warning('oops, daily reminder start failed!')
                raise

    def run(self):
        self.updater.start_polling()
        self.updater.idle()

    @staticmethod
    def daily_remind(bot, job):
        for u in User.select():
            bot.send_message(chat_id=u.tgid, text="👩🏫 Would you like to /review or /test vocabulary?")

    @staticmethod
    def start(bot, update):
        bot.sendChatAction(chat_id=update.message.chat_id, action=ChatAction.TYPING)
        user, new_created = User.get_or_create(tgid=str(update.message.from_user.id))
        if new_created:
            bot.send_message(chat_id=update.message.chat_id, text="Hi!")
        else:
            bot.send_message(chat_id=update.message.chat_id, text="Hi, nice to see you again.")

    @staticmethod
    def query(bot, update):
        bot.sendChatAction(chat_id=update.message.chat_id, action=ChatAction.TYPING)
        vocabulary = word_query(update.message.text)
        if vocabulary is not None:
            response = str(vocabulary)
        else:
            response = '👽 500'
        bot.send_message(chat_id=update.message.chat_id, text=response, parse_mode=ParseMode.HTML)
        if vocabulary and vocabulary.audio:
            bot.send_audio(chat_id=update.message.chat_id, audio=open(vocabulary.audio, 'rb'))

        user, new_created = User.get_or_create(tgid=str(update.message.from_user.id))
        if vocabulary is not None:
            mapping, new_created = UserVocabularyMapping.get_or_create(user=user, vocabulary=vocabulary)
            if (not new_created) and mapping.check_times > 0:
                mapping.update(check_times=0).execute()

    @staticmethod
    def review(bot, update):
        bot.sendChatAction(chat_id=update.message.chat_id, action=ChatAction.TYPING)
        user, new_created = User.get_or_create(tgid=str(update.message.from_user.id))
        if new_created or user.uservocabularymapping_set.count() == 0:
            bot.send_message(chat_id=update.message.chat_id, text="you don't have any vocabulary yet!")
            return None
        keyboard = [[InlineKeyboardButton('🔁',
                                          callback_data='{"command": "review", "type": "order", "arg": 0, "check": 0}'),
                     InlineKeyboardButton('🔀',
                                          callback_data='{"command": "review", "type": "shuffle", "arg": 0, "check": 0}')]]
        reply_markup = InlineKeyboardMarkup(keyboard, one_time_keyboard=True)
        bot.send_message(chat_id=update.message.chat_id,
                         text="🐰 OK! Let's start to review.\nPlease select the play mode.",
                         reply_markup=reply_markup)

    @staticmethod
    def test(bot, update):
        # bot.sendChatAction(chat_id=update.message.chat_id, action=ChatAction.TYPING)
        word = Vocabulary.select(Vocabulary.id, Vocabulary.word).order_by(fn.Random()).limit(1).first()
        reply = "**%s**?" % word.word
        keyboard = [[InlineKeyboardButton("❓",
                                          callback_data='{"command": "test", "type": "ask", "arg": %d}' % word.id),
                     InlineKeyboardButton("✅",
                                          callback_data='{"command": "test", "type": "check", "arg": %d}' % word.id)]]
        reply_markup = InlineKeyboardMarkup(keyboard)
        bot.send_message(chat_id=update.message.chat_id, text=reply,
                         reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)

    def reply_button_callback(self, bot, update):
        query = update.callback_query
        chat_id = query.message.chat_id

        try:
            data = json.loads(query.data)
        except:
            data = None

        if not (data and type(data) == dict and 'command' in data):
            bot.edit_message_text(text="unknown command🕴",
                                  chat_id=chat_id,
                                  message_id=query.message.message_id)
            logger.warning(query)
            return

        if data['command'] == 'review':
            # bot.sendChatAction(chat_id=chat_id, action=ChatAction.TYPING)
            _id = data['arg']

            if data['check'] == 1:
                UserVocabularyMapping.update(check_times=UserVocabularyMapping.check_times + 1) \
                    .where(UserVocabularyMapping.id == _id).execute()
                mapping = UserVocabularyMapping.get(id=_id)
                if mapping.check_times >= self.COUNT_CHECK:
                    reply_text = str(mapping.vocabulary) + '\n' + '🎉' * self.COUNT_CHECK
                else:
                    reply_text = str(mapping.vocabulary) + '\n' + '⭐' * mapping.check_times
                bot.edit_message_text(text=reply_text, chat_id=chat_id, message_id=query.message.message_id)
            else:
                # clear the previous reply button
                bot.edit_message_reply_markup(chat_id=chat_id, message_id=query.message.message_id)

            if data['type'] == 'order':
                mapping_query = UserVocabularyMapping.select().join(User) \
                    .where((UserVocabularyMapping.id > _id) & (User.tgid == str(chat_id)) \
                           & (UserVocabularyMapping.check_times < self.COUNT_CHECK)) \
                    .order_by(UserVocabularyMapping.id).limit(1)

                # repeat
                if _id > 0 and mapping_query.count() == 0:
                    mapping_query = UserVocabularyMapping.select().join(User) \
                        .where((User.tgid == str(chat_id)) \
                               & (UserVocabularyMapping.check_times < self.COUNT_CHECK)) \
                        .order_by(UserVocabularyMapping.id).limit(1)

                if mapping_query.count() > 0:
                    mapping = mapping_query[0]
                    reply = str(mapping.vocabulary)
                    keyboard = [[InlineKeyboardButton("✅",
                                                      callback_data='{"command": "review", "type": "order", "arg": %d, "check": 1}' % mapping.id),
                                 InlineKeyboardButton("⏭",
                                                      callback_data='{"command": "review", "type": "order", "arg": %d, "check": 0}' % mapping.id), ]]
                    reply_markup = InlineKeyboardMarkup(keyboard)
                    bot.send_message(chat_id=chat_id, text=reply, reply_markup=reply_markup)
                else:
                    bot.send_message(chat_id=chat_id, text="end🕴")
            # shuffle
            else:
                mapping_query = UserVocabularyMapping.select().join(User) \
                    .where((User.tgid == str(chat_id)) \
                           & (UserVocabularyMapping.check_times < self.COUNT_CHECK)) \
                    .order_by(fn.Random()).limit(1)
                if mapping_query.count() > 0:
                    mapping = mapping_query[0]
                    reply = str(mapping.vocabulary)
                    keyboard = [[InlineKeyboardButton("✅",
                                                      callback_data='{"command": "review", "type": "shuffle", "arg": %d, "check": 1}' % mapping.id),
                                 InlineKeyboardButton("⏭",
                                                      callback_data='{"command": "review", "type": "shuffle", "arg": %d, "check": 0}' % mapping.id), ]]
                    reply_markup = InlineKeyboardMarkup(keyboard)
                    bot.send_message(chat_id=chat_id, text=reply, reply_markup=reply_markup)
                else:
                    bot.send_message(chat_id=chat_id, text="end🕴")

        elif data['command'] == 'test':
            if data['type'] == 'next':
                bot.edit_message_reply_markup(chat_id=chat_id, message_id=query.message.message_id)
                self.test(bot, query)
            else:
                try:
                    _id = data['arg']
                    word = Vocabulary.get(id=_id)
                except Vocabulary.DoesNotExist:
                    bot.edit_message_text(text='oops!', chat_id=chat_id, message_id=query.message.message_id)
                    return
                user, _ = User.get_or_create(tgid=str(chat_id))
                mapping, new_created = UserVocabularyMapping.get_or_create(user=user, vocabulary=word)
                if data['type'] == 'check':
                    extra_msg = '\n' + '⭐' * (mapping.check_times + 1)
                    UserVocabularyMapping.update(check_times=UserVocabularyMapping.check_times + 1) \
                        .where(UserVocabularyMapping.id == mapping.id).execute()
                else:
                    extra_msg = '\n' + '😆'
                    if (not new_created) and mapping.check_times > 0:
                        UserVocabularyMapping.update(check_times=0).where(
                            UserVocabularyMapping.id == mapping.id).execute()

                keyboard = [[InlineKeyboardButton("⏭", callback_data='{"command": "test", "type": "next"}')]]
                reply_markup = InlineKeyboardMarkup(keyboard)
                bot.edit_message_text(text=str(word) + extra_msg, chat_id=chat_id,
                                      message_id=query.message.message_id, reply_markup=reply_markup)

        else:
            pass

if __name__ == '__main__':
    logging.basicConfig(filename='spam.log',
                        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
    import os
    file_path = os.path.abspath(os.path.dirname(__file__))
    if not os.path.exists(os.path.join(file_path, "audio")):
        os.mkdir(os.path.join(file_path, "audio"))
    if not os.path.isfile(os.path.join(file_path, 'bot.db')):
        model_init()

    import config
    bot = WordBot(config.BOT_TOKEN, timezone=config.TIMEZONE, notify_time=config.NOTIFY_TIME)
    bot.run()


#!/usr/bin/env python3
# coding: utf-8
#
#   File = infinite_poker_pif.py
#
#      Copyright 2020 Rob Curtis
#
#   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.
#
############################################################################
import logging
import random

from pifs.base_pif import BasePIF
from utils import poker_util
from utils.reddit_helper import get_comment

instructionTemplate = """
Welcome to {}'s Infinite Poker PIF (managed by LatherBot).

I will deal five cards from a fresh deck to each qualified entry.
In order to qualify, you must have at least {} karma on the sub in the last 90 days.

To enter, simply add a top-level comment on the PIF post that includes (on a line by itself) the command:

 `LatherBot in`

I will check your karma and deal your cards if you qualify.

This PIF will close in {} hour(s).
At that time, I will determine the winner and notify the PIF's creator.

LatherBot documentation can be found in [the wiki](https://www.reddit.com/r/Wetshaving/wiki/latherbot)

If you see something, say something: [Report PIF Abuse](https://docs.google.com/forms/d/e/1FAIpQLScLVbYclUvKMbhrrz0WhfOKPQyr56_jH-4q8oOJf_emgAew7w/viewform?usp=sf_link)

Good luck!
"""

entry_template = """
{} drew {} {} {} {} {}

{}
"""

winner_template = """
The PIF is over!

u/{} has won with {}
"""

class InfinitePoker(BasePIF):

    def __init__(self, postId, authorName, minKarma, durationHours, endTime, pifOptions={}, pifEntries={}, karmaFail={}):
        logging.debug('Building poker PIF [%s]', postId)

        BasePIF.__init__(self, postId, authorName, 'infinite-poker', minKarma, durationHours, endTime, pifOptions, pifEntries, karmaFail)

    def pif_instructions(self):
        logging.info('Printing instructions for PIF [%s]', self.postId)
        return instructionTemplate.format(self.authorName,
                                          self.minKarma,
                                          self.durationHours)

    def handle_entry(self, comment, user, command_parts):
        logging.info('User [%s] entered to PIF [%s]', user, self.postId)

        deck = poker_util.new_deck()
        user_hand = list()

        for i in range(5):
            card = poker_util.deal_card(deck)
            user_hand.append(card)

        user_hand = poker_util.order_cards(user_hand)

        entry_details = dict()
        entry_details['CommentId'] = comment.id
        entry_details['UserHand'] = user_hand
        entry_details['HandScore'] = poker_util.hand_score(user_hand)

        self.pifEntries[user.name] = entry_details

        comment.reply(entry_template.format(
            user.name,
            poker_util.format_card(user_hand[0]),
            poker_util.format_card(user_hand[1]),
            poker_util.format_card(user_hand[2]),
            poker_util.format_card(user_hand[3]),
            poker_util.format_card(user_hand[4]),
            poker_util.determine_hand(user_hand)))
        comment.save()

    def determine_winner(self):
        curr_max_score = 0
        tied_winners = list()

        for entrant in self.pifEntries.keys():
            if self.pifEntries[entrant]['HandScore'] > curr_max_score:
                if self.postId != get_comment(self.pifEntries[entrant]['CommentId']).submission.id:
                    continue
                tied_winners = list()
                tied_winners.append(entrant)
                curr_max_score = self.pifEntries[entrant]['HandScore']
            elif self.pifEntries[entrant]['HandScore'] == curr_max_score:
                tied_winners.append(entrant)

        if len(tied_winners) == 1:
            self.pifWinner = tied_winners[0]
            logging.info('User [%s] has won PIF [%s]', self.pifWinner, self.postId)
        else:
            logging.info("{} players tied for first", len(tied_winners))
            self.pifWinner = random.choice(tied_winners)
        logging.info('User [%s] has won PIF [%s]', self.pifWinner, self.postId)

    def generate_winner_comment(self):
        return winner_template.format(self.pifWinner,
                                      poker_util.determine_hand(self.pifEntries[self.pifWinner]['UserHand']))