#!/usr/bin/python

import sys
import time
import boto.ec2

#if len(sys.argv) < 3:
#    print('Given the region and id that an AMI images is currently in, this script will copy it to other regions.')
#    exit('Usage: {0} region image_id'.format(sys.argv[0]))

#REGION = sys.argv[1]
#IMAGE_ID = sys.argv[2]
new_images = {}

def get_image_state(region, ec2Connection):
    image = ec2Connection.get_all_images(image_ids=[new_images[region]], owners=['self'])[0]
    if image.state == 'failed':
        exit('Image ({0}) could not be copied.'.format(image.id))
    if image.state == 'pending':
        return False
    if image.state == 'available':
        return True

def main(REGION, IMAGE_ID, SERVICE_NAME):
    global new_images
    regions = ('us-east-1', 'us-west-1', 'us-west-2')
    for region in regions:
        if region == REGION:
            continue

        # Connect to the region the image will be copied to
        ec2Connection = boto.ec2.connect_to_region(region)
        # Copy the image from the source region to the current region
        new_images[region] = ec2Connection.copy_image(
            source_region=REGION,
            source_image_id=IMAGE_ID,
            name=SERVICE_NAME,
            description='Copied from {0} in the {1} region.'.format(IMAGE_ID, REGION)
        ).image_id

    print('Copying new image to other regions: {0}'.format(new_images))

    # Now we watch and wait for the new images to be available
    for region in new_images:
        ec2Connection = boto.ec2.connect_to_region(region)
        while not get_image_state(region, ec2Connection):
            time.sleep(5)

    print('All new images are available.')
    return new_images


from pyspark import SparkContext
import re
import random
import numpy as np
import hashlib
import time
import sys
from datetime import datetime

'''
    Receive a document and return a set of shingles
'''
def shingling(doc, k=6):
    shingles = []
    for i in range(len(doc[1]) - k + 1):
        shingles.append(doc[1][i:i+k])

    return (doc[0],set(shingles))

'''
    Given a set `doc_shingles`, pass each member of the set through all permutation
    functions, and set the `ith` position of `vec` to the `ith` permutation
    function's output if that output is smaller than `vec[i]`.
'''
def minhash(doc):

    # initialize a minhash of length N with positive infinity values
    doc_shingles = doc[1]
    signature_vector = [float('inf') for i in range(N)]

    for val in doc_shingles:

        # ensure doc_shingles is composed of integers
        if not isinstance(val, int): val = hash(val)

        # loop over each "permutation function"
        for perm_idx, perm_vals in enumerate(perms):
            a, b = perm_vals

            # pass `val` through the `ith` permutation function
            hash_value = ((a * val + b) % LARGE_PRIME)

            # conditionally update the `ith` value of vec
            signature_vector[perm_idx] = min(signature_vector[perm_idx], hash_value)
            #if signature_vector[perm_idx] > hash_value:
                #signature_vector[perm_idx] = hash_value

    # the returned vector represents the minimum hash of the set s
    return doc[0], signature_vector

'''
    Calculate the Jaccard Similarity beetween two sets
'''
def jacc_similarity(a,b):
    a = set(a)
    b = set(b)
    return len(a.intersection(b))/len(a.union(b))

'''
    check if two lists have in common, at least, one element
'''
def common_data(list1, list2):
    result = False
    # traverse in the 1st list
    for x in list1:

        # traverse in the 2nd list
        for y in list2:

            # if one common
            if sorted(x) == sorted(y):
                result = True
                return result

    return result

'''
    Get similar pairs of docs - "candidates"
'''
def get_candidates(bands, signatures_dict):
    bands_processed = []
    pairs_candidates = []
    docs = list(bands.keys())
    for i1 in range(len(docs)):
        for i2 in range(i1+1, len(docs)):
            band1 = bands[docs[i1]]
            band2 = bands[docs[i2]]
            if common_data(band1, band2):
                sign1 = signatures_dict[docs[i1]]
                sign2 = signatures_dict[docs[i2]]
                jaccard_similarity = jacc_similarity(sign1, sign2)
                pairs_candidates.append((docs[i1],docs[i2],jaccard_similarity))

    return pairs_candidates

'''
    Bands creation
'''
def split_vector(doc, b=20, r=5):
    signature = doc[1]
    # code splitting signature in b parts
    subvecs = []
    for i in range(0, len(signature), r):
        subvecs.append(signature[i : i+r])
    return doc[0], subvecs

'''
    Given a movie, returns all other movies that are at least 80% similar in terms of their plots but no more than 98%
'''
def similar_movies(movie, similar_candidates, treshold=0.8):
    sim_movies = []
    for m in similar_candidates:
        if (movie == m[0]) and m[2]>0.8 and m[2]<0.98:
            sim_movies.append(m[1])
        if (movie == m[1]) and m[2]>0.8 and m[2]<0.98:
            sim_movies.append(m[0])

    return sim_movies

'''
    Get False Positives rate
'''
def fp_evaluation(shingles_dict, sim_candidates):
    fp = 0
    for cand in sim_candidates:
        doc1, doc2, sim = cand
        shingle1 = shingles_dict[doc1]
        shingle2 = shingles_dict[doc2]
        real_similarity = jacc_similarity(shingle1,shingle2)

        if sim > 0.8 and real_similarity < 0.8: fp+=1

    return (fp/len(sim_candidates))

'''
    Get False Negatives rate
'''
def fn_evaluation(shingles_dict, sim_candidates):
    fn = 0
    total_candidates = 0
    doc_candidates = []
    docs = list(shingles_dict.keys())
    for id1 in range(len(docs)):
        for id2 in range(id1+1, len(docs)):
            sig1 = shingles_dict[docs[id1]]
            sig2 = shingles_dict[docs[id2]]
            similarity_sig = jacc_similarity(sig1,sig2)
            total_candidates += 1
            if similarity_sig > 0.8:
                doc_candidates.append((docs[id1],docs[id2]))

    false_negatives = len(set(sim_candidates) - set(doc_candidates))
    return (fn/total_candidates)

if __name__ == "__main__":
    file = "assign1/data/small_plot_sum.txt"
    try:

        file = sys.argv[1]
        k = int(sys.argv[2])
        r = int(sys.argv[3])
        b = int(sys.argv[4])

    except:
        print("Usage: movies.py <int:k> <int:rows> <int:bands>")
        exit(1)

    sc = SparkContext(master='local', appName="Assignment1_E2")
    LARGE_PRIME = 4294967311

    begin = time.time()
    data = sc.textFile(file)
    item_baskets = data.map(lambda line: re.split('\t', line.lower()))

    #Shingling
    docs_shingles = item_baskets.map(lambda line: shingling(line, k))
    #docs_shingles = item_baskets.map(shingling)
    print(docs_shingles.count())
    print("Time elapsed to shingling: ",time.time()-begin)

    # Min Hashing
    # specify the length of each minhash vector
    N = 128
    #max_val = (2**32)-1
    max_val = 500

    # create N tuples that will serve as permutation functions
    # these permutation values are used to hash all input sets
    perms = [ (random.randint(0,max_val), random.randint(0,max_val)) for i in range(N)]

    # get the signature vectors for each doc
    begin = time.time()
    signatures = docs_shingles.map(minhash)
    print(signatures.count())
    print("Time elapsed to hashing: ",time.time()-begin)

    '''
    Find as candidates at least 99.5% of pairs with 80% similarity and less than 5% of pairs with 40%
    similarity.
    '''
    begin = time.time()
    signatures_dict = { doc:sign for doc,sign in signatures.collect() }
    bands = signatures.map(lambda line: split_vector(line, b, r))
    bands_dict = { doc:band for doc,band in bands.collect() }

    sim_candidates = get_candidates(bands_dict, signatures_dict)
    print("Time elapsed to get candidate pairs: ",time.time()-begin)
    print("Number of Candidates: ",len(sim_candidates))

    #Ex: 2.2 - Similar movies
    movie = "31186339"
    sim_movies = similar_movies(movie, sim_candidates)
    print("Movies similar to {}: {}".format(movie, sim_movies))

    #Ex: 2.3
    shingles_dict = { doc:shingle for doc,shingle in docs_shingles.collect() }

    # FP rate
    if(len(sim_candidates) != 0):
        fp_eval = fp_evaluation(shingles_dict, sim_candidates)
        print("FP eval: ",fp_eval)
    else:
        print("Number of Candidates = 0 !")

    # FN rate
    fn_eval = fn_evaluation(shingles_dict, sim_candidates)
    print("FN eval: ",fn_eval)

    # Save results
    similar_pairs_rdd = sc.parallelize(sim_candidates).sortBy(lambda line: -line[2])
    format_time = str(datetime.now().strftime("%Y-%m-%dT%H_%M_%S"))
    similar_pairs_rdd.saveAsTextFile("{0}/{1}".format("assign1/results", format_time))
    sc.stop()


from application.Models.models import User
from application import db
from application.Team.Utils import commit_changes_to_db, save_to_db

class Team:

    def get_team_account(self):
        team = User.query.filter_by(is_team=1, is_admin=1)
        if not team.count() > 0:
            team = User.query.filter_by(is_admin=1)
            if not team.count() > 0:
                return False
            team = team.first()
            team.is_team = 1
            return save_to_db(team)
        else:
            return team.first() if team.count() > 0 else False

    @commit_changes_to_db
    def update_team_account(self, form):
        team = self.get_team_account()
        if not team or form is None:
            return False

        team.fullname = form.fullname.data
        team.welcome_message = form.welcome_message.data
        return team


#    15-112: Principles of Programming and Computer Science
#    HW07 Programming: Term Project (Tetris)
#    Name      : Umaymah Imran
#    AndrewID  : uimran

#    File Created:
#    Modification History:
#    Start             End
#    2/11 11:46pm     3/11 3:14am
#    3/11 12:01pm     3/11 4:11pm
#    3/11 10:21pm     4/11 1:39am
#    4/11 9:44pm      4/11 11:32pm
#    7/11 5:13pm      7/11 8:21pm
#    8/11 10:45am     8/11 2:37pm
#    9/11 11:56pm     10/11 2:53am
#    10/11 4:07am     10/11 5:52am
#    10/11 2:43pm     10/11 6:17pm
#    11/11 3:12pm     11/11 6:21pm
#    13/11 02:41pm    13/11 04:22pm
#    14/11 06:19pm    14/11 07:56pm
#    17/11 09:48am    17/11 12:43pm
#    17/11 07:32pm    17/11 09:18pm
#    18/11 08:54pm    18/11 10:02pm
#    19/11 11:39pm    20/11 01:34am
#    20/11 05:19pm    20/11 08:16pm
#    21/11 12:04pm    21/11 01:23pm
#    21/11 04:04pm    21/11 08:57pm
#    21/11 09:26pm    22/11 02:56am
#    23/11 08:18pm    24/11 12:12am
#    24/11 03:44am    24/11 05:20am
#    25/11 08:00pm    26/11 05:50am
#    26/11 07:52pm    26/11 10:19pm
#    26/11 10:31pm    27/11 12:45am
#    27/11 10:28am    27/11 11:22am
#    27/11 03:12pm    27/11 07:35pm
#    27/11 09:11pm    27/11 11:08pm
#    28/11 12:00pm    28/11 12:45pm
# import the necessary libraries
import pygame
import random

