#!/usr/bin/env python3
class Piece:
    def __init__(self, c, r, l):
        self._colour = c
        self._role = r
        self._location = l

    def getColour(self):
        return self._colour

    def getRole(self):
        return self._role

    def getLocation(self):
        return self._location

    def getIconChar(self):
        return 9812

    def move(self, currentLocation, newLocation, square):
        self._location = newLocation
        square.squareUpdate(currentLocation, newLocation, self)

    def __str__(self):
        return chr(self.getIconChar())

    def checkMove(self, location, newLocation, square):
        return False

    def getDelta(self, currentLocation, newLocation): # return (deltaX, deltaY) = (column, row) = (alpha, num)
        currentIndex = currentLocation.getMatrixIndex()
        newIndex = newLocation.getMatrixIndex()
        deltaY = newIndex[0] - currentIndex[0]
        deltaX = newIndex[1] - currentIndex[1]
        return (deltaX, deltaY)

    def isEnemy(self, other): # return True if its enemy
        # print('isEnemy')
        # print(self.getColour(), other.getColour())
        if self.getColour() != other.getColour():
            return True
        else:
            return False

    def checkBlock(self, currentLocation, newLocation, square, delta):
        # print(delta)
        if delta[0]: # get one step
            deltaStep = [int(i / abs(delta[0])) for i in delta]
        else:
            deltaStep = [int(i / abs(delta[1])) for i in delta]
        step = currentLocation.add(deltaStep[0], deltaStep[1])
        # print('deltaStep: ', deltaStep)
        # print('current: ', currentLocation.getMatrixIndex())
        # i = 0
        # while i != 2:
        #     i = i + 1
        while not step.getMatrixIndex() == newLocation.getMatrixIndex():
            # print('step: ', step.getMatrixIndex())
            # print('new: ', newLocation.getMatrixIndex())
            if not square.checkEmpty(step): # if not empty, means there's something on the way
                return False
            step = step.add(deltaStep[0], deltaStep[1])
        return True

class King(Piece):
    def __init__(self, c, l):
        super().__init__(c, 'King', l)

    def getIconChar(self):
        if self.getColour() == 'w':
            return super().getIconChar() + 0
        else:
            return super().getIconChar() + 6

    def __str__(self):
        if self.getColour() == 'w':
            return chr(super().getIconChar() + 0)
        else:
            return chr(super().getIconChar() + 6)

    def checkMove(self, currentLocation, newLocation, square):
        delta = self.getDelta(currentLocation, newLocation)
        onNewLocation = square.getSpot(newLocation)
        if abs(delta[0]) == 1:
            if abs(delta[1]) == 1 or abs(delta[1]) == 0:
                if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                    return False # if there is a piece and its not enemy
                elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                    square.capture(onNewLocation)
                    return True # is enemy
                else:
                    return True # no piece
            else:
                return False
        elif abs(delta[0]) == 0 and abs(delta[1]) == 1:
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                square.capture(onNewLocation)
                return True # is enemy
            else:
                return True # no piece
        else:
            return False

class Queen(Piece):
    def __init__(self, c, l):
        super().__init__(c, 'Queen', l)

    def getIconChar(self):
        if self.getColour() == 'w':
            return super().getIconChar() + 1
        else:
            return super().getIconChar() + 7

    def __str__(self):
        if self.getColour() == 'w':
            return chr(super().getIconChar() + 1)
        else:
            return chr(super().getIconChar() + 7)

    def checkMove(self, currentLocation, newLocation, square):
        delta = self.getDelta(currentLocation, newLocation)
        onNewLocation = square.getSpot(newLocation)
        if abs(delta[0]) == abs(delta[1]):
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    square.capture(onNewLocation)
                    return True # if there's a piece and is enemy
            else:
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    return True # if there's no piece
        elif abs(delta[0]) == 0 or abs(delta[1]) == 0:
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    square.capture(onNewLocation)
                    return True # if there's a piece and is enemy
                else:
                    return False
            else:
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    return True # if there's no piece
                else:
                    return False
        else:
            return False

class Castle(Piece):
    def __init__(self, c, l):
        super().__init__(c, 'Castle', l)

    def getIconChar(self):
        if self.getColour() == 'w':
            return super().getIconChar() + 2
        else:
            return super().getIconChar() + 8

    def __str__(self):
        if self.getColour() == 'w':
            return chr(super().getIconChar() + 2)
        else:
            return chr(super().getIconChar() + 8)

    def checkMove(self, currentLocation, newLocation, square):
        delta = self.getDelta(currentLocation, newLocation)
        onNewLocation = square.getSpot(newLocation)
        if abs(delta[0]) == 0 or abs(delta[1]) == 0:
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    square.capture(onNewLocation)
                    return True # if there's a piece and is enemy
                else:
                    return False
            else:
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    return True # if there's no piece
                else:
                    return False
        else:
            return False

class Bishop(Piece):
    def __init__(self, c, l):
        super().__init__(c, 'Bishop', l)

    def getIconChar(self):
        if self.getColour() == 'w':
            return super().getIconChar() + 3
        else:
            return super().getIconChar() + 9

    def __str__(self):
        if self.getColour() == 'w':
            return chr(super().getIconChar() + 3)
        else:
            return chr(super().getIconChar() + 9)

    def checkMove(self, currentLocation, newLocation, square):
        delta = self.getDelta(currentLocation, newLocation)
        onNewLocation = square.getSpot(newLocation)
        #print('onNewLocation', onNewLocation)
        if abs(delta[0]) == abs(delta[1]):
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    square.capture(onNewLocation)
                    return True # if there's a piece and is enemy
                else:
                    return False # the way is blocked
            else:
                if super().checkBlock(currentLocation, newLocation, square, delta):
                    return True # if there's no piece
                else:
                    return False
        else:
            return False

class Knight(Piece): # can be blocked
    def __init__(self, c, l):
        super().__init__(c, 'Knight', l)

    def getIconChar(self):
        if self.getColour() == 'w':
            return super().getIconChar() + 4
        else:
            return super().getIconChar() + 10

    def __str__(self):
        if self.getColour() == 'w':
            return chr(super().getIconChar() + 4)
        else:
            return chr(super().getIconChar() + 10)

    def checkMove(self, currentLocation, newLocation, square):
        delta = self.getDelta(currentLocation, newLocation)
        onNewLocation = square.getSpot(newLocation)
        if abs(delta[0]) == 2 and abs(delta[1]) == 1:
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                square.capture(onNewLocation)
                return True # is enemy
            else:
                return True # no piece
        elif abs(delta[1]) == 2 and abs(delta[0]) == 1:
            if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                return False # if there is a piece and its not enemy
            elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                square.capture(onNewLocation)
                return True # is enemy
            else:
                return True # no piece
        else:
            return False

