from Agent import Agent
import random

# Space object has these attributes:
# int xcoord, ycoord, breeze, stench, probOfP, probOfW, h
# breeze and stench are 0 or 1 based on percept
# probOfP and probOfW are probability that space has pit or wumpus
# h is optimistic number of steps from that space to the exit
# All spaces are unexplored until moved to. This boolean prevents space reassessment if revisited.
class Space(object):
    breeze = stench = probOfP = probOfW = h = g = f = 0
    unexplored = True

    def __init__(self, xc, yc):
        self.xcoord = xc
        self.ycoord = yc

    def __str__(self):
        return "xcoord: " + str(self.xcoord) + "\nycoord: " + str(self.ycoord) + "\nprobOfDeath: " + str(self.probOfW + self.probOfP) + "\nf,h,g: " + str(self.f) + "," + str(self.h) + "," + str(self.g) + "\n"

    def __repr__(self):
        return "xcoord: " + str(self.xcoord) + "\nycoord: " + str(self.ycoord) + "\nprobOfDeath: " + str(self.probOfW + self.probOfP) + "\nf,h,g: " + str(self.f) + "," + str(self.h) + "," + str(self.g) + "\n"

    def __eq__(self, other):
        return self.xcoord == other.xcoord and self.ycoord == other.ycoord

def isFacingSpace(x, y, xpos, ypos, dir):
    if (x == (xpos + 1) ): # Space is to the right
        return (dir == 0)
    elif (x == (xpos - 1) ): # Space is to the left
        return (dir == 2)
    elif (y == (ypos + 1) ): # Space is above
        return (dir == 3)
    else: # Space is below
        return (dir == 1)

def calculateDirection(current, dir):
    #calculate the number of turns to direction
    #used for calculating f(n)
    if (current == dir):
        #already in the correct direction
        return 0
    elif ((current == 1 and dir == 3) or (current == 3 and dir == 1) or (current == 0 and dir == 2) or (current == 2 and dir == 0)):
        #need to do a 180
        return 2
    else:
        #otherwise just turn once
        return 1

def updateDirection(turn, dir):
    if (turn == Agent.Action.TURN_LEFT):
        dir -= 1
        if (dir < 0):
            dir = 3
    else:
        dir += 1
        if dir > 3:
            dir = 0
    return dir

def updatePos(direction, xpos, ypos):
    if ( direction == 0):	# Facing right
        xpos += 1
    elif ( direction == 1):	# Facing down
        ypos -= 1
    elif ( direction == 2):	# Facing left
        xpos -= 1
    else:					# Facing up
        ypos += 1
    return xpos, ypos

def getDirection(xpos, ypos, x, y):
    if (x == (xpos + 1) ): # Space is to the right
        return 0
    elif (x == (xpos - 1) ): # Space is to the left
        return 2
    elif (y == (ypos + 1) ): # Space is above
        return 3
    else: # Space is below
        return 1

