import time
import random
import os

# ----------- Global Variable -------------

# AI global variable
from typing import List

otro = [0, 0]
count = 0
posx = [0]

# Game Board
board = [
    "-", "-", "-",
    "-", "-", "-",
    "-", "-", "-"
]

# If game is still going
game_still_going = True

# User Choosing X or O
current_player = None

# Multiplayer mode
def player():
    is_input_valid = True
    while is_input_valid:
        checks_player = input("What do you want to choose? (X/O) ")
        checks_player = checks_player.upper()

        if checks_player == "X" or checks_player == "O":
            is_input_valid = False
            return checks_player.upper()

        else:
            print("INVALID INPUT!!!")

# Display Board
def display_board():
    print(' ' + board[0] + ' | ' + board[1] + ' | ' + board[2] + '')
    print('---|---|---')
    print(' ' + board[3] + ' | ' + board[4] + ' | ' + board[5] + '')
    print("---|---|---")
    print(' ' + board[6] + ' | ' + board[7] + ' | ' + board[8] + "\n")

# Play a game of Tic Tac Toe
def multi():
    global current_player

    time.sleep(0.5)
    current_player = player()
    time.sleep(0.5)
    display_board()
    time.sleep(0.5)

    # while game is still going
    while game_still_going:
        # handle a single turn of an arbitary player
        handle_turn(current_player)

        # check if the game has ended
        check_for_winner()
        check_if_tie()

        # Flip to the other player
        flip_player()

    # The game has ended
    if winner == "X" or winner == "O":
        print(winner + " won!")

    else:
        print("Tie.")

# Handle a single turn of an arbitary player
def handle_turn( player ):
    print(player + "'s turn.")
    time.sleep(0.2)
    err = True

    while err:
        position = input("Choose a position from 1-9: ")

        # Checks if input is valid or not
        if position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
            err = True
            print("Invalid Input!!")
            time.sleep(0.5)
            print("Please,")

        # Checks if the position was empty or not
        elif board[int(position) - 1] != "-":
            err = True
            print("You can't go there.Try Again!")

        else:
            err = False

    position = int(position) - 1
    board[position] = player

    display_board()

def check_if_game_over():
    check_for_winner()
    check_if_tie()

def check_for_winner():
    # Setting up global variable
    global winner

    # check row
    row_winner = check_row()

    # check column
    column_winner = check_column()

    # check diagonals
    diagonal_winner = check_diag()

    if row_winner or column_winner or diagonal_winner:
        winner = row_winner or column_winner or diagonal_winner

    else:
        # There was no win.
        winner = None

    return

def check_row():
    # Setting up global variable
    global game_still_going

    # Checking if all row have same value
    row1 = board[0] == board[1] == board[2] != "-"
    row2 = board[3] == board[4] == board[5] != "-"
    row3 = board[6] == board[7] == board[8] != "-"

    if row1 or row2 or row3:
        game_still_going = False

    # Return the winner
    if row1:
        return board[0]
    if row2:
        return board[3]
    if row3:
        return board[6]

    return

def check_column():
    # Setting up global variable
    global game_still_going

    # Checking if all column have same value
    column1 = board[0] == board[3] == board[6] != "-"
    column2 = board[1] == board[4] == board[7] != "-"
    column3 = board[2] == board[5] == board[8] != "-"
    if column1 or column2 or column3:
        game_still_going = False

    # Return the winner
    if column1:
        return board[0]
    if column2:
        return board[1]
    if column3:
        return board[2]
    return

def check_diag():
    global game_still_going

    diag1 = board[0] == board[4] == board[8] != "-"
    diag2 = board[2] == board[4] == board[6] != "-"

    if diag1 or diag2:
        game_still_going = False
        return board[4]
    return

def check_if_tie():
    global game_still_going

    if "-" not in board:
        game_still_going = False

    return

# Flip the tuen of player
def flip_player():
    # Global variable we need
    global current_player

    # If the current player was x, then change it to o
    if current_player == "X":
        current_player = "O"

    # If the current player was o, then change it to x
    elif current_player == "O":
        current_player = "X"

    return

# Singleplayer Mode

def solo():
    def tabla():
        print(' ' + board[0] + ' | ' + board[1] + ' | ' + board[2] + '')
        print('---|---|---')
        print(' ' + board[3] + ' | ' + board[4] + ' | ' + board[5] + '')
        print("---|---|---")
        print(' ' + board[6] + ' | ' + board[7] + ' | ' + board[8] + "\n")

    pi = ['1', '2', '3', '4', '5', '6', '7', '8', '9']

    op1 = [1, 2, 3, 4, 6, 7, 8, 9]
    op2 = [5]
    op3 = [1, 3, 7, 9]
    op4 = [2, 4, 6, 8]

    rchai = [1, 3, 5, 7, 9]

    # Formas de ganar
    # horizontal
    wh1 = [1, 2, 3]
    vh1 = [1, 2, 3]
    wh2 = [4, 5, 6]
    vh2 = [4, 5, 6]
    wh3 = [7, 8, 9]
    vh3 = [7, 8, 9]
    Wh1 = [1, 2, 3]
    Wh2 = [4, 5, 6]
    Wh3 = [7, 8, 9]
    # vertical
    wv1 = [1, 4, 7]
    vv1 = [1, 4, 7]
    wv2 = [2, 5, 8]
    vv2 = [2, 5, 8]
    wv3 = [3, 6, 9]
    vv3 = [3, 6, 9]
    Wv1 = [1, 4, 7]
    Wv2 = [2, 5, 8]
    Wv3 = [3, 6, 9]
    # diagonal
    wd1 = [1, 5, 9]
    vd1 = [1, 5, 9]
    wd2 = [3, 5, 7]
    vd2 = [3, 5, 7]
    Wd1 = [1, 5, 9]
    Wd2 = [3, 5, 7]

    # Cuando gana la AI
    def win():
        if wh1.count("O") == 3:
            print("AI wins")
            quit()
        elif wh2.count("O") == 3:
            print("AI wins")
            quit()
        elif wh3.count("O") == 3:
            print("AI wins")
            quit()
        elif wv1.count("O") == 3:
            print("AI wins")
            quit()
        elif wv2.count("O") == 3:
            print("AI wins")
            quit()
        elif wv3.count("O") == 3:
            print("AI wins")
            quit()
        elif wd1.count("O") == 3:
            print("AI wins")
            quit()
        elif wd2.count("O") == 3:
            print("AI wins")
            quit()

    # Poner una X o una O
    def borrar( pos, a ):
        global count
        global otro
        if pos in wh1:
            wh1.remove(pos)
            vh1.remove(pos)
            wh1.append(a)
        if pos in wh2:
            wh2.remove(pos)
            vh2.remove(pos)
            wh2.append(a)
        if pos in wh3:
            wh3.remove(pos)
            vh3.remove(pos)
            wh3.append(a)
        if pos in wv1:
            wv1.remove(pos)
            vv1.remove(pos)
            wv1.append(a)
        if pos in wv2:
            wv2.remove(pos)
            vv2.remove(pos)
            wv2.append(a)
        if pos in wv3:
            wv3.remove(pos)
            vv3.remove(pos)
            wv3.append(a)
        if pos in wd1:
            wd1.remove(pos)
            vd1.remove(pos)
            wd1.append(a)
        if pos in wd2:
            wd2.remove(pos)
            vd2.remove(pos)
            wd2.append(a)
        count += 1
        if count == 9:
            print("It's a draw!")
            quit()

    # Movimiento de la AI
    def movai( pos ):
        posstr = str(pos)
        board.pop(pos - 1)
        pi.remove(posstr)
        board.insert(pos - 1, "O")
        pi.append("F")
        tabla()
        borrar(pos, "O")

    # MOVIMIENTOS
    # Primer movimiento del jugador
    def me1():

        err = True
        while err:
            position = input("Choose a position from 1-9: ")

            # Checks if input is valid or not
            if position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
                err = True
                print("Invalid Input!!")
                time.sleep(0.5)
                print("Please,")

            # Checks if the position was empty or not
            elif board[int(position) - 1] != "-":
                err = True
                print("You can't go there.Try Again!")

            else:
                err = False
        position = int(position)
        while True:
            if str(position) in pi:
                board.pop(position - 1)
                pi.pop(position - 1)
                pi.append("F")
                board.insert(position - 1, "X")
                otro.pop(0)
                otro.insert(0, position)
                posx.append(position)
                posx.pop(0)
                print("\n")
                tabla()
                borrar(position, "X")
                break
            else:
                print('Error')
                position = int(input("Position: "))
        print("AI is thinking...")
        time.sleep(1)
        if position in op1:
            position = 5
            movai(position)
        elif position in op2:
            position = 1
            movai(position)

    def me():
        win()

        err = True
        while err:
            position = input("Choose a position from 1-9: ")

            # Checks if input is valid or not
            if position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
                err = True
                print("Invalid Input!!")
                time.sleep(0.5)
                print("Please,")

            # Checks if the position was empty or not
            elif board[int(position) - 1] != "-":
                err = True
                print("You can't go there.Try Again!")

            else:
                err = False
        position = int(position)
        while True:
            if str(position) in pi:
                board.pop(position - 1)
                posstr = position
                pi.remove(str(posstr))
                if count == 2 or count == 3:
                    otro.pop(1)
                    otro.insert(1, position)
                pi.append("F")
                board.insert(position - 1, "X")
                print("\n")
                tabla()
                borrar(position, "X")
                posx.append(position)
                break
            else:
                print("You can't go there.Try Again!")
                position = int(input("Position: "))
        print("AI is thinking...")
        time.sleep(1)
        ai()

    def ai():
        pos = int(pi[0])
        if count == 0:
            pos = random.choice(rchai)
        elif (wh1.count("O") == 2) and len(vh1) == 1:
            pos = wh1[0]
        elif (wh2.count("O") == 2) and len(vh2) == 1:
            pos = wh2[0]
        elif (wh3.count("O") == 2) and len(vh3) == 1:
            pos = wh3[0]
        elif (wv1.count("O") == 2) and len(vv1) == 1:
            pos = wv1[0]
        elif (wv2.count("O") == 2) and len(vv2) == 1:
            pos = wv2[0]
        elif (wv3.count("O") == 2) and len(vv3) == 1:
            pos = wv3[0]
        elif (wd1.count("O") == 2) and len(vd1) == 1:
            pos = wd1[0]
        elif (wd2.count("O") == 2) and len(vd2) == 1:
            pos = wd2[0]
        else:
            if (wh1.count("X") == 2) and len(vh1) == 1:
                pos = wh1[0]
            elif (wh2.count("X") == 2) and len(vh2) == 1:
                pos = wh2[0]
            elif (wh3.count("X") == 2) and len(vh3) == 1:
                pos = wh3[0]
            elif (wv1.count("X") == 2) and len(vv1) == 1:
                pos = wv1[0]
            elif (wv2.count("X") == 2) and len(vv2) == 1:
                pos = wv2[0]
            elif (wv3.count("X") == 2) and len(vv3) == 1:
                pos = wv3[0]
            elif (wd1.count("X") == 2) and len(vd1) == 1:
                pos = wd1[0]
            elif (wd2.count("X") == 2) and len(vd2) == 1:
                pos = wd2[0]
            else:
                if f == 1 and count == 4:
                    if (('1' not in pi) and ('8' not in pi)) or (('9' not in pi) and ('4' not in pi)):
                        if board[6] == '-':
                            pos = 7
                    elif (('6' not in pi) and ('1' not in pi)) or (('9' not in pi) and ('2' not in pi)):
                        if board[2] == '-':
                            pos = 3
                    elif (('7' not in pi) and ('2' not in pi)) or (('3' not in pi) and ('4' not in pi)):
                        if board[0] == '-':
                            pos = 1
                    elif (('7' not in pi) and ('6' not in pi)) or (('3' not in pi) and ('8' not in pi)):
                        if board[8] == '-':
                            pos = 9
                    else:
                        if board[4] == '-':
                            pos = 5
                        elif board[2] == '-':
                            pos = 3
                        elif board[6] == '-':
                            pos = 7
                        else:
                            pos = int(pi[0])
                elif count == 3:
                    if (otro[0] == 1 and otro[1] == 8) or (otro[0] == 8 and otro[1] == 1):
                        pos = 7
                    elif (otro[0] == 1 and otro[1] == 6) or (otro[0] == 6 and otro[1] == 1):
                        pos = 3
                    elif (otro[0] == 7 and otro[1] == 2) or (otro[0] == 2 and otro[1] == 7):
                        pos = 1
                    elif (otro[0] == 7 and otro[1] == 6) or (otro[0] == 6 and otro[1] == 7):
                        pos = 9
                    elif (otro[0] == 9 and otro[1] == 2) or (otro[0] == 2 and otro[1] == 9):
                        pos = 3
                    elif (otro[0] == 9 and otro[1] == 4) or (otro[0] == 4 and otro[1] == 9):
                        pos = 7
                    elif (otro[0] == 3 and otro[1] == 4) or (otro[0] == 4 and otro[1] == 3):
                        pos = 1
                    elif (otro[0] == 3 and otro[1] == 8) or (otro[0] == 8 and otro[1] == 3):
                        pos = 9
                    elif (posx[0] in op3) and (posx[1] in op3):
                        if board[1] == '-':
                            pos = 2
                        elif board[3] == '-':
                            pos = 4
                    else:
                        if board[4] == '-':
                            pos = 5
                        elif board[2] == '-':
                            pos = 3
                        elif board[6] == '-':
                            pos = 7
                        else:
                            pos = int(pi[0])
                elif count == 2:
                    if posx[1] == 2 or posx[1] == 4:
                        pos = 9
                    elif posx[1] == 6 or posx[1] == 8:
                        pos = 1
                    elif board[4] == "X":
                        if board[0] == 'O':
                            pos = 9
                        elif board[2] == 'O':
                            pos = 7
                        elif board[6] == 'O':
                            pos = 3
                        elif board[8] == 'O':
                            pos = 1
                    else:
                        pos = 2
                else:
                    if board[4] == '-':
                        pos = 5
                    elif board[2] == '-':
                        pos = 3
                    elif board[6] == '-':
                        pos = 7
                    else:
                        pos = int(pi[0])
        movai(pos)

    f = 0
    while True:
        print("Who first? \n 1) Me\n 2) AI\n")
        arranca = input()
        print(" ")
        if arranca == "1":
            me1()
            me()
            me()
            me()
            me()
            break
        elif arranca == "2":
            f = 1
            ai()
            me()
            me()
            me()
            me()
            break
        else:
            time.sleep(0.5)
            print("INVALID INPUT!")
            print("Please try again!")
            time.sleep(1)