class Pawn(Piece):
    def __init__(self, c, l, m = 0):
        super().__init__(c, 'Pawn', l)
        self._move = m

    def getMove(self):
        return self._move

    def countMove(self):
        self._move = self._move + 1

    def move(self, currentLocation, newLocation, square):
        super().move(currentLocation, newLocation, square)
        self.countMove()

    def getIconChar(self):
        if self.getColour() == 'w':
            return super().getIconChar() + 5
        else:
            return super().getIconChar() + 11

    def __str__(self):
        if self.getColour() == 'w':
            return chr(super().getIconChar() + 5)
        else:
            return chr(super().getIconChar() + 11)

    def checkMove(self, currentLocation, newLocation, square):
        delta = self.getDelta(currentLocation, newLocation)
        onNewLocation = square.getSpot(newLocation)
        if delta[0] == 0:
            if self.getColour() == 'w': # white moves forwar, index delta is negative
                if delta[1] == -1 or (delta[1] == -2 and not self.getMove()): # only first move can move two
                    if isinstance(onNewLocation, Piece): # if there's a piece on the spot, it can't move this way
                        return False
                    return True # cannot capture this way
            elif self.getColour() == 'b':
                if delta[1] == 1 or (delta[1] == 2 and not self.getMove()): # black moves forwar, index delta is positive
                    if isinstance(onNewLocation, Piece):
                        return False
                    return True # cannot capture this way
        elif abs(delta[0]) == 1:
            if self.getColour() == 'w' and delta[1] == -1:
                if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                    return False
                elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                    square.capture(onNewLocation)
                    return True # is enemy
                else:
                    return False # no piece -> cannot move this way
            elif self.getColour() == 'b' and delta[1] == 1:
                onNewLocation = square.getSpot(newLocation)
                if isinstance(onNewLocation, Piece) and not self.isEnemy(onNewLocation):
                    return False
                elif isinstance(onNewLocation, Piece) and self.isEnemy(onNewLocation):
                    square.capture(onNewLocation)
                    return True # is enemy
                else:
                    return False # no piece -> cannot move this way
        else:
            return False

class Square:
    def __init__(self, m = [['　' for i in range(8)] for j in range(8)], wDead = [], bDead = [], w = False, c = ['b', 'w'], t = 'w'):
        self._matrix = m
        self._whiteDead = wDead
        self._blackDead = bDead
        self._win = w
        self._winColour = c
        self._colourTurn = t

    def startGame(self):
        self._matrix[1][0] = Pawn('b', Location('A', 7))
        self._matrix[1][1] = Pawn('b', Location('B', 7))
        self._matrix[1][2] = Pawn('b', Location('C', 7))
        self._matrix[1][3] = Pawn('b', Location('D', 7))
        self._matrix[1][4] = Pawn('b', Location('E', 7))
        self._matrix[1][5] = Pawn('b', Location('F', 7))
        self._matrix[1][6] = Pawn('b', Location('G', 7))
        self._matrix[1][7] = Pawn('b', Location('H', 7))
        self._matrix[0][0] = Castle('b', Location('A', 8))
        self._matrix[0][7] = Castle('b', Location('H', 8))
        self._matrix[0][1] = Knight('b', Location('B', 8))
        self._matrix[0][6] = Knight('b', Location('G', 8))
        self._matrix[0][2] = Bishop('b', Location('C', 8))
        self._matrix[0][5] = Bishop('b', Location('F', 8))
        self._matrix[0][3] = Queen('b', Location('D', 8))
        self._matrix[0][4] = King('b', Location('E', 8))

        self._matrix[6][0] = Pawn('w', Location('A', 2))
        self._matrix[6][1] = Pawn('w', Location('B', 2))
        self._matrix[6][2] = Pawn('w', Location('C', 2))
        self._matrix[6][3] = Pawn('w', Location('D', 2))
        self._matrix[6][4] = Pawn('w', Location('E', 2))
        self._matrix[6][5] = Pawn('w', Location('F', 2))
        self._matrix[6][6] = Pawn('w', Location('G', 2))
        self._matrix[6][7] = Pawn('w', Location('H', 2))
        self._matrix[7][0] = Castle('w', Location('A', 1))
        self._matrix[7][7] = Castle('w', Location('H', 1))
        self._matrix[7][1] = Knight('w', Location('B', 1))
        self._matrix[7][6] = Knight('w', Location('G', 1))
        self._matrix[7][2] = Bishop('w', Location('C', 1))
        self._matrix[7][5] = Bishop('w', Location('F', 1))
        self._matrix[7][3] = Queen('w', Location('D', 1))
        self._matrix[7][4] = King('w', Location('E', 1))

    def drawBoard(self):
        print('  Ａ Ｂ Ｃ Ｄ Ｅ Ｆ Ｇ Ｈ ')
        print('  － － － － － － － － ')
        row = 9
        for i in self._matrix:
            row = row - 1
            print(row, end = '')
            print('|', end = '')
            for j in i:
                print(j, end = '|')
            print(row, '\n  － － － － － － － － ')
        print('  Ａ Ｂ Ｃ Ｄ Ｅ Ｆ Ｇ Ｈ ')

    def putPiece(self, Piece, locationXY):
        self._matrix[x - 1][y - 1] = Piece

    def getSpot(self, location):
        (row, column) = location.getMatrixIndex()
        return self._matrix[row][column]

    def setSpot(self, location, newRole): # newRole can be empty or a piece
        (row, column) = location.getMatrixIndex()
        self._matrix[row][column] = newRole

    def checkEmpty(self, location): # return true if is empty
        if self.getSpot(location) == '　':
            return True
        else:
            return False

    def checkTurn(self, Piece):
        if Piece.getColour() == self.getTurn():
            return True
        else:
            return False

    def getTurn(self):
        return self._colourTurn

    def changeTrun(self):
        if self._colourTurn == 'w':
            self._colourTurn = 'b'
        else:
            self._colourTurn = 'w'

    def squareUpdate(self, currentLocation, newLocation, Piece):
        self.setSpot(currentLocation, '　')
        self.setSpot(newLocation, Piece)

    def capture(self, die): # die is the captured piece
        dieColour = die.getColour()
        if dieColour == 'w':
            self._whiteDead.append(die)
        else:
            self._blackDead.append(die)
        if isinstance(die, King):
            self.setWin()
            self.setWinColour(die.getColour())

    def setWin(self):
        self._win = True

    def getWin(self): # see if anyone has won
        return self._win

    def setWinColour(self, c): # remove the LOST colour from the list
        self._winColour.remove(c)

    def getWinColour(self):
        return self._winColour

class Location: # use A1 - H8
    def __init__(self, alph, num):
        self._alphabet = alph
        self._number = num
        self._x = ord(self._alphabet) - 64 - 1 # A - 64 = 1
        self._y = 8 - num

    def getMatrixIndex(self):
        return (self._y, self._x)

    def getNotation(self): # A1 - H8
        return (self._alphabet, self._number)

    def addX(self, n): # add x by n
        (row, column) = self.getMatrixIndex()
        newX = column + n
        return Location(chr(newX + 65), 8 - row)

    def addY(self, n): # add y by n
        (row, column) = self.getMatrixIndex()
        newY = row + n
        return Location(chr(column + 65), 8 - newY)

    def add(self, nx, ny):
        (row, column) = self.getMatrixIndex()
        newX = column + nx
        # print('newx, cl, nx:', newX, column, nx)
        newY = row + ny
        # print('newy, r, ny:', newY, row, ny)
        return Location(chr(newX + 65), 8 - newY)

def checkInput(squareA, squareN): # check if is between A1 - H8
    alphas = set('ABCDEFGH')
    if set(squareA) <= alphas and squareN <= 8 and squareN >= 1:
        return True
    else:
        return False