class MyAI ( Agent ):

    def __init__ ( self ):
        self.MAX_POINTS_SPENT = 50# Prevent endless wandering
        self.points_spent = 0

        # Create 7x7 grid of Space objects
        self.grid = [[ Space(row, col) for col in range(7)] for row in range(7)]

        # Initialize coordinates for Space objects
        # for i in range(7):
        #     for j in range(7):
        #         self.grid[i][j].xcoord = i
        #         self.grid[i][j].ycoord = j

        # Initialize heuristic for Space objects
        for i in range(7):
            for j in range(7):
                self.grid[i][j].h = self.grid[i][j].xcoord + self.grid[i][j].ycoord

        self.max_xpos = self.max_ypos = 6	# Assume 7x7
        self.xpos = self.ypos = 0			# Current x,y position
        self.current_dir = 0				# Let direction 0 be "right", 1 "down", 2 "left", 3 "up"
        self.has_arrow = True
        self.time_to_leave = False
        self.route = []						# LIFO queue for "breadcrumb trail" back to start
        self.first_F_found = False
        self.dead = False					# Is Wumpus dead?
        self.moving = False					# If moving == True, a new space has been chosen and agent is in the process of getting there.
        self.movingToQ = []					# Queue of turning instructions for facing chosen space before moving forward
        self.possible_wumpus = []           # List of possible wumpus coordinate locations
        self.possible_pits = []             # List of possible pit coordinate locations
        self.checked_pits = []              # List of checked pit spaces - include visited spaces and the neighbors
        self.checked_wumpus = []
        self.safe = set()                     # List of safe spaces that can be included in the A* search
        self.blocked_spaces = []            # spaces that are safe, but are currently blocked according to a current state space
        self.visited = []                  # used for the case when all the visited spaces are the safe spaces then just leave

    def getAction( self, stench, breeze, glitter, bump, scream ):
        self.points_spent += 1
        self.MAX_POINTS_SPENT = self.max_xpos*self.max_ypos
        self.grid[self.xpos][self.ypos].g = self.points_spent
        self.grid[self.xpos][self.ypos].f = (self.grid[self.xpos][self.ypos].g + self.grid[self.xpos][self.ypos].h)
        #self.checked.append((self.xpos, self.ypos))
        self.safe.add((self.xpos, self.ypos))
        self.visited.append((self.xpos, self.ypos))

        if (self.points_spent >= self.MAX_POINTS_SPENT):
            self.time_to_leave = True

        if (scream):
            self.dead = True
            # Remove threat of wumpus
            for i in range(7):
                for j in range(7):
                    self.grid[i][j].probOfW = 0

        if (bump):
            if (dir == 0):		# Facing right
                self.max_xpos = self.xpos
                print("Bump! Max x coord: " + str(self.max_xpos) )
            elif (dir == 3):	# Facing up
                self.max_ypos = self.ypos
                print("Bump! Max y coord: " + str(self.max_ypos) )
            # TODO: After discovering a boundary, there may be spaces marked with probOfP or probOfW that we now know must be 0. Update ALL associated probabilities in this change.

        # If this is a previously unvisited space, update the observations
        # and probabilities for current and neighboring Spaces
        # if((self.grid[0][1].breeze or self.grid[0][1].stench) and (self.grid[1][0].breeze or self.grid[1][0].stench)):
        #     print("here")
        #     return Agent.Action.CLIMB

        if (self.grid[self.xpos][self.ypos].unexplored):
            self.grid[self.xpos][self.ypos].unexplored = False

            if (stench):
                if (self.dead):
                    pass
                elif(self.xpos == 0 and self.ypos == 0):
                    #stench at first space then leave
                    return Agent.Action.CLIMB
                elif (len(self.possible_wumpus) == 1):
                    #only one possible location then shoot it
                    #update position and update direction
                    coordinate = self.possible_wumpus.pop(0)
                    updatePos(self.current_dir, coordinate[0], coordinate[1])
                    #shoot
                else:
                    self.grid[self.xpos][self.ypos].stench = 1

                    # Update probOfW for neighbors. Exclude: explored spaces, known out of bound spaces.
                    # TODO: This algorithm is fine for the first encounter of stench, but subsequent encounters may prove spaces that were given some probability as actually Safe.
                    #       It would be nice if we could recognize when this occurs and update those spaces.
                    neighbors = self.getNeighbors()

                    above = below = right = left = 0
                    possibleNumOfSpaces = 0

                    for neighbor in neighbors:
                        if ((neighbor[1].xcoord, neighbor[1].ycoord) not in self.checked_wumpus):
                            possibleNumOfSpaces += 1
                            self.possible_wumpus.append((neighbor[1].xcoord, neighbor[1].ycoord))
                            # right0, left1, below2, above3
                            if (neighbor[0] == 0):
                                right = 1
                            elif (neighbor[0] == 1):
                                left = 1
                            elif (neighbor[0] == 2):
                                below = 1
                            else:  # neighbor[0] == 3
                                above = 1

                    # if ( (self.xpos + 1) <= self.max_xpos and self.grid[self.xpos + 1][self.ypos].unexplored ):
                    #     right = 1
                    #     self.possible_wumpus.append((self.xpos+1, self.ypos))
                    # if ( (self.ypos + 1) <= self.max_ypos and self.grid[self.xpos][self.ypos + 1].unexplored ):
                    #     above = 1
                    #     self.possible_wumpus.append((self.xpos, self.ypos+1))
                    # if ( (self.xpos - 1) >= 0 and self.grid[self.xpos - 1][self.ypos].unexplored ):
                    #     left = 1
                    #     self.possible_wumpus.append((self.xpos - 1, self.ypos))
                    # if ( (self.ypos - 1) >= 0 and self.grid[self.xpos][self.ypos - 1].unexplored ):
                    #     below = 1
                    #     self.possible_wumpus.append((self.xpos, self.ypos - 1))
                    #
                    # possibleNumOfSpaces = right + above + left + below

                    if (possibleNumOfSpaces != 0):
                        if (right == 1):
                            self.grid[self.xpos + 1][self.ypos].probOfW += (1 / possibleNumOfSpaces)
                        if (above == 1):
                            self.grid[self.xpos][self.ypos + 1].probOfW += (1 / possibleNumOfSpaces)
                        if (left == 1):
                            self.grid[self.xpos - 1][self.ypos].probOfW += (1 / possibleNumOfSpaces)
                        if (below == 1):
                            self.grid[self.xpos][self.ypos - 1].probOfW += (1 / possibleNumOfSpaces)
            else:
                #ASK HERE
                #there is no stench so make the propbability of W zero for the neighbors and the current space
                if ((self.xpos, self.ypos) in self.possible_wumpus):
                    self.possible_wumpus.remove((self.xpos, self.ypos))
                    self.checked_wumpus.append((self.xpos, self.ypos))

                neighbors = self.getNeighbors()

                for neighbor in neighbors:
                    neighbor[1].probOfW = 0
                    self.checked_wumpus.append((neighbor[1].xcoord, neighbor[1].ycoord))
                    if(neighbor[1].probOfP == 0):
                        self.safe.add((neighbor[1].xcoord, neighbor[1].ycoord))
                    if((neighbor[1].xcoord, neighbor[1].ycoord) in self.possible_wumpus):
                        self.possible_wumpus.remove((neighbor[1].xcoord, neighbor[1].ycoord))

            if (breeze):
                self.grid[self.xpos][self.ypos].breeze = 1
                if (self.xpos == 0 and self.ypos == 0):
                    # breeze at first space then leave
                    return Agent.Action.CLIMB

                # Update probOfP for neighbors. Exclude: explored spaces, known out of bound spaces.
                # TODO: This is probably not going to generate the most accurate probabilities...
                # As with the probOfW code, there is currently nothing in place that can REDUCE probability when given more information
                neighbors = self.getNeighbors()
                # there is a breeze so the neighbors have a probability of being a pit
                # however, if the neighbor has been checked and that means it has a probability of 0 for W or P then it is safe to enter
                # checked can also be the safe spaces since they are added when they are entered and if their probability is low
                possibleNumOfSpaces = 0
                above = below = right = left = 0

                for neighbor in neighbors:
                    if ( (neighbor[1].xcoord, neighbor[1].ycoord) not in self.checked_pits):
                        possibleNumOfSpaces += 1
                        self.possible_pits.append((neighbor[1].xcoord, neighbor[1].ycoord))
                        # right0, left1, below2, above3
                        if(neighbor[0] == 0):
                            right = 1
                        elif(neighbor[0] == 1):
                            left = 1
                        elif(neighbor[0] == 2):
                            below = 1
                        else: # neighbor[0] == 3
                            above = 1

               #
               #  if ( (self.xpos + 1) <= self.max_xpos and self.grid[self.xpos + 1][self.ypos].unexplored ):
               #      right = 1
               #  if ( (self.ypos + 1) <= self.max_ypos and self.grid[self.xpos][self.ypos + 1].unexplored ):
               #      above = 1
               #  if ( (self.xpos - 1) >= 0 and self.grid[self.xpos - 1][self.ypos].unexplored ):
               #      left = 1
               #  if ( (self.ypos - 1) >= 0 and self.grid[self.xpos][self.ypos - 1].unexplored ):
               #      below = 1
               #
               #  possibleNumOfSpaces = right + above + left + below
               #
               #
                if (possibleNumOfSpaces == 1):
                    if (right == 1):
                        self.grid[self.xpos + 1][self.ypos].probOfP = 1
                    elif (above == 1):
                        self.grid[self.xpos][self.ypos + 1].probOfP = 1
                    elif (left == 1):
                        self.grid[self.xpos - 1][self.ypos].probOfP = 1
                    else:
                        self.grid[self.xpos][self.ypos - 1].probOfP = 1
                elif ( possibleNumOfSpaces == 2):
                    if (right == 1):
                        self.grid[self.xpos + 1][self.ypos].probOfP += 0.5556
                    elif (above == 1):
                        self.grid[self.xpos][self.ypos + 1].probOfP += 0.5556
                    elif (left == 1):
                        self.grid[self.xpos - 1][self.ypos].probOfP += 0.5556
                    else:
                        self.grid[self.xpos][self.ypos - 1].probOfP += 0.5556
                else:
                    if (right == 1):
                        self.grid[self.xpos + 1][self.ypos].probOfP += 0.4098
                    elif (above == 1):
                        self.grid[self.xpos][self.ypos + 1].probOfP += 0.4098
                    elif (left == 1):
                        self.grid[self.xpos - 1][self.ypos].probOfP += 0.4098
                    else:
                        self.grid[self.xpos][self.ypos - 1].probOfP += 0.4098
            #ASK HERE
            else:
                #there is no breeze in the square then adjacent cannot be a pit
                if((self.xpos, self.ypos) in self.possible_pits):
                    self.possible_pits.remove((self.xpos, self.ypos))
                    self.checked_pits.append((self.xpos, self.ypos))

                neighbors = self.getNeighbors()
                for neighbor in neighbors:
                    neighbor[1].probOfP = 0 # cannot be a pit
                    self.checked_pits.append((neighbor[1].xcoord, neighbor[1].ycoord))
                    if(neighbor[1].probOfW == 0):
                        self.safe.add((neighbor[1].xcoord, neighbor[1].ycoord))
                    if ((neighbor[1].xcoord, neighbor[1].ycoord) in self.possible_pits):
                        self.possible_pits.remove((neighbor[1].xcoord, neighbor[1].ycoord))

        if glitter:
            self.time_to_leave = True
            return Agent.Action.GRAB

        if self.time_to_leave:	# Got the gold or ran out of time

            return self.returnFunction()

        else:
            self.blockedUpdate()
            if (self.moving == False): # Choose a new space
                # Assemble list of unvisited neighbors in ascending order of threat

                candidates = []

                if(breeze):
                    #there was a stench here better to go back and take a different route
                    if ((self.xpos + 1) <= self.max_xpos and (self.grid[self.xpos + 1][self.ypos].breeze == 0)):
                        candidates.append(self.grid[self.xpos + 1][self.ypos])
                    if ((self.ypos + 1) <= self.max_ypos and (self.grid[self.xpos][self.ypos + 1].breeze == 0)):
                        candidates.append(self.grid[self.xpos][self.ypos + 1])
                    if ((self.xpos - 1) >= 0 and (self.grid[self.xpos - 1][self.ypos].breeze == 0)):
                        candidates.append(self.grid[self.xpos - 1][self.ypos])
                    if ((self.ypos - 1) >= 0 and (self.grid[self.xpos][self.ypos - 1].breeze == 0)):
                        candidates.append(self.grid[self.xpos][self.ypos - 1])
                elif(stench):
                    # there was a stench here better to go back and take a different route
                    if ((self.xpos + 1) <= self.max_xpos and (self.grid[self.xpos + 1][self.ypos].stench == 0)):
                        candidates.append(self.grid[self.xpos + 1][self.ypos])
                    if ((self.ypos + 1) <= self.max_ypos and (self.grid[self.xpos][self.ypos + 1].stench == 0)):
                        candidates.append(self.grid[self.xpos][self.ypos + 1])
                    if ((self.xpos - 1) >= 0 and (self.grid[self.xpos - 1][self.ypos].stench == 0)):
                        candidates.append(self.grid[self.xpos - 1][self.ypos])
                    if ((self.ypos - 1) >= 0 and (self.grid[self.xpos][self.ypos - 1].stench == 0)):
                        candidates.append(self.grid[self.xpos][self.ypos - 1])

                else:
                    # choose a space that is unexplored and "safe"
                    if ( (self.xpos + 1) <= self.max_xpos and self.grid[self.xpos + 1][self.ypos].unexplored ):
                        candidates.append(self.grid[self.xpos + 1][self.ypos])
                    if ( (self.ypos + 1) <= self.max_ypos and self.grid[self.xpos][self.ypos + 1].unexplored ):
                        candidates.append(self.grid[self.xpos][self.ypos + 1])
                    if ( (self.xpos - 1) >= 0 and self.grid[self.xpos - 1][self.ypos].unexplored ):
                        candidates.append(self.grid[self.xpos - 1][self.ypos])
                    if ( (self.ypos - 1) >= 0 and self.grid[self.xpos][self.ypos - 1].unexplored ):
                        candidates.append(self.grid[self.xpos][self.ypos - 1])

                # if not candidates: # No new space to go to. Revisit a random neighbor (TODO: change this to back up to earlier branch in path)
                #     if ( (self.xpos + 1) <= self.max_xpos ):
                #         candidates.append(self.grid[self.xpos + 1][self.ypos])
                #     if ( (self.ypos + 1) <= self.max_ypos ):
                #         candidates.append(self.grid[self.xpos][self.ypos + 1])
                #     if ( (self.xpos - 1) >= 0 ):
                #         candidates.append(self.grid[self.xpos - 1][self.ypos])
                #     if ( (self.ypos - 1) >= 0 ):
                #         candidates.append(self.grid[self.xpos][self.ypos - 1])
                #
                #     random.shuffle(candidates)
                # else:
                candidates = sorted(candidates, key=lambda space: space.probOfP + space.probOfW)

                safe_candidates = [c for c in candidates if ( ((c.xcoord, c.ycoord) not in self.possible_pits) and ((c.xcoord, c.ycoord) not in self.possible_wumpus) and ((c.xcoord, c.ycoord) not in self.blocked_spaces) )]
                cnt = 0
                for c in safe_candidates:
                    if((c.xcoord, c.ycoord) in self.visited):
                        cnt += 1
                if(cnt == len(self.visited)):
                    return self.returnFunction()

                # for candidate in candidates:
                #     if(((candidate.xcoord, candidate.ycoord) in self.possible_pits) or ((candidate.xcoord, candidate.ycoord) in self.possible_wumpus)):
                #         candidates.remove(candidate)

                # print(candidates)
                # print(safe_candidates)
                # print("Pits: ", self.possible_pits)
                # print("Wumpus: ", self.possible_wumpus)
                if (len(safe_candidates) == 0):
                    # none safe then choose from candidates
                    #movingTo = candidates.pop(0)
                    # self.time_to_leave = True
                    # return self.returnFunction()
                    for c in candidates:
                        self.blocked_spaces.append((c.xcoord, c.ycoord))
                    candidates = self.exploredNeighbors()
                    candidates = sorted(candidates, key=lambda space: space.probOfP + space.probOfW)
                    movingTo = candidates.pop(0)
                else:
                    movingTo = safe_candidates.pop(0)
                # movingTo = safe_candidates.pop()
                # print(movingTo)

                if ( isFacingSpace(movingTo.xcoord, movingTo.ycoord, self.xpos, self.ypos, self.current_dir) ):
                    self.xpos, self.ypos = updatePos(self.current_dir, self.xpos, self.ypos)
                    self.route.append(Agent.Action.FORWARD) # TODO: Remove this when better return route is implemented
                    return Agent.Action.FORWARD
                else: # Initiate moving phase
                    self.moving = True
                    if (movingTo.xcoord == (self.xpos + 1) ): # Space is to the right
                        if (self.current_dir == 1):
                            self.current_dir = updateDirection(Agent.Action.TURN_LEFT, self.current_dir)
                            self.route.append(Agent.Action.TURN_RIGHT)
                            return Agent.Action.TURN_LEFT
                        elif (self.current_dir == 2):
                            self.movingToQ.append(Agent.Action.TURN_RIGHT)
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                        else: # current_dir == 3
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                    elif (movingTo.xcoord == (self.xpos - 1) ): # Space is to the left
                        if (self.current_dir == 0):
                            self.movingToQ.append(Agent.Action.TURN_RIGHT)
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                        elif (self.current_dir == 1):
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                        else: # current_dir == 3
                            self.current_dir = updateDirection(Agent.Action.TURN_LEFT, self.current_dir)
                            self.route.append(Agent.Action.TURN_RIGHT)
                            return Agent.Action.TURN_LEFT
                    elif (movingTo.ycoord == (self.ypos + 1) ): # Space is above
                        if (self.current_dir == 0):
                            self.current_dir = updateDirection(Agent.Action.TURN_LEFT, self.current_dir)
                            self.route.append(Agent.Action.TURN_RIGHT)
                            return Agent.Action.TURN_LEFT
                        elif (self.current_dir == 1):
                            self.movingToQ.append(Agent.Action.TURN_RIGHT)
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                        else: # current_dir == 2
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                    else: 										# Space is below
                        if (self.current_dir == 0):
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
                        elif (self.current_dir == 2):
                            self.current_dir = updateDirection(Agent.Action.TURN_LEFT, self.current_dir)
                            self.route.append(Agent.Action.TURN_RIGHT)
                            return Agent.Action.TURN_LEFT
                        else: # current_dir == 3
                            self.movingToQ.append(Agent.Action.TURN_RIGHT)
                            self.current_dir = updateDirection(Agent.Action.TURN_RIGHT, self.current_dir)
                            self.route.append(Agent.Action.TURN_LEFT)
                            return Agent.Action.TURN_RIGHT
            else: # Currently in moving phase
                if not self.movingToQ: # Should be facing space now
                    self.moving = False
                    self.xpos, self.ypos = updatePos(self.current_dir, self.xpos, self.ypos)
                    self.route.append(Agent.Action.FORWARD) # TODO: Remove this when better return route is implemented
                    return Agent.Action.FORWARD
                else:
                    nextTurn = self.movingToQ.pop()
                    self.current_dir = updateDirection(nextTurn, self.current_dir)
                    if (nextTurn == Agent.Action.TURN_RIGHT):
                        self.route.append(Agent.Action.TURN_LEFT)
                    else:
                        self.route.append(Agent.Action.TURN_RIGHT)
                    return nextTurn

    def getNeighbors(self):
        # returns a list of unvisited neighbors space objects
        neighbors = []

        if ( (self.xpos + 1) <= self.max_xpos and self.grid[self.xpos + 1][self.ypos].unexplored ):
            # right
            neighbors.append([0, self.grid[self.xpos + 1][self.ypos]])
        if ( (self.ypos + 1) <= self.max_ypos and self.grid[self.xpos][self.ypos + 1].unexplored ):
            # above
            neighbors.append([3, self.grid[self.xpos][self.ypos + 1]])
        if ( (self.xpos - 1) >= 0 and self.grid[self.xpos - 1][self.ypos].unexplored ):
            # left
            neighbors.append([1, self.grid[self.xpos - 1][self.ypos]])
        if ( (self.ypos - 1) >= 0 and self.grid[self.xpos][self.ypos - 1].unexplored ):
            # below
            neighbors.append([2, self.grid[self.xpos][self.ypos - 1]])

        return neighbors

    def path_print(self, path):
        board = [[-1 for col in range(7)] for row in range(7)]
        for i in range(self.max_xpos):
            for j in range(self.max_ypos):
                if(self.grid[i][j].unexplored):
                    #not explored
                    board[i][j] = -2
        start_value = 0
        for index, item in enumerate(path):
            board[item[0]][item[1]] = start_value
            start_value += 1
        print('\n'.join([''.join(['{:4}'.format(item) for item in row])
                         for row in board]))

    def returnASearch(self):
        #if they are unexplored then consider them "blocked" or "forbidden"
        #print("here")
        start_node = self.grid[self.xpos][self.ypos] # current node = start node
        start_node.g = start_node.h = start_node.f = 0
        #print(start_node)
        end_node = self.grid[0][0] # 0,0 is the exit = end node
        end_node.g = end_node.h = end_node.f = 0
        #print(end_node)
        direction = self.current_dir

        yet_to_visit_list = []
        visited_list = []
        #add current/start node to the yet to visit list
        yet_to_visit_list.append(start_node)

        while len(yet_to_visit_list) > 0:
            current_node = yet_to_visit_list[0]
            current_index = 0
            xcoord = current_node.xcoord
            ycoord = current_node.ycoord
            for index, item in enumerate(yet_to_visit_list):
                if ( item.f < current_node.f):
                    # continue looping until find the smallest f value
                    direction = getDirection(xcoord, ycoord, item.xcoord, item.ycoord) # gives us the direction we will face when we choose that space
                    current_node = item
                    current_index = index
            yet_to_visit_list.pop(current_index)
            visited_list.append(current_node) # visit the node with the smallest f(n)

            if( current_node == end_node ):
                #print("here")
                break

            neighbors = self.getSafeNeighbors()

            for neighbor in neighbors:
                #neighbor is in the visited list
                if (len([visited_neighbor for visited_neighbor in visited_list if ( visited_neighbor == neighbor[1] ) ]) > 0):
                    continue

                #create f, g, h costs for the neighbor
                neighbor[1].g = current_node.g + 1
                #neighbor[1].g = current_node.g + calculateDirection(direction, getDirection(current_node.xcoord, current_node.ycoord, neighbor[1].xcoord, neighbor[1].ycoord))
                neighbor[1].f = neighbor[1].g + neighbor[1].h

                # check neighbor is in yet_to_visit_list and g_cost
                if (len([n for n in yet_to_visit_list if ( neighbor[1] == n and neighbor[1].g > n.g ) ]) > 0):
                    continue
                yet_to_visit_list.append(neighbor[1])
        return_route = []
        for node in visited_list:
            return_route.append([node.xcoord, node.ycoord])
        return return_route

    def returnFunction(self):
        # when time to leave call this
        if (self.xpos == 0 and self.ypos == 0):  # Agent is at (0,0) & it's time to go!
            return Agent.Action.CLIMB

            # Get agent to 180-turn to get oriented for return trip
        if ((not self.first_F_found) and (self.route[len(self.route) - 1] == Agent.Action.FORWARD)):
            return_route = self.returnASearch()
            # print(return_route)
            # print(self.route)
            # print(self.safe)
            # self.path_print(return_route)
            self.first_F_found = True
            self.route.append(Agent.Action.TURN_RIGHT)
            self.route.append(Agent.Action.TURN_RIGHT)

        nextMove = self.route.pop()

        # If agent will be moving forward, update xpos & ypos
        # Else update direction
        if (nextMove == Agent.Action.FORWARD):
            self.xpos, self.ypos = updatePos(self.current_dir, self.xpos, self.ypos)
        else:
            self.current_dir = updateDirection(nextMove, self.current_dir)

        return nextMove

        #TODO: implement what to do in case of a tie - choose the smaller column number if the same, then choose the smaller row number if columns are the same

    def exploredNeighbors(self):
        neighbors = []

        if ((self.xpos + 1) <= self.max_xpos and self.grid[self.xpos + 1][self.ypos].unexplored == 0):
            neighbors.append(self.grid[self.xpos + 1][self.ypos])
        if ((self.ypos + 1) <= self.max_ypos and self.grid[self.xpos][self.ypos + 1].unexplored == 0):
            neighbors.append(self.grid[self.xpos][self.ypos + 1])
        if ((self.xpos - 1) >= 0 and self.grid[self.xpos - 1][self.ypos].unexplored == 0):
            neighbors.append(self.grid[self.xpos - 1][self.ypos])
        if ((self.ypos - 1) >= 0 and self.grid[self.xpos][self.ypos - 1].unexplored == 0):
            neighbors.append(self.grid[self.xpos][self.ypos - 1])

        return neighbors

    def blockedUpdate(self):
        # go through the blocked spaces list and check the neighbors and if the len of safe neighbors is > 1 then remove it from the blocked spaces
        for b in list.copy(self.blocked_spaces):
            candidates = []

            if ((b[0] + 1) <= self.max_xpos and self.grid[b[0] + 1][b[1]].unexplored):
                candidates.append(self.grid[b[0] + 1][b[1]])
            if ((b[1] + 1) <= self.max_ypos and self.grid[b[0]][b[1] + 1].unexplored):
                candidates.append(self.grid[b[0]][b[1] + 1])
            if ((b[0] - 1) >= 0 and self.grid[b[0] - 1][b[1]].unexplored):
                candidates.append(self.grid[b[0] - 1][b[1]])
            if ((b[1] - 1) >= 0 and self.grid[b[0]][b[1] - 1].unexplored):
                candidates.append(self.grid[b[0]][b[1] - 1])

            safe_candidates = [c for c in candidates if (((c.xcoord, c.ycoord) not in self.possible_pits) and (
                        (c.xcoord, c.ycoord) not in self.possible_wumpus) )]
            if(len(safe_candidates) > 1):
                self.blocked_spaces.remove(b)

    def getSafeNeighbors(self):
        # returns a list of unvisited neighbors space objects
        neighbors = []

        if ( (self.xpos + 1) <= self.max_xpos and ((self.xpos + 1),self.ypos) in self.safe):
            # right
            neighbors.append([0, self.grid[self.xpos + 1][self.ypos]])
        if ( (self.ypos + 1) <= self.max_ypos and (self.xpos,(self.ypos + 1)) in self.safe):
            # above
            neighbors.append([3, self.grid[self.xpos][self.ypos + 1]])
        if ( (self.xpos - 1) >= 0 and ((self.xpos - 1),self.ypos) in self.safe):
            # left
            neighbors.append([1, self.grid[self.xpos - 1][self.ypos]])
        if ( (self.ypos - 1) >= 0 and (self.xpos,(self.ypos - 1)) in self.safe):
            # below
            neighbors.append([2, self.grid[self.xpos][self.ypos - 1]])

        return neighbors


