#--------------------------------Imports---------------------------------------#
import pygame, sys
from pygame.locals import *
import random
#--------------------------------Imports---------------------------------------#
#----------------------------------Solve Methods-------------------------------#
global solvedCells
global playerSolution
counter = 0
base = 0
playerSolution = []
solvedCells = []
for i in range(0, 81):
    playerSolution.append(' ')

def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [a+b for a in A for b in B]

digits   = '123456789'
rows     = 'ABCDEFGHI'
cols     = digits
squares  = cross(rows, cols)
unitlist = ([cross(rows, c) for c in cols] +
            [cross(r, cols) for r in rows] +
            [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])
units = dict((s, [u for u in unitlist if s in u])
             for s in squares)
peers = dict((s, set(sum(units[s],[]))-set([s]))
             for s in squares)

def parse_grid(grid):
    """Convert grid to a dict of possible values, {square: digits}, or
    return False if a contradiction is detected."""
    values = dict((s, digits) for s in squares)
    global counter
    global base
    counter = 0
    for s,d in grid_values(grid).items():
        base = counter
        if d in digits and not assign(values, s, d):
            return False ## (Fail if we can't assign d to square s.)
##        print solvedCells#[base:counter]
##        print "--"
####        print solvedCells[j:counter][::-1], j, counter
        solvedCells[base:counter] = solvedCells[base:counter][::-1]
##        print solvedCells, base, counter
    return values

def grid_values(grid):
    "Convert grid into a dict of {square: char} with '0' or '.' or ' ' for empties."
    chars = [c for c in grid if c in digits or c in '0. ']
    assert len(chars) == 81
    return dict(zip(squares, chars))

def decodeDict(values):
    """Converts the dicts generated by the other functions into an 81 character
    string. Only returns string values of len() == 1, otherwise returns whitespace."""
    a = ''
    for r in rows:
        for c in cols:
            if len(values[r+c]) == 1:
                a = a + values[r+c]
            else:
                a = a + " "
    return a

def assign(values, s, d):
    """Eliminate all the other values (except d) from values[s] and propagate.
    Return values, except return False if a contradiction is detected."""
    peerList = []
    other_values = values[s].replace(d, '')
    global counter
    if all(eliminate(values, s, d2) for d2 in other_values):
        if [s, d, 0] not in solvedCells and [s, d, 1] not in solvedCells and [s, d, 2] not in solvedCells:
            if counter < len(solvedCells):
                counter = counter + 1
            peerList.append(d)
            for s2 in peers[s]:
                if len(values[s2]) == 1 and values[s2] not in peerList:
                    peerList.append(values[s2])
            peerList.sort()
            if ''.join(peerList) == "123456789":
                solvedCells.append([s, d, 2])
            else:
                solvedCells.append([s, d, 0])
        return values
    else:
        return False

def eliminate(values, s, d):
    """Eliminate d from values[s]; propagate when values or places <= 2.
    Return values, except return False if a contradiction is detected."""
    if d not in values[s]:
        return values ## Already eliminated
    values[s] = values[s].replace(d,'')
    ## (1) If a square s is reduced to one value d2, then eliminate d2 from the peers.
    if len(values[s]) == 0:
        return False ## Contradiction: removed last value
    elif len(values[s]) == 1:
        d2 = values[s]
        if not all(eliminate(values, s2, d2) for s2 in peers[s]):
            return False
    ## (2) If a unit u is reduced to only one place for a value d, then put it there.
    for u in units[s]:
        dplaces = [s for s in u if d in values[s]]
        if len(dplaces) == 0:
            return False ## Contradiction: no place for this value
        elif len(dplaces) == 1:
            # d can only be in one place in unit; assign it there
            if not assign(values, dplaces[0], d):
                return False
    return values

def solve(grid): return search(parse_grid(grid))

def search(values):
    "Using depth-first search and propagation, try all possible values."
    if values is False:
        return False ## Failed earlier
    if all(len(values[s]) == 1 for s in squares):
        return values ## Solved!
    ## Chose the unfilled square s with the fewest possibilities
    n,s = min((len(values[s]), s) for s in squares if len(values[s]) > 1)
    return some(search(assign(values.copy(), s, d))
                for d in values[s])

def some(seq):
    "Return some element of seq that is true."
    for e in seq:
        if e: return e
    return False

def square2Cell(squar):
    '''Takes a cell's designation (eg: A1, E5, I9) (string), returns cell number
    (eg: 0, 40, 80) (int).'''
    if squar[0] == "A": cell = -1
    elif squar[0] == "B": cell = 8
    elif squar[0] == "C": cell = 17
    elif squar[0] == "D": cell = 26
    elif squar[0] == "E": cell = 35
    elif squar[0] == "F": cell = 44
    elif squar[0] == "G": cell = 53
    elif squar[0] == "H": cell = 62
    elif squar[0] == "I": cell = 71
    return cell + int(squar[1])

def isSolved(stringGrid):
    "Checks if string representation of puzzle is complete."
    for i in range(0, len(stringGrid)):
        if stringGrid[i] == ' ':
            return False
    return True

def Coord(cellNo):
    "Takes a cell number, returns cell designation."
    a = "ABCDEFGHI"
    return a[cellNo/9] + str(cellNo % 9 + 1)

def genSol(stringGrid):
    "Accepts a string grid and generates an evolving partial solution."
    b = solve(stringGrid)
    del solvedCells[:]
    a = parse_grid(stringGrid)
    sa = list(decodeDict(a))
    sb = list(decodeDict(b))
    while not(isSolved("".join(sa))):
        i = 0
        while i < 81:
            if sa[i] != sb[i]:
                sa[i] = sb[i]
                if [Coord(i), sb[i], 0] not in solvedCells and [Coord(i), sb[i], 1] not in solvedCells and [Coord(i), sb[i], 2] not in solvedCells:
                    solvedCells.append([Coord(i), sb[i], 1])
                break
            i = i + 1
        sa = list(decodeDict(parse_grid("".join(sa))))
    return b

#----------------------------------Solve Methods-------------------------------#
#-------------------------------------Buttons!---------------------------------#

def writeButtons(mouse):
    "Reads button values 1 through 9 from the button grid."
    if mouse[0] in range(widthBuffer + 3 * cellSize, widthBuffer + 6 * cellSize) and mouse[1] in range(heightBuffer + 10 * cellSize, heightBuffer + 13 * cellSize):
        if mouse[0] in range(widthBuffer + 3 * cellSize, widthBuffer + 4 * cellSize) and mouse[1] in range(heightBuffer + 10 * cellSize, heightBuffer + 11 * cellSize):
            writeValue = "1"
        if mouse[0] in range(widthBuffer + 4 * cellSize, widthBuffer + 5 * cellSize) and mouse[1] in range(heightBuffer + 10 * cellSize, heightBuffer + 11 * cellSize):
            writeValue = "2"
        if mouse[0] in range(widthBuffer + 5 * cellSize, widthBuffer + 6 * cellSize) and mouse[1] in range(heightBuffer + 10 * cellSize, heightBuffer + 11 * cellSize):
            writeValue = "3"
        if mouse[0] in range(widthBuffer + 3 * cellSize, widthBuffer + 4 * cellSize) and mouse[1] in range(heightBuffer + 11 * cellSize, heightBuffer + 12 * cellSize):
            writeValue = "4"
        if mouse[0] in range(widthBuffer + 4 * cellSize, widthBuffer + 5 * cellSize) and mouse[1] in range(heightBuffer + 11 * cellSize, heightBuffer + 12 * cellSize):
            writeValue = "5"
        if mouse[0] in range(widthBuffer + 5 * cellSize, widthBuffer + 6 * cellSize) and mouse[1] in range(heightBuffer + 11 * cellSize, heightBuffer + 12 * cellSize):
            writeValue = "6"
        if mouse[0] in range(widthBuffer + 3 * cellSize, widthBuffer + 4 * cellSize) and mouse[1] in range(heightBuffer + 12 * cellSize, heightBuffer + 13 * cellSize):
            writeValue = "7"
        if mouse[0] in range(widthBuffer + 4 * cellSize, widthBuffer + 5 * cellSize) and mouse[1] in range(heightBuffer + 12 * cellSize, heightBuffer + 13 * cellSize):
            writeValue = "8"
        if mouse[0] in range(widthBuffer + 5 * cellSize, widthBuffer + 6 * cellSize) and mouse[1] in range(heightBuffer + 12 * cellSize, heightBuffer + 13 * cellSize):
            writeValue = "9"
        return writeValue
    return False

def clearButton(mouse):
    "Reads the Clr value from the button grid."
    if mouse[0] in range(widthBuffer + 6 * cellSize, widthBuffer + 7 * cellSize + 1) and mouse[1] in range(heightBuffer + 12 * cellSize, heightBuffer + 13 * cellSize + 1):
        return " "
    return False

def writing(a, playerSolution, value, mouse):
    "Writes 'value' to the human grid."
    if mouse[0] in range(widthBuffer, widthBuffer + 9 * cellSize) and mouse[1] in range(heightBuffer, heightBuffer + 9 * cellSize):
        cellNo = (mouse[0] - widthBuffer) // cellSize + 9 * ((mouse[1] - heightBuffer) // cellSize)
        playerSolution[cellNo] = value
        if a[cellNo] == " ":
            pygame.draw.rect(screen, (255, 255, 255), [cellHuman[cellNo][0] + 1, cellHuman[cellNo][1] + 1, cellSize-2, cellSize-2])
            font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
            text = font.render('%s' % value, 1, (150, 150, 150))
            textpos = text.get_rect()
            textpos.centerx = cellHuman[cellNo][0] + cellSize/2
            textpos.centery = cellHuman[cellNo][1] + cellSize/2
            screen.blit(text, textpos)
            pygame.display.update()
        return True
    return False