print("-------------------TIC TAC TOE---------------------")
time.sleep(0.5)
print("\n             Let' start the game.\n")
time.sleep(1)
print("The positions that will be used in this game are here:")
print(" 1 | 2 | 3 ")
print("---|---|---")
print(" 4 | 5 | 6 ")
print("---|---|---")
print(" 7 | 8 | 9 \n")
time.sleep(0.8)
turu = True
while turu:
    mode = input("In which mode do you want to play?\n 1) Solo Mode\n 2) Multiplayer Mode\n\n")
    if mode == "1":
        time.sleep(0.2)
        print("...\n")
        time.sleep(0.9)
        solo()
        turu = False
    elif mode == "2":
        time.sleep(0.2)
        print("...")
        time.sleep(0.9)
        multi()
        turu = False
    else:
        time.sleep(0.5)
        print("INVALID INPUT!")
        print("Please try again!")
        time.sleep(1)


from tkinter import *
import numpy as np
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from scipy import signal as sp
import matplotlib.pyplot as plt

gui_4 = Tk()
gui_4.title('Tarea 1')
gui_4.configure(background='SlateBlue')
gui_4.geometry("1000x800")

# Etiqueta
lab_1 = Label(gui_4, text="Numero de Armonicos")
lab_1.configure(background='White')
lab_1.grid(row=0, column=1, padx=(10, 10), pady=(10, 10))
n = IntVar()
n.set(10)

# Etiqueta
lab_2 = Label(gui_4, text="ti")
lab_2.configure(background='white')
lab_2.grid(row=2, column=0, padx=(10, 10), pady=(10, 10))
ti = DoubleVar()
ti.set(1)

# Etiqueta
lab_1 = Label(gui_4, text="tf")
lab_1.configure(background='white')
lab_1.grid(row=2, column=1, padx=(10, 10), pady=(10, 10))
tf = DoubleVar()
tf.set(10)

# Etiqueta
lab_2 = Label(gui_4, text="dt")
lab_2.configure(background='white')
lab_2.grid(row=2, column=2, padx=(10, 10), pady=(10, 10))
dt = DoubleVar()
dt.set(0.001)

# Caja de texto
ent1 = Entry(gui_4, textvariable=n)
ent1.configure(background='white')
ent1.grid(row=1, column=0, padx=(10, 10), pady=(10, 10))
ent1.config(width=5)

# Caja de texto
ent2 = Entry(gui_4, textvariable=ti)
ent2.configure(background='white')
ent2.grid(row=3, column=0, padx=(10, 10), pady=(10, 10))
ent2.config(width=5)

# Caja de texto
ent3 = Entry(gui_4, textvariable=tf)
ent3.configure(background='white')
ent3.grid(row=3, column=1, padx=(10, 10), pady=(10, 10))
ent3.config(width=5)

# Caja de texto
ent4 = Entry(gui_4, textvariable=dt)
ent4.configure(background='white')
ent4.grid(row=3, column=2, padx=(10, 10), pady=(10, 10))
ent4.config(width=5)

fun1 = StringVar(gui_4)
fun1.set('Señal')

menu = OptionMenu(gui_4, fun1, 'Trigonometrica',
                  'Exponencial', 'Logaritmica', 'Algebraica')
menu.grid(row=1, column=3, padx=(10, 10), pady=(10, 10))

def Mostrar_Grafica():
    harm = n.get()
    ini = ti.get()
    fin = tf.get()
    delt = dt.get()
    op = fun1.get()
    T = fin-ini
    w = (2*np.pi)/T
    t = np.arange(ini, fin, delt)
    ak = np.zeros((harm, 1))
    bk = np.zeros((harm, 1))
    m = len(t)

    if op == 'Trigonometrica':
        x = np.cos(t)
    if op == 'Exponencial':
        x = np.exp(t)
    if op == 'Logaritmica':
        x = np.log(t)
    if op == 'Algebraica':
        x = t**2

# Calculo del coeficiente A0
    A0 = 0
    for i in range(1, m):
        i = int(i)
        A0 = A0 + (1/T)*x[i]*delt

    n_w = np.arange(1, harm+1, 1)
    ck = np.zeros((harm, 1))
    phik = np.zeros((harm, 1))

# Calculo de los armonicos Ak y Bk
    for i in range(1, harm):
        i = int(i)
        for j in range(1, m):
            j = int(j)
            ak[i] = ak[i] + ((2/T)*x[j]*np.cos(i*t[j]*w)*delt)
            bk[i] = bk[i] + ((2/T)*x[j]*np.sin(i*t[j]*w)*delt)
            ck[i] = (ak[i]**2 + bk[i]**2)**0.5
            phik[i] = -1*(np.arctan(bk[i]/ak[i]))

    t1 = np.arange(ini, 2*fin, delt)
    xf = A0
    for i in range(1, harm):
        i = int(i)
        xf = xf + ak[i]*np.cos(i*w*t1) + bk[i]*np.sin(i*w*t1)

    plt.figure(1)
    plt.clf()
    plt.title('Señal')
    plt.plot(t, x)
    plt.gcf().canvas.draw()

    plt.figure(2)
    plt.clf()
    plt.title('Espectro Amplitud')
    plt.stem(n_w, ck)
    plt.gcf().canvas.draw()

    plt.figure(3)
    plt.clf()
    plt.title('Señal en Series')
    plt.plot(t1, xf)
    plt.gcf().canvas.draw()

    plt.figure(4)
    plt.clf()
    plt.title('Espectro Fase')
    plt.stem(n_w, phik)
    plt.gcf().canvas.draw()

fig = plt.figure(figsize=(3, 2))
canv = FigureCanvasTkAgg(fig, master=gui_4)
canv.get_tk_widget().grid(row=9, column=0, padx=(10, 10), pady=(10, 10))

fig2 = plt.figure(figsize=(3, 2))
canv2 = FigureCanvasTkAgg(fig2, master=gui_4)
canv2.get_tk_widget().grid(row=9, column=1, padx=(10, 10), pady=(10, 10))

fig3 = plt.figure(figsize=(3, 2))
canv3 = FigureCanvasTkAgg(fig3, master=gui_4)
canv3.get_tk_widget().grid(row=11, column=0, padx=(10, 10), pady=(10, 10))

fig4 = plt.figure(figsize=(3, 2))
canv4 = FigureCanvasTkAgg(fig4, master=gui_4)
canv4.get_tk_widget().grid(row=11, column=1, padx=(10, 10), pady=(10, 10))

plt.figure(1)
plt.clf()
plt.title('ORIGINAL')

plt.figure(2)
plt.clf()
plt.title('ESPECTRO EN AMPLITUD')

plt.figure(3)
plt.clf()
plt.title('RECONSTRUIDA')

plt.figure(4)
plt.clf()
plt.title('ESPECTRO EN FASE')

# Button
btn = Button(gui_4, text="GRAFICAR", command=Mostrar_Grafica)
btn.grid(row=3, column=3, padx=(10, 10), pady=(10, 10))

gui_4.mainloop()


def call_v2(func):
    data = func()

    if y.is_pointer(data):
        data = y.restore_node(data)

    return data

@y.cached
def to_v2(data, info):
    node = y.copy.copy(data)

    deps = node.pop('deps', [])
    code = node.pop('code', '')
    prepare = node.pop('prepare', '')

    node['host'] = info
    node['prepare'] = y.to_lines(prepare)
    node['build'] = y.to_lines(code)

    return y.fix_v2({
        'node': node,
        'deps': deps,
    })


#!/usr/bin/python
from operator import itemgetter

# Lesson 03, Mailroom Part 1 Assignment

# ------- Global Assignments -------
donor_data = {'John Marks': [5000.34, 2500, 1267],
              'Matt Smith': [750],
              'Kelsey Rodgers': [55.76],
              'John Williams': [500, 1898],
              'Morgan Stanley': [12000.98, 8670],
              'Roger Johnson': [264, 942.23],
              'Sherry Wilson': [4000, 2324.1, 1352],
              'Alex Grant': [8739, 4312]}
# ----------------------------------

def menu_display():
    print("\n\n----- MENU -----\n"
          "1: Send a Thank You\n"
          "2: Create a Report\n"
          "3: Send letters to everyone\n"
          "4: Quit\n")
    menu_sel_ = input("------> "
                      "Select an option from the menu: ")
    return menu_sel_

def list_display():
    print("\n---- List of all Donors ----")
    for item in donor_data:
        print("- {}".format(item))
    print("----------------------------")
    thank_you()

def list_details(data):
    header = "\n{:<18}| {:<12}| {:<10}| {:<12}".format("Donor Name", "Total "
                                                       "Given", "Num Gifts",
                                                       "Average Gift")
    buffer = "------------------------------------------------------------------"
    print(header)
    print(buffer)
    for item in sorted(data, key=itemgetter(-2), reverse=True):
        print("{:<18} $  {:>9.2f}  {:>10}  $   {:>9.2f}".format(item[0], item[2], item[1], item[3]))

def compose_email(donor_name, donation_amount):
    greeting_email = "\nDear {},".format(donor_name)
    body_email = "\nThank you very much for your generous donation of {}".format(donation_amount)
    print(greeting_email, body_email)

def add_donation(donor_name):
    donation_amount = input("\nEnter the donation amount for {} ".format(donor_name))
    donor_data[donor_name].append(float(donation_amount))
    compose_email(donor_name, donation_amount)

def thank_you():
    donor_name = input("\nPlease enter the donor's full name: ")
    if donor_name == 'list':
        list_display()
    else:
        if donor_name in donor_data:
            add_donation(donor_name)
        else:
            donor_data[donor_name] = []
            add_donation(donor_name)

def calc_data():
    summary_data = []
    for i, item in enumerate(donor_data):
        donations_quantity = len(donor_data[item])
        donations_value = sum(donor_data[item])
        donations_average = (float(donations_value / donations_quantity))
        summary_data.append([])
        summary_data[i].extend([item, donations_quantity, donations_value, donations_average])
    return summary_data