def instruction():
    print('Select a piece you want to move and the position you want to move it to. Enter the squares using file letter and rank number, and separate them with a space.')
    print('For example, if I want to move the Pawn at A2 to A3, I enter A2 A3.')

def colour(pieceColour):
    if pieceColour == 'w':
        return 'White'
    else:
        return 'Black'

def main():
    game = Square()
    game.startGame()
    game.drawBoard()
    while not game.getWin():
        inpt = input('{}, Please select a piece and a square you want to move it to (type H for help, Q if you want to quit): '.format(colour(game.getTurn())))
        inptList = inpt.split()
        if inptList[0] == 'h' or inptList[0] == 'H':
            instruction()
            continue
        elif inptList[0] == 'q' or inptList[0] == 'Q':
            break
        elif len(inptList[0]) != 2 or len(inptList[1]) != 2:
            print('Invalid input! Please select a square from A1 - H8.')
            continue
        elif len(inptList) != 2:
            print('Invalid input! Please input two squares separated by space.')
        else:
            fromSquare = inptList[0]
            toSquare = inptList[1]
            fromSquareA = fromSquare[0].upper()
            toSquareA = toSquare[0].upper()
            try:
                fromSquareN = int(fromSquare[1])
                toSquareN = int(toSquare[1])
            except:
                print('Invalid input! Please input squares from A1 - H8')
                continue
            if checkInput(fromSquareA, fromSquareN) and checkInput(toSquareA, toSquareN): # fromSquareN is int
                fromLocation = Location(fromSquareA, fromSquareN)
                toLocation = Location(toSquareA, toSquareN)
                currentPiece = game.getSpot(fromLocation)
                if isinstance(currentPiece, Piece) and currentPiece.getColour() == game.getTurn(): # make sure the selected spot has the right colour
                    if currentPiece.checkMove(fromLocation, toLocation, game): # if the move is valid
                        currentPiece.move(fromLocation, toLocation, game) # then move
                        game.changeTrun()
                        game.drawBoard()
                    else:
                        print('This move is invalid! Please try again.')
                        continue
                elif isinstance(currentPiece, Piece) and currentPiece.getColour() != game.getTurn(): # select the wrong piece (colour)
                    print('It\'s {}\'s turn. Please select a {} piece.'.format(colour(game.getTurn()), colour(game.getTurn())))
                else:
                    print('It\'s an empty square! Please try again.')
                    continue
            else:
                print('Invalid input! Please select squares from A1 - H8')
                continue
    else:
        wonPlayer = colour(game.getWinColour())
        print('{} won!'.format(wonPlayer))

if __name__ == '__main__': main()


import matplotlib.pyplot as plt
import numpy as np
import napari
from config import CMAP, COLOR_PALETTE

plt.style.use('dark_background')

def visualize_image(image, title='Image Viewer'):
    plt.figure()
    plt.imshow(image, cmap=CMAP)
    plt.title(title)
    plt.show()

def plot_accuracy(target_positions, actual_positions, voxel_size=[1, 1, 1]):
    """
    Plot the accuracy of target versus actual positions in 3D coordinates.

    Parameters:
    target_positions (ndarray): Array of target positions.
    actual_positions (ndarray): Array of actual positions.
    voxel_size (list): Voxel size in each dimension.
    """
    # Generate labels for each point
    labels = [f'S{ii + 1}' for ii in range(target_positions.shape[0])]

    # Define accuracy in each dimension
    accuracies = [
        (target_positions[:, 1] - actual_positions[:, 1]) * voxel_size[1],  # X Accuracy
        (target_positions[:, 2] - actual_positions[:, 2]) * voxel_size[2],  # Y Accuracy
        (target_positions[:, 0] - actual_positions[:, 0]) * voxel_size[0]   # Z Accuracy
    ]

    # Plotting accuracies in each dimension
    for i, accuracy in enumerate(accuracies, start=1):
        plot_dimension_accuracy(i, labels, accuracy, f'{["X", "Y", "Z"][i-1]} Accuracy')

    plt.show()

def plot_dimension_accuracy(subplot_index, labels, accuracy, title):
    """
    Helper function to plot accuracy in one dimension.

    Parameters:
    subplot_index (int): Index of the subplot.
    labels (list): Labels for each data point.
    accuracy (ndarray): Accuracy values for the dimension.
    title (str): Title of the subplot.
    """
    c = [COLOR_PALETTE[i % len(COLOR_PALETTE)] for i in range(len(labels))]
    plt.subplot(1, 4, subplot_index)
    plt.title(title)
    plt.scatter(labels, accuracy, c=c)
    plt.grid()

def display_image_napari(image, points_count, points_size, title='Napari Image Viewer', colormap=CMAP, scale=[1, 1, 1], custom_points=None, auto_points=None):
    """
    Display the given image using Napari viewer with the specified colormap, an additional points layer
    positioned around the center of the image in 'select' mode, and text annotations for each point. Optionally,
    display custom points if provided.

    Parameters:
    image (ndarray): The image to visualize.
    points_count (int): The number of points to display in the points layer (ignored if custom_points is provided).
    points_size (float): The size of the points to be displayed.
    title (str): The window title for the Napari viewer.
    colormap (str): The name of the colormap to use.
    custom_points (ndarray): Optional custom points to display instead of the generated points.

    Returns:
    Viewer: The Napari viewer instance.
    """
    viewer = napari.Viewer(title=title)

    if image.ndim == 3:
        viewer.add_image(image, colormap=colormap, scale=scale)
        viewer.dims.ndisplay = 3
    elif image.ndim == 2:
        viewer.add_image(image, colormap=colormap)
        scale = [1, 1]

    # Assign colors from the palette to each point's edge
    point_colors = [COLOR_PALETTE[i % len(COLOR_PALETTE)] for i in range(points_count)]

    # Set the properties for the points including the text
    properties = {'number': [str(i+1) for i in range(points_count)]}  # Starting at 1
    if image.ndim == 2:
        text_parameters = {
            'text': 'S{number}',
            'size': 10,
            'color': 'white',
            'anchor': 'upper_left',
            'translation': [-10, 0]  # Adjust text offset if needed
        }
    elif image.ndim == 3:
        text_parameters = {
            'text': 'S{number}',
            'size': 10,
            'color': 'white',
            'anchor': 'upper_left',
            'translation': [-4, -10, -10]  # Adjust text offset if needed
        }

    # If custom points are provided, use them; otherwise, generate points around the center
    if custom_points is not None:
        points_layer = viewer.add_points(custom_points*scale, size=points_size/10, edge_width=0.1,
                                         face_color=point_colors, edge_color='black',
                                         symbol='cross',
                                         name='Transformed Points')

        points_layer.editable = False

        if auto_points is not None:
            points_layer = viewer.add_points(auto_points*scale, size=points_size/10, edge_width=0.1,
                                            face_color=point_colors, edge_color='black',
                                            symbol='disc',
                                            name='Detected Points')

            points_layer.editable = False
    else:
        # Calculate the center of the image
        center_y, center_x = np.array(image.shape[:2]) / 2

        # Generate points in a circular pattern around the center
        angle_step = 2 * np.pi / points_count
        radius = min(center_x, center_y) / 4  # Adjust the radius as necessary
        points = np.array([
            (center_y + radius * np.sin(i * angle_step), center_x + radius * np.cos(i * angle_step))
            for i in range(points_count)
        ])

        # Add a points layer with the generated points
        points_layer = viewer.add_points(points, size=points_size, edge_width=0.05,
                                            edge_color=point_colors, face_color='transparent',
                                            name='Target Points')

    # Update the points layer with the properties and text
    points_layer.properties = properties
    points_layer.text = text_parameters

    # Set the points layer to 'select' mode
    points_layer.mode = 'select'

    # Start the Napari event loop
    napari.run()

    # After the window is closed, return the coordinates
    return points_layer.data