def RESET(mouse):
    if mouse[0] in range(int(windowWidth/2 + widthBuffer), int(windowWidth/2 + widthBuffer + 3 * cellSize)) and mouse[1] in range(int(heightBuffer + 10 * cellSize), int(heightBuffer + 11 * cellSize)):
        return True
    return False

def NLV(mouse):
    if mouse[0] in range(int(windowWidth/2 + widthBuffer + 6 * cellSize), int(windowWidth/2 + widthBuffer + 9 * cellSize)) and mouse[1] in range(int(heightBuffer + 10 * cellSize), int(heightBuffer + 11 * cellSize)):
        return True
    return False

def PREVIOUSPUZZLE(mouse):
    if mouse[0] in range(int(windowWidth/2 + widthBuffer), int(windowWidth/2 + widthBuffer + 3 * cellSize)) and mouse[1] in range(int(heightBuffer + 11 * cellSize + cellSize/2), int(heightBuffer + 12 * cellSize + cellSize/2)):
        return True
    return False

def NEXTPUZZLE(mouse):
    if mouse[0] in range(int(windowWidth/2 + widthBuffer  + 6 * cellSize), int(windowWidth/2 + widthBuffer  + 6 * cellSize + 3 * cellSize)) and mouse[1] in range(int(heightBuffer + 11 * cellSize + cellSize/2), int(heightBuffer + 12 * cellSize + cellSize/2)):
        return True
    return False

def RANDOMPUZZLE(mouse):
    if mouse[0] in range(int(windowWidth/2 + widthBuffer), int(windowWidth/2 + widthBuffer + 3 * cellSize)) and mouse[1] in range(int(heightBuffer + 13 * cellSize), int(heightBuffer + 14 * cellSize)):
        return True
    return False

def QUIT(mouse):
    if mouse[0] in range(int(windowWidth - 3 * cellSize), windowWidth) and mouse[1] in range(0, cellSize):
        return True
    return False
#-------------------------------------Buttons!---------------------------------#
def main():
#-----------------------------------Inits--------------------------------------#
    random.seed() ## Seeds PRNG, necessary for initialising random number generation used to load puzzles.
    pygame.init() ## Initialises Pygame module.
    global fpsLock, screen ## 'screen' is the surface that the entire interface is being rendered on. 'fpslock' is used to maintain 'fps', defined later.
    global cellHuman ## Global list runs through coordinates for each 'human' cell, i. e., cell on the left-sided grid.
    global windowHeight, windowWidth, gridColour, background, black, gridLines, gridSize, squareSize, cellSize, widthBuffer, heightBuffer, cellHuman
    windowHeight = 720 ## Min. height is 486, min. width is 972. No errors if dimensions are less, but the grids will overlap.
    windowWidth = 1280 ## Every positioning statement uses these values, so all prints will auto - readjust is these values are modified.
    fps = 60 ## Frames per second. Set at 60 because 60 is standard for games, this program doesn't really require it.
    gridColour = (255, 255, 255) ## RGB White
    background = (0, 255, 255) ## RGB Cyan
    black = (0, 0, 0) ## RBG...well, black
    gridLines = (200, 200, 200) ## RGB 'Light Gray'
    cellSize = int((int(windowHeight * 0.45)/3)/3) ## Dimensions of each puzzle
    widthBuffer = int((windowWidth / 2 - 9 * cellSize ) / 2) ## Buffer between the grids, left window margin, right window margin, and dividing line.
    heightBuffer = int((windowHeight - 9 * cellSize) / 2) ## Buffer between grids, top window margin, and bottom window margin.
    cellHuman = [[widthBuffer, heightBuffer]] ## Initialising coordinate list to the top left corner of the top left cell of the left-sided grid.

## Loop runs through top left corner of each cell of the left-sided grid, stores the coordinates as a two dimensional list in 'cellHuman'.
    i = 1
    while i < 81:
        if i % 9 == 0:
            cellHuman.append([widthBuffer, cellHuman[len(cellHuman) -1][1] + cellSize])
        else:
            cellHuman.append([cellHuman[len(cellHuman) -1][0] + cellSize, cellHuman[len(cellHuman) -1][1]])
        i = i + 1

    screen = pygame.display.set_mode((windowWidth, windowHeight))#, FULLSCREEN) ## Defines the size of the surface generated, remove the # infront of FULLSCREEN to make it, uhh, go fullscreen.
## If you get a syntax error when trying to run FULLSCREEN, count the number of brackets in the statement.
    fpsLock = pygame.time.Clock() ## Initializing the lock on fps, called during run-time event loop to tick 'fps' times per second.
    pygame.display.set_caption("Sudoku Solver") ## Window caption, unimportant if running in FULLSCREEN.
    screen.fill(background) ## Fills the entire surface with colour
## Draws rectangle where our sudoku puzzles will go, to give them a different background.
    pygame.draw.rect(screen, gridColour, [widthBuffer, heightBuffer, 9 * cellSize, 9 * cellSize])
    pygame.draw.rect(screen, gridColour, [windowWidth/2 + widthBuffer, heightBuffer, 9 * cellSize, 9 * cellSize])
#-----------------------------------Inits--------------------------------------#
#---------------------------------Draw Methods---------------------------------#
    def drawGrid():
        "Draws two 486x486 resolution, 9x9 cell grids, as well as a dividing line in the centre of the surface. The grids are each centred in their respective half of the surface."
## Loops for drawing the inner 'Light Gray' lines. Lines for the border are also drawn, but later overdrawn by black lines.
        # widthBuffer = int(widthBuffer)
        # heightBuffer = int(heightBuffer)
        # cellSize = int(cellSize)
        for x in range(widthBuffer , widthBuffer + 9 * cellSize + 1, cellSize):
            pygame.draw.line(screen, gridLines, (x, heightBuffer), (x, 9 * cellSize - 1 + heightBuffer))
        for y in range(heightBuffer, heightBuffer + 9 * cellSize + 1, cellSize):
            pygame.draw.line(screen, gridLines, (widthBuffer, y), (9 * cellSize - 1 + widthBuffer, y))

        for x in range(widthBuffer , widthBuffer + 9 * cellSize + 1, 3 * cellSize):
            pygame.draw.line(screen, black, (x, heightBuffer), (x, 9 * cellSize - 1 + heightBuffer))
        for y in range(heightBuffer, heightBuffer + 9 * cellSize + 1, 3 * cellSize):
            pygame.draw.line(screen, black, (widthBuffer, y), (9 * cellSize - 1 + widthBuffer, y))