import redditbots
import random
import time

class MarkovBot(redditbots.Bot):
    def onDBOpen(self, db, curVersion):
        if curVersion == 0:
            db.execute('CREATE TABLE markov (word TEXT KEY, nextWord TEXT KEY, frequency INTEGER)')
            db.execute('CREATE UNIQUE INDEX wordPair ON markov (word, nextWord)')
        db.commit()
        return 1

    def addPair(self, first, second):
        c = self.database.cursor()
        if (first is None):
            c.execute("SELECT frequency FROM Markov WHERE word IS NULL and nextWord = ?", (second,))
        elif (second is None):
            c.execute("SELECT frequency FROM Markov WHERE word = ? AND nextWord IS NULL", (first,))
        else:
            c.execute("SELECT frequency FROM Markov WHERE word = ? AND nextWord = ?", (first, second))
        res = c.fetchone()
        if (res == None):
            c.execute("INSERT INTO Markov (word, nextWord, frequency) VALUES (?, ?, 0)", (first, second))
        if (first is None):
            c.execute("UPDATE Markov SET frequency = frequency+1 WHERE word IS NULL AND nextWord = ?", (second,))
        elif (second is None):
            c.execute("UPDATE Markov SET frequency = frequency+1 WHERE word = ? AND nextWord IS NULL", (first,))
        else:
            c.execute("UPDATE Markov SET frequency = frequency + 1 WHERE word = ? AND nextWord = ?", (first, second))

    def nextWord(self, current):
        c = self.database.cursor()
        if (current is None):
            c.execute("SELECT nextWord FROM Markov WHERE word IS NULL ORDER BY RANDOM() * frequency LIMIT 1")
        else:
            c.execute("SELECT nextWord FROM Markov WHERE word = ? ORDER BY RANDOM() * frequency LIMIT 1", (current,))
        res = c.fetchone()
        if (res == None):
            return None
        return res[0]

    def buildReply(self, word):
        if (word != None):
            phrase = (word,)
        else:
            phrase = ()
        current = self.nextWord(word)
        while(current != None):
            phrase += (current,)
            current = self.nextWord(current)
        return ' '.join(phrase)

    def isWorthwhileText(self, text):
        wordCount = text.count(' ')
        validPunctuation = ('.', '?', '!', '"', "'")
        hasValidPunct = False
        for p in validPunctuation:
            if text.endswith(p):
                hasValidPunct = True
                break
        return hasValidPunct and len(text) > wordCount*4 and wordCount > 10

    def onNewComment(self, comment):
        paragraphs = comment.body.split('\n\n')
        for paragraph in paragraphs:
            words = paragraph.split(' ')
            prev = None
            for next in words:
                self.addPair(prev, next)
                prev = next
            self.addPair(prev, None)
        self.database.commit()

        if self.isWorthwhileText(comment.body):
            goodWords = []
            for word in comment.body.split(' '):
                if len(word) > 4:
                    goodWords.append(word)
            randomWord = random.choice(goodWords)
            randomWord = randomWord[0].upper() + randomWord[1:]
            self.log.debug("Building reply for %s", randomWord)
            reply = self.buildReply(randomWord)
            tries = 10
            while (not self.isWorthwhileText(reply)) and tries > 0:
                self.log.debug("Rejecting short reply: %s", reply)
                reply = self.buildReply(randomWord)
                tries = tries-1
            if self.isWorthwhileText(reply):
                self.log.info("Original text: %s", comment.body)
                self.log.info("Reply: %s", reply)
                self.queueReply(comment, reply)


import json

from scripts.tools.recording_database import RecordingDatabase