def report():
    summary_data = calc_data()
    list_details(summary_data)

def send_all_letters():
    summary_data = calc_data()
    for item in summary_data:
        filename_format = "{}_{}.txt".format(item[0].split()[0], item[0].split()[1])
        thank_you_text = open(filename_format, 'w+')
        thank_you_text.write("Dear {},\n\nThank you very much for your {} generous donations totalling ${}.\n"
                             "\nYour donations will significantly aid our scholarship fund\n\n"
                             "Sincerely,\n - Advancement Office".format(item[0], item[1], item[2]))
        thank_you_text.close()
    print("\nAll thank you letters drafted")

if __name__ == "__main__":

    menu_map = {'1': thank_you, '2': report, '3': send_all_letters, '4': 'exit'}

    while True:
        menu_sel = menu_display()
        if menu_map[menu_sel] == 'exit':
            break
        menu_map[menu_sel]()


#Python that uses filterfalse

import itertools

values = ["cat", "parrot", "dog", "bird"]

# Filter out values with length greater than or equal to 4.
result = itertools.filterfalse(lambda e: len(e) < 4, values)

for element in result:
    print(element)


import sys
import vtk
from PyQt5 import QtCore, QtGui, QtWidgets
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from system.example.slice import *

class myMainWindow(QtWidgets.QMainWindow):

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

        self.frame = QtWidgets.QFrame()

        self.vl = QtWidgets.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)

        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()

        imageViewer = vtkImageViewer2()
        renderWindowInteractor = self.vtkWidget
        imageViewer.SetInputConnection(reslice.GetOutputPort())
        imageViewer.SetupInteractor(renderWindowInteractor)
        imageViewer.SetColorLevel(100)
        imageViewer.SetColorWindow(200)

        imageViewer.Render()

        self.ren.ResetCamera()

        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)

        self.show()

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = myMainWindow()

    sys.exit(app.exec_())


import sys
from PyQt5 import Qt, QtWidgets, QtCore
from MapRequest import *

KEY_LEFT = 65, 16777234, 1060
KEY_UP = 87, 16777235, 1062
KEY_RIGHT = 68, 16777236, 1042
KEY_DOWN = 83, 16777237, 1067