## Drawing button grid
        pygame.draw.rect(screen, (0, 0, 0), [widthBuffer + 3 * cellSize, heightBuffer + 10 * cellSize, 3 * cellSize, 3 * cellSize])
        pygame.draw.rect(screen, (0, 0, 0), [widthBuffer + 6 * cellSize, heightBuffer + 12 * cellSize, cellSize, cellSize])

        for x in range(widthBuffer + 3 * cellSize, widthBuffer + 6 * cellSize + 1, cellSize):
            pygame.draw.line(screen, (255, 255, 255), (x, heightBuffer + 10 * cellSize), (x, heightBuffer + 13 * cellSize))
        for y in range(heightBuffer + 10 * cellSize, heightBuffer + 13 * cellSize + 1, cellSize):
            pygame.draw.line(screen, (255, 255, 255), (widthBuffer + 3 * cellSize, y), (widthBuffer + 6 * cellSize, y))
        pygame.draw.line(screen, (255, 255, 255), (widthBuffer + 6 * cellSize, heightBuffer + 13 * cellSize), (widthBuffer + 7 * cellSize, heightBuffer + 13 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (widthBuffer + 6 * cellSize, heightBuffer + 12 * cellSize), (widthBuffer + 7 * cellSize, heightBuffer + 12 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (widthBuffer + 7 * cellSize, heightBuffer + 12 * cellSize), (widthBuffer + 7 * cellSize, heightBuffer + 13 * cellSize))

        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
        text = font.render("Clr", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = widthBuffer + 6 * cellSize + cellSize/2
        textpos.centery = heightBuffer + 12 * cellSize + cellSize/2
        screen.blit(text, textpos)
        i = 1
        for y in range(int(heightBuffer + 10 * cellSize + cellSize/2), int(heightBuffer + 13 * cellSize), cellSize):
            for x in range(int(widthBuffer + 3 * cellSize + cellSize/2), int(widthBuffer + 6 * cellSize), cellSize):
                text = font.render('%s' % i, 1, (255, 255, 255))
                textpos = text.get_rect()
                textpos.centerx = x
                textpos.centery = y
                screen.blit(text, textpos)
                i = i + 1

## Quit
        pygame.draw.rect(screen, (0, 0, 0), [windowWidth - 3 * cellSize, 0, 3 * cellSize, cellSize])
        pygame.draw.line(screen, (255, 255, 255), (windowWidth - 3 * cellSize, 0), (windowWidth,0))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth - 3 * cellSize, cellSize), (windowWidth, cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth - 3 * cellSize, 0), (windowWidth - 3 * cellSize, cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth - 1, 0), (windowWidth - 1, cellSize))
        text = font.render("Exit", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = windowWidth - 2 * cellSize + cellSize/2
        textpos.centery = cellSize/2
        screen.blit(text, textpos)

## Reset Button
        pygame.draw.rect(screen, (0, 0, 0), [windowWidth/2 + widthBuffer, heightBuffer + 10 * cellSize, 3 * cellSize, cellSize])
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 10 * cellSize), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 10 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 11 * cellSize), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 11 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 10 * cellSize), (windowWidth/2 + widthBuffer, heightBuffer + 11 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 10 * cellSize), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 11 * cellSize))
        text = font.render("Reset", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = windowWidth/2 + widthBuffer + cellSize + cellSize/2
        textpos.centery = heightBuffer + 10 * cellSize + cellSize/2
        screen.blit(text, textpos)

## NLV Button
        pygame.draw.rect(screen, (0, 0, 0), [windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 10 * cellSize, 3 * cellSize, cellSize])
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 10 * cellSize), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 10 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 11 * cellSize), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 11 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 10 * cellSize), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 11 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 10 * cellSize), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 11 * cellSize))
        text = font.render("Next Value", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = windowWidth/2 + widthBuffer + 7 * cellSize + cellSize/2
        textpos.centery = heightBuffer + 10 * cellSize + cellSize/2
        screen.blit(text, textpos)

## Next Puzzle Button
        pygame.draw.rect(screen, (0, 0, 0), [windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 11 * cellSize + cellSize/2, 3 * cellSize, cellSize])
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 11 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 11 * cellSize + cellSize/2))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 12 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 12 * cellSize + cellSize/2))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 11 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 6 * cellSize, heightBuffer + 12 * cellSize + cellSize/2))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 11 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 9 * cellSize, heightBuffer + 12 * cellSize + cellSize/2))
        text = font.render("Next", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = windowWidth/2 + widthBuffer + 7 * cellSize + cellSize/2
        textpos.centery = heightBuffer + 12 * cellSize
        screen.blit(text, textpos)

## Previous Puzzle Button
        pygame.draw.rect(screen, (0, 0, 0), [windowWidth/2 + widthBuffer, heightBuffer + 11 * cellSize + cellSize/2, 3 * cellSize, cellSize])
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 11 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 11 * cellSize + cellSize/2))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 12 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 12 * cellSize + cellSize/2))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 11 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer, heightBuffer + 12 * cellSize + cellSize/2))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 11 * cellSize + cellSize/2), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 12 * cellSize + cellSize/2))
        text = font.render("Previous", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = windowWidth/2 + widthBuffer + cellSize + cellSize/2
        textpos.centery = heightBuffer + 12 * cellSize
        screen.blit(text, textpos)

## Random Puzzle Button
        pygame.draw.rect(screen, (0, 0, 0), [windowWidth/2 + widthBuffer, heightBuffer + 13 * cellSize, 3 * cellSize, cellSize])
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 13 * cellSize), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 13 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 14 * cellSize), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 14 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer, heightBuffer + 13 * cellSize), (windowWidth/2 + widthBuffer, heightBuffer + 14 * cellSize))
        pygame.draw.line(screen, (255, 255, 255), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 13 * cellSize), (windowWidth/2 + widthBuffer + 3 * cellSize, heightBuffer + 14 * cellSize))
        text = font.render("Random", 1, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = windowWidth/2 + widthBuffer + cellSize + cellSize/2
        textpos.centery = heightBuffer + 14 * cellSize - cellSize/2
        screen.blit(text, textpos)

## Dividing line in the middle of the screen.
        pygame.draw.line(screen, black, (windowWidth/ 2, 5), (windowWidth/2, windowHeight - 5))

## Loops for drawing grid and 3x3 square outlines in black.
        for x in range(widthBuffer , widthBuffer + 9 * cellSize + 1, cellSize):
            pygame.draw.line(screen, gridLines, (windowWidth/2 + x, heightBuffer), (windowWidth/2 + x, 9 * cellSize - 1 + heightBuffer))
        for y in range(heightBuffer, heightBuffer + 9 * cellSize + 1, cellSize):
            pygame.draw.line(screen, gridLines, (windowWidth/2 + widthBuffer, y), (windowWidth/2 + 9 * cellSize - 1 + widthBuffer, y))
        for x in range(widthBuffer , widthBuffer + 9 * cellSize + 1, 3 * cellSize):
            pygame.draw.line(screen, black, (windowWidth/2 + x, heightBuffer), (windowWidth/2 + x, 9 * cellSize - 1 + heightBuffer))
        for y in range(heightBuffer, heightBuffer + 9 * cellSize + 1, 3 * cellSize):
            pygame.draw.line(screen, black, (windowWidth/2 + widthBuffer, y), (windowWidth/2 + 9 * cellSize - 1 + widthBuffer, y))
        return None

    def coorMark():
        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
        i = 0
        while i < 9:
            text = font.render('%s' % str(i+1), 1, (0, 0, 0))
            textpos = text.get_rect()
            textpos.centerx = windowWidth/2 + cellHuman[i][0] + cellSize/2
            textpos.centery = cellHuman[i][1] - cellSize/2
            screen.blit(text, textpos)
            i = i + 1

        i = 0
        alpha = "ABCDEFGHI"
        while i < 81:
            text = font.render('%s' % alpha[int(i/9)], 1, (0, 0, 0))
            textpos = text.get_rect()
            textpos.centerx = windowWidth/2 + cellHuman[i][0] - cellSize/2
            textpos.centery = cellHuman[i][1] + cellSize/2
            screen.blit(text, textpos)
            i = i + 9

    def initGridLeft(a):
        "Initialises left-sided grid with values from a, which should be an 81 character string."
        i = 0
        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015)) ## Defines text font and size, None is Pygame default.
        while i < 81:
            text = font.render('%s' % a[i], 1, (0, 0, 0)) ## String in a[i] (In this case, it is a single character) is stored in text. Other attributes are anti-aliasing (1 -> On, 0 -> Off) and colour ((0, 0, 0) is RGB Black).
            textpos = text.get_rect()
## The next bit aligns the x, y centres of the text to the centre of the grid, then blits it onto the surface.
            textpos.centerx = cellHuman[i][0] + cellSize/2
            textpos.centery = cellHuman[i][1] + cellSize/2
            screen.blit(text, textpos)
            i = i + 1

    def initGridRight(a, colour = (0, 0, 0)):
        "Initialises right-sided grid with values from a, which should be an 81 character string."
        i = 0
        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
        while i < 81:
            text = font.render('%s' % a[i], 1, colour)
            textpos = text.get_rect()
            textpos.centerx = cellHuman[i][0] + windowWidth / 2 + cellSize/2
            textpos.centery = cellHuman[i][1] + cellSize/2
            screen.blit(text, textpos)
            i = i + 1

    def emptyGrid(a):
        "Empties grid a (0 for left grid, 1 for right grid)."
        pygame.draw.rect(screen, gridColour, [a * windowWidth/2 + widthBuffer, heightBuffer, 9 * cellSize, 9 * cellSize])
        drawGrid()

    def initCellLeft(a, i):
        "Loads a single cell entry a, into cell i on the left-sided grid."
        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
        text = font.render('%s' % a, 1, (0, 0, 0))
        textpos = text.get_rect()
        textpos.centerx = cellHuman[i][0] + cellSize/2
        textpos.centery = cellHuman[i][1] + cellSize/2
        screen.blit(text, textpos)

    def initCellRight(a, i, colour = (0, 0, 0)):
        "Loads a single cell entry a, into cell i on the right-sided grid."
        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
        text = font.render('%s' % a, 1, colour)
        textpos = text.get_rect()
        textpos.centerx = cellHuman[i][0] + windowWidth / 2 + cellSize/2
        textpos.centery = cellHuman[i][1] + cellSize/2
        screen.blit(text, textpos)

#---------------------------------Draw Methods---------------------------------#

## Execution starts here.
    drawGrid() ## Sets up both grids and dividing line.
    grid = []
    f = open('Puzzles.txt', 'r')
    for line in f:
        grid.append(line)
    f.close()
    puzzleNo = random.randrange(0, len(grid))
    del solvedCells[:]
    coorMark()
    a = grid[puzzleNo]
    i = 0
    playerSolution = list(a)
    b = genSol(a)
    initGridLeft(a)
    initGridRight(a)
    pygame.display.update()
    value = " "
    initGridRight(a)
    pygame.display.update()