class GestureRecorder:

    def __init__(self):
        self.hand_bodypart_name = ["Left", "Right"]
        self.exercise_bodypart_name = ["body"]

        self.activate_gestures = []
        self.gesture_sequences = {}

        self.DB = RecordingDatabase()
        self.frame_index = self.DB.get_last_line_id() + 1
        self.recorded_frames = {}
        self.key_frames = set()  # store all the key frame index
        self.module_name = ""

    def record_gesture(self, frame_data, model):
        if len(model.get_module_names()) == 0:
            return
        module_names = list(model.get_module_names())
        if "hand" in module_names:
            self.module_name = "hand"
        elif "body" in module_names:
            self.module_name = "body"
        frame_landmarks = {}
        body_part_name_list = []

        if self.module_name == 'hand':
            body_part_name_list = self.hand_bodypart_name
        elif self.module_name == 'body':
            body_part_name_list = self.exercise_bodypart_name

        # record landmarks for all the body_part, e.g. hand: Left, Right
        for bodypart_name in body_part_name_list:
            detected_body_part = frame_data.get_data(bodypart_name)
            if detected_body_part is not None:
                frame_landmarks[bodypart_name] = dict()
                for k in detected_body_part.keys():
                    frame_landmarks[bodypart_name][k] = \
                        [detected_body_part[k][0], detected_body_part[k][1], detected_body_part[k][2]]

        activate_events = model.get_activate_events()
        if len(activate_events) > 0 and len(frame_landmarks) > 0:
            self.recorded_frames[self.frame_index] = frame_landmarks

        current_gesture_names = []
        for event in activate_events:
            for gesture_type in event.get_all_used_gestures():
                for body_type in event.get_bodypart_types():
                    gestures_dict = event.get_all_gestures()
                    if gesture_type == 'peace' or body_type == 'speech':
                        continue
                    if gestures_dict[body_type][gesture_type] is not None and gesture_type not in current_gesture_names:
                        current_gesture_names.append(gesture_type)

        deactivate_gestures = list(set(self.activate_gestures) - set(current_gesture_names))
        for gesture in current_gesture_names:
            if gesture not in self.activate_gestures:
                self.activate_gestures.append(gesture)
                self.key_frames.add(self.frame_index)
                if self.gesture_sequences.get(gesture, None) is not None:
                    self.gesture_sequences[gesture].append([self.frame_index])
                else:
                    self.gesture_sequences[gesture] = [[self.frame_index]]

        if len(frame_landmarks) == 0:
            for gesture in self.activate_gestures:
                self.key_frames.add(self.frame_index - 1)
                self.gesture_sequences[gesture][-1].append(self.frame_index - 1)
                self.activate_gestures.remove(gesture)
        elif len(deactivate_gestures) > 0:
            for gesture in deactivate_gestures:
                self.key_frames.add(self.frame_index - 1)
                self.gesture_sequences[gesture][-1].append(self.frame_index - 1)
                self.activate_gestures.remove(gesture)

        self.frame_index += 1

    def write_data_into_DB(self):
        if len(self.activate_gestures) > 0:
            self.key_frames.add(self.frame_index - 1)
            for gesture in self.activate_gestures:
                self.gesture_sequences[gesture][-1].append(self.frame_index - 1)

        if len(self.recorded_frames.keys()) == 0:
            return
        # using reduction_algorithm
        frame_data, compress_data = self.recorded_gesture_reduction()
        # print(len(self.recorded_frames.keys()))
        # print(self.key_frames)
        # print(frame_data.keys())
        # print(compress_data)

        for frame_id, data in frame_data.items():
            compressed = compress_data[frame_id]
            gesture_json_str = json.dumps(data)
            # print(gesture_json_str)
            self.DB.record(frame_id, gesture_json_str, compressed)

        for gesture, gesture_seq in self.gesture_sequences.items():
            for start_id, end_id in gesture_seq:
                self.DB.record_gesture(gesture, start_id, end_id)
        self.DB.close_db()

    def recorded_gesture_reduction(self):
        landmark_num = 0
        if self.module_name == 'hand':
            landmark_num = 18
        elif self.module_name == 'body':
            landmark_num = 5

        x_threshold = 40
        y_threshold = 40
        z_threshold = 30

        x_width = 640
        y_height = 480
        z_depth = 1000

        reduced_frame = {}
        reduced_compress = {}

        trivial_count = 0  # count the trivial frame need to be compressed
        key_frame_index = list(self.recorded_frames.keys())[0]
        key_frame = self.recorded_frames[key_frame_index]  # first frame as key frame
        reduced_frame[key_frame_index] = key_frame

        for i in range(1, len(self.recorded_frames.keys())):  # start from 1
            this_frame_index = list(self.recorded_frames.keys())[i]
            this_frame = self.recorded_frames[this_frame_index]

            # comment out code is used in bodypart number change senario
            '''
            if len(Key_frame.keys()) != len(self.recorded_gesture_sequence["facing_camera"][0][i].keys()):
                print(Key_frame)
                Key_frame = self.recorded_gesture_sequence["facing_camera"][0][i]
                trivial_count = 0
            '''

            if this_frame_index in self.key_frames or len(key_frame.keys()) != len(this_frame.keys()):
                if len(this_frame.keys()) != 0:
                    reduced_compress[key_frame_index] = trivial_count
                    trivial_count = 0
                    key_frame_index = this_frame_index
                    key_frame = this_frame
                    reduced_frame[this_frame_index] = this_frame
                    reduced_compress[this_frame_index] = 0

            else:
                # len(Key_frame.keys())*23 count the number of compared landmark
                landmark_count = 0

                exit_flag = False
                for bodypart in key_frame.keys():
                    if this_frame.get(bodypart, None) is not None:
                        for landmark in key_frame[bodypart].keys():  # calculate delta
                            x = abs(key_frame[bodypart][landmark][0] - this_frame[bodypart][landmark][0])
                            y = abs(key_frame[bodypart][landmark][1] - this_frame[bodypart][landmark][1])
                            z = abs(key_frame[bodypart][landmark][2] - this_frame[bodypart][landmark][2])
                            if x * x_width < x_threshold and y * y_height < y_threshold and z * z_depth < z_threshold:
                                landmark_count = landmark_count + 1
                            else:
                                exit_flag = True
                                break
                    else:
                        continue
                    if exit_flag:
                        exit_flag = False
                        break
                # check whether all landmark delta < threshold, 18 need to be changed in different module
                if landmark_count == len(key_frame.keys()) * landmark_num:
                    trivial_count = trivial_count + 1
                else:
                    reduced_compress[key_frame_index] = trivial_count
                    trivial_count = 0
                    key_frame_index = this_frame_index
                    key_frame = this_frame
                    reduced_frame[this_frame_index] = this_frame
                    reduced_compress[this_frame_index] = 0

        return reduced_frame, reduced_compress


"""Helper script to retrieve nearest
neighbours to the given word in the embedding space
"""

import numpy as np
from scipy import spatial

def get_most_common_words(dictionary, n_words):
    return dictionary[:n_words]

def get_random_words(dictionary, n_words):
    rand_indices = np.random.randint(len(dictionary), size=n_words)
    return [dictionary[i] for i in rand_indices]

def get_closest_words_euler(dictionary, word, n_words, w1):
    word_vec = w1[dictionary.index(word), :]
    distances = np.linalg.norm(w1 - word_vec, axis=1)
    sorted_indices = np.argsort(distances)
    return [dictionary[i] for i in sorted_indices[:n_words]]

def get_closest_words_cosine(dictionary, word, n_words, w1):
    word_vec = w1[dictionary.index(word), :]
    # Cosine similarity is defined as cos(angle between two vecs)
    # 1 means exactly the same, -1 means exactly the opposite.
    # We append minus in from to be able to use argsort
    similarities = []
    for i in range(w1.shape[0]):
        similarities.append(-1 + spatial.distance.cosine(w1[i,:], word_vec))
    sorted_indices = np.argsort(similarities)
    return [dictionary[i] for i in sorted_indices[:n_words]]

def main():
    # Dictionary and embeddings for my code
    dict_file_mine = '../data-out/2018-03-24/new/dictionary.txt'
    w1_file_mine = '../data-out/2018-03-24/new/w1.npy'
    # Dictionary and embeddings from word2vec code
    dict_file_w2v = '../data-out/2018-03-24/old/dictionary.txt'
    w1_file_w2v = '../data-out/2018-03-24/old/w1.npy'

    # Load my dictionary and embeddings
    dictionary_mine = [line.rstrip('\n') for line in open(dict_file_mine)]
    w1_mine = np.load(w1_file_mine)
    w1_mine = np.delete(w1_mine, 0, 0)
    w1_mine = np.delete(w1_mine, 0, 0)
    w1_mine = np.delete(w1_mine, 0, 0)
    # dictionary_mine.remove('UNK')
    # dictionary_mine.remove('EOS')
    # Load word2vec dictionary and embeddings
    # dictionary_w2v = [line.rstrip('\n') for line in open(dict_file_w2v)]
    # w1_w2v = np.loadtxt(w1_file_w2v)
    dictionary_w2v = [line.rstrip('\n') for line in open(dict_file_w2v)]
    w1_w2v = np.load(w1_file_w2v)
    w1_w2v = np.delete(w1_w2v, 0, 0)
    w1_w2v = np.delete(w1_w2v, 0, 0)
    w1_w2v = np.delete(w1_w2v, 0, 0)

    n_freq_words = 50
    n_closest_words = 20

    grouped_words = []

    # Get top 50 most common words from one of the dictionaries
    words = get_most_common_words(dictionary_mine, n_freq_words)
    for word in words:
        closest_words_mine = get_closest_words_euler(dictionary_mine, word, n_closest_words, w1_mine)
        closest_words_w2v = get_closest_words_euler(dictionary_w2v, word, n_closest_words, w1_w2v)
        grouped_words.append((word, closest_words_mine, closest_words_w2v))

    for grouped_word in grouped_words:
        print(grouped_word)

    # Dump the result into a file
    eval_file = open('../data-out/2018-03-24/closest-words.txt', 'w+')
    for grouped_word in grouped_words:
        eval_file.write(grouped_word[0] + ': \n')
        eval_file.write(', '.join(grouped_word[1]) + '\n')
        eval_file.write(', '.join(grouped_word[2]) + '\n\n')
    eval_file.close()

if __name__ == "__main__":
    main()


'''
Created on 27/05/2014

@author:  Bin Liang
@email: bin.liang.ty@gmail.com
'''
from sklearn import preprocessing
from recognition.svm_tool import SvmTool
def crossValidate(train_y, train_X):
    """ Cross validate to get optimal parameters """
    # scale data
    min_max_scaler = preprocessing.MinMaxScaler(feature_range=(-1, 1))
    X_scaledArr = min_max_scaler.fit_transform(train_X)
    X_scaled = X_scaledArr.tolist()

    # write to svm format file
    outputPath = '.\\cv'
    fileName = 'train_data'
    svmTool = SvmTool()
    svmTool.write2SVMFormat(outputPath, fileName, X_scaled, train_y)


import numpy as np
import cv2
import pygame
import glob
import json
import os

def select_start_end(img, n = 5):
    pygame.init()
    gameDisplay = pygame.display.set_mode(img.shape[:2])

    clock = pygame.time.Clock()

    end = None
    starts = []

    img_surf = pygame.surfarray.make_surface(img)
    while len(starts) < n or end is None:
        for e in pygame.event.get():
            if e.type == pygame.MOUSEBUTTONUP:
                if end is None:
                    end = list(pygame.mouse.get_pos())
                else:
                    starts.append(list(pygame.mouse.get_pos()))

        gameDisplay.fill((0,0,0))
        gameDisplay.blit(img_surf, (0,0))
        if end is not None:
            pygame.draw.circle(gameDisplay, (0, 255, 0), end, 3)
        for s in starts:
            pygame.draw.circle(gameDisplay, (0, 0, 255), s, 3)
        pygame.display.update()
        clock.tick(60)

    pygame.quit()
    if end is None:
        return None, None
    for s in starts:
        s[1], s[0] = s[0], s[1]
    end[1], end[0] = end[0], end[1]
    return starts, end

if __name__ == '__main__':
    for file in glob.glob("../Scenes/*.png"):
        img = cv2.imread(file)

        name = os.path.split(file)[-1].split('.')[0]
        obj = {
            'Filepath' : name,
            'Goals' : []
        }
        starts, end = select_start_end(img.transpose(1,0,2), 5)
        for s in starts:
            obj['Goals'].append([s, end])

        with open(f'{name}.json', 'w') as fout:
            json.dump(obj, fout)


p,*o = open(0)
# open(0) : https://www.acmicpc.net/board/view/80793

# Asterisk(*) : https://mingrammer.com/understanding-the-asterisk-of-python/
k = int(p[2:]) # [2:]로 k 값에 접근하는 이유는 p == '10 4200'와 같은 str이기 때문이다.
c = 0
for i in map(int,o[::-1]):
    c += k // i
    k = k % i
print(c)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys, os
sys.path.append("..")
from django.http import HttpResponse
from src.lib import db_mysql
try:
    import simplejson as json
except ImportError:
    import json