import turtle
"""
myTurtle = turtle.Turtle()
myWin = turtle.Screen()

def drawSpiral(myTurtle, lineLen):
    if lineLen > 0:
        myTurtle.forward(lineLen)
        myTurtle.right(90)
        drawSpiral(myTurtle, lineLen-5)

drawSpiral(myTurtle, 100)
myWin.exitonclick()
"""
# Modify the thickness of the branches so that as the branchLen gets smaller, the line gets thinner.
# Modify the color of the branches so that as the branchLen gets very short it is colored like a leaf.
# Modify the angle used in turning the turtle so that at each branch point the angle is selected at random in some range.
# For example choose the angle between 15 and 45 degrees. Play around to see what looks good.
# Modify the branchLen recursively so that instead of always subtracting the same amount you subtract a random amount in some range.

def tree(branchLen, t):
    if branchLen > 5:
        t.forward(branchLen)
        t.right(20)
        tree(branchLen-15, t)
        t.left(40)
        tree(branchLen-10, t)
        t.right(20)
        t.backward(branchLen)

def main():
    t = turtle.Turtle()
    myWin = turtle.Screen()
    t.left(90)
    t.up()
    t.backward(100)
    t.down()
    t.color("pink")
    tree(100, t)
    myWin.exitonclick()

main()


import numpy as np
import cv2
import glob
import matplotlib.pyplot as plt

# %matplotlib qt
# %matplotlib inline

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*9,3), np.float32)
objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d points in real world space
imgpoints = [] # 2d points in image plane.

# Make a list of calibration images
images = glob.glob('../camera_cal/calibration*.jpg')

# Step through the list and search for chessboard corners
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # Find the chessboard corners
    ret, corners = cv2.findChessboardCorners(gray, (9,6),None)

    # If found, add object points, image points
    if ret == True:
        objpoints.append(objp)
        imgpoints.append(corners)

        # Draw and display the corners
        # img = cv2.drawChessboardCorners(img, (9,6), corners, ret)
        # cv2.imshow('img',img)
        # cv2.waitKey(500)

cv2.destroyAllWindows()

import matplotlib.image as mpimg
def show_comparison(img_before, img_after, title_before='', title_after=''):
    f, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 9))
    f.tight_layout()
    ax1.imshow(img_before)
    ax1.set_title(title_before, fontsize=50)
    ax2.imshow(img_after)
    ax2.set_title(title_after, fontsize=50)
    plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
    return ax1, ax2

def cal_undistort(img):
    # Use cv2.calibrateCamera() and cv2.undistort()
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, (img.shape[1], img.shape[0]),None,None)
    undist = cv2.undistort(img, mtx, dist, None, mtx)
    # undist = np.copy(img)  # Delete this line
    return undist

test_img = mpimg.imread("../test_images/test6.jpg")
undist_img = cal_undistort(test_img)
show_comparison(test_img, undist_img, 'Original image', 'Undistorted image')


import time
import pytz
import datetime

def utc_to_local(utc_time_str, utc_format='%Y-%m-%dT%H:%M:%S'):
    local_tz = pytz.timezone('Asia/Shanghai')  # 定义本地时区
    utc_dt = datetime.datetime.strptime(utc_time_str, utc_format)  # 讲世界时间的格式转化为datetime.datetime格式
    local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(
        local_tz)  # 想将datetime格式添加上世界时区，然后astimezone切换时区：世界时区==>本地时区
    formatTime = int(time.mktime(local_dt.timetuple()))
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(formatTime))


import os
import quandl
import pandas as pd
from flask import Flask, render_template, flash, request
from bokeh.plotting import figure, output_file, show
from bokeh.embed import components
from bokeh.resources import INLINE
from bokeh.util.string import encode_utf8

app = Flask(__name__)

def create_figure(stock_ticker,s1):
    dates=[]
    for i in range(1,29):
        dates.append('2018-02-'+str(i))
    dates=','.join(dates)
    s3 = os.environ['APIKEY_DATA']
    quandl.ApiConfig.api_key = s3
    aa=quandl.get_table('WIKI/PRICES', ticker=stock_ticker, date=dates)
    days=aa.date.dt.day
    # create a new plot with a title and axis labels
    p = figure(title="Quandl Wiki EOD Stock Price - Feb 2017",
        x_axis_label='date', y_axis_label='Price (Dollars)')
    l_color = ['blue','red','green','orange']

    ydata = ['open','adj_open','close','adj_close'];
    # add a line renderer with legend and line thickness
    for i in range(4):
        if s1[i] == '1':
            p.line(days, aa.loc[:,ydata[i]], legend=stock_ticker+':'+ydata[i],
                    line_color=l_color[i], line_width=2)
    return p

@app.route('/')
def inputdata():
    return render_template('stock_input.html')

@app.route("/result",methods = ['GET','POST'])
def resultpage():
    # Create the plot
    select = request.form.get('ticker')
    s1 = list(map(request.form.get,('C_P','AC_P','O_P','AO_P')))
    p = create_figure(select,s1)
    # grab the static resources
    js_resources = INLINE.render_js()
    css_resources = INLINE.render_css()

    # render template
    script, div = components(p)
    return render_template(
        'result.html',
        plot_script=script,
        plot_div=div,
        js_resources=js_resources,
        css_resources=css_resources,
    )

if __name__ == "__main__":
	port = int(os.environ.get("PORT",5000))
	app.run(host='0.0.0.0',port=port,debug=True)


#!/usr/bin/env python3.5
# -*- coding: utf-8 -*-
"""
__author__ = xyy
__mtime__ = 2016/10/28
"""
import re

# 正则匹配电话号码
phone = "13893670000"
p2 = re.compile('^0\d{2,3}\d{7,8}$|^1[358]\d{9}$|^147\d{8}')
phonematch = p2.match(phone)

if phonematch:
    print(phonematch.group())
else:
    print("phone number is error!")


import csv
import subprocess
import time
import telebot
import os
from flask import Flask, request
import logging

bot = telebot.TeleBot('1141013801:AAEq32jIEQ0mjppuXm9t_XbldrXCDhVch3c')

class CheckBase:
    def __init__(self, csv1):
        self.csv1 = csv1
        self.base1 = {}
        self.base2 = {}
        self.message = ""

    def open(self):
        with open(self.csv1) as f:
            file = csv.DictReader(f, delimiter=",")
            self.base1 = {row["product_name"]: row["url"] for row in file}

    def check(self):
        for x in self.base1:
            if "Питон" in x or "Python" in x or "python" in x or "питон" in x or "ленд" in x or "Ленд" in x or "Сайт" in x or "сайт" in x or "верст" in x or "Верст" in x or "парс" in x or "Парс" in x:
                if self.base2.get(x) == self.base1.get(x):
                    print("Найдено соответствие")
                else:
                    self.message += "{}\n{}\n\n".format(x, self.base1[x])

    def rewrite(self):
        self.base2 = self.base1
        f = open('fl-python.csv', 'r+')
        f.truncate()
        self.base1 = {}
        self.message = ""