class MainApp(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        # Основные параметры
        self.map_size = 600  # Если слишком большой(маленький) размер каринки, то изменить здесь
        self.x = 37.621094
        self.y = 55.7536
        self.coords_for_dota = self.x, self.y
        self.z = 16
        self.map_type = 'map'
        self.ind = 0
        self.toponym = 'Красная площадь'
        self.map_types = ['map', 'sat', 'sat,skl']

        # Инициализация окна
        self.initUI()

    def initUI(self):
        # Настройки окна
        self.width = self.map_size
        self.height = self.map_size - 30
        self.setGeometry(0, 0, self.width, self.height)
        self.setFixedSize(self.size())
        self.setStyleSheet('background: lightgray')
        self.setWindowTitle('Карты')

        # Поиск объекта на карте
        self.edt_find_toponym = QtWidgets.QLineEdit(self)
        self.edt_find_toponym.setText(self.toponym)
        self.edt_find_toponym.setGeometry(0, 0, 500, 30)
        self.edt_find_toponym.setStyleSheet('background: white')
        self.btn_find_toponym = QtWidgets.QPushButton(self)
        self.btn_find_toponym.setText('Найти!')
        self.btn_find_toponym.setGeometry(500, 0, 100, 30)
        self.btn_find_toponym.clicked.connect(self.switch_toponym)

        # Кнопка сброса запроса
        self.btn_clear_toponym = QtWidgets.QPushButton(self)
        self.btn_clear_toponym.setText('Сброс')
        self.btn_clear_toponym.setGeometry(500, 30, 50, 30)
        self.btn_clear_toponym.clicked.connect(self.clear_toponym)

        # Изменение вида карты
        self.btn_box_map_types = QtWidgets.QPushButton(self)
        self.btn_box_map_types.setText('Тип')
        self.btn_box_map_types.setGeometry(self.width - 50, 30, 50, 30)
        self.btn_box_map_types.clicked.connect(self.switch_map_type)

        # Рамка для картинки
        self.frame_for_picture = QtWidgets.QLabel(self)
        self.frame_for_picture.setGeometry(0, 60, self.width, self.height - 20 - 30 - 30)
        self.frame_for_picture.setStyleSheet('background: white')

        # Рамка для отображения информации
        self.frame_settings_for_search = QtWidgets.QFrame(self)
        self.frame_settings_for_search.setGeometry(0, self.height - 20,
                                                   self.width, 20)
        # Информация о карте
        self.lbl_x = QtWidgets.QLabel(self.frame_settings_for_search)
        self.lbl_x.setGeometry(0, 0, 100, 20)
        self.lbl_y = QtWidgets.QLabel(self.frame_settings_for_search)
        self.lbl_y.setGeometry(100, 0, 100, 20)
        self.lbl_z = QtWidgets.QLabel(self.frame_settings_for_search)
        self.lbl_z.setGeometry(200, 0, 100, 20)

        self.search()

    def search(self):
        # Получаем картинку
        pixmap = get_map_image((self.x, self.y), self.z, self.map_type, self.coords_for_dota)
        resize_coef = min(self.frame_for_picture.width() / pixmap.width(),
                          self.frame_for_picture.height() / pixmap.height())
        pixmap = pixmap.scaled(int(pixmap.width() * resize_coef),
                               int(pixmap.height() * resize_coef))

        # Отображаем параметры
        self.lbl_x.setText(f'x: {round(self.x, 5)}')
        self.lbl_y.setText(f'y: {round(self.y, 5)}')
        self.lbl_z.setText(f'size_coef: {round(self.z / 17, 5)}')

        # Отображаем картинку
        self.frame_for_picture.setPixmap(pixmap)

    def clear_toponym(self):
        self.toponym = ''
        self.edt_find_toponym.setText('')
        self.coords_for_dota = None
        self.search()

    def switch_map_type(self):
        # Переключаем на следующую карту
        self.ind = (self.ind + 1) % 3
        self.map_type = self.map_types[self.ind]
        self.search()

    def switch_toponym(self):
        # Искомый топоним в поле ввода
        toponym = self.edt_find_toponym.text()

        # Получаем ответ от серера
        response = get_map_coords(toponym)
        if isinstance(response, str):
            self.msg_box = QtWidgets.QMessageBox.question(self.frame_for_picture, 'Результат запроса', 'Не найдено',
                                                          QtWidgets.QMessageBox.Cancel)
        else:
            self.x, self.y = response
            self.coords_for_dota = response
            self.toponym = toponym
        self.search()

    def cmd_wheel_up(self):
        self.z += 1
        if self.z >= 17:
            self.z = 17
        self.search()

    def cmd_wheel_down(self):
        self.z -= 1
        if self.z <= 0:
            self.z = 0
        self.search()

    def cmd_key_left(self):
        self.x -= self.z ** (-2)
        self.search()

    def cmd_key_right(self):
        self.x += self.z ** (-2)
        self.search()

    def cmd_key_up(self):
        self.y += self.z ** (-2.4)
        self.search()

    def cmd_key_down(self):
        self.y -= self.z ** (-2.4)
        self.search()

    def keyPressEvent(self, e):
        print(e.key())
        if e.type() == QtCore.QEvent.KeyPress:
            if e.key() in KEY_LEFT:
                self.cmd_key_left()
            if e.key() in KEY_RIGHT:
                self.cmd_key_right()
            if e.key() in KEY_UP:
                self.cmd_key_up()
            if e.key() in KEY_DOWN:
                self.cmd_key_down()

    def wheelEvent(self, e):
        # Прокрутка колёсика мыши
        if e.angleDelta().y() > 0:
            self.cmd_wheel_up()
        elif e.angleDelta().y() < 0:
            self.cmd_wheel_down()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = MainApp()
    ex.show()
    sys.exit(app.exec())


# -*- coding: utf-8 -*-
import openerp
from openerp import models
from openerp.osv import fields

STATES_OUT = {}

STATES_IN = {}

class AccountInvoice(models.Model):
    _name = 'account.invoice'
    _inherit = 'account.invoice'

    def _get_product(self, cr, uid, vals, context=None):
        domain = [('name', '=', vals['product']), ('variant', '=', vals['variant'])]
        product_ids = self.pool.get('product.product').search(cr, uid, domain)
        return product_ids and product_ids[0] or False

    def _convert(self, cr, uid, vals, context=None):
        new_vals = {}
        new_vals['name'] = vals['name']
        new_vals['product_id'] = self._get_product(cr, uid, vals)
        new_vals['price_unit'] = vals['price']
        new_vals['quantity'] = vals['quantity']
        return new_vals

    def _set_status(self, cr, uid, oid, name, value, args, context=None):
        context = context or {}
        if value in STATES_IN:
            self.signal_workflow(cr, uid, [oid], STATES_IN[value], context=context)
            if context.get('receive_object', False):
                self.write(cr, uid, oid, {'to_send': False}, context)
        return True

    def _get_status(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = STATES_OUT.get(obj.state, obj.state)
        return result

    def _set_company(self, cr, uid, oid, name, value, args, context=None):
        return True
        company = self.pool.get('res.company')
        domain = [('name', '=', value['firstname'])]
        if company.search(cr, uid, domain, context=context):
            # This order is not for this company
            raise openerp.exceptions.AccessDenied()
        return True

    def _get_company(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            partner = obj.company_id.partner_id
            var = {}
            var['firstname'] = partner.name
            var['email'] = partner.email
            var['address1'] = partner.street
            var['address2'] = partner.street2
            var['city'] = partner.city
            var['state'] = partner.state_id and partner.state_id.name or False
            var['country'] = partner.country_id and partner.country_id.name or False
            var['phone'] = partner.phone
            var['zipcode'] = partner.zip
            result[obj.id] = var
        return result

    def _set_lines(self, cr, uid, oid, name, value, args, context=None):
        invoice_line = self.pool.get('account.invoice.line')
        context = context or {}
        lines = []
        for var in value:
            vals = self._convert(cr, uid, var, context)
            domain = [
                ('invoice_id', '=', oid),
                ('product_id', '=', vals['product_id']),
            ]
            pl_ids = invoice_line.search(cr, uid, domain)
            lines.append(pl_ids and (1, pl_ids[0], vals) or (0, 0, vals))
        if lines:
            self.write(cr, uid, oid, {'invoice_line': lines}, context)

    def _get_lines(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            lines = []
            for line in obj.invoice_line:
                var = {}
                var['name'] = line.name
                var['product'] = line.product_id.name
                var['variant'] = line.product_id.variant
                var['price'] = line.price_unit
                var['quantity'] = line.quantity
                lines.append(var)
            result[obj.id] = lines
        return result

    _columns = {
        'status': fields.function(_get_status, method=True, type='char',
                                  fnct_inv=_set_status),
        'line_items': fields.function(_get_lines, method=True, type='char',
                                      fnct_inv=_set_lines, priority=2)
    }


# from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework.generics import get_object_or_404
from django.db.models import Q
from perfume_app.models import *
from perfume_app.serializers import *

class BrokerView(APIView):
    """Просмотр маклеров"""
    permission_classes = [permissions.IsAuthenticated, ]

    def get(self, request):
        if request.user.is_superuser:
            brokers = Broker.objects.all()
            serializer = BrokerSerializers(brokers, many=True)
            return Response({"data": serializer.data})
        else:
            brokers = Broker.objects.filter(broker=request.user)
            serializer = BrokerSerializers(brokers, many=True)
            return Response({"data": serializer.data})

class FirmView(APIView):
    """Просмотр фирм"""
    permission_classes = [permissions.IsAuthenticated, ]

    def get(self, request):
        firms = Firm.objects.all()
        serializer = FirmSerializers(firms, many=True)
        return Response({"data": serializer.data})

class DealCRUDView(APIView):
    """CRUD сделок"""
    permission_classes = [permissions.IsAuthenticated, ]

    def get(self, request):
        if request.user.is_superuser:
            deals = Deal.objects.all()
            serializer = DealSerializers(deals, many=True)
            return Response({"data": serializer.data})
        else:
            broker = Broker.objects.filter(broker=request.user)
            deal = Deal.objects.filter(broker__in=broker)
            serializer = DealSerializers(deal, many=True)
            return Response({"data": serializer.data})

    def post(self, request):
        deal = DealCRUDSerializers(data=request.data)
        if deal.is_valid():
            broker_found = Broker.objects.get(broker=request.user)
            broker = get_object_or_404(Broker, id=broker_found.id)
            seller = get_object_or_404(Firm, id=self.request.data.get('seller'))
            buyer = get_object_or_404(Firm, id=self.request.data.get('buyer'))
            deal.save(broker=broker, seller=seller, buyer=buyer)
            return Response(status=201)
        else:
            return Response(status=400)

    def put(self, request, pk):
        saved_deal = get_object_or_404(Deal.objects.all(), pk=pk)
        serializer = DealCRUDSerializers(instance=saved_deal, data=request.data, partial=True)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
        return Response(status=201)

    def delete(self, request, pk):
        deal = get_object_or_404(Deal.objects.all(), pk=pk)
        deal.delete()
        return Response(status=201)

class FabricatorView(APIView):
    """Просмотр производителей"""
    permission_classes = [permissions.IsAuthenticated, ]

    def get(self, request):
        fabricators = Fabricator.objects.all()
        serializer = FabricatorSerializers(fabricators, many=True)
        return Response({"data": serializer.data})

class ProductCRUDView(APIView):
    """CRUD товаров"""
    permission_classes = [permissions.IsAuthenticated, ]

    def get(self, request):
        fabricator = request.GET.get("fabricator")
        if fabricator == None:
            products = Product.objects.all()
            serializer = ProductSerializers(products, many=True)
            return Response({"data": serializer.data})
        else:
            product = Product.objects.filter(fabricator=fabricator)
            serializer = ProductSerializers(product, many=True)
            return Response({"data": serializer.data})

    def post(self, request):
        product = ProductCRUDSerializers(data=request.data)
        if product.is_valid():
            fabricator = get_object_or_404(Fabricator, id=self.request.data.get("fabricator"))
            product.save(fabricator=fabricator)
            return Response(status=201)
        else:
            return Response(status=400)

    def put(self, request, pk):
        saved_product = get_object_or_404(Product.objects.all(), pk=pk)
        serializer = ProductCRUDSerializers(instance=saved_product, data=request.data, partial=True)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
        return Response(status=201)

    def delete(self, request, pk):
        product = get_object_or_404(Product.objects.all(), pk=pk)
        product.delete()
        return Response(status=201)

class OrderDealView(APIView):
    """Просмотр заказов сделки"""
    permission_classes = [permissions.IsAuthenticated, ]

    def get(self, request):
        deal = request.GET.get("deal", -1)
        if deal == -1:
            order_deals = OrderDeal.objects.all()
            serializer = OrderDealSerializers(order_deals, many=True)
            return Response({"data": serializer.data})
        else:
            order_deals = OrderDeal.objects.filter(deal=deal)
            serializer = OrderDealSerializers(order_deals, many=True)
            return Response({"data": serializer.data})


from unittest import mock

from jira_offline.config import load_config, upgrade_schema
from jira_offline.models import AppConfig

@mock.patch('jira_offline.config.AppConfig')
@mock.patch('jira_offline.config.os')
@mock.patch('jira_offline.config.click')
def test_load_config__config_created_when_no_config_file_exists(mock_click, mock_os, mock_appconfig_class):
    '''
    Test that when no config file exists, an AppConfig object is created
    '''
    # config file does not exist
    mock_os.path.exists.return_value = False

    load_config()

    assert mock_appconfig_class.called  # class instantiated

@mock.patch('jira_offline.config.upgrade_schema')
@mock.patch('jira_offline.config.AppConfig')
@mock.patch('jira_offline.config.json')
@mock.patch('jira_offline.config.os')
@mock.patch('jira_offline.config.click')
@mock.patch('builtins.open')
def test_load_config__upgrade_called_when_version_changes(mock_open, mock_click, mock_os, mock_json,
                                                          mock_appconfig_class, mock_upgrade_schema):
    '''
    Ensure the schema upgrade function is called when app.config schema version has changed
    '''
    # config file exists
    mock_os.path.exists.return_value = True

    # mock AppConfig constgructor to return version == 2
    mock_appconfig_class.return_value = AppConfig(schema_version=2)

    # mock config existing file to be scheme version == 1
    mock_json.load.return_value = {
        'schema_version': 1,
        'projects': {
            '09004155d6268ca91d0150a2d6c73c712926743c': {'key': 'TEST', 'name': 'TEST'}
        }
    }

    config = load_config()

    assert mock_upgrade_schema.called
    assert config.schema_version == 2

@mock.patch('jira_offline.config.config_upgrade_1_to_2')
def test_upgrade_schema__calls_correct_upgrade_func(mock_upgrade_func):
    '''
    Ensure the correct upgrade function is called based on the versions

    This is intentionally _not_ testing the upgrade code itself, just the calling mechanism
    '''
    config_json = {
        'schema_version': 1,
        'projects': {
            '09004155d6268ca91d0150a2d6c73c712926743c': {'key': 'TEST', 'name': 'TEST'}
        }
    }

    upgrade_schema(config_json, 1, 2)

    assert mock_upgrade_func.called


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

import sys
import os
import shutil
import re

# 目标page文件
PAGE_NAME = 'page.object.CustomAppRule'
SRC_DIR_NAME = 'js'
DEPS_DIR_NAME = 'deps'

_DEBUG = True

# TODO: 有些文件的_sf_name不是SF.a.b, 而是Ext.a.b, 需要进行处理
# _replace_sf_name需修改

def copy_file(src_path, target_path):
    try:
        if not os.path.exists(src_path):
            raise Exception('copy操作的源文件不存在')
        if os.path.exists(target_path):
            os.remove(target_path)
        if not os.path.exists(os.path.split(target_path)[0]):
            os.makedirs(os.path.split(target_path)[0])
        shutil.copyfile(src_path, target_path)
    except Exception as e:
        print(e)

class CodeFile(object):
    def __init__(self, sf_name, src_dir_name='js'):
        # 形如'SF.a.b'的名称
        self._sf_name = sf_name

        # js源码文件夹
        self._src_dir_name = src_dir_name

        # js/pages文件夹名
        self._pages_dir = 'pages'

        # js/components文件夹名
        self._components_dir = 'components'

        # js/components的绝对路径
        self._components_dir_path = os.path.join(sys.path[0], self._src_dir_name, self._components_dir)

        # xx.js绝对路径
        self._js_path = self._get_js_path()

        # xx.deps绝对路径, 无deps文件则值为None
        self._deps_path = self._get_deps_path()

        # 副本路径,page的形式为xx_new.js, comp的需要其自行决定
        self._js_new_path = self._get_js_new_path()

        # deps文件副本路径
        self._deps_new_path = self._get_deps_new_path()

        # 依赖项列表, 无依赖项则值为None
        self._deps = self._get_deps()

        # js/components/xx,存放组件的地方
        # PageFile的在_create_ct()中具体求出
        # CompFile的自行确定
        self._ct_path = ''

        # 插入代码的起始和结束包裹行
        self._code_start_flag = '/* ---------- dep-tool ---------- */\n'
        self._code_end_flag = '/* ---------- dep-tool-end ---------- */\n'

    def _get_js_path(self):
        re_page = re.compile(r'^page')
        re_comp = re.compile(r'^SF')
        if re_page.search(self._sf_name):
            path = self._sf_name.replace('page.', self._pages_dir + '.')
            path = os.path.join(
                sys.path[0],
                os.path.join(self._src_dir_name, os.path.sep.join(path.split('.')))
            ) + '.js'
        elif re_comp.search(self._sf_name):
            path = os.path.join(
                self._components_dir_path,
                os.path.sep.join([s for s in self._sf_name.split('.') if s != 'SF'])
            ) + '.js'
        else:
            raise Exception('无法解析self._sf_name')

        # 确保存在
        if os.path.isfile(path):
            return path
        else:
            raise Exception('未找到js文件: %s' % path)

    def _get_deps_path(self):
        path = os.path.splitext(self._js_path)[0] + '.deps'
        if not os.path.exists(path):
            path = None
        return path

    def _get_js_new_path(self):
        name, ext = os.path.splitext(self._js_path)
        return name + '_new' + ext

    def _get_deps(self):
        if not self._deps_path:
            return None
        f = open(self._deps_path, 'r', encoding='utf-8')
        re_dep = re.compile(r'^SF\..+$')
        ret = []
        try:
            lines = f.readlines()
            for line in lines:
                line = line.strip()
                if re_dep.search(line):
                    ret.append(line)
        finally:
            f.close()
            return ret

    def _get_deps_new_path(self):
        if bool(self._deps_path):
            return os.path.splitext(self._js_new_path)[0] + '.deps'
        else:
            return None

    def _format_code(self, js_path):
        f = open(js_path, 'r+', encoding='utf-8')
        try:
            lines = f.readlines()
            # 使用"(function(){})();"包裹代码
            lines = self._wrap_code_with_fn(lines)
            # 使用变量替换_sf_name并将其移至代码末端
            lines = self._replace_sf_name(lines)
            # 指针移至起始位,并清空原有文本
            f.seek(0, 0)
            f.truncate()
            f.writelines(lines)
        finally:
            f.close()

    def _wrap_code_with_fn(self, lines):
        lines.insert(0, '(function(){\n\n')
        lines.append('\n})();\n')
        return lines

    def _raise_deps(self):
        f = open(self._js_new_path, 'r+', encoding='utf-8')
        try:
            lines = f.readlines()
            variables = {} # 已占用变量名, 形如{'SF.grids.HostsGrid':'R_HostsGrid'}
            insert_var_pos = self._get_insert_var_pos(lines)

            lines_buffer = self._code_start_flag
            for dep in self._deps:
                name_list = dep.split('.')

                name_index = len(name_list) - 1
                name = name_list[name_index]
                if name == 'index':
                    name_index -= 1
                    name = name_list[name_index]

                while True:
                    if name in variables.values():
                        name_index -= 1
                        name = name_list[name_index] + name_index
                    else:
                        break

                name = 'R_' + name
                variables[dep] = name
                lines_buffer += 'var %s = %s\n' % (name, dep)
            lines_buffer += self._code_end_flag

            self._inserted_line_count = lines_buffer.count('\n')
            lines.insert(insert_var_pos, lines_buffer)
            # 用变量替换代码中的依赖
            self._replace_vars(lines, variables)
            # 指针移至起始位,并清空原有文本
            f.seek(0, 0)
            f.truncate()
            f.writelines(lines)
        finally:
            f.close()

    def _get_insert_var_pos(self, lines):
        re_fn = re.compile(r'\s*\(\s*function\s*\(\s*\)\s*\{')
        finded = False
        for i, line in enumerate(lines):
            if re_fn.search(line):
                finded = True
                return i + 1
        if not finded:
            raise Exception('未找到"(function(){"行,无法确定变量插入位置')

    def _replace_vars(self, lines, var_hash):
        print('执行变量替换: %s' % self._js_new_path)
        re_ignore = re.compile(r'var\s+R_\w+\s*=\s*SF\.')
        re_xname = re.compile(r'\w+\.xname\s*=\s*.page\..+')
        for i, line in enumerate(lines):
            for v in var_hash:
                # 形如"R_xx = SF.xx"的行不执行替换
                if v in line and not re_ignore.search(line):
                    lines[i] = line.replace(v, var_hash[v])
                    print('第%s行: %s -> %s' % (i + self._inserted_line_count, v, var_hash[v]))
                    break
            # 替换Page.xname
            if re_xname.search(line):
                lines[i] = line.replace(self._sf_name, self._sf_name + '_new')
                print('第%s行: %s -> %s' % (i + self._inserted_line_count, self._sf_name, self._sf_name + '_new'))
        print('----- done -----\n')

class PageFile(CodeFile):
    def __init__(self, page_name, src_dir_name):
        super(PageFile, self).__init__(page_name, src_dir_name)

    def _check_dir_exist(self):
        # 检查是否有js文件夹
        near_dir_list = os.listdir(sys.path[0])

        if not (self._src_dir_name in near_dir_list and os.path.isdir(self._src_dir_name)):
            raise Exception('当前位置未找到js文件夹')

        # 检查js文件夹中是否有components与pages文件夹
        js_dir_list = os.listdir(self._src_dir_name)
        if not (
            self._pages_dir in js_dir_list and
            self._components_dir in js_dir_list and
            os.path.isdir(os.path.join(self._src_dir_name, self._pages_dir)) and
            os.path.isdir(os.path.join(self._src_dir_name, self._components_dir))
        ):
            raise Exception('js文件夹中必须同时含有%s和%s文件夹' % (self._pages_dir, self._components_dir))

    # 在js/components中创建存放页面组件的文件夹
    def _create_ct(self):
        # 确定文件夹名称
        name_list = os.path.splitext(self._js_path)[0].split(os.path.sep)
        dir_name = name_list.pop()
        if dir_name == 'index':
            dir_name = name_list.pop()

        # 创建文件夹
        path = os.path.join(self._components_dir_path, dir_name)
        while os.path.exists(path):
            path += '_new'
        os.mkdir(path)
        self._ct_path = path

    def _handle_deps(self):
        self._comps = [CompFile(dep, self) for dep in self._deps]
        for comp in self._comps:
            comp.start()

    def start(self):
        self._check_dir_exist()

        copy_file(self._js_path, self._js_new_path)
        copy_file(self._deps_path, self._deps_new_path)
        self._raise_deps()

        # 在js/components中创建页面组件文件夹
        self._create_ct()

        # 创建依赖项组件对象,并对其处理
        self._handle_deps()

class CompFile(CodeFile):
    def __init__(self, sf_name, parent):
        super(CompFile, self).__init__(sf_name)

        # 指向本组件的使用者
        self._parent = parent

        # 存放依赖的文件夹名字
        self._deps_dir_name = DEPS_DIR_NAME

        # 存放本组件新js文件的文件夹路径
        self._ct_path = self._get_ct_path()

        # 新js文件路径
        self._js_new_path = os.path.join(self._ct_path, self._get_name_smartly()) + '.js'

        # 新deps文件路径
        self._deps_new_path = self._get_deps_new_path()

        # 新的sf名字,形如"SF.a.b"
        self._sf_name_new = self._get_sf_name_new()

    def _get_ct_path(self):
        # parent是page的用page的_ct_path, 否则用parent._js_path同级的deps文件夹
        if isinstance(self._parent, PageFile):
            if bool(self._deps_path):
                # 有依赖的加一层文件夹
                path = os.path.join(self._parent._ct_path, self._get_name_smartly())
                while True:
                    if os.path.exists(path):
                        path += '_new'
                    else:
                        os.mkdir(path)
                        os.mkdir(os.path.join(path, self._deps_dir_name))
                        return path
            else:
                # 没有依赖的直接放
                return self._parent._ct_path
        else:
            path = path = os.path.join(self._parent._ct_path, self._deps_dir_name)
            # 有依赖的加一层文件夹
            if bool(self._deps_path):
                path = os.path.join(path, self._get_name_smartly())
            return path

    def _get_name_smartly(self):
        return [n for n in os.path.splitext(self._js_path)[0].split(os.path.sep) if n != 'index'].pop()

    def _get_sf_name_new(self):
        return os.path.splitext(self._js_new_path)[0].replace(self._components_dir_path, 'SF').replace(os.path.sep, '.')

    # 传入形如'SF.a.b'的组件名, 返回其全路径, 可自选后缀名如.js或.deps
    def _get_comp_path(self, dep, suffix=''):
        return os.path.join(
            self._components_dir_path,
            os.path.sep.join([n for n in dep.split('.') if n != 'SF'])
        ) + suffix

    def _handle_deps(self):
        self._comps = [CompFile(dep, self) for dep in self._deps]
        for comp in self._comps:
            comp.start()

    def _replace_sf_name(self, lines):
        name = self._sf_name.split('.').pop()
        re_equal = re.compile(r'%s\s*=.+' % self._sf_name.replace('.', '\.'))  #匹配形如"SF.a.b = xx"
        for i, line in enumerate(lines):
            if re_equal.search(line):
                lines[i] = line.replace(self._sf_name, 'var %s' % name)
            elif self._sf_name in line:
                lines[i] = line.replace(self._sf_name, name)
        # 此时lines最后一项是'\n}();\n',在其前面插入'Ext.ns('..');\nSF.xx = yy'
        ns = self._sf_name_new.split('.')
        ns.pop()
        ns = '.'.join(ns)
        lines.insert(len(lines) - 1, '\nExt.ns(\'%s\');\n%s = %s;\n' % (ns, self._sf_name_new, name))
        return lines

    def _replace_vars_in_parent(self):
        # 替换deps变量
        if not self._parent._deps_new_path:
            return
        f = open(self._parent._deps_new_path, 'r+', encoding='utf-8')
        try:
            lines = f.readlines()
            for i, line in enumerate(lines):
                if line.strip() == self._sf_name:
                    lines[i] = self._sf_name_new + '\n'
                    break
            # 指针移至起始位,并清空原有文本
            f.seek(0, 0)
            f.truncate()
            f.writelines(lines)
        finally:
            f.close()

        # 替换_parent的js中的变量
        f = open(self._parent._js_new_path, 'r+', encoding='utf-8')
        try:
            lines = f.readlines()
            for i, line in enumerate(lines):
                if self._sf_name in line.strip():
                    lines[i] = line.replace(self._sf_name, self._sf_name_new)
                    break
            # 指针移至起始位,并清空原有文本
            f.seek(0, 0)
            f.truncate()
            f.writelines(lines)
        finally:
            f.close()

    def start(self):
        copy_file(self._js_path, self._js_new_path)
        self._format_code(self._js_new_path)  # 确保代码被IIFE包裹&变量替换
        self._replace_vars_in_parent()

        if bool(self._deps_path):
            copy_file(self._deps_path, self._deps_new_path)
            self._raise_deps()
            self._handle_deps()

class Deptool:
    def __init__(self):
        self._page = PageFile(PAGE_NAME, SRC_DIR_NAME)

    def start(self):
        self._page.start()

def main():
    deptool = Deptool()
    deptool.start()

if (__name__ == '__main__'):
    main()


# 풀이 방법

'''
소욜돌이 배열 만들고 범위만큼 잘라서 출력하는 문제.
1.어느정도 크기로 배열을 만들어야 하는가 -> 절대값이 큰 r1,c2,r2,c2가 결정
2.맵을 만들고 로직을 만들어 내용물을 채워놓고 범위만큼 자른다.
'''

r1, c1, r2, c2 = map(int, input().split())
max_n = max(abs(r1), abs(r2), abs(c1), abs(c2))

Map = [[0 for i in range(max_n*2+1)] for j in range(max_n*2+1)]

Map[max_n][max_n] = '1'

def solution(N, max_n, Map, count):
    if N == max_n+1:
        return

    for i in range(0, N*2):
        Map[max_n+N-1-i][max_n+N] = str(count)
        count += 1

    for i in range(0, N*2):
        Map[max_n-N][max_n+N-1-i] = str(count)
        count += 1

    for i in range(0, N*2):
        Map[max_n-N+1+i][max_n-N] = str(count)
        count += 1

    for i in range(0, N*2):
        Map[max_n+N][max_n-N+1+i] = str(count)
        count += 1

    return solution(N+1, max_n, Map, count)

solution(1, max_n, Map, 2)
for i in range(r1+max_n, r2+max_n+1):
    print(' '.join(Map[i][(c1+max_n):(c2+max_n+1)]))

백준/Python/알고파/11.24/소용돌이 예쁘게 출력하기(1022).py

소용돌이 예쁘게 출력하기(1022).py


import csv
import os
import pandas as pd

import re
import converter as conv
import cleaner as clr
import usersentencedivert as usd
import twitterhandler as twk
def dataextraction(s2):
    import tweepy

    from tweepy.streaming import StreamListener
    from tweepy import OAuthHandler
    from tweepy import Stream
    import json
    import time
    import pandas as pd

    access_token = ""
    access_secret = ""
    consumer_key = ""
    consumer_secret = ""
    auth = OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_secret)
    api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
    searchquery = s2
    users =tweepy.Cursor(api.search,q=searchquery).items()
    count = 0
    start = 0
    errorCount=0
    waitquery = 100      #this is the number of searches it will do before resting
    waittime = 2.0          # this is the length of time we tell our program to rest
    total_number = 10   #this is the total number of queries we want
    justincase = 1         #this is the number of minutes to wait just in case twitter throttles us
    text = [1] * total_number
    secondcount = 0
    idvalues = [1] * total_number
    while secondcount < total_number:
        try:
            user = next(users)
            count += 1
            if (count%waitquery == 0):
                time.sleep(waittime + 5)
        except tweepy.TweepError:
            print ("sleeping....")
            time.sleep(justincase)
            user = next(users)
        except StopIteration:
            break
        try:
            text_value = user._json['text']
            language = user._json['lang']        #print(text_value)
            print(language)
            if "RT" not in text_value:
                if language == "en":
                    text[secondcount] = text_value
                    secondcount = secondcount + 1
                    print("current saved is:")
                    percent=secondcount/2
                    print(percent)
        except UnicodeEncodeError:
            errorCount += 1
            print ("UnicodeEncodeError,errorCount ="+str(errorCount))

    print("Creating dataframe:")

    d = {"text": text}
    df = pd.DataFrame(data = d)
    if os.path.exists('sample.csv'):
        os.remove('sample.csv')
    df.to_csv('sample.csv', header=True, index=False, encoding='utf-8')

    print ("completed")
    list1=[]
    with open('sample.csv', 'r') as f:
        reader = csv.reader(f)
        list1 = list(reader)
    k=len(list1)
    list2=[]
    for i in range(k):
        list2.append(i)
    filename = "sample.csv"
    fields = ['id', 'review']
# writing to csv file
    with open(filename, 'w') as csvfile:
    # creating a csv dict writer object
        writer = csv.DictWriter(csvfile, fieldnames = fields)

    # writing headers (field names)
        writer.writeheader()

        for i in range(1,k):
            mydict =[{'id':i, 'review': list1[i]}]
            writer.writerows(mydict)

    conv.convertcsvtotsv()
    conv.refurbish()


# coding=utf-8
"""The entry point for ``interval_tree`` CLI."""
import argparse
import datetime
from random import randint

from interval_tree.classes import Interval, Node, IntervalTree

def main():
    """Parse arguments, generate a random tree, and describe it with DOT."""
    parser = argparse.ArgumentParser(
        prog='python -m interval_tree',
        description='''\
        Generate a semi-random interval tree. Generate a DOT script describing
        the entire tree, and print that description to stdout.
        ''',
    )
    parser.parse_args()

    # The interval tree is type-agnostic. To demonstrate, change this.
    gen_interval = _gen_integer_interval
    # gen_interval = _gen_date_interval

    tree = IntervalTree()
    for _ in range(10):
        tree.insert(Node(gen_interval()))
    query = gen_interval()
    results = tree.overlapping_intervals(query)
    label = (
        'label="The root node is marked in yellow.\n'
        'The interval {} overlaps the following intervals:\n'
        '{}"'
    ).format(query, ', '.join((str(interval) for interval in results)))
    print('\n'.join(('digraph interval_tree {', tree.as_dot(), label, '}')))

def _gen_integer_interval():
    integers = [randint(-50, 50) for _ in range(2)]
    integers.sort()
    return Interval(*integers)

def _gen_date_interval():
    # python3 -m venv env
    # source env/bin/activate
    # pip install faker
    # …
    # deactivate
    # rm -rf env
    from faker import Factory  # pylint:disable=import-error
    factory = Factory.create()
    dates = [
        datetime.datetime.strptime(factory.date(), '%Y-%m-%d')
        for _ in range(2)
    ]
    dates = [datetime.date(date.year, date.month, date.day) for date in dates]
    dates.sort()
    return Interval(*dates)

if __name__ == '__main__':
    exit(main())


#!/usr/bin/python
# -*- coding: utf-8 -*-
#############################################################################
#####################  K E I O  U N I V E R S I T Y  ########################
#############################################################################
################################  Python  ###################################
#############################################################################
#############################################################################
#########  Yamaguchi Lab., Department of Administration Engineering  ########
#############################################################################
#############################################################################
###                           hsr_motion.py                               ###
###                                                                       ###
###                   composed by Ayanori Yorozu                          ###
###                   at Keio Advanced Research Centers, Keio University  ###
###                                                                       ###
###                               Copyright (2016), All rights reserved.  ###
###                                                                       ###
###             c/o. Yamagughi Lab., Dept. of Administration Engineering, ###
###             3-14-1 Hiyoshi, Kohoku-ku, Yokohama 223-8522              ###
###             E-mail: yamaguti@ae.keio.ac.jp                            ###
#############################################################################
#############################################################################

################################################################################
#                                   Import                                     #
################################################################################
import hsrb_interface
import sys
import rospy
import copy
import tf
import math
import std_msgs
import sensor_msgs
import geometry_msgs
import tf.transformations
from sensor_msgs.msg    import LaserScan
from geometry_msgs.msg  import PoseStamped, Point, Quaternion
from hsrb_interface     import geometry
from geometry_msgs.msg  import Pose2D, Twist
from geometry_msgs.msg  import PoseWithCovarianceStamped
from printeps_hsr_modules.srv   import HsrNav
from printeps_hsr_modules.srv   import HsrNavResponse
from printeps_hsr_modules.srv   import HsrNav2
from printeps_hsr_modules.srv   import HsrNav2Response
from printeps_hsr_modules.srv   import HsrSay
from printeps_hsr_modules.srv   import HsrSayResponse
from printeps_hsr_modules.srv   import HsrPickUpObject
from printeps_hsr_modules.srv   import HsrPickUpObjectResponse
from printeps_hsr_modules.srv   import HsrPlaceObject
from printeps_hsr_modules.srv   import HsrPlaceObjectResponse
from printeps_hsr_modules.srv   import HsrHoldObject
from printeps_hsr_modules.srv   import HsrHoldObjectResponse
from printeps_hsr_modules.srv   import HsrReleaseObject
from printeps_hsr_modules.srv   import HsrReleaseObjectResponse

################################################################################
#                               Main Function                                  #
################################################################################
if __name__ == '__main__':
    # Initialize node ------------------------------------------------------
    rospy.init_node("hsr_demo")

    # ServiceClient ------------------------------------------------------------

        # Navigation Server ----------------------------------------------------
    nav_client  = rospy.ServiceProxy('hsr_navigation', HsrNav)

        # Navigation Server ----------------------------------------------------
    nav2_client  = rospy.ServiceProxy('hsr_navigation2', HsrNav2)

        # PickUpObject Server --------------------------------------------------------
    pick_up_client = rospy.ServiceProxy('hsr_pick_up_object', HsrPickUpObject)

        # Place Server --------------------------------------------------------
    place_client = rospy.ServiceProxy('hsr_place_object', HsrPlaceObject)

        # Hold Server --------------------------------------------------------
    hold_client = rospy.ServiceProxy('hsr_hold_object', HsrHoldObject)

        # Release Server --------------------------------------------------------
    release_client = rospy.ServiceProxy('hsr_release_object', HsrReleaseObject)

    navMotion      =    HsrNav()
    nav2Motion     =    HsrNav2()
    pickupMotion   =    HsrPickUpObject()
    placeMotion    =    HsrPlaceObject()
    holdMotion     =    HsrHoldObject()
    releaseMotion  =    HsrReleaseObject()

    # position setting ---------------------------------------------------------
    facalty=True;
    if facalty:
        #pet
        Pet                 =Pose2D()
        Pet.x               =2.70
        Pet.y               =-0.80
        Pet.theta           =-1.57

        #Table
        Table                 =Pose2D()
        Table.x               = 4.70
        Table.y               = 2.10
        Table.theta           =0
    else:
        #pet
        Pet                 =Pose2D()
        Pet.x               =0.60
        Pet.y               =-1.30
        Pet.theta           =-1.57

        #Table
        Table                 =Pose2D()
        Table.x               = 2.50
        Table.y               = 0.60
        Table.theta           = 0

        # PetFromCart
    PetFromCart         =Pose2D()
    PetFromCart.x       = Pet.x
    PetFromCart.y       = Pet.y+0.70
    PetFromCart.theta   =-1.57

        # CartFromPet
    CartFromPet         =Pose2D()
    CartFromPet.x       =Pet.x-0.10
    CartFromPet.y       =Pet.y+0.60
    CartFromPet.theta   =0

        # CartToTable
    CartToTable         =Pose2D()
    CartToTable.x       =Table.x-0.3;
    CartToTable.y       =Pet.y + 0.4
    CartToTable.theta   =0

        # CartFromTable
    CartFromTable       =Pose2D()
    CartFromTable.x     =Table.x-0.60
    CartFromTable.y     =Pet.y+0.60
    CartFromTable.theta =0

        # TableFromCart
    TableFromCart       =Pose2D()
    TableFromCart.x     =Table.x-0.60;
    TableFromCart.y     =Table.y;
    TableFromCart.theta =0

        # CartToPet
    CartToPet           =Pose2D()
    CartToPet.x         =Pet.x+0.7
    CartToPet.y         =Pet.y+0.3
    CartToPet.theta     =0

        # 0
        # PetFromCart
    Genten              =Pose2D()
    Genten.x            =0
    Genten.y            =0
    Genten.theta        =0

    # 動作 ---------------------------------------------------------------------

# phase:1 ペットボトルをカートに置く
# 1
    # 棚の前に移動する
    nav2Motion.pose=PetFromCart
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # 棚からペットボトル1をとる
    pickupMotion='Pet1'
    pick_up_client(pickupMotion)
    # カートの前に移動する
    nav2Motion.pose=CartFromPet
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートの1番に置く
    placeMotion = 'Cart3'
    place_client(placeMotion)

#2
    # 棚の前に移動する
    nav2Motion.pose=PetFromCart
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # 棚からペットボトル2をとる
    pickupMotion='Pet2'
    pick_up_client(pickupMotion)
    # カートの前に移動する
    nav2Motion.pose=CartFromPet
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートの2番に置く
    placeMotion = 'Cart4'
    place_client(placeMotion)

# phase:2 カートをテーブルの前に移動させる
    # カートの前に移動する
    nav2Motion.pose=CartFromPet
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートをつかむ
    holdMotion='Cart'
    hold_client(holdMotion)
    # テーブルの前まで移動する
    nav2Motion.pose=CartToTable
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートを離す
    releaseMotion='Cart'
    release_client(releaseMotion)

# phase:3 カートからテーブルにペットボトルを移動させる

#1
    # カートの前に移動する
    nav2Motion.pose=CartFromTable
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートの4番からペットボトルをとる
    pickupMotion='Cart4'
    pick_up_client(pickupMotion)
    # テーブルの横に移動する
    # テーブルの前に移動する
    nav2Motion.pose=TableFromCart
    nav2Motion.obstacle_avoidance=True
    nav2Motion.first_rot=True
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # テーブルの1番に置く
    placeMotion = 'Table31'
    place_client(placeMotion)

#2
    # カートの前に移動する
    nav2Motion.pose=CartFromTable
    nav2Motion.obstacle_avoidance=True
    nav2Motion.first_rot=True
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートの3番からペットボトルをとる
    pickupMotion='Cart3'
    pick_up_client(pickupMotion)
    # テーブルの横に移動する
    # テーブルの前に移動する
    nav2Motion.pose=TableFromCart
    nav2Motion.obstacle_avoidance=True
    nav2Motion.first_rot=True
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # テーブルの2番に置く
    placeMotion = 'Table32'
    place_client(placeMotion)

# phase:4 カートを棚の前に移動させる
    # カートの前に移動する
    nav2Motion.pose=CartFromTable
    nav2Motion.obstacle_avoidance=True
    nav2Motion.first_rot=True
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートをつかむ
    holdMotion='Cart'
    hold_client(holdMotion)
    # 棚の前まで移動する
    nav2Motion.pose=CartFromPet
    nav2Motion.obstacle_avoidance=False
    nav2Motion.first_rot=False
    nav2_client(nav2Motion.pose,nav2Motion.obstacle_avoidance,nav2Motion.first_rot)
    # カートを離す
    releaseMotion='Cart'
    release_client(releaseMotion)


#
#  Paranoid Pirate worker
#
#   Author: Daniel Lundin <dln(at)eintr(dot)org>
#
#   restart DEALER socket when queue restarts (timeout to receive queue heartbeat)
#   heartbeat to queue so queue unregisters this worker when unresponsive
#

import time
import sys
from random import randint
from datetime import datetime
import ctypes
import struct

from threading import Thread
from multiprocessing import Process

import zmq

Container = Thread
identities = [b'A', b'B', b'C']

HEARTBEAT = b''
cycle = 0

port = sys.argv[1]
load_duration = float(sys.argv[2])

bind_endpoint = ("tcp://*:" + port).encode()
connect_endpoint = ("tcp://192.168.0.22:" + port).encode()

def p(msg):
    pass
    print('%s   %s' % (datetime.now().strftime('%M:%S:%f')[:-3], msg))

def on_request(request, identity):
    address, control = request[:2]
    reply = [address, control]
    if control == HEARTBEAT:
        reply[1] = HEARTBEAT
        #p("I: RETURN PONG:  %s" % reply)
    else:
        reply.append(b"ACK" + control + b"-" + str(port).encode() + b"-" + identity.encode())
        # global cycle
        # cycle += 1
        # p("I: %s RETURN REPLY: %s, CYCLE=%d" % (identity, reply, cycle))
        # time.sleep(load_duration)  # Do some heavy work
    return reply

def worker_socket(worker_identity, context):
    worker = context.socket(zmq.REP)
    worker.connect("inproc://routing.ipc")
    worker.hwm = 100_000
    time.sleep(.2)  # Wait for threads to stabilize
    while 1:
        try:
            while 1:
                request = worker.recv_multipart(flags=zmq.NOBLOCK)
                # reply = on_request(request, worker_identity)
                worker.send_multipart(request, flags=zmq.NOBLOCK)
        except zmq.Again:
            time.sleep(.001)

def create_server_socket(context, bind, connect):
    server = context.socket(zmq.ROUTER)
    server.sndhwm = 600_000
    server.rcvhwm = 600_000
    server.identity = connect
    server.probe_router = 1
    server.router_mandatory = 1
    server.bind(bind)
    p("I: worker is ready at %s" % connect.decode())
    return server

context = zmq.Context(1)
server_socket = create_server_socket(context, bind_endpoint, connect_endpoint)

# router_socket = context.socket(zmq.DEALER)
# router_socket.bind("inproc://routing.ipc")
# for identity in identities:
#     Container(target=worker_socket, args=(identity.decode(), context)).start()
# time.sleep(1)  # Wait for threads to stabilize
# poller = zmq.Poller()
# poller.register(router_socket, zmq.POLLIN)
# max = randint(90, 500)

counter = tmp = 0
not_yet_started = True
start = 0
timeit = 0
request = None

# try:
#     while 1:
#         try:
#             while 1:
#                 # copy=True seems better for small messages
#                 request = server_socket.recv_multipart(flags=zmq.NOBLOCK, copy=True)
#                 if len(request) > 2:
#                     # print(request)
#                     counter += 1
#                     if not_yet_started:
#                         not_yet_started = False
#                         start = time.time()
#                     elif counter % 50_000 == 0:
#                         timeit = time.time()
#                     router_socket.send_multipart([b''] + request, flags=zmq.NOBLOCK)
#                 else:
#                     # return PONG
#                     server_socket.send_multipart(request, flags=zmq.NOBLOCK, copy=True)
#         except zmq.Again:
#             pass
#         try:
#             while 1:
#                 reply = router_socket.recv_multipart(flags=zmq.NOBLOCK)
#                 server_socket.send_multipart(reply[1:], flags=zmq.NOBLOCK)
#         except zmq.Again:
#             time.sleep(.002)
# except KeyboardInterrupt:
#     duration = timeit - start
#     print("%d requests,     %ds duration,    Average round trip cost: %d req/s " % (counter, duration, counter / duration))

# fmt = struct.Struct('I 9s')
# buffer = ctypes.create_string_buffer(fmt.size)

while 1:
    try:
        while 1:
            hostname = server_socket.recv(flags=zmq.NOBLOCK|zmq.SNDMORE, copy=True)
            request = server_socket.recv(flags=zmq.NOBLOCK, copy=True)  # copy=True seems better for small messages
            if not_yet_started:
                not_yet_started = False
                start = time.time()
            if request:
                # fmt.pack_into(buffer, 0, )
                # request_id, msg = fmt.unpack_from(request[1], 0)
                counter += 1
            server_socket.send(hostname, flags=zmq.NOBLOCK | zmq.SNDMORE)
            server_socket.send(request, flags=zmq.NOBLOCK)
            if counter % 100_000 == 0:
                print("Average round trip cost: %d requests %d, req/s " % (counter, counter / (time.time() - start)))

    except zmq.Again:
        hostname = server_socket.recv(zmq.SNDMORE)  # blocking call
        request = server_socket.recv(flags=zmq.NOBLOCK)
        if not_yet_started:
            not_yet_started = False
            start = time.time()
        if request:
            counter += 1
        server_socket.send(hostname, flags=zmq.NOBLOCK | zmq.SNDMORE)
        server_socket.send(request, flags=zmq.NOBLOCK)

# except KeyboardInterrupt:
#     duration = timeit - start
#     print("%d requests,     %ds duration,    Average round trip cost: %d req/s " % (counter, duration, counter / duration))

# while 1:
# try:
    # events = dict(poller.poll())

    # if events.get(server) == zmq.POLLIN:
    # p("I: RECEIVE REQUEST: %s" % request)
    # router.send_multipart([b''] + request)

    # if events.get(router) == zmq.POLLIN:
    #     reply = router.recv_multipart()
    #     server.send_multipart(reply[1:])
    #     p("I: RETURN REPLY: %s" % reply)

        # if cycle > max and port in ['5555','5556'] and randint(0, 50000000) == 0:
        #     p("I: Simulating CPU overload ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
        #     time.sleep(randint(2, 6))
        # if cycle > max and randint(0, 5950000) == 0:
        #     p("I: Simulating a crash")
        #     import _thread
        #     _thread.interrupt_main()
        #     break

    # except:
    #     p("I: Interrupted!!!!!!!!!!")
    #     break


import traceback
import lark

TAB = "    "

TYPE_MAP = {
	"String": "str",
	"Boolean": "bool",
	"Byte": "int",
	"Integer": "int",
	"Long": "int",
	"LongLong": "int",
	"Single": "float",
	"Double": "float",
	# Currency, Date, Variant
	}

TYPE_SUFFIX_MAP = {
	"$": "str",
	"%": "int", 	# Integer
	"&": "int", 	# Long
	"#": "float", 	# Double
	"!": "float", 	# Single
	# "@":  "float", # Currency
	}

OP_MAP = {
	"=": "==",
	"<>": "!=",
	"And": "and", 	# approximate equivalence. Python does lazy evaluation
	"AndAlso": "and",
	"Or": "or", 	# approximate equivalence. Python does lazy evaluation
	"OrElse": "or",
	"&": "+",
	"Mod": "%",
	"Is": "is",
	}

class GenerateInfos:
	def __init__(self):
		self.indent = ""
		self.option_explicit = False
		self.option_base = 0
		self.def_func_name = None # to handle return value
		self.on_error_resume_next = False
		self.on_error_goto = None
		self.with_stack = []
		self.global_vars = []
		self.vars = self.global_vars

class CustomException(Exception):
    pass

class CustomRethrowException(Exception):
    def __init__(self, message, inner_error):
        super().__init__(message)
        #self.inner_error = inner_error

def generate(ast, verbose=False):
	infos = GenerateInfos()

	src = []
	src.append("import os, sys, numpy as np")
	src.append("")
	src.append("""#sys.path.append(r"..\..\lark\examples")""")
	src.append("from vba_py_app import *")
	src.append("")

	if verbose:
		print(ast.pretty())

	generate_stmts(ast, src, infos)

	print(f"Code generated. \t #lines{len(src)}")
	return '\n'.join(src)

has_unsupported_feature = False
def unsupported_feature(msg, src, infos):
	global has_unsupported_feature
	has_unsupported_feature = True

	print(">!", msg)
	msg = f"{infos.indent}raise Exception(\"{msg}\")";
	if src is not None:
		src.append(msg)
	else:
		return src
	#assert False

def generate_stmts(ast, src, infos):
	assert get_type(ast) == "statements"

	stmts = ast.children
	if len(stmts)==0:
		src.append(f"{infos.indent}pass")
	for s in stmts:
		generate_stmt(s, src, infos)

def generate_stmt(ast, src, infos):
	try:
		generate_stmt_throws(ast, src, infos)
	except Exception as e:
		traceback.print_exc()
		if is_node(ast):
			print("\nAST:\n", ast.pretty(), "\n")
		else:
			print("\nAST is TOKEN:\n", ast, "\n")

		src.append("")
		src.append(f"{infos.indent}#!! Generation error here")
		src.append(f"{infos.indent}raise Exception('Generation error here')")
		src.append("")
		#raise

def generate_stmt_throws(ast, src, infos):
	s = ast
	t = get_type(ast)
	n = len(ast.children) if is_node(ast) else None

	# print("generate_stmt", t )
	if t == "statements":
		generate_stmts(ast, src, infos)
	elif t == "statements_inline":
		for i in range(0, n, 2):
			generate_stmt(ast.children[i], src, infos)
	elif t == "option_stmt":
		generate_option_stmt(ast, src, infos)
	elif t == "dim_stmt":
		generate_dim_stmt(ast, src, infos)
	elif t == "comment_stmt":
		txt = generate_fragment(ast, infos)
		src.append(f"{infos.indent}{txt}")
	elif t == "NEWLINE":
		src.append("")
	elif t == "function_definition_stmt":
		generate_function_definition_stmt(ast, src, infos)
	elif t == "exit_stmt":
		generate_exit_stmt(ast, src, infos)
	elif t == "sub_call_stmt":
		generate_sub_call_stmt(ast, src, infos)
	elif t == "assign_stmt":
		generate_assign_stmt(ast, src, infos)
	elif t == "if_stmt_multilines":
		generate_if_stmt(ast, src, infos)
	elif t == "if_stmt_inline":
		generate_if_stmt(ast, src, infos, inline = True)
	elif t == "for_in_stmt":
		generate_for_in_stmt(ast, src, infos)
	elif t == "for_each_stmt":
		generate_for_each_stmt(ast, src, infos)
	elif t == "while_wend_stmt":
		generate_loop_stmt(ast, src, infos, pre_condition=True, while_condition=True)
	elif t == "while_do_loop_stmts":
		generate_loop_stmt(ast, src, infos, pre_condition=True, while_condition=True)
	elif t == "do_loop_while_stmts":
		generate_loop_stmt(ast, src, infos, pre_condition=False, while_condition=True)
	elif t == "until_do_loop_stmts":
		generate_loop_stmt(ast, src, infos, pre_condition=True, while_condition=False)
	elif t == "do_loop_until_stmts":
		generate_loop_stmt(ast, src, infos, pre_condition=False, while_condition=False)
	elif t == "with_stmt":
		generate_with_stmt(ast, src, infos)
	elif t == "on_error_stmt":
		generate_on_error_stmt(ast, src, infos)
	elif t == "goto_anchor_stmt":
		generate_goto_anchor_stmt(ast, src, infos)
	elif t == "smnt_new_line":
		if n==1:
			# only new line
			pass
		else:
			# comment and newline
			txt = generate_fragment(ast.children[0], infos)
			src.append(f"{infos.indent}{txt}")
	elif t == "empty_new_line":
		src.append("")
	elif t in [ "preprocessor_if_stmt", "goto_stmt", "exit_stmt", "if_stmt_inline", "for_each_stmt" ]:
		# "with_stmt",
		unsupported_feature(f"Unsupported statement type {t}.", src, infos)
	elif t in [ "open_stmt", "print_stmt", "close_stmt" ]:
		unsupported_feature(f"Unsupported file operations (open, print, close).", src, infos)
	else:
		raise Exception(f"Unknown statement type {t}")

def generate_option_stmt(ast, src, infos):
	opt = get_text(ast.children[1])
	if opt == "Explicit":
		infos.option_explicit = True
	elif opt == "Base":
		base = get_int(ast.children[2])
		assert base==0 or base==1 	# as per VBA spec
		infos.option_base = base
	else:
		unsupported_feature(f"Unsupported Option {opt}.", src, infos)

def generate_dim_stmt(ast, src, infos):
	decls = find_nodes_by_type(ast, "dim_decl")
	tmp = []
	for decl in decls:
		var = decl.children[0]
		typ = None
		has_new = False
		range_indices = None

		# implicit type
		if get_type(var) == "TYPED_NAME" and var.value[-1] in TYPE_SUFFIX_MAP:
			typ = TYPE_SUFFIX_MAP[var.value[-1]]
			var = generate_fragment(var, infos)
		# explicit type
		xtyp = find_node_by_type(decl, "type_info")
		if xtyp:
			vb_type = generate_fragment(xtyp.children[-1], infos)
			has_new = find_node_by_type(xtyp, "NEW") is not None
			if vb_type in TYPE_MAP:
				typ = TYPE_MAP[vb_type]
			if has_new:
				typ = vb_type 	# best we can do !!

		xrng = find_node_by_type(decl, "ranges")
		xrngs = find_nodes_by_type(decl, "range")
		if xrng is not None or len(xrngs)>0:
			range_indices = []
		for rng in xrngs:
			if len(rng.children) == 1:
				range_indices.append([ infos.option_base, generate_ith_fragment(rng, 0, infos) ])
			elif len(rng.children) == 3:
				range_indices.append([ generate_ith_fragment(rng, 0, infos), generate_ith_fragment(rng, 2, infos) ])
			else:
				raise False

		if range_indices is not None:
			shape = ", ".join([ f"{rng[1]}-{rng[0]}+1" for rng in range_indices])
			offset = ", ".join([ f"{rng[0]}" for rng in range_indices])
			if typ == "str" or typ == "int" or typ == "float":
				tmp.append(f"{var} = np.ndarray(shape=({shape},), offset_isnt_what_we_need=({offset},), dtype={typ})")
			else:
				tmp.append(f"{var} = np.ndarray(shape=({shape},), offset_isnt_what_we_need=({offset},))")
		elif typ == "ArrayList":
				tmp.append(f"{var} = []")
		else:
			if typ == "str":
				tmp.append(f"{var} = \"\"")
			elif typ == "int":
				tmp.append(f"{var} = 0")
			elif typ == "float":
				tmp.append(f"{var} = 0.0")
			elif has_new:
				tmp.append(f"{var} = {typ}()")
			elif typ is None:
				tmp.append(f"{var} = None")

		infos.vars.append(var)

	src.append(f"{infos.indent}{'; '.join(tmp)}")

def generate_function_definition_stmt(ast, src, infos):
	assert get_type(ast.children[0]) == "function_or_sub"
	assert get_type(ast.children[2]) == "function_args"

	type_anotation = ""
	vb_type = generate_ith_fragment(find_node_by_type(ast, "type_info"), 1, infos)
	if vb_type in TYPE_MAP:
		type_anotation = " -> "+TYPE_MAP[vb_type]
	if get_text(ast.children[0]) == "Sub":
		type_anotation = " -> None "

	name = ast.children[1].value
	args_csv = generate_fragment(ast.children[2], infos)
	stmts = find_node_by_type(ast, "statements")

	src.append(f"def {name}({args_csv}){type_anotation}:" )
	try:
		infos.def_func_name = name
		infos.indent +=TAB
		infos.vars = [] + infos.global_vars 	# clone global scope as local one
		generate_stmts(stmts, src, infos)

		if get_text(ast.children[0]) == "Function":
			src.append(f"{infos.indent}return {infos.def_func_name}")
	finally:
		infos.def_func_name = None
		infos.indent = infos.indent[:-len(TAB)]
		infos.vars = infos.global_vars 	# restore global scope

	src.append(f"") # !!

def generate_exit_stmt(ast, src, infos):
	assert get_type(ast.children[0]) == "EXIT"
	t = get_type(ast.children[1])

	if t == "FUNCTION":
		src.append(f"{infos.indent}return {infos.def_func_name}")
	elif t == "SUB":
		src.append(f"{infos.indent}return")
	elif t == "for":
		# check which for loopwe are exiting from !!
		src.append(f"{infos.indent}break")
	else:
		unsupported_feature("Unsupported Exit {t}", src, infos)

def generate_sub_call_stmt(ast, src, infos):
	if get_type(ast.children[0]) == "call":

		if get_type(ast.children[1]) != "func_call":

			# no arguments, no parentheses, just "Call fct"
			name = generate_fragment(ast.children[1], infos)
			src.append(f"{infos.indent}{name}()")

		else:
			x = generate_func_call(ast.children[1], infos)
			src.append(f"{infos.indent}{x}");

	else:

		assert get_type(ast.children[0]) in [ "any_name", "member_access", "func_call", "with_access" ]
		#assert get_type(ast.children[1]) == "func_args_sub"

		name = generate_fragment(ast.children[0], infos)
		args_csv = generate_func_args(ast.children[1], infos)

		src.append(f"{infos.indent}{name}({args_csv})")

def generate_func_call(ast, infos):
	n = len(ast.children)

	assert get_type(ast.children[0]) in [ "any_name", "member_access", "func_call", "with_access" ]
	assert get_type(ast.children[1]) == "LPAR"
	assert get_type(ast.children[2]) == "func_args"
	assert get_type(ast.children[3]) == "RPAR"

	name = generate_fragment(ast.children[0], infos)
	array_indices =  name in infos.vars or is_builtin_array(name)	# functions can't be assigned to variables, so that must be an array
	args_csv = generate_func_args(ast.children[2], infos, array_indices=array_indices)

	if array_indices:
		return f"{name}{args_csv}"

	return f"{name}({args_csv})"

def is_builtin_array(lhs):
	if lhs.endswith(")") or lhs.endswith("]"):
		return True
	return False

def generate_func_args(ast, infos, array_indices = False):
	assert get_type(ast) == "func_args" or get_type(ast) == "func_args_sub"

	if len(ast.children)==0:
		return ""

	args = []
	prev_is_sep = True
	for arg in ast.children:
		if get_type(arg) == "COMMA":
			if prev_is_sep:
				args.append("None")
			else:
				prev_is_sep = True
		else:
			args.append(generate_fragment(arg, infos))
			prev_is_sep = False
	if prev_is_sep:
		# ending with comma
		args.append("None")

	if array_indices:
		return "".join([ f"[{a}]" for a in args ])
	return ", ".join(args)

def generate_assign_stmt(ast, src, infos):
	if get_type(ast.children[1]) == "EQUAL":
		k=0
	elif get_type(ast.children[2]) == "EQUAL":
		k=1
	else:
		assert False

	var = generate_fragment(ast.children[k+0], infos)
	val = generate_fragment(ast.children[k+2], infos)

	if var == infos.def_func_name:
		# !! if we assign to the name of the function then we can't have recursive code
		# !! if we rename, we have to rename every assignment and evaluation
		pass
	else:
		infos.vars.append(var)

	src.append(f"{infos.indent}{var} = {val}")

def generate_if_stmt(ast, src, infos, inline=False):
	n = len(ast.children)

	for k in range(0, n, 4 if inline else 5):
		t = get_type(ast.children[k+0])
		if t == "if" or t == "elseif":
			expr = generate_fragment(ast.children[k+1], infos)
			stmts = ast.children[k+(3 if inline else 4)]

			ie = "if" if k==0 else "elif"
			src.append(f"{infos.indent}{ie} {expr}:")
			try:
				infos.indent +=TAB
				generate_stmt(stmts, src, infos)
			finally:
				infos.indent = infos.indent[:-len(TAB)]
		elif t == "else" :
			stmts = ast.children[k+(1 if inline else 2)]

			src.append(f"{infos.indent}else:")
			try:
				infos.indent +=TAB
				generate_stmt(stmts, src, infos)
			finally:
				infos.indent = infos.indent[:-len(TAB)]
		elif t == "end":
			pass
		else:
			assert False

def generate_for_in_stmt(ast, src, infos):
	n = len(ast.children)

	assert get_type(ast.children[0]) == "for"
	assert get_type(ast.children[2]) == "EQUAL"
	assert get_type(ast.children[4]) == "to"

	i  = generate_fragment(ast.children[1], infos)
	i0 = generate_fragment(ast.children[3], infos)
	i1 = generate_fragment(ast.children[5], infos)
	di = generate_ith_fragment(find_node_by_type(ast, "for_in_step"), 1, infos)
	stmts = find_node_by_type(ast, "statements")

	if di is None :
		src.append(f"{infos.indent}for {i} in range({i0}, {i1}):")
	else:
		src.append(f"{infos.indent}for {i} in range({i0}, {i1}, {di}):")
	try:
		infos.indent +=TAB
		generate_stmts(stmts, src, infos)
	finally:
		infos.indent = infos.indent[:-len(TAB)]

def generate_for_each_stmt(ast, src, infos):
	n = len(ast.children)

	assert get_type(ast.children[0]) == "for"
	assert get_type(ast.children[1]) == "each"
	assert get_type(ast.children[3]) == "in"

	k  = generate_fragment(ast.children[2], infos)
	v = generate_fragment(ast.children[4], infos)
	stmts = find_node_by_type(ast, "statements")

	src.append(f"{infos.indent}for {k} in {v}:")
	try:
		infos.indent +=TAB
		generate_stmts(stmts, src, infos)
	finally:
		infos.indent = infos.indent[:-len(TAB)]

def generate_loop_stmt(ast, src, infos, pre_condition, while_condition):
	cond = find_node_by_type(ast, "while_condition" if while_condition else "until_condition")
	stmts = find_node_by_type(ast, "statements")

	cond = generate_fragment(cond.children[1], infos)

	if pre_condition:
		if while_condition:
			src.append(f"{infos.indent}while {cond}:")
		else:
			src.append(f"{infos.indent}while not ({cond}):")
	else:
		src.append(f"{infos.indent}while True:")

	try:
		infos.indent +=TAB
		generate_stmts(stmts, src, infos)
		if not pre_condition:
			if while_condition:
				src.append(f"{infos.indent}if not({cond}):")
				src.append(f"{infos.indent}{TAB}break")
			else:
				src.append(f"{infos.indent}if {cond}:")
				src.append(f"{infos.indent}{TAB}break")
	finally:
		infos.indent = infos.indent[:-len(TAB)]

def generate_with_stmt(ast, src, infos):
	n = len(ast.children)

	assert get_type(ast.children[0]) == "with"

	var = f"__x{len(src)+1}"
	val  = generate_fragment(ast.children[1], infos)
	stmts = find_node_by_type(ast, "statements")

	src.append(f"{infos.indent}with {val} as {var}:")
	try:
		infos.with_stack.append(var)
		infos.indent +=TAB
		generate_stmts(stmts, src, infos)
	finally:
		infos.indent = infos.indent[:-len(TAB)]

def generate_with_access(ast, infos):
	n = len(ast.children)

	assert n == 2
	assert get_type(ast.children[0]) == "WITH_PREFIX"

	object = infos.with_stack[-1]
	member = generate_fragment(ast.children[1], infos)

	return f"{object}.{member}"

def generate_on_error_stmt(ast, src, infos):
	action = get_text(ast.children[2])
	tag = get_text(ast.children[3])
	if action == "Resume":
		assert tag == "next"
		infos.on_error_resume_next = True
		infos.on_error_goto = None
	elif action == "GoTo":
		infos.on_error_resume_next = False
		if tag == "0" or tag == 0:
			infos.on_error_goto = None
		else:
			src.append(f"{infos.indent}try:")
			infos.indent +=TAB
			infos.on_error_goto = ast.children[3].value
	else:
		assert False

def generate_goto_anchor_stmt(ast, src, infos):
	tag = generate_fragment(ast.children[0], infos)
	if infos.on_error_goto is not None:
		if infos.on_error_goto == tag:
			# matching On Error Goto Xyz
			infos.indent = infos.indent[:-len(TAB)]
			infos.on_error_goto = None
			src.append(f"{infos.indent}finally:")
			src.append(f"{infos.indent}{TAB}pass")
		else:
			print(infos.on_error_goto, "<>", tag)
			assert False
	else:
		src.append(f"{infos.indent}# Goto tag :{tag}")

def generate_ith_fragment(ast, ith, infos):
	if ast is None: return None
	return generate_fragment(ast.children[ith], infos)

# generate expression fragments
def generate_fragment(ast, infos):
	if ast is None: return None

	t = get_type(ast)
	n = len(ast.children) if is_node(ast) else None
	if t == "NUMBER":
		return ast.value
	elif t == "VB_STRING":
		txt = ast.value[1:-1]
		txt= txt.replace('""', '"')
		txt= txt.replace('\\', '\\\\').replace('"', '\\"')
		return f'"{txt}"'
	elif t == "NAME":
		return ast.value
	elif t == "TYPED_NAME":
		var = ast.value
		if var[-1] in TYPE_SUFFIX_MAP:
			var = var[:-1] 	# ignoring the type suffix
		return var
	elif t == "any_name":
		assert n==1
		return generate_fragment(ast.children[0], infos)
	elif t == "with_access":
		return generate_with_access(ast, infos)
	elif t == "comment_stmt":
		assert len(ast.children)==1
		txt = get_text(ast)
		txt = txt[1:].strip()
		return f"# {txt}"
	elif t == "function_args":
		return ", ".join([ generate_fragment(arg, infos) for arg in ast.children ])
	elif t == "function_arg":
		name = generate_fragment(ast.children[0], infos)

		type_anotation = ""
		vb_type = generate_ith_fragment(find_node_by_type(ast, "type_info"), 1, infos)
		if vb_type in TYPE_MAP:
			type_anotation = " : "+TYPE_MAP[vb_type]

		default_value = generate_ith_fragment(find_node_by_type(ast, "default_value"), 1, infos)
		if default_value is None:
			default_value = ""
		else:
			default_value = f" = {default_value}"

		return f"{name}{type_anotation}{default_value}"
	elif t == "func_call":
		return generate_func_call(ast, infos)
	elif t == "func_arg":
		if n==1:
			return generate_fragment(ast.children[0], infos)
		elif n==2:
			return generate_fragment(ast.children[0], infos) + " = " + generate_fragment(ast.children[1], infos)
		else:
			assert False
	elif t == "member_access":
		assert len(ast.children)==2
		return generate_fragment(ast.children[0], infos) + "." + generate_fragment(ast.children[1], infos)
	elif t == "expr_binary":
		assert n==3
		op = ast.children[1].value
		lhs = generate_fragment(ast.children[0], infos)
		rhs = generate_fragment(ast.children[2], infos)

		if op in OP_MAP:
			op = OP_MAP[op]
		if op in [ "Like", "Eqv", "Imp" ]:
			unsupported_feature(f"Unsupported {op} operator.", None, infos)
		else:
			return  f"{lhs} {op} {rhs}"
	elif t == "expr_unary":
		assert n==2
		op = get_text(ast.children[0])
		arg = generate_fragment(ast.children[1], infos)

		if op == "Not":
			op = "not"
		return  f"{op} {arg}"
	elif t == "type_expr":
		if n==1:
			return ast.children[0].value
		elif n==3:
			return ast.children[0].value + "." + ast.children[2].value
		else:
			assert False
	else:
		raise Exception(f"Unknown expression type {t}")

def get_type(ast):
	if is_node(ast):
		return ast.data
	else:
		return ast.type

def get_text(ast):
	if is_node(ast):
		n = len(ast.children)
		if n == 0: return ast.data
		if n == 1: return ast.children[0].value
		assert False
	else:
		return ast.value

def get_int(ast):
	return int(get_text(ast))

def is_node(ast):
	return isinstance(ast, lark.tree.Tree)

def is_token(ast):
	return isinstance(ast, lark.lexer.Token)

def find_node_by_type(ast, data_type):
	found = None
	for child in ast.children:
		if get_type(child)== data_type:
			assert found is None
			found = child
	return found

def find_nodes_by_type(ast, data_type):
	# recursive !!
	tmp = ast.find_data(data_type)
	tmp = list(tmp)
	return tmp

if __name__ == '__main__':
	import vba_parser as p
	test_file = r"vba_demo_input.bas"
	#test_file = r"..\..\xjs\vba\modJsonStringify.bas"
	src = p.transpile_one(test_file, verbose=False, generate=True)
	print()
	print(src)