def query_account_balance(request):
    from src.lib import django_api
    django_api.DjangoApi().os_environ_update()
    mysql_conn = db_mysql.MyPymysqlPool()
    data_list = []
    body_dict = {}
    result_dict = {'code': 500, 'success': False, 'message': 'fail', 'body': body_dict}
    table_name = 'cost_account_balance'

    # 获取总条数，用于返回的json里面输出
    try:
        sql = "select count(id) from %s;" % table_name
        total_count = int(mysql_conn.select(sql)[0][0])
    except Exception as e:
        total_count = 0

    if total_count > 0:
        try:
            sql = "select balance.cost_item_id,item.item_remark,balance.balance,balance.update_time from " \
                  "cost_account_balance balance,cost_item item where item.id = balance.cost_item_id " \
                  "order by balance desc;"
            print(sql)
            tmp_result = mysql_conn.select(sql)
        except Exception as e:
            print('except, reason: %s' % e)
        else:
            result_dict['success'] = True
            result_dict['message'] = 'success'
            result_dict['code'] = 0
            for record in tmp_result:
                single_record = {}
                item_id = record[0]
                item_remark = record[1]
                balance = record[2]
                record_time = record[3].strftime("%Y-%m-%d %H:%M:%S")
                single_record['item_id'] = item_id
                single_record['item_remark'] = item_remark
                single_record['balance'] = balance
                single_record['record_time'] = record_time
                data_list.append(single_record)
        finally:
            mysql_conn.dispose()

    body_dict['data'] = data_list
    result_dict['count'] = total_count
    result_dict['body'] = body_dict
    result_json = json.dumps(result_dict, ensure_ascii=False)
    return HttpResponse(result_json, content_type="application/json,charset=utf-8")

if __name__ == "__main__":
    query_account_balance('xxx')


from tkinter import *
import math

# establish root
root = Tk()
root.title("Calculator 2.0")
root.iconbitmap(
    r"C:\Users\chesb\OneDrive\Documents\VSC\PY4E\Calculator\calc.ico")

# change window size
root.geometry("438x605")

# Create entry box
e = Entry(root, width=25, borderwidth=7,
          font="Calibri 20", justify=RIGHT, )
e.grid(row=0, columnspan=4, padx=2, pady=10)

# -------------------------------------------------------------------CREATE BUTTON FUNCTIONS-----------------------------------------------------------------------------

def click(number):
    current = e.get()
    e.delete(0, END)
    e.insert(0, str(current) + str(number))

def clear():
    e.delete(0, END)

def add():
    num1 = e.get()
    global f_num
    global expression
    expression = "addition"
    f_num = int(num1)
    e.delete(0, END)

def subtract():
    num1 = e.get()
    global f_num
    global expression
    expression = "subtraction"
    f_num = int(num1)
    e.delete(0, END)

def multiply():
    num1 = e.get()
    global f_num
    global expression
    expression = "multiplication"
    f_num = int(num1)
    e.delete(0, END)

def divide():
    num1 = e.get()
    global f_num
    global expression
    expression = "division"
    f_num = int(num1)
    e.delete(0, END)

def square():
    num1 = e.get()
    global f_num
    global expression
    expression = "square"
    f_num = int(num1)
    e.delete(0, END)
    e.insert(0, int(math.pow(f_num, 2)))

def squareRoot():
    num1 = e.get()
    global f_num
    global expression
    expression = "squareRoot"
    f_num = int(num1)
    e.delete(0, END)
    e.insert(0, int(math.sqrt(f_num)))

def equals():
    num2 = e.get()
    e.delete(0, END)

    if expression == "addition":
        e.insert(0, f_num + int(num2))

    if expression == "subtraction":
        e.insert(0, f_num - int(num2))

    if expression == "multiplication":
        e.insert(0, int(f_num) * int(num2))

    if expression == "division":
        e.insert(0, int(f_num) / int(num2))

# -------------------------------------------------------------------CREATE BUTTONS--------------------------------------------------------------------------------------
button1 = Button(root, text="1", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(1))
button2 = Button(root, text="2", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(2))
button3 = Button(root, text="3", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(3))
button4 = Button(root, text="4", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(4))
button5 = Button(root, text="5", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(5))
button6 = Button(root, text="6", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(6))
button7 = Button(root, text="7", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(7))
button8 = Button(root, text="8", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(8))
button9 = Button(root, text="9", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(9))
button0 = Button(root, text="0", padx=40, pady=30,
                 bg="grey", font="Calibri 17 bold", command=lambda: click(0))
buttonclear = Button(root, text="C", padx=40, pady=30,
                     bg="grey", font="Calibri 17 bold", command=clear)
buttonequals = Button(root, text="=", padx=40, pady=30,
                      bg="grey", font="Calibri 17 bold", command=equals)
buttonplus = Button(root, text="+", padx=40, pady=30,
                    bg="grey", font="Calibri 17 bold", command=add)
buttonminus = Button(root, text="-", padx=40, pady=30,
                     bg="grey", font="Calibri 17 bold", command=subtract)
buttonmultiply = Button(root, text="x", padx=40, pady=30,
                        bg="grey", font="Calibri 17 bold", command=multiply)
buttondivide = Button(root, text="÷", padx=40, pady=30,
                      bg="grey", font="Calibri 17 bold", command=divide)
buttonsquare = Button(root, text="x²", padx=40, pady=30,
                      bg="grey", font="Calibri 15 bold", command=square)
buttonsquareroot = Button(root, text="√x", padx=40, pady=30,
                          bg="grey", font="Calibri 15 bold", command=squareRoot)

# grid format buttons 1-3, add
button1.grid(column=0, row=1, sticky=NSEW)
button2.grid(column=1, row=1, sticky=NSEW)
button3.grid(column=2, row=1, sticky=NSEW)
buttonplus.grid(column=3, row=1, sticky=NSEW)

# grid format buttons 4-6
button4.grid(column=0, row=2, sticky=NSEW)
button5.grid(column=1, row=2, sticky=NSEW)
button6.grid(column=2, row=2, sticky=NSEW)
buttonminus.grid(column=3, row=2, sticky=NSEW)

# grid format buttons 7-9
button7.grid(column=0, row=3, sticky=NSEW)
button8.grid(column=1, row=3, sticky=NSEW)
button9.grid(column=2, row=3, sticky=NSEW)
buttonmultiply.grid(column=3, row=3, sticky=NSEW)

# grid format square root, 0, squared, and divide buttons
buttonsquareroot.grid(column=0, row=4, sticky=NSEW)
button0.grid(column=1, row=4, sticky=NSEW)
buttonsquare.grid(column=2, row=4, sticky=NSEW)
buttondivide.grid(column=3, row=4, sticky=NSEW)

buttonclear.grid(column=3, row=5, sticky=NSEW)

buttonequals.grid(column=0, columnspan=3, row=5, sticky=NSEW)

# run window
root.mainloop()


import unittest
from classFuncionario import Funcionario

class TesteFuncionario(unittest.TestCase):
    def test_metodo_apresentar(self):
        nomeFuncionario = "Manoel"
        idadeFuncionario = 25

        novoFuncionario = Funcionario(nomeFuncionario, idadeFuncionario)

        self.assertEqual(novoFuncionario.apresentar(), "Olá meu nome é Manoel e tenho 25 anos", "Houve um erro no método apresentar()")

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

Programador de Sistemas - UC 3/Repositório de Exemplos - Turma 2/Aula 9/TestesPython/Exercicio 2/testeFuncionario.py


import logging
from sqlalchemy import create_engine, Column, ForeignKey, Integer, BigInteger, String, UnicodeText, Boolean
from sqlalchemy import ext
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker, scoped_session
from sqlalchemy.future import select
from . import Base

# For PM Permit
class AuthorizedUsers(Base):
	__tablename__ = 'AuthorizedUsers'
	# The user id
	id = Column(BigInteger, primary_key=True)
	# If they're approved
	approved = Column(Boolean)
	# If they've been warned already
	warned = Column(Boolean)
	# Whether they requested my attention
	requested = Column(Boolean)
	# The spam score they have
	retardlevel = Column(Integer)

	def __init__(self, id, approved, warned, requested):
		self.id = id
		self.approved = approved
		self.warned = warned
		self.requested = requested
		self.retardlevel = 0

	def __repr__(self):
		return f"<AuthorizedUsers id={self.id} warned={self.warned} approved={self.approved} retardlevel={self.retardlevel}>"

async def get_authorized(user_id):
	from . import session
	try:
		return (await session.execute(select(AuthorizedUsers).where(AuthorizedUsers.id == user_id))).scalars().one_or_none()
	except:
		logging.exception("Failure in get_authorized")
		await session.rollback()
		return None


import numpy as np
from activation import fun_dict

class ArtificialNeuralNetwork:
    """
    Simple Neural Network with back propagation.
    """
    __name__: str = 'Artificial Neural Network'
    n: int  # Number of elements (instances)
    dim: int  # Dimension of the data (features)
    t: int  # Dimension of the target (labels)
    max_iter: int  # Number of iterations
    neurons: int  # Number of neurons in the input layer
    learning_rate: float  # Step
    # Matrix
    input_weight: np.array
    output_weight: np.array
    bias_input_layer: np.array
    bias_output_layer: np.array
    temp_h: np.array  # Value of the hidden layer before applying activation.
    temp_o: np.array  # Value of the output layer before applying activation.
    # Neuronal functions
    activation = None
    activation_der = None

    def __init__(self):
        """
        Fix the random number generator.
        """
        np.random.seed(0)

    def get_layers(self):
        """
        Feed forward random assignation of the two layers.
        """
        self.get_input_layer()
        self.get_output_layer()

    def get_input_layer(self):
        """
        Weights and bias for the hidden layer.
        """
        self.input_weight = np.random.random((self.dim,
                                              self.neurons)) * 2.0 - 1.0
        # self.bias_input_layer = np.random.random((self.neurons, 1))
        self.bias_input_layer = np.zeros((self.neurons, 1))

    def get_output_layer(self):
        """
        Weight and bias for the output layer.
        """
        self.output_weight = np.random.random((self.neurons, 1)) * 2.0 - 1.0
        # self.bias_output_layer = np.random.random((self.t, 1))
        self.bias_output_layer = np.zeros((self.t, 1))

    def initial(self, x, y,
                max_iter,
                neurons,
                learning_rate,
                neuronal_fun):
        """
        Initialize the neural network layers.

        :param x: numpy.array with data (intances and features).
        :param y: numpy.array with the target to predict.
        :param int max_iter: number of iterations for training.
        :param int neurons: number of neurons in the hidden layer.
        :param float learning_rate: step to add in each iteration.
        :param str neuronal_fun: function for activation functions in neurons.
        """
        self.dim = x.shape[1]
        self.t = y.shape[1]
        self.max_iter = max_iter
        self.neurons = neurons
        self.learning_rate = learning_rate
        self.activation = fun_dict[neuronal_fun]['activation']
        self.activation_der = fun_dict[neuronal_fun]['derivative']
        self.get_layers()
        return self

    def train(self, x, y,
              max_iter: int = 1000,
              neurons: int = 10,
              learning_rate: float = 1.0,
              neuronal_fun='sigmoid'):
        """
        Train the neural network with gradient descent.

        :param x: numpy.array with data (intances and features).
        :param y: numpy.array with the target to predict.
        :param int max_iter: number of iterations for training.
        :param int neurons: number of neurons in the hidden layer.
        :param float learning_rate: step to add in each iteration.
        :param str neuronal_fun: function for activation functions in neurons.
        """
        self.initial(x=x,
                     y=y,
                     max_iter=max_iter,
                     neurons=neurons,
                     learning_rate=learning_rate,
                     neuronal_fun=neuronal_fun)

        for iteration in range(self.max_iter):
            # print('Iteration =', iteration)
            self.backward(x, y)

    def backward(self, x, y):
        """
        Adjust the weight after the prediction.

        :param x:
        :param y:
        :return:
        """
        hidden_layer, output_layer = self.forward(x)
        error = output_layer - y
        # print('Error =', np.linalg.norm(error))

        # Adjust output layer
        output_delta = error * self.activation_der(self.temp_o)
        # print('Norm of gradient output layer =', np.linalg.norm(output_delta))
        self.bias_output_layer -= np.mean(self.learning_rate * output_delta)
        self.output_weight -= self.learning_rate * np.dot(hidden_layer.T, output_delta)

        # Adjust hidden layer
        hidden_delta = np.dot(output_delta,
                              self.output_weight.T) * self.activation_der(self.temp_h)
        # print('Norm of gradient hidden layer =', np.linalg.norm(hidden_delta))
        self.bias_input_layer -= np.mean(self.learning_rate * hidden_delta)
        self.input_weight -= self.learning_rate * np.dot(x.T, hidden_delta)

    def forward(self, x):
        """
        Calculate the layers in the net when x is added.

        :param x:
        :return: both hidden and output layers.
        """
        self.temp_h = np.dot(x, self.input_weight) + self.bias_input_layer.T
        hidden_layer = self.activation(self.temp_h)
        self.temp_o = np.dot(hidden_layer, self.output_weight) + self.bias_output_layer.T
        output_layer = self.activation(self.temp_o)
        return hidden_layer, output_layer

    def predict(self, x):
        """
        Predict value.

        :param x: Data to predict
        :return:
        """
        _, output = self.forward(x)
        return output