bashCommand = "scrapy runspider fl/spiders/fl_title.py"

@bot.message_handler(commands=['start'])
def start_message(message):
    base = CheckBase("fl-python.csv")
    while True:
        subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
        base.open()
        base.check()
        if base.message != "":
            bot.send_message(message.chat.id, base.message)
        base.rewrite()
        time.sleep(30)

# Проверим, есть ли переменная окружения Хероку (как ее добавить смотрите ниже)
if "HEROKU" in list(os.environ.keys()):
    logger = telebot.logger
    telebot.logger.setLevel(logging.INFO)

    server = Flask(__name__)
    @server.route("/bot", methods=['POST'])
    def getMessage():
        bot.process_new_updates([telebot.types.Update.de_json(request.stream.read().decode("utf-8"))])
        return "!", 200
    @server.route("/")
    def webhook():
        bot.remove_webhook()
        bot.set_webhook(url="https://serene-peak-20980.herokuapp.com/bot") # этот url нужно заменить на url вашего Хероку приложения
        return "?", 200
    server.run(host="0.0.0.0", port=os.environ.get('PORT', 80))
else:
    # если переменной окружения HEROKU нету, значит это запуск с машины разработчика.
    # Удаляем вебхук на всякий случай, и запускаем с обычным поллингом.
    bot.remove_webhook()
    bot.polling(none_stop=True)


import site
site.addsitedir("../../../PDFNetC/Lib")
import sys
from PDFNetPython import *

import platform

sys.path.append("../../LicenseKey/PYTHON")
from LicenseKey import *

#---------------------------------------------------------------------------------------
# The following sample illustrates how to use the PDF.Convert utility class to convert
# documents and files to Word, Excel and PowerPoint.
#
# The Structured Output module is an optional PDFNet Add-on that can be used to convert PDF
# and other documents into Word, Excel, PowerPoint and HTML format.
#
# The PDFTron SDK Structured Output module can be downloaded from
# https://docs.apryse.com/documentation/core/info/modules/
#
# Please contact us if you have any questions.
#---------------------------------------------------------------------------------------

# Relative path to the folder containing the test files.
inputPath = "../../TestFiles/"
outputPath = "../../TestFiles/Output/"

def main():
    # The first step in every application using PDFNet is to initialize the
    # library. The library is usually initialized only once, but calling
    # Initialize() multiple times is also fine.
    PDFNet.Initialize(LicenseKey)

    PDFNet.AddResourceSearchPath("../../../PDFNetC/Lib/")

    if not StructuredOutputModule.IsModuleAvailable():
        print("")
        print("Unable to run the sample: PDFTron SDK Structured Output module not available.")
        print("-----------------------------------------------------------------------------")
        print("The Structured Output module is an optional add-on, available for download")
        print("at https://docs.apryse.com/documentation/core/info/modules/. If you have already")
        print("downloaded this module, ensure that the SDK is able to find the required files")
        print("using the PDFNet::AddResourceSearchPath() function.")
        print("")
        return

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

    try:
        # Convert PDF document to Word
        print("Converting PDF to Word")

        outputFile = outputPath + "paragraphs_and_tables.docx"

        Convert.ToWord(inputPath + "paragraphs_and_tables.pdf", outputFile)

        print("Result saved in " + outputFile)
    except Exception as e:
        print("Unable to convert PDF document to Word, error: " + str(e))

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

    try:
        # Convert PDF document to Word with options
        print("Converting PDF to Word with options")

        outputFile = outputPath + "paragraphs_and_tables_first_page.docx"

        wordOutputOptions = WordOutputOptions()

        # Convert only the first page
        wordOutputOptions.SetPages(1, 1)

        Convert.ToWord(inputPath + "paragraphs_and_tables.pdf", outputFile, wordOutputOptions)

        print("Result saved in " + outputFile)
    except Exception as e:
        print("Unable to convert PDF document to Word, error: " + str(e))

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

    try:
        # Convert PDF document to Excel
        print("Converting PDF to Excel")

        outputFile = outputPath + "paragraphs_and_tables.xlsx"

        Convert.ToExcel(inputPath + "paragraphs_and_tables.pdf", outputFile)

        print("Result saved in " + outputFile)
    except Exception as e:
        print("Unable to convert PDF document to Excel, error: " + str(e))

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

    try:
        # Convert PDF document to Excel with options
        print("Converting PDF to Excel with options")

        outputFile = outputPath + "paragraphs_and_tables_second_page.xlsx"

        excelOutputOptions = ExcelOutputOptions()

        # Convert only the second page
        excelOutputOptions.SetPages(2, 2)

        Convert.ToExcel(inputPath + "paragraphs_and_tables.pdf", outputFile, excelOutputOptions)

        print("Result saved in " + outputFile)
    except Exception as e:
        print("Unable to convert PDF document to Excel, error: " + str(e))

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

    try:
        # Convert PDF document to PowerPoint
        print("Converting PDF to PowerPoint")

        outputFile = outputPath + "paragraphs_and_tables.pptx"

        Convert.ToPowerPoint(inputPath + "paragraphs_and_tables.pdf", outputFile)

        print("Result saved in " + outputFile)
    except Exception as e:
        print("Unable to convert PDF document to PowerPoint, error: " + str(e))

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

    try:
        # Convert PDF document to PowerPoint with options
        print("Converting PDF to PowerPoint with options")

        outputFile = outputPath + "paragraphs_and_tables_first_page.pptx"

        powerPointOutputOptions = PowerPointOutputOptions()

        # Convert only the first page
        powerPointOutputOptions.SetPages(1, 1)

        Convert.ToPowerPoint(inputPath + "paragraphs_and_tables.pdf", outputFile, powerPointOutputOptions)

        print("Result saved in " + outputFile)
    except Exception as e:
        print("Unable to convert PDF document to PowerPoint, error: " + str(e))

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

    PDFNet.Terminate()
    print("Done.")

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
"""Asynchronous Advantage Actor-Critic (A3C).
A Fork from: https://github.com/gabrieledcjr/DeepRL
"""
import logging
import numpy as np
import os
import pathlib
import signal
import sys
import threading
import time
import pandas as pd
import math
import tensorflow as tf
import csv

from threading import Event, Thread
from common_worker import CommonWorker
from a3c_training_thread import A3CTrainingThread
from common.game_state import GameState
from common.util import prepare_dir
from common.util import transform_h
from common.util import transform_h_inv
from game_ac_network import GameACFFNetwork
from queue import Queue
from copy import deepcopy
from setup_functions import *

logger = logging.getLogger("a3c")

try:
    import cPickle as pickle
except ImportError:
    import pickle