#############################################FUNCTION DEFINITIONS#######################################################
# Taken references and help from the following links:
# https://www.youtube.com/watch?v=Ign-VmKmz9g
# https://pythonprogramming.net/
# https://github.com/DanielSlater/PyGamePlayer/blob/master/games/tetris.py
# https://github.com/yash-iiith/Tetris-Game-in-Python-without-Pygame-/blob/master/tetris.py
# https://inventwithpython.com/pygame/chapter7.html
# https://gist.github.com/silvasur/565419/d9de6a84e7da000797ac681976442073045c74a4
# https://www.pygame.org/docs/ref/event.html
# https://github.com/matachi/python-tetris/blob/master/main.py
# http://www.discoveryplayground.com/computer-programming-for-kids/rgb-colors/
# Image for main screen taken from: https://www.ubisoft.com/en-us/game/tetris-ultimate
# Sound for collision from: http://soundbible.com/1742-Anvil-Impact-1x.html
# Sound for removal of rows: http://soundbible.com/1891-Flyby.html
# Sound for main screen: https://downloads.khinsider.com/game-soundtracks/album/tetris-gameboy-rip-/tetris-gameboy-01.mp3

# Code taken from: https://pythonprogramming.net/pygame-start-menu-tutorial/
# function(text_objects) is used to centre align the text of a button
def text_objects(text, font):
    textSurface = font.render(text, True, cyan)
    return textSurface, textSurface.get_rect()