if __name__ == "__main__":
    # Train the neural network using a training set
    train_x = np.array([[0, 0, 1],
                        [1, 1, 1],
                        [1, 0, 1],
                        [0, 1, 1],
                        [1, 1, 1],
                        [0, 0, 0]])
    train_y = np.array([[0],
                        [1],
                        [1],
                        [0],
                        [1],
                        [0]])

    neural_network = ArtificialNeuralNetwork()
    neural_network.train(x=train_x,
                         y=train_y,
                         neuronal_fun='tanh')

    # Test the neural network with a new situation.
    print("Testing data [1, 0, 0] = 1: ")
    test_x = np.array([1, 0, 0])
    print(neural_network.predict(test_x))


import math
import pandas as pd
import numpy as np

def load_data(file_name):
    col_names = ['Diagnosis']
    for i in range(1, 23):
        col_names.append(f'F{i}')
    data = pd.read_csv(file_name, names=col_names)
    y = data['Diagnosis'].values
    x = data[col_names[1:]].values
    y[y == 0] = -1
    return x, y

class Stump:
    def __init__(self, x, y, split_attr, predictions):
        self.split_attr = split_attr
        self.predictions = predictions

    def predict(self, value):
        return self.predictions[value[self.split_attr]]

    def __str__(self):
        return f'Split:{self.split_attr}, Predictions:{self.predictions}'

def generate_stumps(x, y):
    stumps = []
    for a in range(x.shape[1]):
        for z in [-1, 1]:
            for o in [-1, 1]:
                stumps.append(Stump(x, y, a, [z, o]))
    return stumps

def loss(x, y, stumps, alphas):
    loss_total = 0
    for xi, yi in zip(x, y):
        exp_total = 0
        for alpha, stump in zip(alphas, stumps):
            exp_total += alpha * stump.predict(xi)
        loss_total += math.exp(-yi * exp_total)
    return loss_total

def update_alpha_n(x, y, alphas, n, stumps):
    numerator = 0
    denominator = 0
    for xi, yi in zip(x, y):
        exp_total = 0
        for i, (alpha, stump) in enumerate(zip(alphas, stumps)):
            if i != n:
                exp_total += alpha * stump.predict(xi)
        if stumps[n].predict(xi) == yi:
            numerator += math.exp(-yi * exp_total)
        else:
            denominator += math.exp(-yi * exp_total)
    alpha_n = .5 * math.log(numerator/denominator)
    return alpha_n

def coordinate_descent(x, y, stumps):
    alphas = np.array([0.0] * len(stumps))
    for n, _ in enumerate(alphas):
        for j in range(100000):
            alpha_n = update_alpha_n(x, y, alphas, n, stumps)
            if alpha_n == alphas[n]:
                break
            alphas[n] = alpha_n
    return alphas

def update_weights(x, y, stump, weights, round, error, alpha):
    for i, w in enumerate(weights[round]):
        weights[round + 1][i] = w * math.exp(-y[i] * stump.predict(x[i]) * alpha) / (2 * math.sqrt((1 - error) * error))

def get_best_stump(x, y, stumps, weights=None):
    if weights is None:
        weights = [1/x.shape[0]]*x.shape[0]
    best = (0, stumps[0])
    for s in stumps:
        acc = weighted_accuracy(x, y, weights, s)
        if acc > best[0]:
            best = (acc, s)
    return best[1]

def weighted_accuracy(x, y, weights, stump):
    correct = 0
    for xi, yi, wi in zip(x, y, weights):
        correct += wi * (stump.predict(xi) == yi)
    return correct

def ada_boost(x, y, stumps, rounds=20):
    weights = np.ones((rounds + 1, x_train.shape[0])) * (1 / x_train.shape[0])
    ada_stumps = []
    ada_errors = []
    ada_alphas = []
    for r in range(rounds):
        ada_stumps.append(get_best_stump(x, y, stumps, weights[r]))
        ada_errors.append(1 - weighted_accuracy(x, y, weights[r], ada_stumps[r]))
        ada_alphas.append(0.5 * math.log((1 - ada_errors[r]) / ada_errors[r]))
        update_weights(x, y, ada_stumps[r], weights, r, ada_errors[r], ada_alphas[r])
    return ada_stumps, np.array(ada_alphas)

def accuracy(x, y, stumps, alphas):
    correct = 0
    for xi, yi in zip(x, y):
        curr = 0
        for s, a in zip(stumps, alphas):
            curr += s.predict(xi) * a
        correct += (curr * yi >= 0)
    return correct/len(y)

def bagging(x, y, stumps, bags=20):
    bag_stumps = []
    for b in range(bags):
        shuffle = np.arange(x.shape[0])
        shuffle = np.random.choice(shuffle, x.shape[0])
        bag_x = x[shuffle]
        bag_y = y[shuffle]
        bag_stumps.append(get_best_stump(bag_x, bag_y, stumps))
    return bag_stumps

def bag_accuracy(x, y, bag_stumps):
    correct = 0
    for xi, yi in zip(x, y):
        curr = 0
        for s in bag_stumps:
            curr += s.predict(xi) * (1/len(bag_stumps))
        correct += (curr * yi >= 0)
    return correct/len(y)

x_train, y_train = load_data('heart_train.data')
x_test, y_test = load_data('heart_test.data')
stumps = generate_stumps(x_train, y_train)

print(f'{"Coordinate Descent":=^40}')
coord_alphas = coordinate_descent(x_train, y_train, stumps)
print(coord_alphas)
print(f'Training Accuracy: {accuracy(x_train, y_train, stumps, coord_alphas):<3.1%}')
print(f'Test Accuracy: {accuracy(x_test, y_test, stumps, coord_alphas):<3.1%}')
print(f'Training Loss: {loss(x_train, y_train, stumps, coord_alphas):<3.2f}')

print()
print(f'{"Ada Boost":=^40}')
ada_stumps, ada_alphas = ada_boost(x_train, y_train, stumps)
print(ada_alphas)
print(f'Training Accuracy: {accuracy(x_train, y_train, ada_stumps, ada_alphas):<3.1%}')
print(f'Test Accuracy: {accuracy(x_test, y_test, ada_stumps, ada_alphas):<3.1%}')

print()
print(f'{"Bagging":=^40}')
bag_stumps = bagging(x_train, y_train, stumps)
print(f'Training Accuracy: {bag_accuracy(x_train, y_train, bag_stumps):<3.1%}')
print(f'Test Accuracy: {bag_accuracy(x_test, y_test, bag_stumps):<3.1%}')


"""
比对(不比对逻辑上已经删除了的, 每次从数据库取1000, 处理完之后清空缓存, 再取1000), 有效的设置为Y, 失效的设置为N
"""

import logging

from thor_crawl.utils.db.daoUtil import DaoUtils
from thor_crawl.utils.http.proxyIpUtil import ProxyIpUtil

logger = logging.getLogger(__name__)

class VerifyProxyIp(object):
    # 数据库表
    __DB_TABLE_MAIN = 'proxy_ip'

    def __init__(self):
        self.dao = DaoUtils()

    def handle(self):
        proxy_ip_group = self.dao.get_all('select id, ip, port, ip_type from ' + VerifyProxyIp.__DB_TABLE_MAIN)
        for proxy_ip_row in proxy_ip_group:
            is_str = str(proxy_ip_row['id'])
            ip_type = proxy_ip_row['ip_type'].lower()
            proxy_ip = ip_type + '://' + proxy_ip_row['ip'] + ':' + proxy_ip_row['port']
            if ProxyIpUtil.is_effective(ip_type, proxy_ip):
                self.dao.modify('update ' + VerifyProxyIp.__DB_TABLE_MAIN + ' set status = 1 where id = ' + is_str)
                print(1111)
            else:
                self.dao.modify('update ' + VerifyProxyIp.__DB_TABLE_MAIN + ' set status = 0 where id = ' + is_str)
                print(2222)

if __name__ == '__main__':
    print(VerifyProxyIp().handle())
    # while True:
    #     print(VerifyProxyIp().handle())


from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='RecacheSchedule',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('url', models.TextField(unique=True)),
                ('datetime', models.DateTimeField(db_index=True)),
            ],
        ),
    ]


import pytest

from src.data.labels import EventLabel

from src.converters.labelstograph.eventresolver import get_all_neighbors_of_type as neighbors

@pytest.fixture
def events() -> list[EventLabel]:
    c1 = EventLabel('L1', name='Cause1', begin=0, end=1)
    c2 = EventLabel('L2', name='Cause2', begin=1, end=2)
    c3 = EventLabel('L3', name='Cause3', begin=2, end=3)
    e1 = EventLabel('L4', name='Effect1', begin=3, end=4)
    e2 = EventLabel('L5', name='Effect2', begin=4, end=5)
    e3 = EventLabel('L6', name='Effect3', begin=5, end=6)

    c1.set_successor(c2, junctor='AND')
    c2.set_successor(c3, junctor='AND')
    c3.set_successor(e1, junctor='AND')
    e1.set_successor(e2, junctor='AND')
    e2.set_successor(e3, junctor='AND')

    return [c1, c2, c3, e1, e2, e3]

@pytest.mark.unit
def test_preceeding_causes(events):
    candidates = neighbors(startlabel=events[1], direction='predecessor', type='Cause')

    assert len(candidates) == 1
    assert candidates[0] == events[0]

@pytest.mark.unit
def test_succeeding_causes(events):
    candidates = neighbors(startlabel=events[1], direction='successor', type='Cause')

    assert len(candidates) == 1
    assert candidates[0] == events[2]

@pytest.mark.unit
def test_preceeding_effects(events):
    candidates = neighbors(startlabel=events[1], direction='predecessor', type='Effect')

    assert len(candidates) == 0

@pytest.mark.unit
def test_succeeding_effects(events):
    candidates = neighbors(startlabel=events[1], direction='successor', type='Effect')

    assert len(candidates) == 3
    assert candidates[0] == events[3]
    assert candidates[1] == events[4]
    assert candidates[2] == events[5]


def in_range_helper(lesser:int, greater:int, x:int):
	if x >= lesser or x <= greater:
		return True
	return False