def run_a3c(args):
    """Run A3C experiment."""
    GYM_ENV_NAME = args.gym_env.replace('-', '_')
    GAME_NAME = args.gym_env.replace('NoFrameskip-v4','')

    # setup folder name and path to folder
    folder = pathlib.Path(setup_folder(args, GYM_ENV_NAME))

    # setup GPU options
    # (NOTE: no gpu support in aeolus)
    import tensorflow as tf
    gpu_options = None

    ######################################################
    # setup default device: cpu
    device = "/cpu:0"

    global_t = 0
    rewards = {'train': {}, 'eval': {}}
    best_model_reward = -(sys.maxsize)

    stop_req = False

    game_state = GameState(env_id=args.gym_env)
    action_size = game_state.env.action_space.n
    game_state.close()
    del game_state.env
    del game_state

    input_shape = (args.input_shape, args.input_shape, 4)

    #######################################################
    # setup global A3C
    GameACFFNetwork.use_mnih_2015 = args.use_mnih_2015
    global_network = GameACFFNetwork(
        action_size, -1, device, padding=args.padding,
        in_shape=input_shape)
    logger.info('A3C Initial Learning Rate={}'.format(args.initial_learn_rate))

    time.sleep(2.0)

    ############## Setup Thread Workers BEGIN ################
    # 16 total number of local threads for all experiments
    assert args.parallel_size ==16

    startIndex = 0
    all_workers = []

    # a3c learning rate and optimizer
    learning_rate_input = tf.placeholder(tf.float32, shape=(), name="opt_lr")
    grad_applier = tf.train.RMSPropOptimizer(
        learning_rate=learning_rate_input,
        decay=args.rmsp_alpha,
        epsilon=args.rmsp_epsilon)

    # setup common workers
    setup_common_worker(CommonWorker, args, action_size)

    # setup a3c workers
    setup_a3c_worker(A3CTrainingThread, args, startIndex)

    for i in range(startIndex, args.parallel_size):
        local_network = GameACFFNetwork(
            action_size, i, device=device,
            padding=args.padding,
            in_shape=input_shape)

        a3c_worker = A3CTrainingThread(
            i, global_network, local_network,
            args.initial_learn_rate, learning_rate_input, grad_applier,
            device=device, no_op_max=30)

        all_workers.append(a3c_worker)
    ############## Setup Thread Workers END ################

    # setup config for tensorflow
    config = tf.ConfigProto(
        gpu_options=gpu_options,
        log_device_placement=False,
        allow_soft_placement=True)

    # prepare sessions
    sess = tf.Session(config=config)
    sess.run(tf.global_variables_initializer())

    # summary writer for tensorboard
    summ_file = args.save_to+'log/a3c/{}/'.format(GYM_ENV_NAME) + str(folder)[12:]
    summary_writer = tf.summary.FileWriter(summ_file, sess.graph)

    # init or load checkpoint with saver
    root_saver = tf.train.Saver(max_to_keep=1)
    saver = tf.train.Saver(max_to_keep=3)
    best_saver = tf.train.Saver(max_to_keep=1)

    checkpoint = tf.train.get_checkpoint_state(str(folder)+'/model_checkpoints')
    if checkpoint and checkpoint.model_checkpoint_path:
        root_saver.restore(sess, checkpoint.model_checkpoint_path)
        logger.info("checkpoint loaded:{}".format(
            checkpoint.model_checkpoint_path))
        tokens = checkpoint.model_checkpoint_path.split("-")

        # restore global step
        global_t = int(tokens[-1])
        logger.info(">>> global step set: {}".format(global_t))

        # restore wall time
        wall_t_fname = folder / 'wall_t'
        with wall_t_fname.open('r') as f:
            wall_t = float(f.read())

        # restore reward files
        best_reward_file = folder / 'model_best/best_model_reward'
        with best_reward_file.open('r') as f:
            best_model_reward = float(f.read())
        reward_file = folder / '{}-a3c-rewards.pkl'.format(GYM_ENV_NAME)
        rewards = pickle.load(reward_file.open('rb'))
    else:
        logger.warning("Could not find old checkpoint")
        # set wall time
        wall_t = 0.0
        prepare_dir(folder, empty=True)
        prepare_dir(folder / 'model_checkpoints', empty=True)
        prepare_dir(folder / 'model_best', empty=True)
        prepare_dir(folder / 'frames', empty=True)

    lock = threading.Lock()

    def next_t(current_t, freq):
        return np.ceil((current_t + 0.00001) / freq) * freq

    next_global_t = next_t(global_t, args.eval_freq)
    next_save_t = next_t(
        global_t, args.eval_freq*args.checkpoint_freq)

    step_t = 0

    last_temp_global_t = global_t

    def train_function(parallel_idx, th_ctr):
        nonlocal global_t, step_t, rewards, lock, next_global_t, \
            next_save_t, last_temp_global_t

        parallel_worker = all_workers[parallel_idx]
        parallel_worker.set_summary_writer(summary_writer)

        with lock:
            # Evaluate model before training
            if not stop_req and global_t == 0 and step_t == 0:
                # Log the reward, and the transformed reward
                reward_t = parallel_worker.testing(sess, args.eval_max_steps, global_t, folder, worker=all_workers[-1])[0]
                trans_reward_t = transform_h(reward_t + 0.99 * transform_h_inv(reward_t))
                rewards['eval'][step_t] = [reward_t, trans_reward_t]
                # save checkpoint
                checkpt_file = folder / 'model_checkpoints'
                checkpt_file /= '{}_checkpoint'.format(GYM_ENV_NAME)
                saver.save(sess, str(checkpt_file), global_step=global_t)
                save_best_model(rewards['eval'][global_t][0])
                # dump reward pickle
                reward_fname = folder / '{}-a3c-rewards.pkl'.format(GYM_ENV_NAME)
                pickle.dump(rewards, reward_fname.open('wb'), pickle.HIGHEST_PROTOCOL)
                logger.info('Dump pickle at step {}'.format(global_t))

                step_t = 1

        # set start_time
        start_time = time.time() - wall_t
        parallel_worker.set_start_time(start_time)

        while True:
            if stop_req:
                return

            if global_t >= (args.max_time_step * args.max_time_step_fraction):
                return

            # a3c training thread worker
            th_ctr.get()

            train_out = parallel_worker.train(sess, global_t, rewards)
            diff_global_t, episode_end, part_end = train_out

            th_ctr.put(1)

            # ensure only one thread is updating global_t at a time
            with lock:
                global_t += diff_global_t
                # if during a thread's update, global_t has reached a evaluation interval
                if global_t > next_global_t:
                    next_global_t = next_t(global_t, args.eval_freq)
                    step_t = int(next_global_t - args.eval_freq)
                    # wait 30min max for all threads to finish before testing,
                    # in case one thread fails
                    time_waited = 0
                    while not stop_req and th_ctr.qsize() < len(all_workers):
                        time.sleep(0.01)
                        time_waited += 0.01
                        if time_waited > 1800:
                            sys.exit('Exceed waiting time, exiting...')

                    step_t = int(next_global_t - args.eval_freq)
                    # test A3C agent
                    reward_t = parallel_worker.testing(sess, args.eval_max_steps, global_t, folder, worker=all_workers[-1])[0]
                    trans_reward_t = transform_h(reward_t + 0.99 * transform_h_inv(reward_t))
                    rewards['eval'][step_t] = [reward_t, trans_reward_t]
                    #print("\n\n\nGLOBAL_T: {}\nREWARD: {}\nTRANS REWARD: {}\ R[EVAL]: {}\n\n\n".format(global_t, reward_t, trans_reward_t, rewards['eval'][step_t]))
                    save_best_model(rewards['eval'][step_t][0])

                if global_t > next_save_t:
                    next_save_t = next_t(global_t, args.eval_freq*args.checkpoint_freq)
                    # save a3c
                    checkpt_file = folder / 'model_checkpoints'
                    checkpt_file /= '{}_checkpoint'.format(GYM_ENV_NAME)
                    saver.save(sess, str(checkpt_file), global_step=global_t,
                            write_meta_graph=False)
                    # dump pickle
                    reward_fname = folder / '{}-a3c-rewards.pkl'.format(GYM_ENV_NAME)
                    pickle.dump(rewards, reward_fname.open('wb'), pickle.HIGHEST_PROTOCOL)
                    logger.info('Dump pickle at step {}'.format(global_t))

    def signal_handler(signal, frame):
        nonlocal stop_req
        logger.info('You pressed Ctrl+C!')
        stop_req = True
        if stop_req and global_t == 0:
            sys.exit(1)

    def save_best_model(test_reward):
        nonlocal best_model_reward
        if test_reward > best_model_reward:
            best_model_reward = test_reward
            best_reward_file = folder / 'model_best/best_model_reward'

            with best_reward_file.open('w') as f:
                f.write(str(best_model_reward))

            best_checkpt_file = folder / 'model_best'
            best_checkpt_file /= '{}_checkpoint'.format(GYM_ENV_NAME)
            best_saver.save(sess, str(best_checkpt_file))

    train_threads = []
    th_ctr = Queue()
    for i in range(args.parallel_size):
        th_ctr.put(1)

    for i in range(args.parallel_size):
        worker_thread = Thread(
            target=train_function,
            args=(i, th_ctr, ))
        train_threads.append(worker_thread)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    # set start time and start threads
    start_time = time.time() - wall_t
    for t in train_threads:
        t.start()

    print('Press Ctrl+C to stop')

    # end of training
    for t in train_threads:
        t.join()

    logger.info('Now saving data. Please wait')

    # write wall time
    wall_t = time.time() - start_time
    wall_t_fname = folder / 'wall_t'
    with wall_t_fname.open('w') as f:
        f.write(str(wall_t))

    checkpoint_file = str(folder / '{}_checkpoint_a3c'.format(GYM_ENV_NAME))
    root_saver.save(sess, checkpoint_file, global_step=global_t)

    reward_fname = folder / '{}-a3c-rewards.pkl'.format(GYM_ENV_NAME)
    pickle.dump(rewards, reward_fname.open('wb'), pickle.HIGHEST_PROTOCOL)
    logger.info('Data saved!')

    sess.close()