## Event loop, keeps the everything as is until QUIT button is hit.
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEBUTTONDOWN:
                if writeButtons(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    value = writeButtons(pygame.mouse.get_pos())

                elif clearButton(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    value = clearButton(pygame.mouse.get_pos())

                elif writing(a, playerSolution, value, pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    if ' ' not in playerSolution:
                        if "".join(playerSolution[0:81]) == decodeDict(b):
                            compMesg = "Correct Solution!"
                        else:
                            compMesg = "Sorry :( Wrong Answer"
                        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
                        text = font.render('%s' % compMesg, 1, (0, 0, 0))
                        textpos = text.get_rect()
                        textpos.centerx = (windowWidth/2)/2
                        textpos.centery = heightBuffer/2
                        screen.blit(text, textpos)

                elif RESET(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    emptyGrid(0)
                    initGridLeft(a)
                    pygame.display.update()

                elif PREVIOUSPUZZLE(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    del solvedCells[:]
                    emptyGrid(0)
                    emptyGrid(1)
                    if puzzleNo == 0:
                        puzzleNo = len(grid) - 1
                    else:
                        puzzleNo = puzzleNo - 1
                    a = grid[puzzleNo]
                    i = 0
                    playerSolution = list(a)
                    b = genSol(a)
                    initGridLeft(a)
                    initGridRight(a)

                elif NEXTPUZZLE(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    del solvedCells[:]
                    emptyGrid(0)
                    emptyGrid(1)
                    if puzzleNo == len(grid) - 1:
                        puzzleNo = 0
                    else:
                        puzzleNo = puzzleNo + 1
                    a = grid[puzzleNo]
                    i = 0
                    playerSolution = list(a)
                    b = genSol(a)
                    initGridLeft(a)
                    initGridRight(a)

                elif RANDOMPUZZLE(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    del solvedCells[:]
                    emptyGrid(0)
                    emptyGrid(1)
                    puzzleNo = random.randrange(0, len(grid))
                    a = grid[puzzleNo]
                    i = 0
                    playerSolution = list(a)
                    b = genSol(a)
                    initGridLeft(a)
                    initGridRight(a)

                elif QUIT(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    pygame.quit()
                    sys.exit()

                elif NLV(pygame.mouse.get_pos()):
                    pygame.draw.rect(screen, background, [0, 0, windowWidth/2 - 1, heightBuffer - 1])
                    pygame.draw.rect(screen, background, [windowWidth/2 + 1, cellSize + 1, windowWidth/2 - 1, heightBuffer - 2*cellSize])
                    if i >= 81:
                        break
                    while list(a)[square2Cell(solvedCells[i][0])] == solvedCells[i][1] and i < len(solvedCells):
                        i = i + 1
                    if a[square2Cell(solvedCells[i][0])] == " " and i < len(solvedCells):
                        font = pygame.font.Font("FreeSans.ttf", int(windowWidth * 0.015))
                        mesg =  solvedCells[i][1] + " in " + solvedCells[i][0]
                        if solvedCells[i][2] == 0:
                            mesg = mesg + " using elimination."
                        elif solvedCells[i][2] == 1:
                            mesg = mesg + " using backtracking."
                        else:
                            mesg = mesg + " as no value other than " + solvedCells[i][1] + " fits in that cell."
                        text = font.render('%s' % mesg, 1, (0, 0, 0))
                        textpos = text.get_rect()
                        textpos.centerx = windowWidth/2 + (windowWidth/2)/2
                        textpos.centery = heightBuffer/2
                        screen.blit(text, textpos)
                        initCellRight(solvedCells[i][1], square2Cell(solvedCells[i][0]), (150, 150, 150))
                        pygame.display.update()
                        pygame.time.delay(100) ## Change TD to Button.
                    i = i + 1
        pygame.display.update()
        fpsLock.tick(fps) ## Refreshes the screen 'fps' times per second.

if __name__ == '__main__':
    main()


"""
@author Chr.yl
    使用套接字,客户端
"""
import socket

tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接
tcp_client.connect(('127.0.0.1', 8080))
file_name = input('请输入要下载的文件名:\n')
# 发送文件名
tcp_client.send(file_name.encode())
with open('/Users/chryl/upload/20200329/' + file_name, 'wb') as file:
    while True:
        file_data = tcp_client.recv(1024)
        # 判断是否传输完成
        if file_data:
            file.write(file_data)
        else:
            break

tcp_client.close()


def combine_res(bed_in_dir1,bed_in_dir2,bed_in_dir3,bed_out_dir):
	f1=open(bed_in_dir1)
	f2=open(bed_in_dir2)
	f3=open(bed_in_dir3)
	fo=open(bed_out_dir,'w')
	whole=[]
	for line in f1:
		seq=line.replace('\n','').split('\t')
		whole.append([seq[0],int(seq[2]),seq[3],seq[4],seq[5]])
	for line in f2:
		seq=line.replace('\n','').split('\t')
		whole.append([seq[0],int(seq[2]),seq[3],seq[4],seq[5]])
	for line in f3:
		seq=line.replace('\n','').split('\t')
		whole.append([seq[0],int(seq[2]),seq[3],seq[4],seq[5]])
	whole.sort()
	for one in whole:
		fo.write(one[0]+'\t'+str(one[1]-1)+'\t'+str(one[1])+'\t'+one[2]+'\t'+one[3]+'\t'+one[4]+'\n')
	f1.close()
	f2.close()
	f3.close()
	fo.close()


import os
import matplotlib.pyplot as plt
import csv
import numpy as np
import math
import unicodedata

problemy = ["MST", "SP", "MF"]
algorytmy = {
    "MF": ["Ford-Fulkerson-BFS", "Ford-Fulkerson-DFS"],
    "MST": ["Kruskal", "Prim"],
    "SP": ["Dijkstra", "Bellman-Ford"]
}

"""
Wczytywanie plików csv z danymi
"""
sciezka = os.getcwd()
listaPlikow = []
for root, dirs, files in os.walk(sciezka+'\\Dane\\'):
    for file in files:
        if file.endswith(".csv"):
             listaPlikow.append(os.path.join(root, file))

#print(listaPlikow)

print("Autor: Mikołaj Chmielecki")
print("Generowanie wykresów na podstawie plików csv z aktualnego katalogu...")

listaListDanych = []
listaTytulow = []
"""
Tworzenie listy list plików do każdego wykresu
"""
nrProblemu = 0
for problem in problemy:
    for i in range(6):
        listaListDanych.append([])
    listaTytulow.append(problem + " - macierz sąsiedztwa")
    listaTytulow.append(problem + " - lista sąsiedztwa")
    listaTytulow.append(problem + " - gęstość 25%")
    listaTytulow.append(problem + " - gęstość 50%")
    listaTytulow.append(problem + " - gęstość 75%")
    listaTytulow.append(problem + " - gęstość 99%")
    for plik in listaPlikow:
        head, tail = os.path.split(plik)
        plikName = tail
        if (algorytmy[problem][0] in plikName or algorytmy[problem][1] in plikName):
            if "macierz" in plik:
                listaListDanych[nrProblemu*6].append(plik)
            if "lista" in plik:
                listaListDanych[nrProblemu*6+1].append(plik)
            if "25" in plik:
                listaListDanych[nrProblemu*6+2].append(plik)
            if "50" in plik:
                listaListDanych[nrProblemu*6+3].append(plik)
            if "75" in plik:
                listaListDanych[nrProblemu*6+4].append(plik)
            if "99" in plik:
                listaListDanych[nrProblemu*6+5].append(plik)

    nrProblemu += 1

"""
Generowanie wykresu dla każdego pliku z danymi
"""
licznikWykresu = 0
for lista in listaListDanych:
    plt.close()
    plt.title(listaTytulow[licznikWykresu])

    for plik in lista:

        liczbaElemetnow = []
        czasOperacji = []
        nazwa = ""
        """
        Otwieranie pliku z danymi
        """
        with open(plik, 'r') as csvfile:
            plots = csv.reader(csvfile, delimiter=';')
            i = 0
            """
            Czytanie kolejnych wierszy
            """
            for row in plots:
                if i == 0:
                    nazwa = row[0]
                else:
                    liczbaElemetnow.append(int(row[0]))
                    czasOperacji.append(float(row[1].replace(',', '.')))
                i += 1

        nowaLista = [x / 1000 for x in czasOperacji]
        czasOperacji = nowaLista[:]
        jednostka = "ms"
        """
        jednostka = "µs"
        if  max(czasOperacji) > 999:
            nowaLista = [x/1000 for x in czasOperacji]
            czasOperacji = nowaLista[:]
            jednostka = "ms"
        if max(czasOperacji) > 999:
            nowaLista = [x/1000 for x in czasOperacji]
            czasOperacji = nowaLista[:]
            jednostka = "s"
        """

        plt.plot(liczbaElemetnow, czasOperacji, marker='o', label=nazwa)
        plt.xticks(liczbaElemetnow)
        plt.xlabel('Liczba elementów')
        plt.ylabel(f'Czas operacji [{jednostka}]')

    #plt.ticklabel_format(useOffset=False, style='plain')
    plt.legend()
    plt.tight_layout()
    normalize = unicodedata.normalize('NFD', listaTytulow[licznikWykresu]).encode('ascii', 'ignore')
    plt.savefig("Dane/" + str(normalize).replace("b\'","").replace("\'","").replace("%","") + ".pdf" )
    plt.close()
    licznikWykresu += 1

print("Generowanie zakończone")


import pytest
import System
import Student

def test_viewAssignments(student_system):
    course = 'fakeCourse'
    assert student_system.view_assignments(course)

@pytest.fixture
def student_system():
    gradingSystem = System.System()
    gradingSystem.load_data()
    name = 'akend3'
    studentSystem = Student.Student(name, gradingSystem.users, gradingSystem.courses)
    return studentSystem


from sklearn.model_selection import train_test_split
import xgboost as xgb
import numpy as np
import pandas as pd

def read_data(TRAIN_DIR, TEST_DIR, nrows=None):
    data_train = pd.read_csv(TRAIN_DIR,
                             parse_dates=["pickup_datetime",
                                          "dropoff_datetime"],
                             nrows=nrows)
    data_test = pd.read_csv(TEST_DIR,
                            parse_dates=["pickup_datetime"],
                            nrows=nrows)
    data_train = data_train.drop(['dropoff_datetime'], axis=1)
    data_train.loc[:, 'store_and_fwd_flag'] = data_train['store_and_fwd_flag'].map({'Y': True,
                                                                                'N': False})
    data_test.loc[:, 'store_and_fwd_flag'] = data_test['store_and_fwd_flag'].map({'Y': True,
                                                                                'N': False})
    data_train = data_train[data_train.trip_duration < data_train.trip_duration.quantile(0.99)]

    xlim = [-74.03, -73.77]
    ylim = [40.63, 40.85]
    data_train = data_train[(data_train.pickup_longitude> xlim[0]) & (data_train.pickup_longitude < xlim[1])]
    data_train = data_train[(data_train.dropoff_longitude> xlim[0]) & (data_train.dropoff_longitude < xlim[1])]
    data_train = data_train[(data_train.pickup_latitude> ylim[0]) & (data_train.pickup_latitude < ylim[1])]
    data_train = data_train[(data_train.dropoff_latitude> ylim[0]) & (data_train.dropoff_latitude < ylim[1])]

    return (data_train, data_test)

def train_xgb(X_train, labels):
    Xtr, Xv, ytr, yv = train_test_split(X_train.values,
                                        labels,
                                        test_size=0.2,
                                        random_state=0)

    dtrain = xgb.DMatrix(Xtr, label=ytr)
    dvalid = xgb.DMatrix(Xv, label=yv)

    evals = [(dtrain, 'train'), (dvalid, 'valid')]

    params = {
        'min_child_weight': 1, 'eta': 0.166,
        'colsample_bytree': 0.4, 'max_depth': 9,
        'subsample': 1.0, 'lambda': 57.93,
        'booster': 'gbtree', 'gamma': 0.5,
        'silent': 1, 'eval_metric': 'rmse',
        'objective': 'reg:linear',
    }

    model = xgb.train(params=params, dtrain=dtrain, num_boost_round=60, #227,
                      evals=evals, early_stopping_rounds=60, maximize=False,
                      verbose_eval=10)

    print('Modeling RMSE %.5f' % model.best_score)
    return model

def predict_xgb(model, X_test):
    dtest = xgb.DMatrix(X_test.values)
    ytest = model.predict(dtest)
    X_test['trip_duration'] = np.exp(ytest) - 1
    return X_test[['trip_duration']]

def feature_importances(model, feature_names):
    feature_importance_dict = model.get_fscore()
    fs = ['f%i' % i for i in range(len(feature_names))]
    f1 = pd.DataFrame({'f': list(feature_importance_dict.keys()),
                       'importance': list(feature_importance_dict.values())})
    f2 = pd.DataFrame({'f': fs, 'feature_name': feature_names})
    feature_importance = pd.merge(f1, f2, how='right', on='f')
    feature_importance = feature_importance.fillna(0)
    return feature_importance[['feature_name', 'importance']].sort_values(by='importance',
                                                                          ascending=False)

def get_train_test_fm(feature_matrix):
    X_train = feature_matrix[feature_matrix['test_data'] == False]
    X_train = X_train.drop(['test_data'], axis=1)
    labels = X_train['trip_duration']
    X_train = X_train.drop(['trip_duration'], axis=1)
    X_test = feature_matrix[feature_matrix['test_data'] == True]
    X_test = X_test.drop(['test_data', 'trip_duration'], axis=1)
    return (X_train, labels, X_test)

def duplicate_columns(frame):
    groups = frame.columns.to_series().groupby(frame.dtypes).groups
    dups = []
    for t, v in groups.items():
        dcols = frame[v].to_dict(orient="list")

        vs = dcols.values()
        ks = dcols.keys()
        lvs = len(vs)

        for i in range(lvs):
            for j in range(i+1,lvs):
                if vs[i] == vs[j]:
                    dups.append(ks[i])
                    break
    return dups


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

import re
import six
import sys
import unicodedata
from typing import List, Sequence

from .bleu_util import compute_bleu
from .metric import metric_registry

class UnicodeRegex(object):
    """Ad-hoc hack to recognize all punctuation and symbols.

    Attributes:
        nondigit_punct_re: The compiled regular expressions to recognize
          punctuation preceded with a digit.
        punct_nondigit_re: The compiled regular expressions to recognize
          punctuation followed by a digit.
        symbol_re: The compiled regular expressions to recognize symbols.
    """

    def __init__(self) -> None:
        """Initialize the regular expressions."""
        punctuation = self.property_chars("P")
        self.nondigit_punct_re = re.compile(r"([^\d])([" + punctuation + r"])")
        self.punct_nondigit_re = re.compile(r"([" + punctuation + r"])([^\d])")
        self.symbol_re = re.compile("([" + self.property_chars("S") + "])")

    def property_chars(self, prefix: str) -> str:
        """Collect all Unicode strings starting with a specific prefix.

        Args:
            prefix: The specific prefix.

        Returns:
            punctuation: The join result of all Unicode strings starting
              with a specific prefix.
        """
        punctuation = "".join(six.unichr(x) for x in range(sys.maxunicode) \
                              if unicodedata.category(six.unichr(x)).startswith(prefix))
        return punctuation

uregex = UnicodeRegex()

def bleu_tokenize(string: str) -> List[str]:
    """Tokenize a string following the official BLEU implementation.

    See https://github.com/moses-smt/mosesdecoder/"
            "blob/master/scripts/generic/mteval-v14.pl#L954-L983

    Args:
        string: The string to be tokenized.

    Returns:
        tokens: A list of tokens.
    """
    string = uregex.nondigit_punct_re.sub(r"\1 \2 ", string)
    string = uregex.punct_nondigit_re.sub(r" \1 \2", string)
    string = uregex.symbol_re.sub(r" \1 ", string)
    tokens = string.split()
    return tokens

@metric_registry('BLEU', 'tensorflow, tensorflow_itex')
class BLEU(object):
    """Computes the BLEU (Bilingual Evaluation Understudy) score.

    BLEU is an algorithm for evaluating the quality of text which has
    been machine-translated from one natural language to another.
    This implementent approximate the BLEU score since we do not
    glue word pieces or decode the ids and tokenize the output.
    By default, we use ngram order of 4 and use brevity penalty.
    Also, this does not have beam search.

    Attributes:
        predictions: List of translations to score.
        labels: List of the reference corresponding to the prediction result.
    """

    def __init__(self) -> None:
        """Initialize predictions and labels."""
        self.predictions = []
        self.labels = []

    def reset(self) -> None:
        """Clear the predictions and labels in the cache."""
        self.predictions = []
        self.labels = []

    def update(self, prediction: Sequence[str], label: Sequence[str]) -> None:
        """Add the prediction and label.

        Args:
            prediction: The prediction result.
            label: The reference corresponding to the prediction result.

        Raises:
            ValueError: An error occurred when the length of the prediction
            and label are different.
        """
        if len(label) != len(prediction):
            raise ValueError("Reference and prediction files have different number "
                             "of lines. If training only a few steps (100-200), the "
                             "translation may be empty.")
        label = [x.lower() for x in label]
        prediction = [x.lower() for x in prediction]
        label = [bleu_tokenize(x) for x in label]
        prediction = [bleu_tokenize(x) for x in prediction]
        self.labels.extend(label)
        self.predictions.extend(prediction)

    def result(self) -> float:
        """Compute the BLEU score.

        Returns:
            bleu_score: The approximate BLEU score.
        """
        bleu_score = compute_bleu(self.labels, self.predictions) * 100
        return bleu_score


# -*- coding: utf-8 -*-
"""
Created on Wed Jan 13 11:32:13 2021

@author: Hrishi_rich
"""
# import computer vision library
import cv2

# Face & Smile Classifier
face_detector = cv2.CascadeClassifier('frontalface_default.xml')
smile_detector = cv2.CascadeClassifier('haarcascade_smile.xml')

# Grab Webcam
webcam = cv2.VideoCapture(0) #'Why_so_serious.mp4'

# Show the current frame
while True:

    # Read current frame from webcam
    successful_frame_read, frame = webcam.read()

    # If there's an error abort
    if not successful_frame_read:
        break

    # Change to grayscale
    frame_grayscale = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Detect faces
    faces = face_detector.detectMultiScale(frame_grayscale)

    # Run face detection within each of those faces
    for (x, y, w, h) in faces:

        # Draw a rectangle around the face
        cv2.rectangle(frame, (x, y), (x+w, y+h), (100, 200, 50), 2)

        # Get the sub frame (using numpy N-dimensional array slicing)
        the_face = frame[y:y+h, x:x+w]

        # Change to grayscale
        face_grayscale = cv2.cvtColor(the_face, cv2.COLOR_BGR2GRAY)

        smile = smile_detector.detectMultiScale(face_grayscale, scaleFactor=1.7, minNeighbors=20)

        # Lable this faces as smiling
        if len(smile) > 0:
            cv2.putText(frame, 'smiling', (x, y+h+40), fontScale=3, fontFace=cv2.FONT_HERSHEY_PLAIN, color=(255, 255, 255))

# Show the current frame
cv2.imshow('Smile Detector', frame)

# Display
cv2.waitkey(1)

#cleanup
webcam.release()
cv2.destroyAllWindows()

print("code complete")


import re

with open('input.txt', 'r') as f:
    lines = sorted(f.readlines())

    extract_numbers = re.compile(r'\d+')
    # DATE id
    # DATE F
    # DATE W
    def extract(line):
        nums = re.findall(extract_numbers, line)
        nums = list(map(int, nums))
        if "falls asleep" in line:
            nums.append('F')
        elif "wakes up" in line:
            nums.append('W')
        return nums

    def elapsed_time(time1, time2):
        year1, month1, day1, hour1, minute1, _ = time1
        year2, month2, day2, hour2, minute2, _ = time2
        return minute2 - minute1

    guards = {}
    prev_time = extract(lines[0])
    cur_guard = prev_time[-1]
    is_awake = True
    for line in lines[1:]:
        cur_time = extract(line)

        action = cur_time[-1]
        if action == 'F':
            is_awake = False
        elif action == 'W':
            is_awake = True

            if cur_guard not in guards:
                guards[cur_guard] = 0
            guards[cur_guard] += elapsed_time(prev_time, cur_time)
        else:
            cur_guard = action
            is_awake = True

        prev_time = cur_time

    sleepiest = sorted(guards.items(), key = lambda item: item[1])[-1][0]
    asleep = [0] * 60

    prev_time = extract(lines[0])
    cur_guard = prev_time[-1]
    is_awake = True
    for line in lines[1:]:
        cur_time = extract(line)

        action = cur_time[-1]
        if action == 'F':
            is_awake = False
        elif action == 'W':
            is_awake = True

            if cur_guard == sleepiest:
                for minute in range(prev_time[4], cur_time[4]):
                    asleep[minute] += 1
        else:
            cur_guard = action
            is_awake = True

        prev_time = cur_time

    most = max(asleep)

    for  minute, count in enumerate(asleep):
        if count == most:
            print(minute * sleepiest)
            break

    # Part 2
    sleepmins = {}
    prev_time = extract(lines[0])
    cur_guard = prev_time[-1]
    is_awake = True
    for line in lines[1:]:
        cur_time = extract(line)

        action = cur_time[-1]
        if action == 'F':
            is_awake = False
        elif action == 'W':
            is_awake = True

            if not cur_guard in sleepmins:
                sleepmins[cur_guard] = [0] * 60
            for minute in range(prev_time[4], cur_time[4]):
                sleepmins[cur_guard][minute] += 1
        else:
            cur_guard = action
            is_awake = True

        prev_time = cur_time

    sleepy_guard, most, sleepiest_min = None, 0, 0
    for guard, minutes in sleepmins.items():
        for m, count in enumerate(minutes):
            if count > most:
                most = count
                sleepy_guard = guard
                sleepiest_min = m

    print(sleepy_guard, sleepiest_min, sleepy_guard * sleepiest_min)


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

import copy
import logging

from oslo_config import cfg

from cloudferry.lib.base.action import converter
from cloudferry.lib.utils import utils as utl

CONF = cfg.CONF
LOG = logging.getLogger(__name__)
CEPH = 'ceph'
ACTIVE = 'active'
BARE = "bare"

def require_methods(methods, obj):
    for method in methods:
        if method not in dir(obj):
            return False
    return True

class ConvertVolumeToImage(converter.Converter):
    def run(self, storage_info=None, **kwargs):
        disk_format = self.cfg.migrate.disk_format
        container_format = self.cfg.migrate.container_format
        volumes_info = storage_info and copy.deepcopy(storage_info) or {}
        resource_storage = self.cloud.resources[utl.STORAGE_RESOURCE]
        resource_image = self.cloud.resources[utl.IMAGE_RESOURCE]
        images_info = {}
        if not require_methods(['upload_volume_to_image'], resource_storage):
            raise RuntimeError("No require methods")
        images_from_volumes = {}
        for volume in volumes_info[utl.VOLUMES_TYPE].values():
            vol = volume['volume']
            LOG.debug(
                "| | uploading volume %s [%s] to image service bootable=%s",
                vol['display_name'], vol['id'],
                vol['bootable'] if hasattr(vol, 'bootable') else False)
            _, image_id = resource_storage.upload_volume_to_image(
                vol['id'], force=True, image_name=vol['id'],
                container_format=container_format,
                disk_format=disk_format)
            timeout = CONF.migrate.storage_backend_timeout
            resource_image.wait_for_status(image_id,
                                           resource_image.get_status,
                                           ACTIVE, timeout=timeout)
            resource_image.patch_image(resource_image.get_backend(), image_id)
            image_vol = resource_image.get_image_by_id_converted(image_id)
            img_new = {
                utl.IMAGE_BODY: (
                    image_vol[utl.IMAGES_TYPE][image_id][utl.IMAGE_BODY]),
                utl.META_INFO: volume[utl.META_INFO]
            }
            img_new[utl.META_INFO][utl.VOLUME_BODY] = vol
            images_from_volumes[image_id] = img_new
        images_info[utl.IMAGES_TYPE] = images_from_volumes
        return {
            'images_info': images_info
        }


'''
PR 2.4: Ciferný súčet (Ľubovoľné číslo)

Vstup: celé kladné číslo.

Výstup: ciferný súčet tohto čísla.

Overenie: číslo 1236544 => ciferný súčet je 25

PR 2.5: Prevrátené číslo (ľubovoľné číslo)

Vstup: celé kladné číslo (ľubovoľný počet cifier).

Výstup: prevrátené číslo (číslo napísané odzadu).
'''

cislo = int(input("Zadajte cislo: "))
cif_sucet = 0
obratene = ""

while cislo > 0:
	x = cislo % 10
	cif_sucet += x
	obratene += str(x)
	cislo //= 10
print(f"Ciferny sucet: {cif_sucet}")
print(f"Obratene k {obratene[::-1]}: {obratene}")


import pandas as pd

body_url = 'https://raw.githubusercontent.com/wmgriffi3/barbell-beasts/master/FitNotes_BodyTracker_Export.csv'
body_data = pd.read_csv(body_url, error_bad_lines=False)

standards_url = 'https://raw.githubusercontent.com/wmgriffi3/barbell-beasts/master/weight_lifting_standards.csv'
standards_data = pd.read_csv(standards_url, error_bad_lines=False)

exercise_url = 'https://raw.githubusercontent.com/wmgriffi3/barbell-beasts/master/FitNotes_Export.csv'
exercise_data = pd.read_csv(exercise_url, error_bad_lines=False)

body_data.head()
standards_data.head()
exercise_data.head()

from io import BytesIO

import requests
r = requests.get('https://docs.google.com/spreadsheets/d/e/2PACX-1vQmHR9YOt6BhTolpVXR9m8eVSHM-2AnPmhVhYypo2liHRpZ1REQeEtE5rEoBQQfQfCt-5MGk6bU1ipQ/pub?output=csv')
data = r.content

dataf = pd.read_csv(BytesIO(data), index_col=0)

dataf.head()


from math import ceil

# O_i: the original sequence that is all 'L' except one 'G' at i-th tile.
# F_i: final artwork from O_i (with complexity C)
# We only need to consider cases of {C_i}_{0 <= i < K}.
#   Necessity: obvious;
#   Sufficiency: any original pattern with 'G' at j-th tile must have 'G'
#                anywhere F_j has 'G'.
# F_i has 'G' at j-th tile iff j, written in base K with C digits, has digit i.
#   Let c' be the index of i's first occrence (left to right) in j (base K). Then
#   the triangle that contains this 'G' starts at complexity level c'.
#   Notice j, written in base K, has C digits.
def find(k, c, s):
    if s < ceil(k / c):
        return None
    places = []
    i = j = 0
    while i < k:
        j = k * j + i
        i += 1
        if i % c == 0:
            places.append(j)
            j = 0
    if k % c > 0:
        places.append(j)
    return places

f = open('D-small-attempt0.in', 'r')
o = open('D.out', 'w')

m = int(f.readline().strip())
i = 1

while i <= m:
    k, c, s = list(map(int, next(f).split()))
    places = find(k, c, s)
    if places == None:
        print('Case #{0}: IMPOSSIBLE'.format(i), file = o)
    else:
        one_indexed_str = ' '.join(map(lambda p: str(p + 1), places))
        print('Case #{0}: {1}'.format(i, one_indexed_str), file = o)
    i += 1

f.close()
o.close()


import sys
import sqlite3
sys.path.append('/afs/cern.ch/cms/PPD/PdmV/tools/McM/')
from rest import McM

# McM instance
mcm = McM(dev=False)

def pick_chained_requests(chained_requests):
    """
    Select chained requests with newest NanoAOD version
    """
    tree = {}
    selected_chained_requests = []
    for chained_request in chained_requests:
        steps = chained_request_to_steps(chained_request)
        mini_step = steps.get('miniaod')
        nano_step = steps.get('nanoaod')
        if mini_step is None or nano_step is None:
            selected_chained_requests.append(chained_request)
            continue

        mini_step = mini_step.split('-')[1]
        nano_step = nano_step.split('-')[1]
        if mini_step not in tree:
            tree[mini_step] = {}

        if nano_step not in tree[mini_step]:
            tree[mini_step][nano_step] = []

        tree[mini_step][nano_step].append(chained_request)

    for mini_campaign in tree:
        print('  %s' % (mini_campaign))
        nano_campaigns = sorted(tree[mini_campaign].keys())
        for n in nano_campaigns:
            print('    %s' % (n))

        selected_chained_requests.extend(tree[mini_campaign][nano_campaigns[-1]])

    if len(chained_requests) > 1:
        prepids = [x['prepid'] for x in chained_requests]
        selected_prepids = [x['prepid'] for x in selected_chained_requests]
        for p in prepids:
            print('%s %s' % ('*' if p in selected_prepids else ' ', p))

    return selected_chained_requests

def chained_request_to_steps(chained_request):
    """
    Split chained request into dictionary of step prepids
    """
    steps = {}
    for req_prepid in chained_request['chain']:
        if 'pLHE' in req_prepid:
            steps['plhe'] = req_prepid
        elif 'GS' in req_prepid:
            steps['gs'] = req_prepid
        elif 'DR' in req_prepid:
            steps['dr'] = req_prepid
        elif 'MiniAOD' in req_prepid:
            steps['miniaod'] = req_prepid
        elif 'NanoAOD' in req_prepid:
            steps['nanoaod'] = req_prepid

    return steps

def get_sample_if_exists(sql_args, cursor, table):
    campaign = sql_args[0]
    chained_request_prepid = sql_args[2]
    dataset_name = sql_args[3]
    root_request_prepid = sql_args[4]
    campaign_equals = '=' if campaign is not None else 'IS'
    chained_request_equals = '=' if chained_request_prepid is not None else 'IS'
    dataset_equals = '=' if dataset_name is not None else 'IS'
    root_request_equals = '=' if root_request_prepid is not None else 'IS'
    rows = [r for r in cursor.execute('''SELECT uid, interested_pwgs, original_interested_pwgs, root_request, miniaod, notes
                                         FROM %s
                                         WHERE campaign %s ? AND
                                               chained_request %s ? AND
                                               dataset %s ? AND
                                               root_request %s ?''' % (table,
                                                                       campaign_equals,
                                                                       chained_request_equals,
                                                                       dataset_equals,
                                                                       root_request_equals),
                                      [campaign,
                                       chained_request_prepid,
                                       dataset_name,
                                       root_request_prepid])]
    return rows

def insert_or_update(sql_args, cursor, table):
    """
    0. campaign,
    1. campaign_group
    2. chained_request_prepid
    3. dataset_name
    4. root_request_prepid
    5. root_request_priority
    6. root_request_total_events
    7. root_request_done_events
    8. root_request_status
    9. root_request_output
    10. miniaod_prepid
    11. miniaod_priority
    12. miniaod_total_events
    13. miniaod_done_events
    14. miniaod_status
    15. miniaod_output
    16. interested_pwgs
    17. original_interested_pwgs
    18. notes
    """
    existing_sample = get_sample_if_exists(sql_args, cursor, table)
    nice_description = '%s %s %s %s' % (sql_args[0], sql_args[2], sql_args[3], sql_args[4])
    if len(existing_sample) > 1:
        print('Something bad, there are multiple %s in %s' % (nice_description, table))
        print(existing_sample)
        return

    if len(existing_sample) == 1:
        existing_sample = existing_sample[0]
        if table == 'samples':
            current_interested_pwgs = set([x.strip().upper() for x in existing_sample[1].split(',') if x.strip()])
            original_interested_pwgs = set([x.strip().upper() for x in existing_sample[2].split(',') if x.strip()])
            current_notes = existing_sample[5]
            # Get root request or MiniAOD request from McM that was used before
            mcm_request = mcm.get('requests', existing_sample[4] if existing_sample[4] else existing_sample[3])
            print('Will check %s' % (mcm_request['prepid']))
            mcm_interested_pwgs = set([x.strip().upper() for x in mcm_request.get('interested_pwg', [])])
            samples_added = current_interested_pwgs - original_interested_pwgs
            samples_removed = original_interested_pwgs - current_interested_pwgs
            mcm_added = mcm_interested_pwgs - original_interested_pwgs
            mcm_removed = original_interested_pwgs - mcm_interested_pwgs
            all_added = samples_added.union(mcm_added)
            all_removed = samples_removed.union(mcm_removed)
            new_pwgs = (original_interested_pwgs - all_removed).union(all_added)
            original_interested_pwgs_string = ','.join(sorted(original_interested_pwgs))
            new_interested_pwgs_string = ','.join(sorted(new_pwgs))
            mcm_notes = mcm_request.get('notes')
            if original_interested_pwgs_string != new_interested_pwgs_string or mcm_notes != current_notes:
                print('Interested PWGs:')
                print('  Reference: %s' % (','.join(original_interested_pwgs)))
                print('  Samples added: %s' % (','.join(samples_added)))
                print('  Samples removed: %s' % (','.join(samples_removed)))
                print('  McM added: %s' % (','.join(mcm_added)))
                print('  McM removed: %s' % (','.join(mcm_removed)))
                print('  All added: %s' % (','.join(all_added)))
                print('  All removed: %s' % (','.join(all_removed)))
                print('  New PWGs: %s' % (','.join(new_pwgs)))
                print('%s must be updated in McM. Set interested PWGs to %s' % (mcm_request['prepid'], new_interested_pwgs_string))
                print('%s must be updated in McM. Set notes to %s' % (mcm_request['prepid'], current_notes))
                mcm_request['interested_pwg'] = list(new_pwgs)
                mcm_request['notes'] = current_notes
                print(mcm.update('requests', mcm_request))
                new_request = sql_args[10] if sql_args[10] else sql_args[4]
                if new_request == mcm_request['prepid']:
                    sql_args[16] = sql_args[17] = new_interested_pwgs_string

        # interested_pwgs = ','.join(sorted(x.strip().upper() for x in sql_args[14].split(',') if x.strip()))
        # if table == 'samples' and samples_interested_pwgs != interested_pwgs:
        #     miniaod_prepid = sql_args[9]
        #     print('This must be updated in McM. %s != %s' % (samples_interested_pwgs, interested_pwgs))
        #     if miniaod_prepid:
        #         req = mcm.get('requests', miniaod_prepid)
        #     else:
        #         req = mcm.get('requests', root_request_prepid)

        #     req['interested_pwg'] = [x for x in samples_interested_pwgs.split(',') if x.strip()]
        #     print(mcm.update('requests', req))
        #     sql_args[14] = samples_interested_pwgs

        print('Updating %s' % (nice_description))
        sql_args.append(existing_sample[0])
        cursor.execute('''UPDATE %s
                          SET campaign = ?,
                              campaign_group = ?,
                              chained_request = ?,
                              dataset = ?,
                              root_request = ?,
                              root_request_priority = ?,
                              root_request_total_events = ?,
                              root_request_done_events = ?,
                              root_request_status = ?,
                              root_request_output = ?,
                              miniaod = ?,
                              miniaod_priority = ?,
                              miniaod_total_events = ?,
                              miniaod_done_events = ?,
                              miniaod_status = ?,
                              miniaod_output = ?,
                              interested_pwgs = ?,
                              original_interested_pwgs = ?,
                              notes = ? WHERE uid = ?''' % (table), sql_args)
    else:
        print('Inserting %s' % (nice_description))
        cursor.execute('''INSERT INTO %s
                          VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)''' % (table), sql_args)

def process_request(request, campaign, cursor, table):
    campaign_group = campaign.replace('wmLHEGEN', '').replace('wmLHEGS', '').replace('pLHE', '').replace('GEN', '').replace('GS', '')
    if len(request['member_of_chain']) == 0:
        # Create a fake chain request
        chained_requests = [{'prepid': None,
                             'chain': [request['prepid']]}]
    else:
        chained_requests = []
        for chained_request_prepid in request['member_of_chain']:
            chained_request = mcm.get('chained_requests', chained_request_prepid)
            if chained_request:
                chained_requests.append(chained_request)
            else:
                print('No %s?' % (chained_request_prepid))

        chained_requests = pick_chained_requests(chained_requests)

    for chained_request in chained_requests:
        steps = chained_request_to_steps(chained_request)
        chained_request_prepid = chained_request['prepid']
        root_request_prepid = chained_request['chain'][0]
        root_request = mcm.get('requests', root_request_prepid)
        dataset_name = root_request['dataset_name']
        root_request_priority = root_request['priority']
        root_request_total_events = root_request['total_events']
        root_request_done_events = root_request['completed_events']
        root_request_status = root_request['status']
        root_request_output = None
        if root_request['output_dataset']:
            root_request_output = root_request['output_dataset'][-1]

        miniaod_prepid = steps.get('miniaod')
        if miniaod_prepid:
            miniaod_request = mcm.get('requests', miniaod_prepid)
        else:
            miniaod_request = {}

        miniaod_priority = miniaod_request.get('priority')
        miniaod_total_events = miniaod_request.get('total_events')
        miniaod_done_events = miniaod_request.get('completed_events')
        miniaod_status = miniaod_request.get('status')
        miniaod_output = None
        if miniaod_request:
            # If MiniAOD exists, use MiniAOD interested PWGs
            interested_pwgs = ','.join(miniaod_request.get('interested_pwg', []))
            notes = miniaod_request.get('notes')

            if miniaod_request['output_dataset']:
                miniaod_output = miniaod_request['output_dataset'][-1]
        else:
            # If MiniAOD does not exist, use root request PWGs
            interested_pwgs = ','.join(root_request.get('interested_pwg', []))
            notes = root_request.get('notes')

        sql_args = [campaign,
                    campaign_group,
                    chained_request_prepid,
                    dataset_name,
                    root_request_prepid,
                    root_request_priority,
                    root_request_total_events,
                    root_request_done_events,
                    root_request_status,
                    root_request_output,
                    miniaod_prepid,
                    miniaod_priority,
                    miniaod_total_events,
                    miniaod_done_events,
                    miniaod_status,
                    miniaod_output,
                    interested_pwgs,
                    interested_pwgs,
                    notes]

        insert_or_update(sql_args, cursor, table)

campaigns = ['RunIISummer19UL16GEN', 'RunIISummer19UL16wmLHEGEN', 'RunIISummer19UL16pLHEGEN',
             'RunIISummer19UL17GEN', 'RunIISummer19UL17wmLHEGEN', 'RunIISummer19UL17pLHEGEN',
             'RunIISummer19UL18GEN', 'RunIISummer19UL18wmLHEGEN', 'RunIISummer19UL18pLHEGEN',
             #'RunIIFall18GS', 'RunIIFall18wmLHEGS', 'RunIIFall18pLHE'
             #'RunIIFall17GS', 'RunIIFall17wmLHEGS', 'RunIIFall17pLHE'
             #'RunIISummer15GS', 'RunIISummer15wmLHEGS', 'RunIIWinter15pLHE'
         ]

conn = sqlite3.connect('data.db')
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE IF NOT EXISTS samples
             (uid integer PRIMARY KEY AUTOINCREMENT,
              campaign text,
              campaign_group text,
              chained_request text,
              dataset text,
              root_request text,
              root_request_priority integer,
              root_request_total_events integer,
              root_request_done_events integer,
              root_request_status text,
              root_request_output text,
              miniaod text,
              miniaod_priority integer,
              miniaod_total_events integer,
              miniaod_done_events integer,
              miniaod_status text,
              miniaod_output text,
              interested_pwgs text,
              original_interested_pwgs text,
              updated integer,
              notes text)''')

c.execute('''CREATE TABLE IF NOT EXISTS twiki_samples
             (uid integer PRIMARY KEY AUTOINCREMENT,
              campaign text,
              campaign_group text,
              chained_request text,
              dataset text,
              root_request text,
              root_request_priority integer,
              root_request_total_events integer,
              root_request_done_events integer,
              root_request_status text,
              root_request_output text,
              miniaod text,
              miniaod_priority integer,
              miniaod_total_events integer,
              miniaod_done_events integer,
              miniaod_status text,
              miniaod_output text,
              interested_pwgs text,
              original_interested_pwgs text,
              updated integer,
              notes text)''')

c.execute('''CREATE TABLE IF NOT EXISTS action_history
             (campaign text NOT NULL,
              dataset text NOT NULL,
              root_request text NOT NULL,
              chained_request text,
              username text NOT NULL,
              role text,
              action text NOT NULL,
              pwg text NOT NULL,
              updated integer)
             ''')

conn.commit()

# TWiki samples - old mode
with open('MainSamplesFall18.txt') as f:
    twiki_samples_fall_18 = [line.strip().split('\t') for line in f if line.strip()]

# Remove this!
# twiki_samples_fall_18 = twiki_samples_fall_18[:5]
# campaigns = [campaigns[3], campaigns[5]]
# Remove this!

twiki_added_requests = set()
for index, sample in enumerate(twiki_samples_fall_18):
    print('%s/%s %s' % (index + 1, len(twiki_samples_fall_18), sample[0]))
    requests_for_sample = mcm.get('requests', query='prepid=%s-%s*&dataset_name=%s' % (sample[4], sample[3], sample[0]))
    if not requests_for_sample:
        continue

    for req in requests_for_sample:
        prepid = req['prepid']
        if prepid in twiki_added_requests:
            # print('%s is already there' % (prepid))
            continue

        if int(req['extension']) != int(sample[1]):
            # print('Extension is wrong %s != %s' % (req['extension'], sample[1]))
            continue

        if int(req['total_events']) != int(sample[2]):
            # print('Total events is wrong %s != %s' % (req['total_events'], sample[2]))
            continue

        twiki_added_requests.add(prepid)
        print('Found %s' % (prepid))
        process_request(req, req['member_of_campaign'], c, 'twiki_samples')
        conn.commit()
        break
    else:
        print('Could not find anything for %s' % (' '.join(sample)))

conn.commit()

# McM samples
for campaign in campaigns:
    # This is a very stupid thing
    requests_in_campaign = mcm.get('requests', query='member_of_campaign=%s' % (campaign))
    for index, request in enumerate(requests_in_campaign):
        print('%s/%s %s' % (index + 1, len(requests_in_campaign), request['prepid']))
        process_request(request, campaign, c, 'samples')
        conn.commit()

    conn.commit()

conn.commit()
conn.close()


import logging
from fractions import Fraction

from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import Group

from taggit.managers import TaggableManager

from .utils import get_exif

# Get an instance of a logger
logger = logging.getLogger(__name__)

class Exif(models.Model):
    """
    Represents the exif data.
    """
    taken_date = models.DateField(editable=False, verbose_name=_('Taken Date'))
    focal_length = models.CharField(
        max_length=8, editable=False, verbose_name=_('Focal Length'))
    aperture = models.CharField(
        max_length=16, editable=False, verbose_name=_('Aperture'))
    iso = models.IntegerField(editable=False, verbose_name=_('ISO'))
    shutter_speed = models.CharField(
        max_length=16, editable=False, verbose_name=_('Shutter Speed'))
    camera_make = models.CharField(
        max_length=32, editable=False, verbose_name=_('Camera Make'))
    camera_model = models.CharField(
        max_length=32, editable=False, verbose_name=_('Camera Model'))
    lens_make = models.CharField(
        max_length=32,
        editable=False,
        blank=True,
        null=True,
        verbose_name=_('Lens Make'))
    lens_model = models.CharField(
        max_length=32, editable=False, verbose_name=_('Lens Model'))

    @classmethod
    def create(cls, exif_data: dict):
        """
        Constructor helper
        See https://docs.djangoproject.com/en/1.9/ref/models/instances/#django.db.models.Model.clean
        """
        exif = cls(
            iso=exif_data['ISOSpeedRatings'],
            taken_date=exif_data['DateTimeOriginal'].replace(':', '-')[0:10],
            camera_make=exif_data['Make'],
            camera_model=exif_data['Model'],
            lens_make=exif_data.get('LensMake'),
            lens_model=exif_data['LensModel'],
            focal_length=exif_data['FocalLength'][0] /
            exif_data['FocalLength'][1],
            shutter_speed=Fraction(exif_data['ExposureTime'][0],
                                   exif_data['ExposureTime'][1]),
            aperture=exif_data['FNumber'][0] / exif_data['FNumber'][1],
        )
        return exif

    def __str__(self):
        return '{} {}, ƒ/{}, {}s, {}mm, ISO {}'.format(
            self.camera_make.capitalize(), self.camera_model, self.aperture,
            self.shutter_speed, self.focal_length, self.iso)

class Picture(models.Model):
    """
    Represents a Picture. Could be a photograph or a screenshot.
    """
    title = models.CharField(max_length=255, verbose_name=_('Title'))
    description = models.TextField(blank=True, verbose_name=_('Description'))
    published_date = models.DateTimeField(
        auto_now_add=True, verbose_name=_('Published Date'))
    exif = models.OneToOneField(
        Exif,
        on_delete=models.CASCADE,
        editable=False,
        null=True,
        blank=True,
        verbose_name=_('EXIF'))

    def __str__(self):
        return self.title

    def validate_image(fieldfile_obj):
        """Check whether the exif data can be retrieve without issue."""
        exif = get_exif(fieldfile_obj)
        try:
            # Test whether the exif data is valid by attempting
            # to create an Exif instance.
            Exif.create(exif)
        except KeyError as ex:
            logger.exception('Failed to retrieve exif data.')
            raise ValidationError('Failed to retrieve exif data.')

    image = models.ImageField(upload_to='photos/', validators=[validate_image])
    tags = TaggableManager()

    CC0 = 'CC0'
    BY = 'BY'
    BY_SA = 'BY-SA'
    BY_NC = 'BY-NC'
    BY_NC_SA = 'BY-NC-SA'
    NO_LICENSE = 'NONE'

    AVAILABLE_LICENSES = (
        (CC0, _('CC0')),
        (BY, _('Attribution')),
        (BY_SA, _('Attribution-ShareAlike')),
        (BY_NC, _('Attribution-NonCommercial')),
        (BY_NC_SA, _('Attribution-NonCommercial-ShareAlike')),
        (NO_LICENSE, _('All rights reserved')),
    )

    license = models.CharField(
        max_length=10,
        choices=AVAILABLE_LICENSES,
        default=BY,
        verbose_name=_('License'),
        help_text=
        "See https://en.wikipedia.org/wiki/Creative_Commons_license for more information"
    )

    view_count = models.PositiveIntegerField(
        verbose_name=_('View count'), default=0, editable=False)

    download_count = models.PositiveIntegerField(
        verbose_name=_('Download count'), default=0, editable=False)

    is_private = models.BooleanField(verbose_name=_("Private"), default=True)

    public_for_user_groups = models.ManyToManyField(
        Group, verbose_name=_('Public for user groups'), blank=True)

    def increment_view_count(self):
        self.view_count += 1
        models.Model.save(self)

    def increment_download_count(self):
        self.download_count += 1
        models.Model.save(self)


import pygame
pygame.init()

SIZE = WIDTH, HEIGHT = 720, 480
FPS = 60
BACKGROUND_COLOR = pygame.Color('white')

screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()

class Hunter(pygame.sprite.Sprite):

    def __init__(self, position):
        super(Hunter, self).__init__()

        self.image = pygame.Surface((64, 64))
        self.image.fill(pygame.Color('red'))
        self.rect = self.image.get_rect(topleft=position)
        self.position = pygame.math.Vector2(position)
        self.speed = 2

    def hunt_player(self, player):
        player_position = player.rect.topleft
        direction = player_position - self.position
        velocity = direction.normalize() * self.speed

        self.position += velocity
        self.rect.topleft = self.position

    def update(self, player):
        self.hunt_player(player)

class Player(pygame.sprite.Sprite):

    def __init__(self, position):
        super(Player, self).__init__()

        self.image = pygame.Surface((64, 64))
        self.image.fill(pygame.Color('green'))
        self.rect = self.image.get_rect(topleft=position)

        self.position = pygame.math.Vector2(position)
        self.velocity = pygame.math.Vector2(0, 0)
        self.speed = 3

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.velocity.x = -self.speed
        elif keys[pygame.K_RIGHT]:
            self.velocity.x = self.speed
        else:
            self.velocity.x = 0

        if keys[pygame.K_UP]:
            self.velocity.y = -self.speed
        elif keys[pygame.K_DOWN]:
            self.velocity.y = self.speed
        else:
            self.velocity.y = 0

        self.position += self.velocity
        self.rect.topleft = self.position

player = Player(position=(350, 220))
monster = Hunter(position=(680, 400))
running = True
while running:

    clock.tick(FPS)

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

    player.update()
    monster.update(player)

    screen.fill(BACKGROUND_COLOR)
    screen.blit(player.image, player.rect)
    screen.blit(monster.image, monster.rect)

    pygame.display.update()


''' 1 - With a Hash Table '''

class Node:
    def __init__(self,v):
        self.v = v
        self.n = None

n5 = Node(5)
n4 = Node(10)
n3 = Node(4)
n2 = Node(6)
n1 = Node(1)
n5.n = n4
n4.n = n3
n3.n = n2
n2.n = n1

def nth_last_element(h:Node,n:int) -> Node:
    i = 0
    lookup = dict(i=h)
    while h.n is not None:
        i += 1
        h = h.n
        lookup[i] = h
    if n > i+1:
        return None
    return lookup[i-n+1]

nth_last_element(n5,2).v

''' 2 - With a recursive function '''

def nth_last_element_rec(h:Node, n:int) -> Node:
    # Base cases
    if h.n is None:
        return 1
    # Recursive Case
    n_ = nth_last_element_rec(h.n, n)
    if n_ == n:
        return h.n
    return n_th_last_element_rec(h.n, n)

nth_last_element_rec(n5,2)