# Code modified but orginially taken from: https://pythonprogramming.net/pygame-start-menu-tutorial/
# function(button) is used to create a button on the screen. It takes the text for the button, its x and y coordinates,
# its width and height, and calls the specified action(function) when the button is clicked
def button(msg, x, y, w, h, on, off, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x + w > mouse[0] > x and y + h > mouse[1] > y:
        pygame.draw.rect(screen, off, (x, y, w, h))
        if click[0] == 1 and action != None:
            action()
    else:
        pygame.draw.rect(screen, on, (x, y, w, h))

    if msg == "Back" or (msg == "Quit" and gameover == False) or msg == "Sound":
        smallText = pygame.font.Font("freesansbold.ttf", 14)
    else:
        smallText = pygame.font.Font("freesansbold.ttf", 20)

    textSurf, textRect = text_objects(msg, smallText)
    textRect.center = ((x + (w / 2)), (y + (h / 2)))
    screen.blit(textSurf, textRect)

# Code taken from:https://stackoverflow.com/questions/28005641/how-to-add-a-background-image-into-pygame
# class Background is used to set an image as the background of a screen
class Background(pygame.sprite.Sprite):
    def __init__(self, image_file, location):
        pygame.sprite.Sprite.__init__(self)  # call Sprite initializer
        self.image = pygame.image.load(image_file)
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.top = location

# function(quitgame) exits the pygame window when clicked on 'X'
def quitgame():
    pygame.quit()
    quit()

# function(board) returns a 2D list 'board' in which each item in the list represents a row, and each element in the row
# represents a column. It takes the number of rows and columns as parameters. Each row is intialized as [0,0,0....,n],
# where n represents the number of columns. At the end, an extra row with [1,1,1,....,n] is intialized - this is to
# detect when a block touches the bottom of the board (by using the function collision_occured)
def new_board(rows, cols):
    board = []
    for i in range(rows):
        row = []
        for j in range(cols):
            row.append(0)
        board.append(row)
    extra_row = []
    for k in range(cols):
        extra_row.append(1)
    board.append(extra_row)
    return board

# function(collision_occured) takes the board, the shape definition, the sxth col and the syth row as inputs (sx and sy
# are the x and y positions of the shape). Using this, it determines when the shape has collided with either the edges,
# with the button of the board or with another shape
def collision_occured(board, shape, shape_x, shape_y):
    i = 0  # i and j are  variables for the while loop in order to go through the indexes of the item (shape in
    j = 0  # case of i and row in case of j) specified

    # The following code segment goes through each row of a shape and accesses each column of the shape and compares it to the
    # value in the board. If the value at the board is 0, collision has not occured. If it's any value between 1-7, and the shape
    # touches it, then collision has occured and the shape stops
    while i < len(shape):
        row = shape[i]
        while j < len(row):
            col = row[j]
            try:
                if col and board[i + shape_y][j + shape_x]:
                    return True

            except IndexError:
                return True
            j += 1 #increment j by 1
        i += 1 #increment i by 1
        j = 0 #initialize j to 0 as next row will start
    return False

def collision_occured_bottom(board, shape, shape_x, shape_y):
    i = 0  # i and j are  variables for the while loop in order to go through the indexes of the item (shape in
    j = 0  # case of i and row in case of j) specified

    # The following code segment goes through each row of a shape and accesses each column of the shape and compares it to the
    # value in the board. If the value at the board is 0, collision has not occured. If it's any value between 1-7, and the shape
    # touches it, then collision has occured and the shape stops
    while i < len(shape):
        row = shape[i]
        while j < len(row):
            col = row[j]
            try:
                if col and board[i + shape_y+1][j + shape_x]:
                    return True

            except IndexError:
                return True
            j += 1 #increment j by 1
        i += 1 #increment i by 1
        j = 0 #initialize j to 0 as next row will start
    return False

# function(place_shape) adds the the digits 1-7 to the board when the shape is placed in it and returns the updated version of the
# board. It takes the current board, the shape that is moving down, the x (column) and y (row) location of the shape and mute (so
# that the functionality for the 'Sound' button can be controlled)
def place_shape(board, shape, shape_x, shape_y , mute):
    i = 0  # i and j are  variables for the while loop in order to go through the indexes of the item (shape in
    j = 0  # case of i and row in case of j) specified

    # The following code segment goes through each row of a shape and accesses each column of the shape and adds it to the specific
    # location of the board where the shape settles. If mute is False, then the sound to identify the collision/settlement of the
    # shape will play
    while i < len(shape):
        row = shape[i]
        while j < len(row):
            if shape[i][j]:
                board[i+shape_y-1][shape_x+j] = shape[i][j]
                if not mute:
                    pygame.mixer.Channel(0).play(pygame.mixer.Sound('collision.wav')) # sound plays in the same channel as main sound
            j += 1 #increment j by 1
        i += 1 #increment i by 1
        j = 0 #initialize j to 0 as next row will start
    return board

# function (remove_row) removes complete, non-zero horizontal rows from the board. This function returns the number of lines removed,
# the updated version of the board (the rows above the removed row(s) move down and row(s) with 0s are initialized at the top in their
# place) and the updated myscore (as score increases with removal of lines).
def remove_row(board, myscore, lines, mute):
    rows_removed = 0 # keeps track of the zero rows removed, this is required for updating myscore
    zero_rows = [] #zero_rows are the newly initialized rows that will be appended to the board when row(s) is/are removed
    update = [] #update holds the final return value of the function
    score_inc = 40 # score_inc is the variable that stores the value with which rows_removed is to be multipled (for updating myscore)
    # By starting from the top most row, the following loop iterates through each row and loops for non-zero rows. Since the bottom
    # most row of the board is [1,1,1,....1], the loop will disregard that row.
    for i in range(len(board) - 2, -1, -1):
        if 0 not in board[i]:
            if not mute:
                pygame.mixer.Channel(1).play(pygame.mixer.Sound('remove_row.wav')) #when the row is removed, a 'swish' sound is played
            del board[i]
            rows_removed += 1

    myscore += rows_removed * score_inc #myscore updates
    lines += rows_removed #updates number of lines that have been removed so far

    #This loop adds as many zero rows as non-zero rows were removed
    for j in range(0, rows_removed):
        zero_rows += [[0 for i in range(0, cols)]]

    board = zero_rows + board #adds the zero rows to top most of current board

    #stores the updated values for the board, myscore and line in the 'updated' list
    update.append(board)
    update.append(myscore)
    update.append(lines)
    return update

# function (shape_rotation) will change the orientation of the shape every time the 'up' arrow key is pressed. It takes the board, the
# description of the current shape and its x (column) and y (row) locations as input. If, by pressing the 'up' key a collision is occuring,
# the shape will not rotate and will remain as it is. Otherwise, the function returns the new shape description, causing the shape to
# rotate at 90 degrees with each key press of 'up'.
def shape_rotation(board,current_shape_desc,shape_x,shape_y):
    new_shape = []

    # The following code segment changes the row and column wise description of the shape. In other words, it tranposes the 2D matrix (which
    # is the shape of the object)
    for y in range(len(current_shape_desc[0]) - 1, -1, -1):
        l = []
        for x in range(len(current_shape_desc)):
            l.append(current_shape_desc[x][y])
        new_shape.append(l)

    # The new shape will return if there is no collision on all four sides of the shape
    if not collision_occured(board, new_shape, shape_x, shape_y):
        return new_shape

    # Otherwise, the current shape description will be returned as it is
    return current_shape_desc

# function(new_shape) initializes the properties of a shape. It generates a random shape from the list All_shapes.
# It then returns the details of the shape, which are stored in a dictionary, that is, the shape's color and description
def new_shape(All_shapes):
    properties_current_shape = [random.choice(All_shapes)] #shapes are randomly generated
    item = properties_current_shape[0]
    return item

# function (initialize_game) is used to restart the game if the Back button on the Game Play screen is pressed and then if the player
# returns to the game OR to restart the game at the time of game over
def initialize_game():
    # The following variables are globalized to change and store the change in their state, by setting all variables to their initial values
    global board
    global current_shape_desc
    global current_shape_col
    global next_predicted_shape
    global shape_x
    global shape_y
    global mute
    global pause
    global fileopen
    global rules
    global start
    global started
    global back
    global home
    global collide
    global gameover
    global hscore
    global myscore
    global lines
    global p_count

    p_count = 25
    mute = False
    pause = False
    fileopen = True
    rules = False
    start = True
    started = False
    back = False
    home = False
    running = True
    collide = False
    gameover = False
    hscore = False
    myscore = 0
    lines = 0
    initial_shape = new_shape(All_shapes)
    current_shape_desc = initial_shape["shape"]
    current_shape_col = initial_shape["color"]
    next_predicted_shape = new_shape(All_shapes)
    shape_x = 4
    shape_y = 0
    board = new_board(rows, cols)

    file = 'maintheme.mp3'  # the main sound being played in the background
    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load(file)
    pygame.mixer.music.play(-1)
    pygame.mixer.music.set_volume(0.5)

#function(check_top) checks if there is any non-zero number in the first row of the
#board. If there is, it will return False, otherwise it'll return True
def check_top (board):
    if not 0 in board[0]:
        return False
    return True

# Definitions of all colors used
black = (0, 0, 0)
white = (255, 255, 255)
darkblue = (72, 61, 139)
cyan = (224, 255, 255)
blue = (25, 25, 112)
staleblue = (72, 61, 139)
med_blue = (25, 25, 112)
red = (178, 34, 34)
yellow = (230, 200, 48)
green = (34, 139, 34)
purple = (130, 50, 204)
orange = (210, 105, 30)
pink = (176, 48, 96)

# The shapes and their colors that I'm using. The arrangement of each shape can be imagined as this one for the simple
# square (where * represents a number):
# [[*,*]
#  [*,*]]
All_shapes = [{"shape": [[1, 1], [1, 1]], "color": yellow}, {"shape": [[0, 5, 0], [5, 5, 5]], "color": med_blue},
              {"shape": [[0, 2, 2], [2, 2, 0]], "color": green}, {"shape": [[7, 7, 0], [0, 7, 7]], "color": red},
              {"shape": [[3, 0, 0], [3, 3, 3]], "color": purple}, {"shape": [[0, 0, 6], [6, 6, 6]], "color": pink},
              {"shape": [[4, 4, 4, 4]], "color": orange}]

# The dictionary color_shape_mapping assigns colors to each digit value (which signifies a specific shape)
color_shape_mapping = {"1": yellow, "5": med_blue, "2": green, "7": red, "3": purple, "6": pink, "4": orange}

# INITIALIZING THE FOLLOWING VARIABLES

mute = False # if 'Sound' is pressed then mute is True and the sounds discontinue, otherwise it is set to False by default and sound plays

pause = False # pause determines whether or not the game is in pause state

fileopen = True # fileopen is the file for storing the high score. It is open by default so that it can be updated when required (run-time)

rules = False # rules is for determining the state of the RULES screen. If it's false, then the screen for Rules is not open (vice-versa)

start = False # start is for determining the state of the START screen. If it's false, then the screen for Start is not open (vice-versa)

started = False # started is for indicating that the game has started.

back = False # back is for determining the states of the back button and for determining the required screens

home = True # home is for determining the state of the HOME/MAIN screen. If it's false, then the screen for Home is not open (vice-versa)

running = True # running is for the game loop

collide = False # collide is False by default, it becomes True if the shapes reach the top-most part of the board

gameover = False # if the shapes reach the top-most part of the board, the game is over

hscore = False # hscore determines the state of the high score. If it's True, the High Score of the game will update

play_music = True # play_music controls the background music

myscore = 0 # intially, the score is set to 0. It only increases if you press the down key or if complete non-zero rows are removed

lines = 0 # lines stores the number of non-zero rows removed

p_count = 25 # p_count is the pixel size of the box for drawing the shapes

tempo = 0 # tempo is used allow the shape to shift a bit after it hits a surface

# The first shape and the shape after that are determined
initial_shape = new_shape(All_shapes)
current_shape_desc = initial_shape["shape"]
current_shape_col = initial_shape["color"]
next_predicted_shape = new_shape(All_shapes)

# shape_x: xth column from where the shape drops
# shape_y: yth row from where the shape drops
shape_x = 4
shape_y = 0

# the board has a total of 20 rows and 10 columns
rows = 20
cols = 10

board = new_board(rows, cols)  # initialize the board for the gameplay

###################################################MAIN CODE############################################################
pygame.init()  # initializes all imported pygame modules
clock = pygame.time.Clock()  # clock is used to track and control the framerate of the game

# BackGround_MainScreen sets the background image for the main screen
BackGround_MainScreen = Background('TetrisMain.jpg', [0, 0])

# window_size is the height and width for the screen
window_size = (400, 500)

# screen initializes screen ans its size
screen = pygame.display.set_mode(window_size)

# sets the title for the window
pygame.display.set_caption('Tetris')

# applies changes to screen
screen.blit(BackGround_MainScreen.image, BackGround_MainScreen.rect)

# The following is an event type to appear on the event queue after every 1000 milliseconds
pygame.time.set_timer(pygame.USEREVENT + 1, 1000)

if play_music:
    file = 'maintheme.mp3' # the main sound being played in the background
    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load(file)
    pygame.mixer.music.play(-1)
    pygame.mixer.music.set_volume(0.5)

# While the game is running, the following events can possibly occur. Based on what event is
# true, carry out the neccesary steps
while running:
    for event in pygame.event.get():

        # pygame.QUIT: allows to quit the window when clicked on 'X' in the top right corner
        if event.type == pygame.QUIT:
            running = False

        # pygame.MOUSEBUTTONDOWN: detects a click on the screen
        elif event.type == pygame.MOUSEBUTTONDOWN:

            # get the coordinates on the x and y axis when you click on the screen
            x, y = pygame.mouse.get_pos()

            # the following conditions specify the range of click for x and y coordinates in order to
            # activate a particular button

            if (x > 130 and x < 310 and y > 280 and y < 330) and (start == False and rules == False):
                # after clicking on the button "START", the conditional statement for 'start' is made
                # true and therefore, executed
                click = pygame.mouse.get_pressed()
                initialize_game()
                if click[0] == 1:
                    start = True
                    rules = False
                    back = True
                    home = False

            elif (x > 130 and x < 310 and y > 340 and y < 390) and (start == False and rules == False):
                # after clicking on the button "RULES", 'rules' is made true and the conditional statement for
                # it are executed
                click = pygame.mouse.get_pressed()

                if click[0] == 1:
                    rules = True
                    back = True
                    home = False

            elif (x > 130 and x < 310 and y > 400 and y < 450) and (start == False and rules == False):
                # after clicking on the button "QUIT", the function(quitgame) is called
                click = pygame.mouse.get_pressed()

            elif (x > 0 and x < 80 and y > 0 and y < 30) and back == True:
                # when you click on the button "RULES", a screen with an image of the rules for the game
                # appear with a "BACK" button in the top left corner. By clicking on this back button,
                # the user is lead to the home screen again
                rules = False
                back = False
                home = True

            elif (x > 170 and x < 270 and y > 315 and y < 350) and gameover == True:
                # after clicking on the button "RESTART", in gameover, the states of the following variables change:
                start = True
                gameover = False
                rules = False
                home = False

            elif (x > 170 and x < 270 and y > 360 and y < 395) and gameover == True:
                # after clicking on the button "RULES", in gameover, the states of the following variables change:
                gameover = False
                rules = True
                start = False
                home = False

            elif (x > 300 and x < 360 and y > 390 and y < 415) and start == True:
                # after clicking on the button "Sound", in game play, the sound is stopped (or played) - depending on
                # its previous state:
                mute = not mute
                if mute:
                    pygame.mixer.music.pause()
                else:
                    pygame.mixer.music.unpause()

            elif (x > 300 and x < 360 and y > 420 and y < 445) and (start == True and back == True):
                # after clicking on the button "Back", in game play, the states of the following variables change and
                # the player is directed to the main screen:
                click = pygame.mouse.get_pressed()
                if click[0] == 1:
                    start = False
                    rules = False
                    back = False
                    home = True

            elif (x > 300 and x < 360 and y > 450 and y < 475) and start == True:
                # after clicking on the button "Quit", in game play, the program exits:
                click = pygame.mouse.get_pressed()
                quitgame()

        # pygame.KEYDOWN: detects if a key is pressed
        elif event.type == pygame.KEYDOWN and start == True:

            # the following show the initialization of the variables 'down' (holding the value when the
            # down arrow key is pressed), 'right' (holding the value when the right arrow key is pressed),
            # 'left' (holding the value when the left arrow key is pressed)
            down = pygame.key.get_pressed()[pygame.K_DOWN]
            left = pygame.key.get_pressed()[pygame.K_LEFT]
            right = pygame.key.get_pressed()[pygame.K_RIGHT]
            up = pygame.key.get_pressed()[pygame.K_UP]
            paused = pygame.key.get_pressed()[pygame.K_p]
            # restricts the movement towards the left if there is already a shape lying on that side. otherwise,
            # it decreases the value of the x-axis by 1 block
            if left and not collision_occured(board, current_shape_desc, shape_x - 1, shape_y):
                if shape_x > 0:
                    shape_x -= 1

            # restricts the movement towards the right if there is already a shape lying on that side. otherwise,
            # it increases the value of the x-axis by 1 block
            elif right and not collision_occured(board, current_shape_desc, shape_x + 1, shape_y):
                if shape_x < 9:
                    shape_x += 1

            # restricts the rotation of the shape if there is already a shape/boundary on a side. otherwise,
            # returns the rotated shape
            elif up and not collision_occured(board, current_shape_desc, shape_x, shape_y):
                current_shape_desc = shape_rotation(board, current_shape_desc, shape_x, shape_y)

            # if the down key is pressed, the value of the y-axis increments by 1 block
            elif down and not collision_occured(board, current_shape_desc, shape_x, shape_y + 1):
                    shape_y += 1
                    myscore += 1
                    if collision_occured_bottom(board, current_shape_desc, shape_x, shape_y):
                        tempo = 100

            # if the 'P' key is pressed, the opposite of the present state of the game pause is returned
            elif paused:
                pause = not pause

        # pygame.USEREVENT +1: allows the block to automatically move downwards after one click, since it keeps
        # decrementing the value of the y-axis. It also updates the board by returning the new board if the rows
        # are removed and the corresponding change in myscore and lines removed.
        elif event.type == pygame.USEREVENT+1:

            if start:
                shape_y += 1
                update = remove_row(board, myscore, lines, mute)
                board = update[0]
                myscore = update[1]
                lines = update[2]

    # checking if the game is paused, if yes, then game stays within this loop until unpaused
    while pause:

        # displays the message that the game is paused
        largeText = pygame.font.Font("freesansbold.ttf", 60)
        msg = "Paused"
        textSurf, textRect = text_objects(msg, largeText)
        textRect.center = (190, 235)
        screen.blit(textSurf, textRect)

        for event in pygame.event.get():

            # pygame.QUIT: allows to quit the window when clicked on 'X' in the top right corner
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            # pygame.KEYDOWN: detects if a key is pressed
            elif event.type == pygame.KEYDOWN and start == True:
                paused = pygame.key.get_pressed()[pygame.K_p]
                # unpause the game if its paused, and so exits this loop
                if paused:
                    pause = not pause

            # pygame.MOUSEBUTTONDOWN: detects a click on the screen
            elif event.type == pygame.MOUSEBUTTONDOWN:

                # get the coordinates on the x and y axis when you click on the screen
                x, y = pygame.mouse.get_pos()
                if (x > 300 and x < 360 and y > 420 and y < 445) and (start == True):
                    # after clicking on the button "Back", in game play, the states of the following variables change and
                    # the player is directed to the main screen:
                    click = pygame.mouse.get_pressed()
                    if click[0] == 1:
                        start = False
                        rules = False
                        back = False
                        home = True
                        pause = False

                if (x > 300 and x < 360 and y > 390 and y < 415) and (start == True):
                    # after clicking on the button "Sound", in game play, the sound is stopped (or played) - depending on
                    # its previous state:
                    click = pygame.mouse.get_pressed()
                    if click[0] == 1:
                        mute = not mute
                        if mute:
                            pygame.mixer.music.pause()
                        else:
                            pygame.mixer.music.unpause()

        button("Sound", 300, 390, 60, 25, blue, staleblue)
        button("Back", 300, 420, 60, 25, blue, staleblue)
        button("Quit", 300, 450, 60, 25, blue, staleblue, quitgame)

        # update screen
        pygame.display.update()
        clock.tick(20)

    # if any of the HOME, RULES or START screens is activated (or True), the subsequent if-condition will be executed

    # 'home' is the bool variable for the main screen. If it is true, the following code is executed. The home screen
    # first appears when the game is started
    if home:

        # shows the display including the background and necessary buttons
        screen.blit(BackGround_MainScreen.image, [0, 0])
        button("START", 110, 280, 180, 50, blue, staleblue)
        button("RULES", 110, 340, 180, 50, blue, staleblue)
        button("QUIT", 110, 400, 180, 50, blue, staleblue, quitgame)

    # 'rules' is the bool variable for the rules screen. If it is true, the following code is executed. The rule screen
    # appears when the button "RULES" is clicked
    elif rules:
        rule = Background("rules.png", [0, 0])
        screen.blit(rule.image, [0, 0])
        button("BACK", 0, 0, 80, 30, blue, staleblue)

    # 'start' is the bool variable for the game play screen. If it is true, the following code is executed. The start
    # (or game play) screen appears when the button "START" is clicked
    elif start:
        # window initializes the total size for the game play window. In this, we will be using the first 250 pixels
        # (from left to right) for the tetris game play and the remaining 150 pixels to draw the side panel (which includes
        # the score, next piece, lines)

        window = (400, 500)

        # updates the screen
        screen = pygame.display.set_mode(window)
        background = pygame.Surface(window)
        screen.blit(background, (0, 0))

        # font1 & font2 are font types and their sizes to use for headings on the side panel
        font1 = pygame.font.Font("freesansbold.ttf", 20)
        font2 = pygame.font.Font("freesansbold.ttf", 16)

        # draw a rectangular panel on the right side
        pygame.draw.rect(screen, darkblue, (250, 0, 150, 500))

        # add the heading 'Next:' to the rectangular panel with the upcoming shape
        text = font1.render("Next:", 1, white)
        screen.blit(text, (260, 100))

        # Draw the black box in which the next piece should appear
        pygame.draw.rect(screen, black, (265, 140, 120, 95))

        # add the heading 'Lines:' to the rectangular panel with the updated removed lines
        text = font2.render("Lines: " + str(lines), 1, white)
        screen.blit(text, (260, 280))

        # add the heading 'Score:' to the rectangular panel with the updated current score
        text = font2.render("Score: " + str(myscore), 1, white)
        screen.blit(text, (260, 310))

        f = open("high_score.txt", 'r') # opens the file to read the current high score value
        line = f.read()
        highscore = line.strip()
        highscore = int(highscore)

        if myscore > highscore: # if the highscore value is less than the current myscore, then the current
            highscore = myscore # score becomes the high score

        # add the heading 'High Score:' to the rectangular panel with the updated high score
        text = font2.render("High Score: " + str(highscore), 1, white)
        screen.blit(text, (260, 340))

        # draw a white line b/w the gameplay screen and the rectangular panel
        pygame.draw.line(screen, white, (250, 0), (250, 500))

        # initialize buttons on the right panel to activate sound, pause the game, or to quit the game
        button("Sound", 300, 390, 60, 25, blue, staleblue)
        button("Back", 300, 420, 60, 25, blue, staleblue)
        button("Quit", 300, 450, 60, 25, blue, staleblue)

        # the following segment draws the block as it moves downwards (from top to bottom)
        y, x = 0, 0
        for row in current_shape_desc:
            for col in row:
                if col:
                    # to draw the shape
                    pygame.draw.rect(screen, current_shape_col, pygame.Rect((shape_x + x) * p_count, (shape_y + y) * p_count, 25, 25), 0)

                    # to draw the outline of the shape
                    pygame.draw.rect(screen, black, pygame.Rect((shape_x + x) * p_count, (shape_y + y) * p_count, 25, 25), 1)
                x += 1
            y += 1
            x = 0

        # draw the next predicted shape and align the next shape in the black rectangular box (below Next) according
        # to the shape dimensions
        # In this code segment, the digits being added to x and y represent the column and row from where the shape
        # should be started for drawing
        y, x = 0, 0
        for row in next_predicted_shape["shape"]:
            for col in row:
                if col:
                    if 1 in row: # if the shape is a square

                        # to draw the shape
                        pygame.draw.rect(screen, next_predicted_shape["color"],
                                         pygame.Rect((12 + x) * p_count, (6.5 + y) * p_count, 25, 25), 0)

                        # to draw the outline of the shape
                        pygame.draw.rect(screen, black,
                                         pygame.Rect((12 + x) * p_count, (6.5 + y) * p_count, 25, 25), 1)

                    elif 4 in row: #if the shape is a straight line

                        # to draw the shape
                        pygame.draw.rect(screen, next_predicted_shape["color"],
                                         pygame.Rect((11 + x) * p_count, (7 + y) * p_count, 25, 25), 0)
                        # to draw the outline of the shape
                        pygame.draw.rect(screen, black,
                                         pygame.Rect((11 + x) * p_count, (7 + y) * p_count, 25, 25), 1)

                    else: #any other shape

                        # to draw the shape
                        pygame.draw.rect(screen, next_predicted_shape["color"],
                                         pygame.Rect((11.5 + x) * p_count, (6.5 + y) * p_count, 25, 25), 0)

                        # to draw the outline of the shape
                        pygame.draw.rect(screen, black,
                                         pygame.Rect((11.5 + x) * p_count, (6.5 + y) * p_count, 25, 25), 1)
                x += 1
            y += 1
            x = 0

        # if collision occurs at the maximum top of the screen, it indicates the end of the game
        if collision_occured(board, current_shape_desc, 4, 0) :
            if check_top (board):
                collide = True
                pygame.time.delay(2000)
                start = False
                gameover = True
                file = 'gameover.wav'  # the sound in the background being played
                pygame.mixer.music.stop()
                pygame.mixer.music.load(file)
                pygame.mixer.music.play()
                pygame.mixer.music.set_volume(0.5)

        # otherwise, the game continues
        if collide == False:
            if collision_occured_bottom(board, current_shape_desc, shape_x, shape_y):
                if tempo<10:
                    tempo = tempo+1
                else:
                    tempo=0
                    place_shape(board, current_shape_desc, shape_x, shape_y+1, mute)
                    shape_x = 4
                    shape_y = 0
                    next_shape = next_predicted_shape
                    next_predicted_shape = new_shape(All_shapes)
                    current_shape_col = next_shape["color"]
                    current_shape_desc = next_shape["shape"]

            # the following segment draws the block at the bottom of the board when it is settled
            y, x = 0, 0
            for row in board:
                for col in row:
                    if col:

                        color = color_shape_mapping[str(col)]

                        # to draw the shape
                        pygame.draw.rect(screen, color, pygame.Rect(x * p_count, y * p_count, 25, 25), 0)

                        # to draw the outline of the shape
                        pygame.draw.rect(screen, black, pygame.Rect(x * p_count, y * p_count, 25, 25), 1)
                    x += 1
                y += 1
                x = 0

    # 'gameover' is the bool variable for the gameover screen. If it is true, the following code is executed. The gameover screen
    # first appears when the collision occurs at the top most portion of the board
    elif gameover:
        # sets screen to black
        screen.fill(black)

        # initialize fonts
        font3 = pygame.font.Font("freesansbold.ttf", 40)
        font4 = pygame.font.Font("freesansbold.ttf", 20)

        # open the file that scores the high score for read and write
        hisc = open("high_score.txt", 'r+')

        #first read the high score
        line = hisc.read()
        highscore = line.strip()
        highscore = int(highscore)

        #if the highscore is less than the current score, update the highscore value in the file
        #by overwriting the current highscore value
        if fileopen:
            if myscore > highscore:
                hisc.seek(0)
                hisc.truncate()
                fileopen = False
                myscore = str(myscore)
                hisc.write(myscore)
                highscore = int(myscore)
                hscore = True
            hisc.close()

        # if there was a new high score, then show the message of New High Score to user with the current score
        if hscore:
            text = font4.render("New High Score!", 1, white)
            screen.blit(text, (120, 230))
            text = font4.render("Score: " + str(myscore), 1, white)
            screen.blit(text, (150, 260))

        #otherwise, just show the user their ending score
        else:
            text = font4.render("Score: " + str(myscore), 1, white)
            screen.blit(text, (150, 260))

        # add the heading to the Gameover screen
        text = font3.render("Game Over", 1, white)
        screen.blit(text, (80, 160))

        # add buttons to the gameover screen:

        # restart the game:
        button("RESTART", 110, 300, 180, 50, blue, staleblue)

        # go to rules:
        button("RULES", 110, 360, 180, 50, blue, staleblue)

        # quit the game:
        button("QUIT", 110, 420, 180, 50, blue, staleblue, quitgame)

    # update the screen
    clock.tick(30)
    pygame.display.update()

pygame.quit()


from module import HandDetector
import cv2
import math
import time
import pygame
import serial

Arduino = serial.Serial(port='COM3  ', baudrate=9600)

class Timer:
    def _init_(self, time_between=5):
        self.start_time = time.time()
        self.time_between = time_between

    def can_send(self):
        if time.time() > (self.start_time + self.time_between):
            self.start_time = time.time()
            return True
        return False

def cvimage_to_pygame(image):
    return pygame.image.frombuffer(image.tostring(), image.shape[1::-1], "RGB")

cap = cv2.VideoCapture(0)
detector = HandDetector(maxHands=2, minTrackCon=0.6, detectionCon=0.6)

width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

SCREEN = pygame.display.set_mode((int(width), int(height)))

wheel = pygame.image.load('wheel.png')

REVERSE = False
orientation = "Forward"

timer  = Timer(time_between=5)

Running = True
while Running:
    flag = False
    success, img = cap.read()
    hands = detector.findHands(img, draw=False)

    for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Running = False

    if len(hands) == 1:
        hand = hands[0]
        fingers = detector.fingersUp(hand)
        print(fingers)
        if fingers == [1, 1, 1, 1, 1]:
            if timer.can_send():
                REVERSE = not REVERSE

    elif len(hands) == 2:
        flag = True
        hand1 = hands[0]
        hand2 = hands[1]
        centerPoint1 = hand1['center']
        centerPoint2 = hand2['center']

        x1, y1 = centerPoint1
        x2, y2 = centerPoint2

        stearing_center = (int((x1 + x2)/2), int((y2 + y1)/2))
        distance = int(math.hypot(x2 - x1, y2 - y1)/2)

        if REVERSE == True:
            orientation = "REVERSE"
        else:
            orientation = "FORWARD"
        command = orientation
        try:
            slope = (y2 - y1) / (x2 - x1)
            if slope > 1:

                # print("Go LEFT")
                command += " GO LEFT\n"
                # Arduino.write(b"Left\n")

            elif slope < -1:
                # print("GO RIGHT")
                command += " GO RIGHT\n"
                # Arduino.write(b"Right\n")
            else:
                # print("Forward")
                command += " GO STRAIGHT\n"
                # Arduino.write(b"Forward\n")
        except:
            pass
    else:
        # print("Stop")
        command = "STOP\n"
        # Arduino.write(b"Stop\n")

    Arduino.write(bytes(command, 'utf-8'))
    print(command.strip())

    img = cv2.flip(img, 1)
    cv2.putText(img=img, text=str(orientation), org=(10, 20), fontFace=cv2.FONT_HERSHEY_TRIPLEX, fontScale=1, color=(0, 255, 0),thickness=3)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cvimage_to_pygame(img)
    SCREEN.blit(img, (0, 0))
    if flag:
        wheel1 =  pygame.transform.scale(wheel, (distance*2, distance*2))
        x, y = stearing_center
        x -= distance
        y -= distance
        x = width - x - (distance*2)
        wheel1 = pygame.transform.rotate(wheel1, math.degrees(math.atan(slope)))
        SCREEN.blit(wheel1, (x, y))
    pygame.display.update()

pygame.quit()
cap.release()


from .helpers import build_dataset
import nussl
import gin
import torch
import os
import logging
from torch import multiprocessing
from ignite.contrib.handlers import ProgressBar
from .handlers import add_train_handlers
from datetime import datetime

@gin.configurable
def build_model_optimizer_scheduler(model_config, optimizer_class,
                                    scheduler_class=None, device='cuda',
                                    verbose=False):
    model = nussl.ml.SeparationModel(
        model_config, verbose=verbose).to(device)
    # the rest of optimizer params comes from gin
    optimizer = optimizer_class(model.parameters())
    scheduler = scheduler_class(optimizer)
    return model, optimizer, scheduler

@gin.configurable
def train(batch_size, loss_dictionary, num_data_workers, seed,
          output_folder, num_epochs, val_loss_dictionary=None,
          val_batch_size=None, combination_approach='combine_by_sum',
          device='cuda', epoch_length=None, resume=False,
          save_by_epoch=None):
    nussl.utils.seed(seed)

    with gin.config_scope('train'):
        train_dataset = build_dataset()
    with gin.config_scope('val'):
        val_dataset = build_dataset()

    model, optimizer, scheduler = build_model_optimizer_scheduler(device=device)
    logging.info(model)

    if not torch.cuda.is_available():
        device = 'cpu'

    os.makedirs(output_folder, exist_ok=True)
    logging.info(f'Saving to {output_folder}')

    num_data_workers = min(num_data_workers, multiprocessing.cpu_count())
    val_batch_size = batch_size if val_batch_size is None else val_batch_size

    # Set up dataloader
    train_dataloader = torch.utils.data.DataLoader(
        train_dataset, num_workers=num_data_workers,
        batch_size=batch_size, shuffle=True)
    val_dataloader = torch.utils.data.DataLoader(
        val_dataset, num_workers=num_data_workers,
        batch_size=val_batch_size, shuffle=True)

    val_loss_dictionary = (
        loss_dictionary
        if val_loss_dictionary is None
        else val_loss_dictionary
    )

    # Build the closures for each loop
    train_closure = nussl.ml.train.closures.TrainClosure(
        loss_dictionary, optimizer, model,
        combination_approach=combination_approach)
    val_closure = nussl.ml.train.closures.ValidationClosure(
        val_loss_dictionary, model,
        combination_approach=combination_approach)

    # Build the engine and add handlers
    train_engine, val_engine = nussl.ml.train.create_train_and_validation_engines(
        train_closure, val_closure, device=device)
    nussl.ml.train.add_validate_and_checkpoint(
        output_folder, model, optimizer, train_dataset, train_engine,
        val_data=val_dataloader, validator=val_engine, save_by_epoch=save_by_epoch)
    nussl.ml.train.add_stdout_handler(train_engine, val_engine)

    now = datetime.now()
    tensorboard_folder = os.path.join(
        output_folder, 'logs', now.strftime("%Y.%m.%d-%H.%M.%S"))

    logging.info(f'Logging to {tensorboard_folder}')

    nussl.ml.train.add_tensorboard_handler(
        tensorboard_folder, train_engine)
    nussl.ml.train.add_progress_bar_handler(
        train_engine, val_engine)

    # handlers and their config come from gin config
    add_train_handlers(
        train_engine, model, scheduler, optimizer,
        train_closure, device
    )

    # print what we are using
    logging.info(gin.operative_config_str())

    if resume:
        model_path = os.path.join(
            output_folder, 'checkpoints', 'latest.model.pth')
        logging.info(f"Model resuming from {model_path}")
        model_state = torch.load(
            model_path, map_location=lambda storage, loc: storage)
        model.load_state_dict(model_state['state_dict'])

        optimizer_path = os.path.join(
            output_folder, 'checkpoints', 'latest.optimizer.pth')
        logging.info(f"Optimizer resuming from {optimizer_path}")
        optimizer_state = torch.load(
            optimizer_path, map_location=lambda storage, loc: storage)
        optimizer.load_state_dict(optimizer_state)

        logging.info(f"Trainer updating to {model_state['metadata']['trainer.state_dict']}")
        train_engine.load_state_dict(model_state['metadata']['trainer.state_dict'])
        train_engine.state.epoch_history = model_state['metadata']['trainer.state.epoch_history']

    # run the engine
    train_engine.run(
        train_dataloader, max_epochs=num_epochs,
        epoch_length=epoch_length)

@gin.configurable
def cache(num_cache_workers, batch_size, scopes=['train', 'val']):
    num_cache_workers = min(
        num_cache_workers, multiprocessing.cpu_count())
    for scope in scopes:
        with gin.config_scope(scope):
            dataset = build_dataset()
            dataset.cache_populated = False
            cache_dataloader = torch.utils.data.DataLoader(
                dataset, num_workers=num_cache_workers,
                batch_size=batch_size)
            nussl.ml.train.cache_dataset(cache_dataloader)

    alert = "Make sure to change cache_populated = True in your gin config!"
    border = ''.join(['=' for _ in alert])

    logging.info(
        f'\n\n{border}\n'
        f'{alert}\n'
        f'{border}\n'
    )


from bs4 import BeautifulSoup
import requests
from models import Listing
import pandas as pd
from serializer import Serializer
import re
import os

class PreviewScraper:

    def __init__(self, search_query, url="", soup=None):
        self.search_query = search_query
        self.url = url
        self.soup = soup
        self.get_url()
        self.generate_soup()

    def get_url(self):
        self.url = self.search_query.url
        return self.url

    def generate_soup(self):
        self.get_url()
        r = requests.get(self.url)
        soup = BeautifulSoup(r.text, 'html.parser')
        self.soup = soup

    def get_listings_urls(self, first_page_url):
        urls = []
        r = requests.get(first_page_url)
        soup = BeautifulSoup(r.text, 'html.parser')
        main = soup.find("div", {"id": "listing-index"})
        listings_thumbnails = main.find_all("div", {"class": "advert"})
        for l in listings_thumbnails:
            ad_img_link = l.find("a", {"class": "advert__image-link"})
            urls.append(ad_img_link["href"])

        return urls

    def check_last_page(self, url):
        r = requests.get(url)
        soup = BeautifulSoup(r.text, 'html.parser')
        pagination = soup.find("ul", {"class": "pagination"})
        if pagination.find("li", {"class": ["last", "paging-next"]}):
            return False
        else:
            return True

    def get_all_pages_urls(self):
        pages_urls = []

        # LIMITED for testing
        while len(pages_urls) < 50:
            url = self.search_query.url
            pages_urls.append(url)
            print("~~> added page: ", self.search_query.page)
            self.search_query.next_page()

            try:
                if self.check_last_page(url):
                    break
            except:
                continue

        return pages_urls

class ListingScraper:

    def __init__(self, url, soup=None):
        self.url = url
        self.soup = soup
        self.generate_soup()

    def generate_soup(self):
        r = requests.get(self.url)
        soup = BeautifulSoup(r.text, 'html.parser')
        self.soup = soup

    def scrape_tables(self):
        rows = []
        tables = self.soup.find_all("table", class_=["profile-table", "profile__text-data"])
        try:
            for table in tables:
                for sibling in table.tr.next_siblings:
                    row = []
                    print(sibling)
                    for td in sibling:
                        print("td: ", td)
                        try:
                            if td != ' ':
                                row.append(td.text.replace('\n', ''))
                        except:
                            # print("error adding value to row")
                            continue
                    print(row)
                    if len(row) > 0:
                        print(len(row))
                        rows.append(row)
        except:
            print("Error adding rows to the table")
            pass
        return rows

    def scrape_details(self):
      find = self.soup.find
      rows = []
      apt_features = find("p", class_="profile-info-panels__text")
      if apt_features:
          rows.append([apt_features.b.text.replace('\n', ''),
                       apt_features.b.next_sibling.text.replace('\n', '')])

      try:
          description = find("div", class_="profile__text")
          rows.append(["description", description.text.replace('\n', '')])
      except:
          print("couldn't add the description")

      try:
          title = find("div", class_="profile__header-container")
          rows.append(["title", title.text.replace('\n', '')])
      except:
          print("couldn't add the title")

      images_urls = self.scrape_img_urls()
      if images_urls:
          rows.append(["images", images_urls])

      return rows

    def scrape_listing(self):
        # returns a dict with all the values to save
        table = []
        table_rows = self.scrape_tables()
        details_rows = self.scrape_details()
        url_row = [["url", self.url]]
        table += table_rows + details_rows + url_row

        df = pd.DataFrame(table)
        df.dropna()
        print(df)
        return df

    # def scrape_map(self):
    #     # not completed - experimental feature
    #     url = self.url
    #     driver = webdriver.Chrome()
    #     driver.get(url)
    #     time.sleep(5)
    #     driver.set_window_size(100,1000)
    #     # accept cookies
    #     driver.find_element_by_css_selector('.cc_btn.cc_btn_accept_all').click()
    #     driver.find_element_by_class_name("ol-zoom-out").click()
    #     report_button = driver.find_element_by_class_name("report")
    #     map_ = driver.find_element_by_class_name('ol-unselectable')
    #     actions = ActionChains(driver)
    #     actions.move_to_element(report_button).perform()
    #     time.sleep(4)
    #     # save map_
    #     # Upload to dropbox
    #     file_name = re.findall('\d{6}', url)[0]
    #     map_.screenshot(f'{file_name}.png')
    #     dbx.files_upload(open(f'{file_name}.png',"rb").read(),f'/{file_name}.png')
    #     return file_url

    def scrape_img_urls(self):
        images_divs = self.soup.find_all("div", class_="owl-gallery__content")
        images_urls = []
        if images_divs:
            for div in images_divs:
                try:
                    img = div.find("img")["src"]
                    print(img)
                    type(img)
                    images_urls.append(img)
                except:
                    pass

        formatted = []
        for img in set(images_urls):
            formatted.append({"url": img})
        return formatted

    def download_images_urls(self):
        images_urls = self.scrape_img_urls()

# pc = PreviewScraper()
# pc.scrape(listings_thumbnails)


# show the learned policy

import gym
import pickle
import numpy as np
from copy import deepcopy

path_q_table = 'q_table.pickle'

with open(path_q_table, 'rb') as f:
    q_table = pickle.load(f)

NUM_OBS = q_table.shape[0]

env = gym.make('MountainCar-v0', render_mode='human')

start = env.reset()

obs, _ = start

done = False

# we need to round the obs space to the defined number of values
obs_min = env.observation_space.low
obs_max = env.observation_space.high
n_obs = len(obs_min)

# create concrete bins for the observations
obs_bins = []

# do this for all observations
for i in range(n_obs):
    obs_bin = np.arange(obs_min[i], obs_max[i] + 0.0001, (obs_max[i] - obs_min[i]) / NUM_OBS)
    obs_bins.append(obs_bin)

total_reward = 0
episodes = 0

while not done:

    # make the observation discrete
    obs_cat = []

    for bins, o in zip(obs_bins, obs):

        # subtract the obs from the bins and make each number positive to get the closest bin using argmin
        bin = deepcopy(bins) - o
        bin = [abs(b) for b in bin]
        bin = np.argmin(bin)  # this is the current obs rounded

        obs_cat.append(bin)

    best_action = np.argmax(q_table[obs_cat[0], obs_cat[1], :])

    obs, reward, done, _, _ = env.step(best_action)

    total_reward += reward
    episodes += 1

print(f'Finished after {episodes} with {total_reward} reward')


import torch
import torch.nn as nn
from torch import Tensor

from nugi_rl.model.components.Transformer import EncoderLayer, DecoderLayer

class GlobalExtractor(nn.Module):
    def __init__(self, dim: int, num_layers = 2) -> None:
        super().__init__()

        object_queries = torch.ones(1, 1, dim)
        self.register_buffer('object_queries', object_queries)

        self.encoder    = nn.ModuleList([EncoderLayer(dim, heads = 4, b = 8) for _ in range(num_layers)])
        self.decoder    = nn.ModuleList([DecoderLayer(dim, heads = 4, b = 8) for _ in range(num_layers)])

    def forward(self, inputs: Tensor, mask: Tensor) -> Tensor:
        src_mask        = self.transform_mask(mask)
        src_embeddings  = inputs
        tgt_embeddings  = self.object_queries

        for layer in self.encoder:
            src_embeddings = layer(src_embeddings, src_mask)

        for layer in self.decoder:
            tgt_embeddings = layer(tgt_embeddings, src_embeddings)

        return tgt_embeddings

    def transform_mask(self, mask: Tensor) -> Tensor:
        mask = mask != -1
        return mask.unsqueeze(1).unsqueeze(2)

class Policy_Model(nn.Module):
    def __init__(self, state_dim: int, action_dim: int):
        super(Policy_Model, self).__init__()

        self.feedforward_1 = nn.Sequential(
            nn.Linear(state_dim, 256),
            nn.GELU(),
            nn.Linear(256, 64),
            nn.GELU(),
        )

        self.feedforward_3 = nn.Sequential(
            nn.Linear(8, 64),
            nn.GELU(),
        )

        self.extractors = GlobalExtractor(64)

        self.feedforward_2 = nn.Sequential(
            nn.Linear(128, 16),
            nn.GELU(),
            nn.Linear(16, action_dim),
            nn.Softmax(-1)
        )

    def forward(self, states: Tensor, detach: bool = False) -> tuple:
        masks = states[0][:, :, -1]

        x = self.feedforward_1(states[0])
        x = self.extractors(x, masks).squeeze(1)

        x2 = self.feedforward_3(states[1])
        x = torch.cat([x, x2], dim = 1)

        action = self.feedforward_2(x)

        if detach:
            return (action.detach(), )
        else:
            return (action, )

class Value_Model(nn.Module):
    def __init__(self, state_dim: int):
        super(Value_Model, self).__init__()

        self.feedforward_1 = nn.Sequential(
            nn.Linear(state_dim, 256),
            nn.GELU(),
            nn.Linear(256, 64),
            nn.GELU(),
        )

        self.feedforward_3 = nn.Sequential(
            nn.Linear(8, 64),
            nn.GELU(),
        )

        self.extractors = GlobalExtractor(64)

        self.feedforward_2 = nn.Sequential(
            nn.Linear(128, 16),
            nn.GELU(),
            nn.Linear(16, 1)
        )

    def forward(self, states: Tensor, detach: bool = False) -> Tensor:
        masks = states[0][:, :, -1]

        x = self.feedforward_1(states[0])
        x = self.extractors(x, masks).squeeze(1)

        x2 = self.feedforward_3(states[1])
        x = torch.cat([x, x2], dim = 1)

        value = self.feedforward_2(x)

        if detach:
            return value.detach()
        else:
            return value


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

from django import forms
from django.core.exceptions import ImproperlyConfigured
from django.forms.models import ModelForm
from django.utils.encoding import smart_text
from django.utils.translation import ugettext as _

from cms.api import create_page
from cms.constants import TEMPLATE_INHERITANCE_MAGIC
from cms.models import Page, UserSettings
from cms.test_utils.testcases import CMSTestCase, TransactionCMSTestCase
from cms.wizards.wizard_base import Wizard
from cms.wizards.wizard_pool import wizard_pool, AlreadyRegisteredException

class WizardForm(forms.Form):
    pass

class ModelWizardForm(ModelForm):
    class Meta:
        model = UserSettings
        exclude = []

class BadModelForm(ModelForm):
    class Meta:
        pass

class WizardTestMixin(object):
    page_wizard = None
    title_wizard = None

    def assertSequencesEqual(self, seq_a, seq_b):
        seq_a = list(seq_a)
        seq_b = list(seq_b)
        zipped = list(zip(seq_a, seq_b))
        if len(zipped) < len(seq_a) or len(zipped) < len(seq_b):
            self.fail("Sequence lengths are not the same.")
        for idx, (a, b) in enumerate(zipped):
            if a != b:
                self.fail("Sequences differ at index {0}".format(idx))

    @classmethod
    def setUpClass(cls):
        super(WizardTestMixin, cls).setUpClass()
        # This prevents auto-discovery, which would otherwise occur as soon as
        # tests start, creating unexpected starting conditions.
        wizard_pool._discovered = True

        class PageWizard(Wizard):
            pass

        # This is a basic Wizard
        cls.page_wizard = PageWizard(
            title=_(u"Page"),
            weight=100,
            form=WizardForm,
            model=Page,
            template_name='my_template.html',  # This doesn't exist anywhere
        )

        class SettingsWizard(Wizard):
            pass

        # This is a Wizard that uses a ModelForm to define the model
        cls.user_settings_wizard = SettingsWizard(
            title=_(u"UserSettings"),
            weight=200,
            form=ModelWizardForm,
        )

        class TitleWizard(Wizard):
            pass

        # This is a bad wizard definition as it neither defines a model, nor
        # uses a ModelForm that has model defined in Meta
        cls.title_wizard = TitleWizard(
            title=_(u"Page"),
            weight=100,
            form=BadModelForm,
            template_name='my_template.html',  # This doesn't exist anywhere
        )

class TestWizardBase(WizardTestMixin, TransactionCMSTestCase):

    def test_str(self):
        self.assertEqual(str(self.page_wizard), self.page_wizard.title)

    def test_repr(self):
        self.assertEqual(self.page_wizard.__repr__(), 'Wizard: "Page"')

    def test_user_has_add_permission(self):
        # Test does not have permission
        user = self.get_staff_user_with_no_permissions()
        self.assertFalse(self.page_wizard.user_has_add_permission(user))

        # Test has permission
        user = self.get_superuser()
        self.assertTrue(self.page_wizard.user_has_add_permission(user))

    def test_get_success_url(self):
        user = self.get_superuser()
        page = create_page(
            title="Sample Page",
            template=TEMPLATE_INHERITANCE_MAGIC,
            language="en",
            created_by=smart_text(user),
            parent=None,
            in_navigation=True,
            published=False
        )
        url = "{0}?edit".format(page.get_absolute_url(language="en"))
        self.assertEqual(self.page_wizard.get_success_url(
            page, language="en"), url)

        # Now again without a language code
        url = "{0}?edit".format(page.get_absolute_url())
        self.assertEqual(self.page_wizard.get_success_url(page), url)

    def test_get_model(self):
        self.assertEqual(self.page_wizard.get_model(), Page)
        self.assertEqual(self.user_settings_wizard.get_model(), UserSettings)
        with self.assertRaises(ImproperlyConfigured):
            self.title_wizard.get_model()

class TestWizardPool(WizardTestMixin, CMSTestCase):

    def test_discover(self):
        wizard_pool._reset()
        self.assertFalse(wizard_pool._discovered)
        self.assertEqual(len(wizard_pool._entries), 0)
        wizard_pool._discover()
        self.assertTrue(wizard_pool._discovered)

    def test_register_unregister_isregistered(self):
        wizard_pool._clear()
        self.assertEqual(len(wizard_pool._entries), 0)
        wizard_pool.register(self.page_wizard)
        # Now, try to register the same thing
        with self.assertRaises(AlreadyRegisteredException):
            wizard_pool.register(self.page_wizard)

        self.assertEqual(len(wizard_pool._entries), 1)
        self.assertTrue(wizard_pool.is_registered(self.page_wizard))
        self.assertTrue(wizard_pool.unregister(self.page_wizard))
        self.assertEqual(len(wizard_pool._entries), 0)

        # Now, try to unregister something that is not registered
        self.assertFalse(wizard_pool.unregister(self.user_settings_wizard))

    def test_get_entry(self):
        wizard_pool._clear()
        wizard_pool.register(self.page_wizard)
        entry = wizard_pool.get_entry(self.page_wizard)
        self.assertEqual(entry, self.page_wizard)

    def test_get_entries(self):
        """
        Test that the registered entries are returned in weight-order, no matter
        which order they were added.
        """
        wizard_pool._clear()
        wizard_pool.register(self.page_wizard)
        wizard_pool.register(self.user_settings_wizard)
        wizards = [self.page_wizard, self.user_settings_wizard]
        wizards = sorted(wizards, key=lambda e: getattr(e, 'weight'))
        entries = wizard_pool.get_entries()
        self.assertSequencesEqual(entries, wizards)

        wizard_pool._clear()
        wizard_pool.register(self.user_settings_wizard)
        wizard_pool.register(self.page_wizard)
        wizards = [self.page_wizard, self.user_settings_wizard]
        wizards = sorted(wizards, key=lambda e: getattr(e, 'weight'))
        entries = wizard_pool.get_entries()
        self.assertSequencesEqual(entries, wizards)


# 10개 정수입력받아 500미만의 수 중 가장 큰수와 500초과 수중 가장 작은 수
arr = list(map(int, input().split()))
max1 = -1
max2 = 1001

for i in arr:
    if i > max1 and i < 500:
        max1 = i

    elif i < max2 and i > 500:
        max2 = i

print(max1, max2)


def solve(data):
    binary = get_bin_data(data)
    return decode_package(binary)[0]

def decode_package(binary):
    if len(binary) <= 7:
        return 0, ""
    version = int(binary[:3], 2)
    type_ = binary[3:6]
    if type_ == "100":
        package_data = ""
        for i in range(6, ((len(binary)) // 5) * 5, 5):
            start = binary[i]
            num_data = binary[i + 1: i+5]
            package_data += num_data
            b = binary[i + 5:]
            if start == '0':
                return int(package_data, 2), binary[i + 5:]
    else:
        mode = binary[6]
        values = []
        binary_snippet = ""
        if mode == '0':
            length = int(binary[7: 7 + 15], 2)
            binary_snippet = binary[7 + 15: 7 + 15 + length]
            binary_rest = binary[7 + 15 + length:]
            while len(binary_snippet) > 0:
                v, binary_snippet = decode_package(binary_snippet)
                values.append(v)
            binary_snippet += binary_rest
        elif mode == '1':
            number_of_packages = int(binary[7: 7 + 11], 2)
            binary_snippet = binary[7 + 11:]
            for i in range(number_of_packages):
                v, binary_snippet = decode_package(binary_snippet)
                values.append(v)

        type_ = int(type_, 2)
        if type_ == 0: return sum(values), binary_snippet
        elif type_ == 1:
            result = 1
            for v in values:
                result *= v
            return result, binary_snippet
        elif type_ == 2: return min(values), binary_snippet
        elif type_ == 3: return max(values), binary_snippet
        elif type_ == 5: return (1 if values[0] > values[1] else 0), binary_snippet
        elif type_ == 6: return (1 if values[0] < values[1] else 0), binary_snippet
        elif type_ == 7: return (1 if values[0] == values[1] else 0), binary_snippet
    return 0, binary

def get_bin_data(data):
    result = ""
    for c in data.strip():
        binary = bin(int(c, 16))[2:].zfill(4)
        result += binary
    return result

if __name__ == "__main__":
    with open("16/input.txt", "r") as f:
        data = f.readlines()[0]
        print(solve(data))


import c4d
import random

def main():

    if not op:
        c4d.gui.MessageDialog('Please select Polygons')
        return
    if not isinstance(op, c4d.PolygonObject):
        c4d.gui.MessageDialog('Please select Polygons!')
        return

    bs = op.GetPolygonS()
    selda = bs.GetAll(op.GetPolygonCount())
    if bs.GetCount() < 1:
        c4d.gui.MessageDialog('Please select Polygons!!')
        return

    seltag = op.MakeTag(c4d.Tpolygonselection)
    seltag.SetName(''.join(['OrnatrixS', str(random.randrange(1, 100))]))
    tag_sel = seltag.GetBaseSelect()
    bs.CopyTo(tag_sel)

    doc.StartUndo()

    orn_ho = c4d.BaseObject(1050340)
    orn_ho.MakeTag(c4d.Tphong)

    orn_gfm = c4d.BaseObject(1050342)
    orn_gfm[c4d.gfm_InputMeshAttribute] = seltag

    orn_edg = c4d.BaseObject(1050454)

    orn_ha = c4d.BaseObject(1050343)
    orn_ha[c4d.hfg_UseFaceIncludeAttribute] = True

    orn_ha.InsertUnder(orn_ho)
    orn_edg.InsertUnder(orn_ho)
    orn_gfm.InsertUnder(orn_ho)

    doc.InsertObject(orn_ho)
    doc.AddUndo(c4d.UNDOTYPE_NEW, orn_ho)
    c4d.EventAdd()

if __name__ == '__main__':
    main()


import logging
import magic
import os

from cms.medias.utils import get_file_type_size
from django.conf import settings
from django.core.files.uploadedfile import InMemoryUploadedFile

from . import settings as app_settings
from . utils import to_webp

logger = logging.getLogger(__name__)
FILETYPE_IMAGE = getattr(settings, 'FILETYPE_IMAGE',
                         app_settings.FILETYPE_IMAGE)

def set_file_meta(media_object):
    data = get_file_type_size(media_object)
    media_object.file_size = data['file_size']
    media_object.file_type = data['mime_type']

def webp_image_optimizer(media_object):

    for field_name in ('file', 'image'):
        field = getattr(media_object, field_name, None)
        if field:
            break

    if not getattr(field, '_file', None): # pragma: no cover
        return

    mimetype = magic.Magic(mime=True).from_buffer(field._file.file.read())
    if mimetype in FILETYPE_IMAGE:
        field._file.seek(0)
        byte_io = to_webp(field._file)
        byte_io.seek(0, os.SEEK_END)
        content_size = byte_io.tell()
        byte_io.seek(0)

        fname = '.'.join(field.name.split('.')[:-1]) + '.webp'
        field._file = InMemoryUploadedFile(file = byte_io,
                                           name = fname,
                                           content_type = 'image/webp',
                                           size = content_size,
                                           charset='utf-8',
                                           field_name = field_name)
        field._file._name = fname
        field.name = fname

        field._file.size = content_size
        field._file.content_type = 'image/webp'

        # if they are valuable ... otherwise nothins happens to model
        media_object.file_size = content_size
        media_object.file_type = 'image/webp'
        logger.info(f'Image {fname} converted from {mimetype} to {media_object.file_type}')
        return True

def remove_file(media_object):
    fpath = media_object.file.path
    try:
        os.remove(fpath)
    except Exception as e: # pragma: no cover
        _msg = 'Media Hook remove_file: {} cannot be removed: {}'
        logger.error(_msg.format(fpath, e))


import copy
import json
import logging
import optparse
import os
import random
import sys
import threading

import customtabs_benchmark

_SRC_PATH = os.path.abspath(os.path.join(
    os.path.dirname(__file__), '..', '..', '..', '..'))

sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil'))
from devil.android import device_utils

sys.path.append(os.path.join(_SRC_PATH, 'build', 'android'))
import devil_chromium

_KEYS = ['url', 'warmup', 'no_prerendering', 'delay_to_may_launch_url',
         'delay_to_launch_url', 'cold']

def _ParseConfiguration(filename):
  """Reads a JSON file and returns a list of configurations.

  Each valid value in the JSON file can be either a scalar or a list of
  values. This function expands the scalar values to be lists. All list must
  have the same length.

  Sample configuration:
  {
    "url": "https://www.android.com",
    "warmup": [false, true],
    "no_prerendering": false,
    "delay_to_may_launch_url": [-1, 1000],
    "delay_to_launch_url": [-1, 1000],
    "cold": true
  }

  Args:
    filename: (str) Point to a file containins a JSON dictionnary of config
              values.

  Returns:
    A list of configurations, where each value is specified.
  """
  config = json.load(open(filename, 'r'))
  has_all_values = all(k in config for k in _KEYS)
  assert has_all_values
  config['url'] = str(config['url']) # Intents don't like unicode.
  has_list = any(isinstance(config[k], list) for k in _KEYS)
  if not has_list:
    return [config]
  list_keys = [k for k in _KEYS if isinstance(config[k], list)]
  list_length = len(config[list_keys[0]])
  assert all(len(config[k]) == list_length for k in list_keys)
  result = []
  for i in range(list_length):
    result.append(copy.deepcopy(config))
    for k in list_keys:
      result[-1][k] = result[-1][k][i]
  return result

def _CreateOptionParser():
  parser = optparse.OptionParser(description='Loops tests on all attached '
                                 'devices, with randomly selected '
                                 'configurations, and outputs the results in '
                                 'CSV files.')
  parser.add_option('--config', help='JSON configuration file. Required.')
  parser.add_option('--output_file_prefix', help='Output file prefix. Actual '
                    'output file is prefix_<device ID>.csv', default='result')
  return parser

def _RunOnDevice(device, output_filename, configs, should_stop):
  """Loops the tests described by configs on a device.

  Args:
    device: (DeviceUtils) device to run the tests on.
    output_filename: (str) Output file name.
    configs: (list of dict) List of configurations.
    should_stop: (Event) When set, this function should return.
  """
  with open(output_filename, 'a') as f:
    while not should_stop.is_set():
      config = configs[random.randint(0, len(configs) - 1)]
      result = customtabs_benchmark.RunOnce(
          device, config['url'], config['warmup'], config['no_prerendering'],
          config['delay_to_may_launch_url'], config['delay_to_launch_url'],
          config['cold'])
      if result is not None:
        f.write(result + '\n')
        f.flush()
      should_stop.wait(10.)

def _Run(output_file_prefix, configs):
  """Loops the tests described by the configs on connected devices.

  Args:
    output_file_prefix: (str) Prefix for the output file name.
    configs: (list of dict) List of configurations.
  """
  devices = device_utils.DeviceUtils.HealthyDevices()
  should_stop = threading.Event()
  threads = []
  for device in devices:
    output_filename = '%s_%s.csv' % (output_file_prefix, str(device))
    thread = threading.Thread(
        target=_RunOnDevice,
        args=(device, output_filename, configs, should_stop))
    thread.start()
    threads.append(thread)
  for thread in threads:
    try:
      thread.join()
    except KeyboardInterrupt as e:
      should_stop.set()

def main():
  parser = _CreateOptionParser()
  options, _ = parser.parse_args()
  if options.config is None:
    logging.error('A configuration file must be provided.')
    sys.exit(0)
  devil_chromium.Initialize()
  configs = _ParseConfiguration(options.config)
  _Run(options.output_file_prefix, configs)

if __name__ == '__main__':
  main()


defterolepta = int(input('Δώσε τον αριθμό των δευτερολέπτων: '))
if defterolepta < 60:
    print('Δευτερόλεπτα: ', float(defterolepta), sep='')
elif defterolepta >= 60 and defterolepta < 3600:
    lepta = (defterolepta // 60) % 60
    defterolepta = defterolepta % 60
    print('Λεπτά: ', float(lepta), '\nΔευτερόλεπτα: ',
          float(defterolepta), sep='')
elif defterolepta >= 3600 and defterolepta < 86400:
    ores = defterolepta // 3600
    lepta = (defterolepta // 60) % 60
    defterolepta = defterolepta % 60
    print('Ώρες: ', float(ores), '\nΛεπτά: ', float(lepta), '\nΔευτερόλεπτα: ',
          float(defterolepta), sep='')
else:
    # Το 90000 είναι το αποτέλεσμα του 86400 + 3600 και το κάνουμε έτσι ώστε
    # στην δεύτερη 'else' να εμφανίζει μόνο τις ημέρες, τα λεπτά και τα
    # δευτερόλεπτα και όχι τις ώρες.
    if defterolepta >= 90000:
        imeres = (defterolepta // 3600) % 60
        imeres = imeres // 24
        ores = defterolepta - 86400
        ores = ores // 3600
        lepta = (defterolepta // 60) % 60
        defterolepta = defterolepta % 60
        print('Ημέρες: ', float(imeres), '\nΏρες: ', float(ores), '\nΛεπτά: ',
              float(lepta), '\nΔευτερόλεπτα: ', float(defterolepta), sep='')
    else:
        imeres = (defterolepta // 3600) % 60
        imeres = imeres // 24
        lepta = (defterolepta // 60) % 60
        defterolepta = defterolepta % 60
        print('Ημέρες: ', float(imeres), '\nΛεπτά: ', float(lepta),
              '\nΔευτερόλεπτα: ', float(defterolepta), sep='')


import os
from flask import Flask
from flask import render_template
app = Flask(__name__, template_folder='./templates')

@app.route('/')
def hello_world():
	name = os.environ.get("MAIN_TEXT")
	color = os.environ.get("COLOR")
	print(color)
	print(name)
	return render_template('index.html', name=name, color=color)


import sys

input =sys.stdin.readline

count = 1
E, S, M = map(int,input().split())

while True:
    if E%15==count%15 and S%28==count%28 and M%19==count%19:
        break
    count+=1
print(count)


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

from processr.processr import (
    rename_keys,
    project_dict,
    transform_values,
    transform_dict,
    transform_values_strict)

import pytest

##############################################################
#                        rename_keys                         #
##############################################################

def test_rename_keys():
    d = {'the_answer': 42}
    opts = {'the_answer': 'the_universe_and_everything'}
    expected_output = {'the_universe_and_everything': 42}

    output = rename_keys(d, opts)
    assert output == expected_output

def test_rename_keys_extra_fields():
    d = {'the_answer': 42, 'not_the_answer': 43}
    opts = {'the_answer': 'the_universe_and_everything'}
    expected_output = {'the_universe_and_everything': 42, 'not_the_answer': 43}

    output = rename_keys(d, opts)
    assert output == expected_output

##############################################################
#                          project                           #
##############################################################

def test_project_dict():
    d = {'the_answer': 42, 'not_the_answer': 43}
    opts = ('the_answer', )
    expected_output = {'the_answer': 42}

    output = project_dict(d, opts)
    assert output == expected_output

def test_project_dict_extra_fields():
    d = {'the_answer': 42, 'not_the_answer': 43}
    opts = ('the_answer', 'the_universe')

    with pytest.raises(KeyError):
        project_dict(d, opts)

##############################################################
#                      transform_values                      #
##############################################################

def test_transform_values():
    d = {'not_the_answer': [9, 9, 9, 9, 9, 9]}
    opts = {'not_the_answer': [sum, str]}

    # I always thought something was fundamentally wrong with the universe
    expected_output = {'not_the_answer': '54'}
    output = transform_values(d, opts)
    assert output == expected_output

def test_transform_values_extra_fields():
    d = {'not_the_answer': [9, 9, 9, 9, 9, 9], 'the_answer': 42}
    opts = {'not_the_answer': [sum, str]}

    expected_output = {'not_the_answer': '54', 'the_answer': 42}
    output = transform_values(d, opts)
    assert output == expected_output

def test_transform_values_non_strictness():
    d = {'not_the_answer': [9, 9, 9, 9, 9, 9]}
    opts = {'the_answer': [str]}

    expected_output = {'not_the_answer': [9, 9, 9, 9, 9, 9]}
    output = transform_values(d, opts)
    assert output == expected_output

def test_transform_values_strict():
    d = {'not_the_answer': [9, 9, 9, 9, 9, 9]}
    opts = {'not_the_answer': [sum, str]}

    expected_output = {'not_the_answer': '54'}
    output = transform_values_strict(d, opts)
    assert output == expected_output

def test_transform_values_strict_ko():
    d = {'not_the_answer': [9, 9, 9, 9, 9, 9]}
    opts = {'the_answer': [str]}

    with pytest.raises(KeyError):
        transform_values_strict(d, opts)

##############################################################
#                       transform_dict                       #
##############################################################

def test_dict_transform():
    d = {'the_answer': 42, 'not_the_answer': 43}
    ops = [
        lambda d: dict((v, k) for k, v in d.items())  # Invert key and values
    ]

    expected_output = {42: 'the_answer', 43: 'not_the_answer'}
    output = transform_dict(d, ops)
    assert output == expected_output


from pygame import*
from time import time as tim
from random import randint
def Fliby_bird_game():

    init()
    mixer.init()

    window = display.set_mode((1100, 600))
    display.set_caption("Fliby Bird")
    clock = time.Clock()

    background = transform.scale(
        image.load("fliby bird/background.jpg"), (1100, 600))

    window.blit(background, (0,0))

    mixer.music.load("fliby bird/Angry Birds.mp3")
    mixer.music.play()

    class Sprite():
        def __init__(self, filename, x, y, width, height, speed):
            self.speed  = speed
            self.rect = Rect(x, y, width, height)
            self.image = transform.scale(image.load(filename), (70, 70))

        def draw_sprite(self):
            window.blit(self.image, (self.rect.x, self.rect.y))

        def fall(self):
            self.rect.y += self.speed

        def up(self):
            self.rect.y -= 40

        def colliderect(self, rect):
            return self.rect.colliderect(rect)

    class GameCard():

        def __init__(self, x, y, width, height, color = None):
            self.rect = Rect(x, y, width, height)
            self.fill_color = color

        def frame(self, color= (0, 0, 0), thinkness = 5):
            draw.rect(window, color, self.rect, thinkness)

        def draw_rect(self):
            draw.rect(window, self.fill_color, self.rect)
            self.frame()

        def colliderect(self, rect):
            return self.rect.colliderect(rect)

        def set_text(self, text, fsize = 70, text_color=(0,0,0)):
            self.image = font.SysFont("Arial", fsize).render(text, True, text_color)

        def draw_text(self, shift_x=5, shift_y=55):
            window.blit(self.image, (self.rect.x + shift_x, self.rect.y + shift_y))

        def draw_info(self):
            draw.rect(window, self.fill_color, self.rect)
            window.blit(self.image,(self.rect.x, self.rect.y))

    class Wall(Sprite):

        def __init__(self,filename, x, y, width, height):
            self.filename = filename
            self.rect = Rect(x,y,width,height)
            self.image = transform.scale(image.load(filename), (90,400))

        def move(self, speed=5):
            self.rect.x -= speed

    player = Sprite("fliby bird/player.png",100,250,30,30,1)

    walls_down = []
    walls_up = []
    animation_time = tim()
    wall_time = animation_time# інтервал створення монстрів
    interval = 5

    ready = 3
    start = GameCard(0,0,50, 100)

    score = 0
    speed = 5
    counter = 0
    game = True
    while game:
        new_time = tim()

        y = randint(190,300)
        speed += 0.001

        for e in event.get():
            if e.type == QUIT:
                mixer.stop()
                mixer.music.load("fliby bird/fail.mp3")
                mixer.music.play()
                finish_image = font.SysFont("Goudy Stout", 50).render("YOU LOSE", True, (255,0,0))
                game = False

            if e.type == KEYDOWN:
                if e.key ==  K_SPACE:
                    player.up()

            if new_time - wall_time >= interval:
                wall1 = Wall("fliby bird/klipartz.com.png", window.get_width(), (y+100), 30, 240)
                wall2 = Wall("fliby bird/klipartz_up.com.png", window.get_width(), (-y+100), 30, 240)
                walls_down.append(wall1)
                walls_up.append(wall2)
                wall_time = new_time
                interval = randint(1, 5) / 1.5

        player.fall()

        window.blit(background, (0,0))
        player.draw_sprite()

        for wall in walls_down:
            wall.move(speed)
            wall.draw_sprite()
            if player.colliderect(wall):
                window.blit(background, (0,0))
                finish_image = font.SysFont("Goudy Stout", 50).render("YOU LOSE", True, (255,0,0))
                game = False

        for wall in walls_up:
            wall.move(speed)
            wall.draw_sprite()
            if player.colliderect(wall):
                window.blit(background, (0,0))
                finish_image = font.SysFont("Goudy Stout", 50).render("YOU LOSE", True, (255,0,0))
                game = False

        if player.rect.y >= window.get_height() - 60:
            window.blit(background, (0,0))
            finish_image = font.SysFont("Goudy Stout", 50).render("YOU LOSE", True, (255,0,0))
            game = False

        if player.rect.y <= 0:
            player.rect.y += 50

        score += speed
        display.update()
        clock.tick(120)
        while counter != 5*60 and game:
            for e in event.get():
                if e.type == QUIT:
                    game = False
            counter += 1
            clock.tick(120)

    window.blit(finish_image,(window.get_width() / 2 - 220, window.get_height() / 2 - 70))
    score = int(score / 100)
    mage = font.SysFont("Montserrat", 50).render("SCORE : "+str(score), True, (0,0,0))
    window.blit(mage,(window.get_width() / 2 - 100, window.get_height() / 2 + 100))
    display.update()
    counter = 0
    game = True
    while counter != 5*60 and game:
            for e in event.get():
                if e.type == QUIT:
                    game = False
            counter += 1
            clock.tick(120)


# Digits in Words

# The program must accept an integer N as the input. The program must print the corresponding words separated by space(s) for each digit in N as the output. The words must be printed as given below,
# 0 - zero
# 1 - one
# 2 - two
# 3 - three
# 4 - four
# 5 - five
# 6 - six
# 7 - seven
# 8 - eight
# 9 - nine

# Boundary Condition(s):
# 1 <= N <= 10^9

# Input Format:
# The first line contains the value of N.

# Output Format:
# The first line contains the words separated by space(s).

# Example Input/Output 1:
# Input:
# 100

# Output:
# one zero zero

# Example Input/Output 2:
# Input:
# 3892

# Output:
# three eight nine two

values = ['zero','one','two','three','four','five','six','seven','eight','nine']
for c in input().strip():
    print(values[int(c)],end=' ')


"""
Link: https://codeforces.com/problemset/problem/468/B
Time complexity: O(N * Log(N))
Space complexity: O(N)
Author: Nguyen Duc Hieu
"""

class Union_Find:
    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.rank = [0] * N
        self.component = N

    def find(self, u):
        if u != self.parent[u]:
            self.parent[u] = self.find(self.parent[u])
        return self.parent[u]

    def union(self, u, v):
        root_u = self.find(u)
        root_v = self.find(v)
        if root_v == root_u:
            return False
        self.component -= 1
        if self.rank[root_u] > self.rank[root_v]:
            self.parent[root_v] = root_u
        elif self.parent[root_v] > self.parent[root_u]:
            self.parent[root_u] = root_v
        else:
            self.parent[root_u] = root_v
            self.rank[root_v] += 1
        return True

def method_1():
    global values
    N, A, B = map(int, input().split())
    values = list(map(int, input().split()))
    map = dict()
    union_find = Union_Find(N + 2)
    for i in range(len(values)):
        map[values[i]] = i
    for k in range(2):
        for val in values:
            if map.get(val, -1) > -1:
                if map.get(A - val, -1) > -1 >= map.get(B - val, -1):
                    union_find.union(N, map[val])
                    union_find.union(N, map[A - val])
                    map[val] = -1
                    map[A - val] = -1
                elif map.get(A - val, -1) <= -1 < map.get(B - val, -1):
                    union_find.union(N + 1, map[val])
                    union_find.union(N + 1, map[B - val])
                    map[val] = -1
                    map[B - val] = -1
                else:
                    if -1 >= map.get(A - val, -1) and -1 >= map.get(B - val, -1):
                        print("NO")
                        exit()
    print("YES")
    root_0 = union_find.find(N)
    root_1 = union_find.find(N + 1)
    for i in range(len(values)):
        if union_find.find(i) == root_0:
            print("0", end=" ")
        else:
            print("1", end=" ")

def method_2():
    N, A, B = map(int, input().split())
    values = list(map(int, input().split()))
    map_index = dict()
    for i in range(N):
        val = values[i]
        map_index[val] = i
        if val >= max(A, B):
            print("NO")
            exit()
    union_find = Union_Find(N + 2)
    for val in values:
        if (A - val) in map_index:
            union_find.union(map_index[val], map_index[A - val])
        else:
            union_find.union(N + 1, map_index[val])
        if (B - val) in map_index:
            union_find.union(map_index[val], map_index[B - val])
        else:
            union_find.union(N, map_index[val])
    root_A = union_find.find(N)
    root_B = union_find.find(N + 1)
    if root_A == root_B:
        print("NO")
        exit()
    print("YES")
    for i in range(N):
        if union_find.find(i) == root_A:
            print("0", end=" ")
        else:
            print("1", end=" ")

if __name__ == '__main__':
    # method_1()
    method_2()