def find_index(mylist, myint:int):
    min, max, idx = 0, len(mylist) - 1, len(mylist) // 2
    while( in_range_helper(mylist[min], mylist[max], myint) ):
        idx = (min + max) // 2
        if min == idx or max == idx:
                break
        if myint == mylist[idx]:
            return idx
        elif myint > mylist[idx]:
            min = idx
        elif myint < mylist[idx]:
            max = idx

def freq_count(mylist, myint:int) -> int:
    count = 0
    idx = find_index(mylist, myint)
    if idx is None:
        # print('idx is None:')
        return count
    # print('idx is":', idx)
    left_idx = right_idx = idx
    while (left_idx >= 0 and mylist[right_idx] == myint):
        count += 1
        left_idx-=1
    while (right_idx < len(mylist)-1 and mylist[right_idx] == myint):
        count += 1
        right_idx+=1
    return count

if __name__ == "__main__":
    #        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
    list1 = [1,1,1,6,6,6,6,6,7,7,7,7,7,9,9,9,9] # myint= 7
    list2 = [1,1,1,1,1,1,1,1,1,1,1,1,1] # myint = 1
    list3 = [1,1,1,1,1,1,1,1,4,5,6,7,8] # myint = 1
    list4 = [-1,-1,-1,-1,-1,-1,-1,-1,-4,-5,-6,-7,-8] # myint = 1
    list5 = [1,1,1,6,6,6,6,6,7,7,7,7,7,9,9,9,9] # myint= 7
    list6 = [1,5,5,6,6,6,6,6,7,7,7,7,7,9,9,9,9] # myint= 7
    list7 = [1,1,1,6,6,6,6,6,7,7,7,7,7,9,9,9,12] # myint= 7
    print('list1:', freq_count(list1, 5))
    print('list2:',freq_count(list2, 1))
    print('list3:',freq_count(list3, 4))
    print('list4:',freq_count(list4, -1))


import torch
from sklearn.metrics import f1_score, classification_report

from compent.comm import get_rank, accumulate_results_from_multiple_gpus

class Evaler_HAN():
    def __init__(self, cfg, logger, loader):
        self.cfg = cfg
        self.logger = logger
        self.loader = loader
        self.rank = get_rank()

    def __call__(self, model):
        self.logger.info('start eval')
        model.eval()
        with torch.no_grad():
            label_cur_GPU = []
            pred_cur_GPU = []
            sentence_cur_GPU = []
            for batch_input, batch_label, sentence in self.loader:
                num_sample = len(batch_label)
                batch_input = batch_input.cuda()
                # batch_label = batch_label.cuda()

                model.module._init_hidden_state(num_sample)

                outputs = model(batch_input)
                # pred_score = outputs.logits
                pred = torch.argmax(outputs, dim = 1).tolist()

                label_cur_GPU += batch_label.tolist()
                pred_cur_GPU += pred
                sentence_cur_GPU += sentence

        model.train()
        self.logger.visdom_text(text = 'before' + str(len(label_cur_GPU)), win_name = 'test GPU count')
        all_labels = accumulate_results_from_multiple_gpus(label_cur_GPU)
        self.logger.visdom_text(text = 'after' + str(len(all_labels)), win_name = 'test GPU count')
        all_preds = accumulate_results_from_multiple_gpus(pred_cur_GPU)
        all_sentences = accumulate_results_from_multiple_gpus(sentence_cur_GPU)

        self.logger.info('accumulate labels:{}, preds:{}'.format(len(all_labels), len(all_preds)))

        print(classification_report(y_true = all_labels, y_pred = all_preds))

        f1_macro = f1_score(y_true = all_labels, y_pred = all_preds, average = 'macro')
        f1_micro = f1_score(y_true = all_labels, y_pred = all_preds, average = 'micro')
        test_metrics = {}
        test_metrics['f1_macro'] = f1_macro
        test_metrics['f1_micro'] = f1_micro
        test_metrics['sentence'] = all_sentences
        test_metrics['all_preds'] = all_preds
        return test_metrics


# 383. 赎金信
# 为了不在赎金信中暴露字迹，从杂志上搜索各个需要的字母，组成单词来表达意思。

# 给你一个赎金信 (ransomNote) 字符串和一个杂志(magazine)字符串，判断 ransomNote 能不能由 magazines 里面的字符构成。

# 如果可以构成，返回 true ；否则返回 false 。

# magazine 中的每个字符只能在 ransomNote 中使用一次。

# 来源：力扣（LeetCode）
# 链接：https://leetcode-cn.com/problems/ransom-note
# 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。

import collections

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        rc = collections.Counter(ransomNote)
        mc = collections.Counter(magazine)
        for k in rc.keys():
            if k not in mc:
                return False
            if rc[k]>mc[k]:
                return False
        return True

sol = Solution()
ransomNote = "a"
magazine = "b"
print(sol.canConstruct(ransomNote,magazine))


import csv
# Написать программу которая из фала "2019.csv" возьмёт топ 10 стран по любому из пунктов (не первые три)

with open('../008_csv_json_xml/002_csv_module/csv_files/2019.csv', 'r', encoding='utf8') as csv_file:
    csv_reader = list(csv.DictReader(csv_file))

while True:
    user_choise = input('1.TOP 10 GDP per capita\n'
                        '2.TOP 10 Social support\n'
                        '3.TOP 10 Healthy life expectancy\n'
                        '4.TOP 10 Freedom to make life choices\n'
                        '5.TOP 10 Generosity\n'
                        '6.TOP 10 Perceptions of corruption\n'
                        '0.Exit\n'
                        '-->')
    if user_choise == '1':
        column_name = 'GDP per capita'
    elif user_choise == '2':
        column_name = 'Social support'
    elif user_choise == '3':
        column_name = 'Healthy life expectancy'
    elif user_choise == '4':
        column_name = 'Freedom to make life choices'
    elif user_choise == '5':
        column_name = 'Generosity'
    elif user_choise == '6':
        column_name = 'Perceptions of corruption'
    elif user_choise == '0':
        print('Good bye!')
        break
    else:
        print('Choise is out of range')
    countries_data = {}
    for line in csv_reader:
        country = line['Country or region']
        value = float(line[column_name])
        countries_data[country] = value
    top_10_countries = dict(sorted(countries_data.items(), key=lambda x: x[1], reverse=True)[:10])
    for country, value in top_10_countries.items():
        print(f"{country}: {value}")

# 008230717/2019.csv/


"""
    https://leetcode.com/problems/maximum-number-of-visible-points/
"""
import math
from typing import List

class Solution:
    # pylint: disable=too-few-public-methods
    """
    Solution
    """

    def visible_points(
        self, points: List[List[int]], angle: int, location: List[int]
    ) -> int:
        # pylint: disable=no-self-use
        """
        Return the max number of points the agent can see at the given location
        and with the given wide angle
        """
        num_points = len(points)
        num_always_visible = 0

        point_angles = []
        for i in range(num_points):
            # Make the agent location be the origin
            new_x = points[i][0] - location[0]
            new_y = points[i][1] - location[1]

            if new_x == 0 and new_y == 0:
                # It is always visible to the agent.
                num_always_visible += 1
                continue

            # Convert all points to angles from the positive x-axis counter-clockwise
            radian = math.atan2(new_y, new_x)
            if radian < 0:
                radian = 2 * math.pi + radian

            point_angle = math.degrees(radian)
            point_angles.append(point_angle)
            # For circular loop
            point_angles.append(360 + point_angle)

        # Sort the points by their angle
        point_angles.sort()

        start = 0
        max_visible = 0

        for end in range(0, len(point_angles)):
            if point_angles[start] >= 360:
                break
            if point_angles[end] - point_angles[start] > angle:
                start += 1

            # record
            max_visible = max(max_visible, end - start + 1)

        return max_visible + num_always_visible


from .baseline import *

def build_model(config, num_classes):
    model = Baseline(num_classes=num_classes,
                     last_stride=int(config['MODEL']['LAST_STRIDE']),
                     model_path=config['MODEL']['PRETRAIN_PATH'],
                     model_name=config['MODEL']['NAME'],
                     using_fc_bias=config['MODEL']['FC_BIAS'],
                     using_norm=config['MODEL']['USING_NORM'],
                     norm_type=config['MODEL']['NORM_TYPE'])
    return model

def bulid_classifier(num_classes, dim=2048):
    ide_net = IDENet(dim, num_classes)

    return ide_net


class TreeNode:
    def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None
class Solution:
    def closestValue(self, root: TreeNode, target: float) -> int:
        self.difference = float('inf')
        self.res = 0
        def DFS(root):
            if not root: return
            temp = abs(root.val - target)
            if temp < self.difference:
                self.difference = temp
                self.res = root.val
            DFS(root.left)
            DFS(root.right)
        DFS(root)
        return self.res


import jax.numpy as jnp
from jaxman import KalmanFilter
import pytest as pt
import pykalman as pk
import numpy as np
import jax.random as jxrnd

def error(y_true, y_hat):
    return jnp.abs((y_true - y_hat) / y_true).mean()

def kalman_configurations():
    yield (
        (0.5, 1.0, 1.0, 1.0),
        (1, 1)
    )

    yield (
        (0.5 * jnp.eye(2), jnp.eye(2), jnp.ones(2), 1.0),
        (2, 1)
    )

    yield (
        (0.5 * jnp.eye(2), jnp.eye(2), jnp.ones((3, 2)), jnp.eye(3)),
        (2, 3)
    )

def kalman_filters_with_pykalman():
    trans_mat = 1.0
    obs_mat = 1.0

    trans_cov = 0.1
    obs_cov = 0.1

    yield (
        pk.KalmanFilter(transition_covariance=trans_cov, transition_matrices=trans_mat, observation_covariance=obs_cov, observation_matrices=obs_mat),
        KalmanFilter(trans_mat, trans_cov, obs_mat, obs_cov)
    )

    trans_mat = np.eye(1, 5)
    trans_mat = np.concatenate((trans_mat, np.eye(4, 5)))
    trans_cov = 0.1 * trans_mat

    obs_mat = np.ones(trans_mat.shape[-1]).cumsum()[::-1]
    obs_mat /= obs_mat.sum()

    yield (
        pk.KalmanFilter(transition_covariance=trans_cov, transition_matrices=trans_mat, observation_covariance=obs_cov, observation_matrices=obs_mat),
        KalmanFilter(trans_mat, trans_cov, obs_mat, obs_cov)
    )

class TestKalman(object):
    EPS = 1e-6

    @pt.mark.parametrize("conf_and_expected", kalman_configurations())
    def test_initializer(self, conf_and_expected):
        conf, exp = conf_and_expected
        kf = KalmanFilter(*conf)

        assert kf.trans_cov.shape == (exp[0], exp[0])
        assert kf.trans_mat.shape == kf.trans_cov.shape

        assert kf.obs_cov.shape == (exp[1], exp[1])
        assert kf.obs_mat.shape == (exp[1], exp[0])

    @pt.mark.parametrize("conf_and_expected", kalman_configurations())
    @pt.mark.parametrize("batch_shape", [(), (100,), (1_000,)])
    def test_predict_correct(self, conf_and_expected, batch_shape):
        conf, shape = conf_and_expected
        kf = KalmanFilter(*conf)

        c = kf.initialize()
        p = kf.predict(c)

        c = kf.correct(jnp.ones((*batch_shape, shape[-1])), p)

        assert c.mean.shape == (*batch_shape, shape[0])
        assert c.covariance.shape == (*batch_shape, shape[0], shape[0])

    @pt.mark.parametrize("pykf_kf", kalman_filters_with_pykalman())
    @pt.mark.parametrize("replicas", [1, 10, 100])
    def test_compare_with_pykalman(self, pykf_kf, replicas):
        pykf, kf = pykf_kf

        m = list()
        c = list()

        _, y = kf.sample(100, jxrnd.PRNGKey(123), (replicas,))
        for i in range(replicas):
            m_, c_ = pykf.filter(y[:, i])

            m.append(m_)
            c.append(c_)

        m = np.stack(m, axis=1)
        c = np.stack(c, axis=1)

        jax_result = kf.filter(y)
        m_jax, c_jax = jax_result.filtered()

        # NB: We only compare the last 50% of the series as the approach is somewhat different.
        ind = int(y.shape[0] * 0.5)

        m_error = error(m[ind:], m_jax[ind:])
        c_error = error(c[ind:], c_jax[ind:])

        assert m_error < self.EPS and c_error < self.EPS