import math
import re
from copy import copy

#log(x) = log(1 + x)
supported_complex_functions = [('exp', 1), ('sqrt', 1), ('log', 1), ('+', 2), ('*', 2), ('/', 2), ('1', 0)]

class NodeException(Exception):
    def __init__(self, message):
        self.message = message

class Node:
    def __init__(self, name, children):
        self.name = name
        self.children = copy(children)

    def count(self, numbers):
        children_results = [child.count(numbers) for child in self.children]
        if self.name == 'exp':
            return math.exp(children_results[0])
        elif self.name == 'sqrt':
            if children_results[0] < 0:
                return 0
            return children_results[0] ** 0.5
        elif self.name == 'log':
            if 1 + children_results[0] <= 0:
                return 0
            return math.log(1 + children_results[0])
        elif self.name == '+':
            return children_results[0] + children_results[1]
        elif self.name == '*':
            return children_results[0] * children_results[1]
        elif self.name == '/':
            if abs(children_results[1]) < 1e-02:
                return 0
            return children_results[0] / children_results[1]
        elif self.name == '1':
            return 1
        elif re.search('^#[0-9]+$', self.name):
            #return numbers.data[int(self.name[1:])]
            return numbers[0][int(self.name[1:])]
        else:
            raise NodeException("Unknown function")

    def __str__(self):
        children_results = ','.join([str(child) for child in self.children])
        result = ''.join([self.name, '(', children_results, ')'])
        return result

#be accurate! the same node can be in different trees

def generate_functions(max_depth, functions):
    generated_nodes = []

    for function, valance in functions:
        #print(function, valance)
        if max_depth == 1 and valance > 0:
            continue

        if valance == 0:
            generated_nodes.append(Node(function, []))
        else:
            children = []
            for i in range(valance):
                children_side = generate_functions(max_depth - 1, functions)
                children.append(children_side)

            cur = [0 for i in range(valance)]
            while True:
                generated_nodes.append(Node(function, [children[i][cur[i]] for i in range(valance)]))
                for i in range(valance - 1, -1, -1):
                    cur[i] += 1
                    if cur[i] == len(children[i]):
                        cur[i] = 0
                    else:
                        break

                end = True
                for i in range(valance):
                    if cur[i] != 0:
                        end = False
                if end:
                    break

    return generated_nodes

def main():
    functions = copy(supported_complex_functions)
    n = 2
    for i in range(n):
        functions.append((['#' + str(i), 0]))

    generated_functions = generate_functions(3, functions)
    for root in generated_functions:
        print(root)

if __name__ == '__main__':
    main()


# coding=utf-8

from take_card import getchecktime

def attcalc_oneemp_oneday(u,currentday,empcheckdata,empleavedata,emptx,usersch,etempsch,holidays):
    '''
    #计算每个人每天的考勤
    usersch 人员的班次列表
    '''
    weekday = (currentday.weekday()+1)%7    #---得到星期数
    from schedule_utils import getshift_byuserdate
    empshift,schclassdetail = getshift_byuserdate(u,currentday,weekday,usersch) #---当天班次ID 和 该班次当天时段ID列表(可能有多个)
    ################################# 得到 班次、时段、是否弹性等信息 ######################
    empshiftschclass = None    #--- 正常班次时段对象
    try:
       temp = []    #---------当天[临时排班的时段]对象
       tempworktype=[]  #---当天[临时排班的工作类型]
       tempflag=0   #---是否追加在排班之后
       if etempsch: #---有临时排班
          for e in etempsch:    #---每个临时排班    'SchclassID','WorkType','ComeTime','LeaveTime','Flag'
              if e[2]<=(currentday+datetime.timedelta(minutes=1439)) and e[3]>=currentday:  #---当天在排班日期范围内 (若当天存在多个临时排班则'当天存在员工排班'以最后一次为准)
                 for elem in schclass_all:  #---所有时段
                     if elem.pk==e[0]:
                        temp.append(elem)
                        tempworktype.append(e[1])   #---排班(次)的工作类型
                        tempflag=e[4]   #---排班(次)当天存在员工排班时(是否追加在排班之后)
       emptempsch = temp    #---当天临时排班的时段
    except:
       import traceback;traceback.print_exc()
       pass
    if len(schclassdetail)==0 and not empshift and not emptempsch:  #如果没有排班及时段也没有临时排班时段(总之，没有时段)，则为弹性班次。
       schclassdetail =[(1,),]  #---正常时段初始化
       empshift=1   #---正常排班初始化 为弹性班次(ID)    是否弹性班次的依据

    if len(schclassdetail)>0:
       empshiftschclass = [e for e in schclass_all if e.pk in schclassdetail] #----正常班次时段或者弹性班次时段

    if empshift==1:
        empworktype = getworktype_byuserdate(currentday,True,holidays) #---得到当前日期类型  0平日,2休息日,3节假日。
    else:
        empworktype = getworktype_byuserdate(currentday,False,holidays)

    ############################## 正常班次时段或弹性班次时段  时的处理 ##############################
    if empshiftschclass != None:
       try:
         ############################## 非弹性班次 ##############################
         if empshift!=1: #---非弹性班次
            lasttime = datetime.datetime(1900,1,1,0,0,0) #---签到与签退的后一次
            ###################无临时排班，或，有临时排班且临时排班是追加在排班之后。
            if not emptempsch or len(emptempsch)==0 or (len(emptempsch)>0 and tempflag==2):
               iii=0    #---正常班次时段计数
               for ef in empshiftschclass:  #---正常班次时段循环
                   acttime = getchecktime(ef,empcheckdata,currentday,lasttime,['I','O','0','1'],empshift,empshiftschclass[0].StartTime,iii,len(empshiftschclass) -1)  #---取签卡
                   if emptx:   #存在调休
                      calcresult = calcitemandsave(acttime,ef,currentday,u,empleavedata,calctx(ef,currentday,emptx,empworktype,empshiftschclass[0].StartTime),empshift,1)  #计算实际的项目并保存。
                   else:
                      calcresult = calcitemandsave(acttime,ef,currentday,u,empleavedata,empworktype,empshift,1)  #计算实际的项目并保存。
                   lasttime = acttime['lasttime']
                   iii = iii+1

            ######################有临时排班，且类型为"仅临时排班有效"
            else:
                iii=0
                for ef in emptempsch: #---临时班次时段循环
                    acttime = getchecktime(ef,empcheckdata,currentday,lasttime,['8,9'],empshift,emptempsch[0].StartTime,iii,len(emptempsch) -1)
                    if emptx:
                       calcresult = calcitemandsave(acttime,ef,currentday,u,empleavedata,calctx(ef,currentday,emptx,tempworktype[iii],empshiftschclass[0].StartTime),0,1)
                    else:
                       calcresult = calcitemandsave(acttime,ef,currentday,u,empleavedata,tempworktype[iii],0,1)
                    lasttime = acttime['lasttime']
                    iii=iii+1
         ################################# 弹性班次 ##############################
         else: #---弹性班次
             try:
                lasttime = datetime.datetime(1900,1,1,0,0,0)
                empshiftschclass =  filter(lambda f:f.pk in (1,),schclass_all)  #---得到弹性时段对象
                #----构造循环次数
                if len(empcheckdata)>=2: #---签卡次数2次以上
                   ii = len([e for e in empcheckdata if (e.TTime).day == currentday.day]) #---本日签卡次数
                   if ii in [0,1]:
                      ii = 2
                      forlist = range(ii/2)
                else:
                   forlist = [0]
                #----循环计算开始
                iii=0
                for i  in forlist:
                    acttime = getchecktime(empshiftschclass[0],empcheckdata,currentday,lasttime,['I','O','0','1','8','9'],empshift,empshiftschclass[0].StartTime,iii,(ii/2) -1)  #取刷卡时间并对应签到签退
                    if emptx:
                       calcresult = calcitemandsave(acttime,empshiftschclass[0],currentday,u,empleavedata,calctx(empshiftschclass[0],currentday,emptx,empworktype,empshiftschclass[0].StartTime),empshift,(i+1))  #计算实际的项目并保存。
                    else:
                       calcresult = calcitemandsave(acttime,empshiftschclass[0],currentday,u,empleavedata,empworktype,empshift,(i+1))  #计算实际的项目并保存。
                    lasttime = acttime['lasttime']
                    iii = iii +1
             except:
                import traceback;traceback.print_exc()
                pass
       except:
         import traceback;traceback.print_exc()
         pass
    ############################### 没有正常班次时段时的处理 #################################
    else:
        #没有排班，但是有临时排班的情况。
        if emptempsch :
           try:
              lasttime = datetime.datetime(1900,1,1,0,0,0)
              iii =0
              nworktype=0
              for ef in emptempsch:
                  acttime = getchecktime(ef,empcheckdata,currentday,lasttime,['I','o','1','0','8,9'],empshift,emptempsch[0].StartTime,iii,len(emptempsch) -1)
                  if emptx:
                     calcresult = calcitemandsave(acttime,ef,currentday,u,empleavedata,calctx(ef,currentday,emptx,tempworktype[nworktype],emptempsch[0].StartTime),empshift,1)  #工作类型、班次代码(未知)、第几段
                  else:
                     calcresult = calcitemandsave(acttime,ef,currentday,u,empleavedata,tempworktype[nworktype],0,1)  #工作类型、班次代码(未知)、第几段
                  lasttime = acttime['lasttime']
                  iii = iii +1
                  nworktype = nworktype+1
           except:
              import traceback;traceback.print_exc()
              pass
        else:  #既没有排班，也没有临时排班的情况,视为弹性班次(第二次做默认处理)。
           try:
              empshiftschclass =  filter(lambda f: f.pk in (1,),schclass_all)
              lasttime = datetime.datetime(1900,1,1,0,0,0)
              ii = filattercord(currentday,empcheckdata)
              if ii in [0,1]:
                 ii = 2
              if ii>=2:
                 iii =0
                 for i  in range(ii/2):
                     acttime = getchecktime(empshiftschclass[0],empcheckdata,currentday,lasttime,['I','O','0','1','8','9'],empshift,empshiftschclass[0].StartTime,iii,ii/2)  #取刷卡时间并对应签到签退
                     if emptx:
                        calcresult = calcitemandsave(acttime,empshiftschclass[0],currentday,u,empleavedata,calctx(empshiftschclass[0],currentday,emptx,empworktype,empshiftschclass[0].StartTime),empshift,i)  #计算实际的项目并保存。
                     else:
                        calcresult = calcitemandsave(acttime,empshiftschclass[0],currentday,u,empleavedata,empworktype,empshift,i)  #计算实际的项目并保存。
                     lasttime = acttime['lasttime']
                     iii = iii +1
              else:
                 iii =0
                 for i  in [0]:
                     acttime = getchecktime(empshiftschclass[0],empcheckdata,currentday,lasttime,['I','O','0','1','8','9'],empshift,empshiftschclass[0].StartTimem,iii,0)  #取刷卡时间并对应签到签退
                     if emptx:
                        calcresult = calcitemandsave(acttime,empshiftschclass[0],currentday,u,empleavedata,calctx(empshiftschclass[0],currentday,emptx,empworktype,empshiftschclass[0].StartTime),empshift,i)  #计算实际的项目并保存。
                     else:
                        calcresult = calcitemandsave(acttime,empshiftschclass[0],currentday,u,empleavedata,empworktype,empshift,i)  #计算实际的项目并保存。
                     lasttime = acttime['lasttime']
                     iii = iii +1
           except:
              import traceback;traceback.print_exc()
              pass