import numpy as np
import time
import pycuda.autoinit
from config_pso import config_pso
import pycuda.driver as cuda
from pycuda.compiler import SourceModule
from pycuda.driver import cudaMemcpy, cudaMemcpyHostToDevice

mod = SourceModule("""
    __global__ void update_particles(float *particles, float *velocities, float *best_positions, float *global_best_position, float w, float c1, float c2, int nb_part, int dim)
    {
        int idx = blockIdx.x * blockDim.x + threadIdx.x;
        if (idx < nb_part * dim) {
            int i = idx / dim;
            int j = idx % dim;
            float rp = (float)rand() / (float)RAND_MAX;
            float rg = (float)rand() / (float)RAND_MAX;
            velocities[idx] = w * velocities[idx] + c1 * rp * (best_positions[idx] - particles[idx]) + c2 * rg * (global_best_position[j] - particles[idx]);
            particles[idx] += velocities[idx];
        }
    }
""")

update_particles = mod.get_function("update_particles")

def pso_opti_gpu(fct, params):
    begin = time.time()

    nb_part = params["nb_part"]
    dim = params["Dim"]
    nb_iter = params["max_ite"]
    nb_block = 128
    nb_thread = 512

    particles = np.random.uniform(params["min_x"], params["max_x"], (nb_part, dim)).astype(np.float32)
    velocities = np.random.uniform(-params["vit"], params["vit"], (nb_part, dim)).astype(np.float32)
    best_positions = np.copy(particles)
    costs = np.array([fct(particles[i]) for i in range(nb_part)], dtype=np.float32)
    best_costs = np.copy(costs)
    global_best_index = np.argmax(costs)
    global_best_cost = costs[global_best_index]
    global_best_position = particles[global_best_index].astype(np.float32)

    particles_gpu = cuda.to_device(particles)
    velocities_gpu = cuda.to_device(velocities)
    best_positions_gpu = cuda.to_device(best_positions)
    global_best_position_gpu = cuda.to_device(global_best_position)

    for _ in range(nb_iter):
        update_particles(
            particles_gpu, velocities_gpu, best_positions_gpu, global_best_position_gpu,
            np.float32(params["w"]), np.float32(params["c1"]), np.float32(params["c2"]),
            np.int32(nb_part), np.int32(dim),
            block=(nb_block, 1, 1), grid=(nb_thread, 1, 1)
        )

        cuda.memcpy_dtoh(particles, particles_gpu)

        costs = np.array([fct(particles[i]) for i in range(nb_part)], dtype=np.float32)
        improved_mask = costs > best_costs
        best_positions[improved_mask] = particles[improved_mask]
        best_costs[improved_mask] = costs[improved_mask]

        global_best_index = np.argmax(costs)
        new_global_best_cost = costs[global_best_index]
        if new_global_best_cost > global_best_cost:
            global_best_cost = new_global_best_cost
            global_best_position = particles[global_best_index].astype(np.float32)
            cudaMemcpy(global_best_position_gpu, global_best_position, global_best_position.nbytes, cudaMemcpyHostToDevice)

    end = time.time()
    print("Global best cost: ", global_best_cost)
    print("Global best position: ", global_best_position)
    print("Execution time: ", end - begin)

if __name__ == "__main__":

    params = config_pso()

    pso_opti_gpu(params['function'], params)


def tournamentWinner(competitions, results):
    teamScores = {}
    maxScore = 0
    highestScoreTeam = None
    for c, r in zip(competitions, results):
        winner = c[1] if r == 0 else c[0]
        teamScores[winner] = teamScores.get(winner, 0) + 3
        if teamScores[winner] > maxScore:
            maxScore = teamScores[winner]
            highestScoreTeam = winner

    return highestScoreTeam

import unittest

class TestProgram(unittest.TestCase):
    def test_case_1(self):
        competitions = [["HTML", "C#"], ["C#", "Python"], ["Python", "HTML"]]
        results = [0, 0, 1]
        expected = "Python"
        actual = tournamentWinner(competitions, results)
        self.assertEqual(actual, expected)


import numpy as np
import torch
import torch.nn.functional as F
from torch_geometric.nn import ChebConv
from torch_geometric.utils import dense_to_sparse

from association.types import *
from association.nn.basic import *

__all__ = ['AssociationModule', 'GAT', 'GC', 'GCN', 'INA']

class GC(torch.nn.Module):
    def __init__(self,
                 num_nodes: int,
                 num_in_channels: int,
                 num_add_channels: Optional[int],
                 dist_mat: Union[torch.Tensor, np.ndarray],
                 *,
                 dist_threshold: Union[int, float] = 2e5,
                 k: int = 2,
                 eps: float = 1e-5,
                 dtype: str = 'float32') -> None:
        super().__init__()
        self.num_nodes = num_nodes
        self.num_add_channels = num_add_channels
        dtype = getattr(torch, dtype)
        num_add_channels = 1 if num_add_channels is None else num_add_channels
        mask = dist_mat <= dist_threshold
        dist_mat = dist_mat * mask
        self.edge_idx, edge_w = dense_to_sparse(torch.tensor(1 / (dist_mat + eps)))
        self.edge_w = edge_w.to(dtype)
        self.conv = ChebConv(num_in_channels, num_add_channels, K=k)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        self.edge_idx = self.edge_idx.to(x.device)
        self.edge_w = self.edge_w.to(x.device)
        y = self.conv(x, self.edge_idx, self.edge_w)
        y = F.sigmoid(y)
        y = y.reshape(-1, self.num_nodes, self.num_add_channels)
        y = torch.cat((x, y), dim=-1)
        return y

class GCN(torch.nn.Module):

    def __init__(self,
                 num_in_channels: int,
                 num_out_channels: Optional[int],
                 dist_mat: torch.Tensor,
                 *,
                 dist_threshold: float = 2e5,
                 dtype: str = 'float32'):
        super().__init__()
        dtype = getattr(torch, dtype)
        num_out_channels = num_in_channels if num_out_channels is None else num_out_channels
        adj_mat = (dist_mat < dist_threshold)
        adj_mat = adj_mat.to(dtype)
        adj_mat.fill_diagonal_(1)
        neighbors = adj_mat.sum(dim=-1, keepdims=True)
        self.adj_mat = adj_mat / neighbors
        self.projection = torch.nn.Linear(in_features=num_in_channels,
                                          out_features=num_out_channels,
                                          dtype=dtype)
        torch.nn.init.xavier_uniform_(self.projection.weight)

    def forward(self, x: torch.Tensor):
        self.adj_mat = self.adj_mat.to(x.device)
        x = self.projection(x)
        node_feats = torch.einsum('ij, ...jc -> ...ic', self.adj_mat, x)
        return node_feats

class GAT(torch.nn.Module):

    def __init__(self,
                 num_nodes: int,
                 num_in_channels: int,
                 num_hidden_channels: Optional[int],
                 dist_mat: torch.Tensor,
                 *,
                 dist_threshold: float = 2e5,
                 alpha: float = 0.01,
                 dtype: str = 'float32'):
        super().__init__()
        self.num_nodes = num_nodes
        self.num_hidden_channels = 32 if num_hidden_channels is None else num_hidden_channels
        dtype = getattr(torch, dtype)
        adj_mat = (dist_mat < dist_threshold)
        self.adj_mat = adj_mat.to(dtype)
        self.adj_mat.fill_diagonal_(1)

        self.projection = torch.nn.Linear(in_features=num_in_channels,
                                          out_features=num_hidden_channels,
                                          dtype=dtype)
        self.a = torch.nn.Linear(in_features=num_hidden_channels * 2,
                                 out_features=1,
                                 bias=False,
                                 dtype=dtype)
        self.leakyrelu = torch.nn.LeakyReLU(alpha)
        torch.nn.init.xavier_uniform_(self.projection.weight)
        torch.nn.init.xavier_uniform_(self.a.weight)

    def forward(self, x: torch.Tensor):
        self.adj_mat = self.adj_mat.to(x.device)
        x = self.projection(x)
        is_batched = x.dim() == 3
        x_concat = torch.cat([
            torch.repeat_interleave(x, self.num_nodes, dim=-1).reshape(-1, self.num_nodes**2,
                                               self.num_hidden_channels),
            torch.repeat_interleave(x, self.num_nodes, dim=-2).reshape(-1, self.num_nodes**2,
                                                                       self.num_hidden_channels)
        ],
                             dim=-1)
        x_concat = x_concat.reshape(-1, self.num_nodes, self.num_nodes,
                                    self.num_hidden_channels * 2)
        x_activated = self.leakyrelu(self.a(x_concat)).reshape(
            -1, self.num_nodes, self.num_nodes)
        attention_mat = torch.where(self.adj_mat > 0, x_activated, -1e15)
        attention_mat = F.softmax(attention_mat, dim=-1)
        y = torch.einsum('...ij, ...jc -> ...ic', attention_mat, x)
        return y if is_batched else y.squeeze(0)

class INA(torch.nn.Module):

    def __init__(self,
                 num_nodes: int,
                 num_in_channels: int,
                 num_hidden_channels: Optional[int],
                 *,
                 alpha: float = 0.01,
                 dtype: str = 'float32'):
        super().__init__()
        self.num_nodes = num_nodes
        self.num_hidden_channels = 32 if num_hidden_channels is None else num_hidden_channels
        dtype = getattr(torch, dtype)

        # self.w = Weight((num_in_channels,), dtype=dtype)
        self.w = torch.nn.Parameter(torch.randn((num_in_channels), dtype=dtype))
        self.b = Bias((num_in_channels,), dtype=dtype)

        self.projection = torch.nn.Linear(in_features=num_in_channels,
                                          out_features=num_hidden_channels,
                                          dtype=dtype)
        self.node_eval = torch.nn.Linear(in_features=num_hidden_channels,
                                         out_features=1,
                                         bias=False,
                                         dtype=dtype)
        self.a = torch.nn.Linear(in_features=2,
                                 out_features=1,
                                 bias=False,
                                 dtype=dtype)
        self.leakyrelu = torch.nn.LeakyReLU(alpha)
        torch.nn.init.xavier_uniform_(self.projection.weight)
        torch.nn.init.xavier_uniform_(self.a.weight)

    def forward(self, x: torch.Tensor):
        x = self.projection(x)
        is_batched = x.dim() == 3

        y = x * self.w + self.b
        y = self.projection(y)
        y = self.node_eval(y).reshape(-1, self.num_nodes, 1)

        y_concat = torch.cat([
            torch.repeat_interleave(y, self.num_nodes, dim=-1).reshape(-1, self.num_nodes**2, 1),
            torch.repeat_interleave(y, self.num_nodes, dim=-2).reshape(-1, self.num_nodes**2, 1)
        ], dim=-1)
        y_concat = y_concat.reshape(-1, self.num_nodes, self.num_nodes, 2)
        x_activated = self.leakyrelu(self.a(y_concat)).reshape(
            -1, self.num_nodes, self.num_nodes)
        attention_mat = F.softmax(x_activated, dim=-1)
        return attention_mat if is_batched else attention_mat.squeeze(0)