from fpdf import FPDF
from pathlib import Path
from tkinter import END, Tk, Canvas, Entry, Button, PhotoImage, Toplevel, Label, StringVar, OptionMenu
import datetime
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
import os

today = datetime.date.today().strftime("%d/%m/%Y")

OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path("./assets")

def relative_to_assets(path: str) -> Path:
    return ASSETS_PATH / Path(path)

#Lists start
billing_list = []
shipping_list = []
invoice_date_duedate_list = []
seller_details_list = []
own_company_name = []
inventory = ['select an item','custom item']
item_list = []
#Lists end

#Read me start
def open_readme():
    os.system("open " + "README.txt")
#Read me end

#Loading inventory start
inventory_exel = pd.read_excel('inventory.xlsx')
item_row_len = len(inventory_exel['Item Name'])
for i in range(item_row_len):
    inventory.append(inventory_exel['Item Name'][i])
#Loading inventory end

def print_seller_details():

    #Grabbing details for printing start
    street_address = seller_details_list[0]
    ciy_state_zip = seller_details_list[1]
    phone = seller_details_list[2]
    email_address = seller_details_list[3]
    website = seller_details_list[4]
    gst_no = seller_details_list[5]
    invoice_no = f'Invoice No   {invoice_date_duedate_list[1]}'
    bill_reciepient_name = billing_list[0]
    bill_company_name = billing_list[1]
    bill_street_address = billing_list[2]
    bill_city_state_zip = billing_list[3]

    bill_phone = billing_list[4]
    ship_reciepient_name = shipping_list[0]
    ship_company_name = shipping_list[1]
    ship_street_address = shipping_list[2]
    ship_city_state_zip = shipping_list[3]
    ship_phone = shipping_list[4]
    subtotal_print = entry_4.get()
    discount_print = entry_3.get()
    tax_print = entry_2.get()
    total_print = entry_1.get()
    #Grabbing details for printing end

    #Declraing PDF Class start
    class PDF(FPDF):

        def header(self):
            # Apple Font
            self.image('logo.png', 25, 21, 10)
            self.ln(20)
            self.set_font('helvetica', '', 25)
            self.set_text_color(55, 55, 55)
            self.cell(26)
            self.cell(0, 0, own_company_name[0], border=False, ln=0, align='')

            # Invoice Font
            self.set_font('helvetica', '', 35)
            self.set_text_color(137, 137, 137)
            title_w = self.get_string_width('Invoice') + 26
            doc_w = self.w
            self.set_x(doc_w - title_w)
            self.cell(0, 0, 'Invoice', border=False, ln=1)

        def footer(self):
            self.set_y(-15)
            doc_w = self.w
            logo_position = (doc_w - 5) // 2
            self.image('logo.png', logo_position, 260, 5)
            self.set_font('helvetica', '', 10)
            self.set_text_color(0, 132, 255)
            self.cell(0, 10, website, align='C', link=website)
    #Declraing PDF Class end

    #PDF Initialization start
    pdf = PDF('P','mm','Letter')
    pdf.set_auto_page_break(auto=True, margin=15)
    pdf.add_page()
    doc_w = pdf.w
    #PDF Initialization end

    #Print Seller Detials start
    pdf.set_font('helvetica','',13)
    pdf.set_text_color(130,130,130)
    pdf.ln(10)
    pdf.cell(15)
    pdf.cell(0,0,f'{street_address}')
    pdf.ln(6)
    pdf.cell(15)
    pdf.cell(0,0,f'{ciy_state_zip}')
    pdf.set_x(doc_w - pdf.get_string_width(f'GSTIN   {gst_no}') - 26)
    pdf.cell(0,0,f'GSTIN   {gst_no}',align='L')
    pdf.ln(6)
    pdf.cell(15)
    pdf.cell(0,0,f'{phone}')
    pdf.set_x(doc_w - pdf.get_string_width(f'Date   {today}') - 26)
    pdf.cell(0,0,f'Date   {today}',align='L')
    pdf.ln(6)
    pdf.cell(15)
    pdf.cell(0,0,f'{email_address}')
    pdf.set_x(doc_w - pdf.get_string_width(f'{invoice_no}') - 26)
    pdf.cell(0,0,f'{invoice_no}',align='L')
    pdf.ln(6)
    pdf.cell(15)
    pdf.cell(0,0,f'{website}')
    pdf.set_x(doc_w - pdf.get_string_width(f'Due date   {today}') - 26)
    pdf.cell(0,0,f'Due date   {today}',align='L')
    #Print Seller Detials end

    #Billing and Shipping Details start
    pdf.ln(15)
    pdf.cell(15)
    pdf.set_text_color(60,60,60)
    pdf.set_fill_color(250,250,250)
    pdf.set_font('helvetica','',12)
    pdf.cell(81.15,7,'      BILLED TO',fill=1)
    pdf.cell(0.5)
    pdf.cell(81.15,7,'      SHIPPED TO',fill=1)
    pdf.ln()
    pdf.cell(15)
    pdf.set_font('helvetica','',10)
    pdf.set_text_color(130,130,130)
    pdf.cell(81.15,6,f'       {bill_reciepient_name}',fill=1)
    pdf.cell(0.5)
    pdf.cell(81.15,6,f'       {ship_reciepient_name}',fill=1)
    pdf.ln()
    pdf.cell(15)
    pdf.cell(81.15,6,f'       {bill_company_name}',fill=1)
    pdf.cell(0.5)
    pdf.cell(81.15,6,f'       {ship_company_name}',fill=1)
    pdf.ln()
    pdf.cell(15)
    pdf.cell(81.15,6,f'       {bill_street_address}',fill=1)
    pdf.cell(0.5)
    pdf.cell(81.15,6,f'       {ship_street_address}',fill=1)
    pdf.ln()
    pdf.cell(15)
    pdf.cell(81.15,6,f'       {bill_city_state_zip}',fill=1)
    pdf.cell(0.5)
    pdf.cell(81.15,6,f'       {ship_city_state_zip}',fill=1)
    pdf.ln()
    pdf.cell(15)
    pdf.cell(81.15,6,f'       {bill_phone}',fill=1)
    pdf.cell(0.5)
    pdf.cell(81.15,6,f'       {ship_phone}',fill=1)
    #Billing and Shipping Details end

    #Description Quantity UnitPrice Amount Printing start
    pdf.ln(15)
    pdf.cell(15)
    pdf.set_text_color(60,60,60)
    pdf.cell(98.34,6,'   Description',fill=1)
    pdf.set_text_color(130,130,130)
    pdf.cell(9.365714285714287,6,'Qty',align='C',fill=1)
    pdf.cell(28.09714285714286,6,'Unit Price',align='C',fill=1)
    pdf.cell(28.09714285714286,6,'Amount',align='C',fill=1)
    #Description Quantity UnitPrice Amount Printing end

    #Bill Items
    for item in item_list:
        print_item = item[0]
        print_quantity = item[1]
        print_unit_price = item[2]
        print_amount = print_quantity*print_unit_price
        pdf.ln()
        pdf.cell(15)
        pdf.set_text_color(60,60,60)
        pdf.cell(98.34,6,f'   {print_item}',fill=1)
        pdf.set_text_color(130,130,130)
        pdf.cell(9.365714285714287,6,f'{print_quantity}',align='C',fill=1)
        pdf.cell(28.09714285714286,6,f'{print_unit_price}',align='C',fill=1)
        pdf.cell(28.09714285714286,6,f'{print_amount}',align='C',fill=1)
    item_list_len = len(item_list)
    if item_list_len<14:
        empty_print = (14-item_list_len)*7
        pdf.ln(empty_print)

    #Subtotal Discount Tax Total printing start
    pdf.ln()
    pdf.cell(122.7057142857143)
    pdf.cell(28.09714285714286,6,'Subtotal',align='R')
    pdf.set_font('helvetica','B',10)
    pdf.set_text_color(44,44,46)
    pdf.cell(28.09714285714286,6,f'{round(float(subtotal_print),2)}',align='R')

    pdf.ln()
    pdf.cell(122.7057142857143)
    pdf.set_font('helvetica','',10)
    pdf.set_text_color(130,130,130)
    pdf.cell(28.09714285714286,6,'Discount',align='R')
    pdf.set_font('helvetica','B',10)
    pdf.set_text_color(44,44,46)
    pdf.cell(28.09714285714286,6,f'{round(float(discount_print),2)}',align='R')

    pdf.ln()
    pdf.cell(122.7057142857143)
    pdf.set_font('helvetica','',10)
    pdf.set_text_color(130,130,130)
    pdf.cell(28.09714285714286,6,'Tax',align='R')
    pdf.set_font('helvetica','B',10)
    pdf.set_text_color(44,44,46)
    pdf.cell(28.09714285714286,6,f'{round(float(tax_print),2)}',align='R')

    pdf.ln()
    pdf.cell(122.7057142857143)
    pdf.set_font('helvetica','',10)
    pdf.set_text_color(130,130,130)
    pdf.cell(28.09714285714286,6,'Total',align='R')
    pdf.set_font('helvetica','B',10)
    pdf.set_text_color(44,44,46)
    pdf.cell(28.09714285714286,6,f'{round(float(total_print),2)}',align='R')
    #Subtotal Discount Tax Total printing end

    #PDF output start
    pdf.output('invoice.pdf')
    #PDF output end

#Getting details from gui start
def get_item_details():

    item = ''
    quantity = ''
    unit_price = ''

    if variable.get() != 'select an item':
        item = entry_8.get()

    try:
        quantity = eval(entry_7.get())
        unit_price = eval(entry_6.get())
    except:
        quantiy = ''
        unit_price = ''

    if item != '' and quantity != '' and unit_price != '':
        item_obj = [item,quantity,unit_price]
        item_list.append(item_obj)
    print(item_list)

    subtotal = 0
    for item in item_list:
        subtotal += item[1]*item[2]
    entry_4.delete(0,END)
    entry_4.insert(0,subtotal)

    discount_decimal = entry_23.get()
    discount_decimal = discount_decimal.replace('%','')
    if discount_decimal == 0 or discount_decimal == '':
        entry_3.delete(0,END)
        entry_3.insert(0,'NA')
    else:
        discount_price = subtotal*((eval(discount_decimal))/100)
        entry_3.delete(0,END)
        entry_3.insert(0,discount_price)

    tax_decimal = entry_22.get()
    tax_decimal = tax_decimal.replace('%','')
    if tax_decimal == 0 or tax_decimal == '':
        entry_2.delete(0,END)
        entry_2.insert(0,'NA')
    else:
        if entry_3.get() == 'NA':
            tax_price = subtotal*((eval(tax_decimal))/100)
        else:
            tax_price = (subtotal-discount_price)*((eval(tax_decimal))/100)
        entry_2.delete(0,END)
        entry_2.insert(0,tax_price)

    if entry_2.get() == 'NA' and entry_3.get() == 'NA':
        total = subtotal
    elif entry_2.get() == 'NA':
        total = subtotal-discount_price
    elif entry_3.get() == 'NA':
        total = subtotal+tax_price
    else:
        total = subtotal-discount_price+tax_price
    entry_1.delete(0,END)
    entry_1.insert(0,total)

    variable.set(inventory[0])
    entry_7.delete(0,END)
    entry_6.delete(0,END)
#Getting details from gui start

#Setting item start
def set_item():
    if variable.get() == 'custom item':
        pass
    elif variable.get() != 'select an item':
        entry_8.delete(0,END)
        entry_8.insert(0,variable.get())
    else:
        entry_8.delete(0,END)
    window.after(1,set_item)
#Setting item end

#Setting amount start
def set_amount():
    try:
        amount = eval(entry_7.get())*eval(entry_6.get())
        entry_5.delete(0,END)
        entry_5.insert(0,amount)
    except:
        entry_5.delete(0,END)
    finally:
        window.after(1, set_amount)
#Setting amount end

#Getting billing and shipping details start
def get_billing_shipping():

    billing_list.clear()
    billing_list.append(entry_9.get())
    billing_list.append(entry_10.get())
    billing_list.append(entry_11.get())
    billing_list.append(entry_12.get())
    billing_list.append(entry_13.get())

    shipping_list.clear()
    shipping_list.append(entry_14.get())
    shipping_list.append(entry_15.get())
    shipping_list.append(entry_16.get())
    shipping_list.append(entry_17.get())
    shipping_list.append(entry_18.get())

    invoice_date_duedate_list.clear()
    invoice_date_duedate_list.append(entry_19.get())
    invoice_date_duedate_list.append(entry_20.get())
    invoice_date_duedate_list.append(entry_21.get())

    print(billing_list)
    print(shipping_list)
    print(invoice_date_duedate_list)
#Getting billing and shipping details start

#pop-up window start
def ocm():
    global pop
    pop = Toplevel(window)
    pop.geometry("332x107")
    pop.configure(bg = "#FFFFFF")
    pop.title("Seller Details")

    #text box start
    pop_entry_1 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_1.insert(0,"type here")
    pop_entry_1.place(
        x=23.0,
        y=41.0,
        width=286.0,
        height=23.0
    )
    #text box end

    #Button Start
    button_1 = Button(
        pop,
        borderwidth=0,
        bg='white',
        activebackground='black',
        fg='black',
        activeforeground='black',
        text='save',
        command=lambda:get_own_company_name()
    )
    button_1.place(
        x=118.0,
        y=73.0,
        width=96.0,
        height=25.0
    )
    #Button End

    #Text start(don't edit)
    pop_label = Label(pop,
                text="Enter your comany name",
                bg="white",
                fg="#0336FF",
                font=('Arial Bold', 18 * -1)
                )
    pop_label.place(x=20,y=5)
    #Text end(don't edit)

    def get_own_company_name():
        own_company_name.clear()
        own_company_name.append(pop_entry_1.get())
        pop.withdraw()
        print(own_company_name)
#pop-up window end

#pop-up window start
def sd():
    global pop
    pop = Toplevel(window)
    pop.geometry("332x277")
    pop.configure(bg = "#FFFFFF")
    pop.title("Seller Details")

    #Seller Street Address start
    pop_entry_1 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_1.insert(0,"Street Address")
    pop_entry_1.place(
        x=23.0,
        y=41.0,
        width=286.0,
        height=23.0
    )
    #Seller Street Address end

    #Seller City, State, Zip start
    pop_entry_2 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_2.insert(0,"City, State, Zip")
    pop_entry_2.place(
        x=23.0,
        y=75.0,
        width=286.0,
        height=23.0
    )
    #Seller City, State, Zip end

    #Seller Phone start
    pop_entry_3 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_3.insert(0,"Phone")
    pop_entry_3.place(
        x=23.0,
        y=109.0,
        width=286.0,
        height=23.0
    )
    #Seller Phone end

    #Seller Email start
    pop_entry_4 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_4.insert(0,"Email")
    pop_entry_4.place(
        x=23.0,
        y=143.0,
        width=286.0,
        height=23.0
    )
    #Seller Email end

    #Seller Website start
    pop_entry_5 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_5.insert(0,"Website")
    pop_entry_5.place(
        x=23.0,
        y=177.0,
        width=286.0,
        height=23.0
    )
    #Seller Website end

    #Seller GSTIN Start
    pop_entry_6 = Entry(
        pop,
        bd=0,
        bg="#F0F0F0",
        highlightthickness=0,
        font=('Arial 16'),
        fg='black'
    )
    pop_entry_6.insert(0,"GSTIN")
    pop_entry_6.place(
        x=23.0,
        y=211.0,
        width=286.0,
        height=23.0
    )
    #Seller GSTIN end

    #Button Start
    button_1 = Button(
        pop,
        borderwidth=0,
        bg='white',
        activebackground='black',
        fg='black',
        activeforeground='black',
        text='save',
        command=lambda:get_seller_details()
    )
    button_1.place(
        x=118.0,
        y=243.0,
        width=96.0,
        height=25.0
    )
    #Button End

    #Text start(don't edit)
    pop_label = Label(pop,
                text="Seller Details",
                bg="white",
                fg="#0336FF",
                font=('Arial Bold', 18 * -1)
                )
    pop_label.place(x=20,y=5)
    #Text end(don't edit)

    def get_seller_details():
        seller_details_list.clear()
        seller_details_list.append(pop_entry_1.get())
        seller_details_list.append(pop_entry_2.get())
        seller_details_list.append(pop_entry_3.get())
        seller_details_list.append(pop_entry_4.get())
        seller_details_list.append(pop_entry_5.get())
        seller_details_list.append(pop_entry_6.get())
        pop.withdraw()
        print(seller_details_list)
#pop-up window end

#Window start
window = Tk()
window.geometry("866x768")
window.configure(bg = "#FFFFFF")
window.title("Instarts")
#Window end

#Canvas start
#Canvas created
canvas = Canvas(
    window,
    bg = "#FFFFFF",
    height = 768,
    width = 866,
    bd = 0,
    highlightthickness = 0,
    relief = "ridge"
)
canvas.place(x = 0, y = 0)
#White background rectangle created
canvas.create_rectangle(
    0.0,
    0.0,
    724.0,
    768.0,
    fill="#FFFFFF",
    outline="")
#Blue background rectangle created
canvas.create_rectangle(
    724.0,
    0.0,
    866.0,
    768.0,
    fill="#0336FF",
    outline="")
#Canvas end

#Total display box start
entry_1 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=("Arial 18"),
    fg='black',
    justify='right'
)
entry_1.place(
    x=544.0,
    y=671.0,
    width=150.0,
    height=19.0
)
#Total display box end

#Taxes display box start
entry_2 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=("Arial 18"),
    fg='black',
    justify='right'
)
entry_2.place(
    x=544.0,
    y=627.0,
    width=150.0,
    height=19.0
)
#Taxes dislpay box end

#Discount dislpay box start
entry_3 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=("Arial 18"),
    fg='black',
    justify='right'
)
entry_3.place(
    x=544.0,
    y=593.0,
    width=152.0,
    height=19.0
)
#Discount dislpay box end

#Subtotal display box start
entry_4 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=("Arial 18"),
    fg='black',
    justify='right'
)
entry_4.place(
    x=544.0,
    y=563.0,
    width=150.0,
    height=19.0
)
#Subtotal display box end

#Amount display box start
entry_5 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=("Arial 16"),
    fg='black',
)
entry_5.place(
    x=631.0,
    y=494.0,
    width=63.0,
    height=23.0
)
#Amount display box end

#Unit price start
entry_image_6 = PhotoImage(
    file=relative_to_assets("entry_6.png"))
entry_bg_6 = canvas.create_image(
    545.5,
    504.50000000000006,
    image=entry_image_6
)
entry_6 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=("Arial 16"),
    fg='black'
)
entry_6.place(
    x=514.0,
    y=494.0,
    width=63.0,
    height=23.0
)
#Unit price end

#Quantity start
entry_image_7 = PhotoImage(
    file=relative_to_assets("entry_7.png"))
entry_bg_7 = canvas.create_image(
    426.0,
    504.50000000000006,
    image=entry_image_7
)
entry_7 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=("Arial 16"),
    fg='black'
)
entry_7.place(
    x=400.0,
    y=494.0,
    width=52.0,
    height=23.0
)
#Quantity end

#Item start
entry_image_8 = PhotoImage(
    file=relative_to_assets("entry_8.png"))
entry_bg_8 = canvas.create_image(
    181.0,
    504.50000000000006,
    image=entry_image_8
)
entry_8 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=("Arial 16"),
    fg='black'
)
entry_8.place(
    x=38.0,
    y=494.0,
    width=286.0,
    height=23.0
)
#Item end

variable = StringVar(window)
variable.set(inventory[0]) # default value
w = OptionMenu(window, variable, *inventory)
w.place(x=30.0,y=465.0)
entry_8.insert(0,variable.get())

#Bill Recipient start
entry_image_9 = PhotoImage(
    file=relative_to_assets("entry_9.png"))
entry_bg_9 = canvas.create_image(
    181.0,
    227.50000000000006,
    image=entry_image_9
)
entry_9 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_9.insert(0,"Reciepient name")
entry_9.place(
    x=38.0,
    y=217.0,
    width=286.0,
    height=23.0
)
#Bill Recipient end

#Bill company start
entry_image_10 = PhotoImage(
    file=relative_to_assets("entry_10.png"))
entry_bg_10 = canvas.create_image(
    181.0,
    261.50000000000006,
    image=entry_image_10
)
entry_10 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_10.insert(0,"Company name")
entry_10.place(
    x=38.0,
    y=251.0,
    width=286.0,
    height=23.0
)
#Bill company end

#Bill Street Address start
entry_image_11 = PhotoImage(
    file=relative_to_assets("entry_11.png"))
entry_bg_11 = canvas.create_image(
    181.0,
    295.50000000000006,
    image=entry_image_11
)
entry_11 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_11.insert(0,"Street address")
entry_11.place(
    x=38.0,
    y=285.0,
    width=286.0,
    height=23.0
)
#Bill Street Address end

#Bill City, State, Zip start
entry_image_12 = PhotoImage(
    file=relative_to_assets("entry_12.png"))
entry_bg_12 = canvas.create_image(
    181.0,
    329.50000000000006,
    image=entry_image_12
)
entry_12 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_12.insert(0,"City,State,Zip")
entry_12.place(
    x=38.0,
    y=319.0,
    width=286.0,
    height=23.0
)
#Bill City, State, Zip end

#Bill Phone start
entry_image_13 = PhotoImage(
    file=relative_to_assets("entry_13.png"))
entry_bg_13 = canvas.create_image(
    181.0,
    363.50000000000006,
    image=entry_image_13
)
entry_13 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_13.insert(0,"Phone")
entry_13.place(
    x=38.0,
    y=353.0,
    width=286.0,
    height=23.0
)
#Bill Phone end

#Ship Recipient start
entry_image_14 = PhotoImage(
    file=relative_to_assets("entry_14.png"))
entry_bg_14 = canvas.create_image(
    543.0,
    227.50000000000006,
    image=entry_image_14
)
entry_14 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_14.insert(0,"Reciepient name")
entry_14.place(
    x=400.0,
    y=217.0,
    width=286.0,
    height=23.0
)
#Ship Recipient end

#Ship Comapany start
entry_image_15 = PhotoImage(
    file=relative_to_assets("entry_15.png"))
entry_bg_15 = canvas.create_image(
    543.0,
    261.50000000000006,
    image=entry_image_15
)
entry_15 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_15.insert(0,"Company name")
entry_15.place(
    x=400.0,
    y=251.0,
    width=286.0,
    height=23.0
)
#Ship Comapany end

#Ship Street Address start
entry_image_16 = PhotoImage(
    file=relative_to_assets("entry_16.png"))
entry_bg_16 = canvas.create_image(
    543.0,
    295.50000000000006,
    image=entry_image_16
)
entry_16 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_16.insert(0,"Street Address")
entry_16.place(
    x=400.0,
    y=285.0,
    width=286.0,
    height=23.0
)
#Ship Street Address end

#Ship City, State, Zip start
entry_image_17 = PhotoImage(
    file=relative_to_assets("entry_17.png"))
entry_bg_17 = canvas.create_image(
    543.0,
    329.50000000000006,
    image=entry_image_17
)
entry_17 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_17.insert(0,"City,State,Zip")
entry_17.place(
    x=400.0,
    y=319.0,
    width=286.0,
    height=23.0
)
#Ship City, State ,Zip end

#Ship Phone start
entry_image_18 = PhotoImage(
    file=relative_to_assets("entry_18.png"))
entry_bg_18 = canvas.create_image(
    543.0,
    363.50000000000006,
    image=entry_image_18
)
entry_18 = Entry(
    bd=0,
    bg="#F0F0F0",
    highlightthickness=0,
    font=('Arial 16'),
    fg='black'
)
entry_18.insert(0,"Phone")
entry_18.place(
    x=400.0,
    y=353,
    width=286.0,
    height=23.0
)
#Ship Phone end

#Instarts name tag start
canvas.create_text(
    30.0,
    23.000000000000057,
    anchor="nw",
    text="Instarts",
    fill="#000000",
    font=("Arial Bold", 34 * -1)
)
#Instarts name tag end

#Date start
entry_image_19 = PhotoImage(
    file=relative_to_assets("entry_19.png"))
entry_bg_19 = canvas.create_image(
    134.0,
    132.50000000000006,
    image=entry_image_19
)
entry_19 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=('Arial 20'),
    fg='black'
)
entry_19.insert(0,today)
entry_19.place(
    x=83.0,
    y=121.00000000000006,
    width=102.0,
    height=21.0
)
canvas.create_text(
    30.0,
    120.00000000000006,
    anchor="nw",
    text="Date:",
    fill="#000000",
    font=("Arial", 20 * -1)
)
#Date end

#Invoice# start
entry_image_20 = PhotoImage(
    file=relative_to_assets("entry_20.png"))
entry_bg_20 = canvas.create_image(
    377.5,
    131.00000000000006,
    image=entry_image_20
)
entry_20 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=('Arial 24'),
    fg='black'
)
entry_20.insert(0,"#000001")
entry_20.place(
    x=329.0,
    y=117.00000000000006,
    width=97.0,
    height=26.0
)
canvas.create_text(
    247.0,
    116.00000000000006,
    anchor="nw",
    text="Invoice",
    fill="#000000",
    font=("Arial", 24 * -1)
)
#Invoice# end

#Due date start
entry_image_21 = PhotoImage(
    file=relative_to_assets("entry_21.png"))
entry_bg_21 = canvas.create_image(
    644.0,
    132.50000000000006,
    image=entry_image_21
)
entry_21 = Entry(
    bd=0,
    bg="#FFFFFF",
    highlightthickness=0,
    font=('Arial 20'),
    fg='black'
)
entry_21.insert(0,today)
entry_21.place(
    x=593.0,
    y=121.00000000000006,
    width=102.0,
    height=21.0
)
canvas.create_text(
    498.0,
    120.00000000000006,
    anchor="nw",
    text="Due Date:",
    fill="#000000",
    font=("Arial", 20 * -1)
)
#Due date end

#Text start(don't edit)
canvas.create_text(
    30.0,
    180.00000000000006,
    anchor="nw",
    text="Bill To",
    fill="#000000",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    392.0,
    180.00000000000006,
    anchor="nw",
    text="Ship To",
    fill="#000000",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    30.0,
    424.00000000000006,
    anchor="nw",
    text="Item",
    fill="#000000",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    392.0,
    424.00000000000006,
    anchor="nw",
    text="Quantity",
    fill="#000000",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    506.0,
    424.00000000000006,
    anchor="nw",
    text="Unit Price",
    fill="#000000",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    631.0,
    424.00000000000006,
    anchor="nw",
    text="Amount",
    fill="#000000",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    383.0,
    561.0,
    anchor="nw",
    text="Subtotal",
    fill="#979797",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    383.0,
    593.0,
    anchor="nw",
    text="Discount",
    fill="#979797",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    383.0,
    625.0,
    anchor="nw",
    text="Taxes",
    fill="#979797",
    font=("Arial", 18 * -1)
)

canvas.create_text(
    383.0,
    669.0,
    anchor="nw",
    text="Total",
    fill="#000000",
    font=("Arial Bold", 18 * -1)
)
#Text end(don't edit)

#Add item button start
button_image_1 = PhotoImage(
    file=relative_to_assets("button_1.png"))
button_1 = Button(
    image=button_image_1,
    borderwidth=0,
    highlightthickness=0,
    command=get_item_details,
    relief="flat"
)
button_1.place(
    x=30.0,
    y=560.0,
    width=90.0,
    height=23.0
)
#Add item button end

#Need help button start
button_image_2 = PhotoImage(
    file=relative_to_assets("button_2.png"))
button_2 = Button(
    image=button_image_2,
    borderwidth=0,
    highlightthickness=0,
    command=lambda:open_readme(),
    relief="flat"
)
button_2.place(
    x=30.0,
    y=724.0,
    width=181.0,
    height=24.0
)
#Need help button end

#Text start(don't edit)
canvas.create_text(
    747.0,
    116.00000000000006,
    anchor="nw",
    text="Invoice\nSettings",
    fill="#FFFFFF",
    font=("Arial Bold", 24 * -1)
)

canvas.create_text(
    747.0,
    185.00000000000006,
    anchor="nw",
    text="Tax",
    fill="#FFFFFF",
    font=("Arial", 14 * -1)
)
#Text end(don't edit)

#Tax rectangle start
image_image_1 = PhotoImage(
    file=relative_to_assets("image_1.png"))
image_1 = canvas.create_image(
    795.0,
    229.00000000000006,
    image=image_image_1
)
#Tax rectangle end

#%t start
entry_image_22 = PhotoImage(
    file=relative_to_assets("entry_22.png"))
entry_bg_22 = canvas.create_image(
    794.5,
    229.00000000000006,
    image=entry_image_22
)
entry_22 = Entry(
    bd=0,
    bg="#0336FF",
    highlightthickness=0,
    font=("Arial 14"),
    fg='white',
    justify='center'
)
entry_22.insert(0,"%")
entry_22.place(
    x=775.0,
    y=222.0,
    width=39.0,
    height=14.0
)
#%t end

#Text start(don't edit)
canvas.create_text(
    747.0,
    349.00000000000006,
    anchor="nw",
    text="Discount",
    fill="#FFFFFF",
    font=("Arial", 14 * -1)
)
#Text end(don't edit)

#Discount rectangle start
image_image_2 = PhotoImage(
    file=relative_to_assets("image_2.png"))
image_2 = canvas.create_image(
    795.0,
    393.00000000000006,
    image=image_image_2
)
#Discount rectangle end

#%d start
entry_image_23 = PhotoImage(
    file=relative_to_assets("entry_23.png"))
entry_bg_23 = canvas.create_image(
    794.5,
    393.00000000000006,
    image=entry_image_23
)
entry_23 = Entry(
    bd=0,
    bg="#0336FF",
    highlightthickness=0,
    font=("Arial 14"),
    fg='white',
    justify='center'
)
entry_23.insert(0,"%")
entry_23.place(
    x=775.0,
    y=386.0,
    width=39.0,
    height=14.0
)
#%d end

#Text start(don't edit)
canvas.create_text(
    747.0,
    267.00000000000006,
    anchor="nw",
    text="Your name",
    fill="#FFFFFF",
    font=("Arial", 14 * -1)
)
#Text end(don't edit)

#own company name button start
button_image_3 = PhotoImage(
    file=relative_to_assets("button_3.png"))
button_3 = Button(
    image=button_image_3,
    borderwidth=0,
    highlightthickness=0,
    command=ocm,
    relief="flat"
)
button_3.place(
    x=747.0,
    y=291.00000000000006,
    width=96.0,
    height=40.0
)
#own company name button end

#Text start(don't edit)
canvas.create_text(
    747.0,
    431.00000000000006,
    anchor="nw",
    text="Seller Details",
    fill="#FFFFFF",
    font=("Arial", 14 * -1)
)
#Text end(don't edit)

#click here button start
button_image_4 = PhotoImage(
    file=relative_to_assets("button_4.png"))
button_4 = Button(
    image=button_image_4,
    borderwidth=0,
    highlightthickness=0,
    command=sd,
    relief="flat",
)
button_4.place(
    x=747.0,
    y=455.00000000000006,
    width=96.0,
    height=40.0
)
#click here button end

#Text start(don't edit)
canvas.create_text(
    747.0,
    544.0,
    anchor="nw",
    text="Export",
    fill="#FFFFFF",
    font=("Arial Bold", 24 * -1)
)
#Text end(don't edit)

#save invoice button start
button_image_5 = PhotoImage(
    file=relative_to_assets("button_5.png"))
button_5 = Button(
    image=button_image_5,
    borderwidth=0,
    highlightthickness=0,
    command=get_billing_shipping,
    relief="flat"
)
button_5.place(
    x=747.0,
    y=585.0,
    width=96.0,
    height=40.0
)
#save invoice button end

#print invoice button start
button_image_6 = PhotoImage(
    file=relative_to_assets("button_6.png"))
button_6 = Button(
    image=button_image_6,
    borderwidth=0,
    highlightthickness=0,
    command=print_seller_details,
    relief="flat"
)
button_6.place(
    x=747.0,
    y=647.0,
    width=96.0,
    height=40.0
)
#print invioce button end

#Settings icon start
image_image_3 = PhotoImage(
    file=relative_to_assets("image_3.png"))
image_3 = canvas.create_image(
    829.0,
    43.00000000000006,
    image=image_image_3
)
#Settings icon end

#Lines start
canvas.create_rectangle(
    30.0,
    78.00000000000006,
    724.0,
    80.00000000000006,
    fill="#0336FF",
    outline="")

canvas.create_rectangle(
    724.0,
    78.00000000000006,
    844.0,
    80.00000000000006,
    fill="#FFFFFF",
    outline="")

canvas.create_rectangle(
    30.0,
    414.00000000000006,
    694.0,
    416.00000000000006,
    fill="#F0F0F0",
    outline="")

canvas.create_rectangle(
    30.0,
    454.00000000000006,
    694.0,
    456.00000000000006,
    fill="#F0F0F0",
    outline="")

canvas.create_rectangle(
    30.0,
    550.0,
    694.0,
    552.0,
    fill="#F0F0F0",
    outline="")

canvas.create_rectangle(
    383.0,
    655.0,
    694.0,
    657.0,
    fill="#F0F0F0",
    outline="")

canvas.create_rectangle(
    30.0,
    703.0,
    694.0,
    705.0,
    fill="#F0F0F0",
    outline="")
#Lines end

set_amount()
set_item()
window.resizable(False, False)
window.mainloop()


import os
from openai import OpenAI
from requests import get
from .base_model import Model

api_key = os.environ.get("OPENAI_API_KEY")

class DallE(Model):
  def __init__(self):
    self.client = OpenAI(api_key=api_key)

  def create(self, prompt, directory):
    response = self.client.images.generate(
      model="dall-e-3",
      prompt=prompt,
      size="1792x1024",
      quality="standard",
      n=1,
    )

    with open(directory + "/image.png", "wb") as file:
      response = get(response.data[0].url)
      file.write(response.content)


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

AUTHOR = u'Lorenzo'
SITENAME = u'RugbyHuesca'
SITEURL = ''

TIMEZONE = 'Europe/Paris'

DEFAULT_LANG = u'es'

# Blogroll
LINKS =  (('Twitter', 'https://twitter.com/RugbyHuesca'),
          ('Facebook', 'http://www.facebook.es'),)

# Social widget
SOCIAL = (('PEÑA LOS 30', 'http://los30.es'),
          ('Twitter Personal', 'https://twitter.com/Lperezsaez'),)

DEFAULT_PAGINATION = False

STATIC_PATHS=["images"]


from .core import world
import constants

CREATURE_DEFAULTS = {
    "name": "Creature",
    "energy": 0,
    "melee": 1,
    "armor_class": 0,
    "damage": 0,
    "max_hp": 10
}

def set_player(entity):
    world.player = entity

def add_creature(x, y=None, z=None, **attributes):
    pos = get_coor(x, y, z)
    cell = get_cell(x, y, z)
    if cell:
        return
    kwargs = dict()
    kwargs.update(CREATURE_DEFAULTS)
    kwargs["sprite"] = x, y, z, constants.IMG_MONSTER
    kwargs["cell"] = pos
    kwargs.update(attributes)
    creature = world.new_entity(**kwargs)
    return creature

def add_block(x, y=None, z=None, **attributes):
    pos = get_coor(x, y, z)
    cell = get_cell(x, y, z)
    if cell:
        return
    kwargs = dict()
    kwargs["sprite"] = x, y, z, constants.IMG_GRANITE
    kwargs["cell"] = pos
    kwargs.update(attributes)
    block = world.new_entity(**kwargs)
    return block

def get_cell(x, y=None, z=None):
    pos = get_coor(x, y, z)
    eid = world["cell"].inverse.get(pos, None)
    if eid is not None:
        return world.get_entity(eid)

def get_coor(x, y=None, z=None):
    if y is not None:
        return x, y, z
    else:
        return x


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Magnetometer module
-------------------

Created by jboeer <jonas.boeer@kinemic.de> on 2016-09-07

"""

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

import re
import logging

from pymetawear import libmetawear
from pymetawear.exceptions import PyMetaWearException
from mbientlab.metawear.cbindings import MagBmm150Odr, MagBmm150Preset
from pymetawear.modules.base import PyMetaWearLoggingModule, Modules, data_handler

log = logging.getLogger(__name__)

def require_bmm150(f):
    def wrapper(*args, **kwargs):
        if getattr(args[0], 'mag_p_class', None) is None:
            raise PyMetaWearException("There is not Magnetometer "
                                      "module on your MetaWear board!")
        return f(*args, **kwargs)

    return wrapper

class MagnetometerModule(PyMetaWearLoggingModule):
    """MetaWear accelerometer module implementation.

    :param ctypes.c_long board: The MetaWear board pointer value.
    :param int module_id: The module id of this accelerometer
        component, obtained from ``libmetawear``.
    :param bool debug: If ``True``, module prints out debug information.

    """

    def __init__(self, board, module_id):
        super(MagnetometerModule, self).__init__(board)
        self.current_power_preset = None

        self.module_id = module_id

        self.power_presets = {}
        self.odr = {}

        if self.module_id == Modules.MBL_MW_MODULE_NA:
            # No magnetometer present!
            self.mag_o_class = None
            self.mag_p_class = None
        else:
            self.mag_o_class = MagBmm150Odr
            self.mag_p_class = MagBmm150Preset

        if self.mag_p_class is not None:
            # Parse possible presets for this magnetometer.
            for key, value in vars(self.mag_p_class).items():
                if re.search('^([A-Z\_]*)', key) and isinstance(value,int):
                    self.power_presets.update({key.lower(): value})

        if self.mag_o_class is not None:
            # Parse possible data rates for this magnetometer.
            for key, value in vars(self.mag_o_class).items():
                if re.search('^_([0-9\_]*Hz)', key) and isinstance(value,int):
                    self.odr.update({key[1:-2]: value})

    def __str__(self):
        return "{0} {1}: Power presets: {2}".format(
            self.module_name, self.sensor_name,
            [float(k) for k in sorted(self.power_presets.keys())])

    def __repr__(self):
        return str(self)

    @property
    def module_name(self):
        return "Magnetometer"

    @property
    def sensor_name(self):
        if self.mag_p_class is not None:
            return self.mag_p_class.__name__.replace(
                'Mag', '').replace('Preset', '')
        else:
            return ''

    @property
    @require_bmm150
    def data_signal(self):
        return libmetawear.mbl_mw_mag_bmm150_get_b_field_data_signal(self.board)

    def _get_power_preset(self, value):
        if value.lower() in self.power_presets:
            return self.power_presets.get(value.lower())
        else:
            raise ValueError("Requested power preset ({0}) was not part of "
                             "possible values: {1}".format(value.lower(), [self.power_presets.keys()]))

    @require_bmm150
    def get_current_settings(self):
        return {
            'power_preset': self.current_power_preset
        }

    @require_bmm150
    def get_possible_settings(self):
        return {
            'power_preset': [sorted(self.power_presets.keys(), key=lambda x:(x.lower()))],
        }

    @require_bmm150
    def set_settings(self, power_preset=None):
        """Set magnetometer settings.

         .code-block:: python

            mwclient.magnetometer.set_settings(power_preset="LOW_POWER")

        Call :meth:`~get_possible_settings` to see which values
        that can be set for this sensor.

        :param str power_preset: The power preset, influencing the data rate,
            accuracy and power consumption

        """
        if power_preset is not None:
            pp = self._get_power_preset(power_preset)
            log.debug("Setting Magnetometer power preset to {0}".format(pp))
            libmetawear.mbl_mw_mag_bmm150_set_preset(self.board, pp)
            self.current_power_preset = pp

    @require_bmm150
    def notifications(self, callback=None):
        """Subscribe or unsubscribe to magnetometer notifications.

        Convenience method for handling magnetometer usage.

        Example:

        .. code-block:: python

            def handle_notification(data):
                # Handle dictionary with [epoch, value] keys.
                epoch = data["epoch"]
                xyz = data["value"]
                print(str(data))

            mwclient.magnetometer.notifications(handle_notification)

        :param callable callback: Magnetometer notification callback function.
            If `None`, unsubscription to magnetometer notifications is registered.

        """
        if callback is None:
            self.stop()
            self.toggle_sampling(False)
            super(MagnetometerModule, self).notifications(None)
        else:
            super(MagnetometerModule, self).notifications(data_handler(callback))
            self.toggle_sampling(True)
            self.start()

    @require_bmm150
    def start(self):
        """Switches the magnetometer to active mode."""
        libmetawear.mbl_mw_mag_bmm150_start(self.board)

    @require_bmm150
    def stop(self):
        """Switches the magnetometer to standby mode."""
        libmetawear.mbl_mw_mag_bmm150_stop(self.board)

    @require_bmm150
    def toggle_sampling(self, enabled=True):
        """Enables or disables magnetometer sampling.

        :param bool enabled: Desired state of the magnetometer.

        """
        if enabled:
            libmetawear.mbl_mw_mag_bmm150_enable_b_field_sampling(self.board)
        else:
            libmetawear.mbl_mw_mag_bmm150_disable_b_field_sampling(self.board)


from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *

import hn

class TabsWidget(QWidget):
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)

        self.layout = QHBoxLayout(self)

        self.initialize_tab_screen()

        self.add_tabs_to_screen()

        self.add_tabs_to_widget()

        self.populate_tab_main()

        self.initialize_tab_reader()

    def initialize_tab_screen(self):
        self.tabs = QTabWidget()
        self.tab_main = QWidget()
        self.tab_reader = QWidget()
        self.tabs.resize(300,200)

    def add_tabs_to_screen(self):
        self.tabs.addTab(self.tab_main, "Articles")

    def populate_tab_main(self):
        self.tab_main.layout = QGridLayout(self)

        self.tab_main.article_list = QListWidget()

        list_item_style = "QListWidget::item { border: 1px solid #fff; padding: 15px; font-family: Noto Mono,Menlo,Monaco,Consolas,monospace; font-size: 25px; }"
        list_item_hover = "QListWidget::item:hover { background: #2a2a2a;  }"

        self.tab_main.article_list.setStyleSheet(list_item_style)
        self.tab_main.article_list.setStyleSheet(list_item_hover)
        self.tab_main.article_list.setCursor(QCursor(Qt.PointingHandCursor))
        self.tab_main.article_list.setFont(QFont('Mono', 12, QFont.Bold))

        self.articles = hn.get_articles()

        for rank, article in self.articles.items():

            text = "\n".join([
                "",
                f"{rank}. {article['title']}",
                f"| {article['score']} points | {article.get('descendants', 0)} comments |",
                "",
            ])

            self.tab_main.article_list.insertItem(rank, text)

        self.tab_main.article_list.clicked.connect(self.article_clicked)

        self.tab_main.layout.addWidget(self.tab_main.article_list)

        self.tab_main.setLayout(self.tab_main.layout)

    def initialize_tab_reader(self):
        self.tab_reader.layout = QHBoxLayout(self)
        self.read_split = QSplitter(Qt.Horizontal)

        self.tab_reader.browser_article = QWebEngineView()
        self.read_split.addWidget(self.tab_reader.browser_article)

        self.tab_reader.browser_comments = QWebEngineView()
        self.read_split.addWidget(self.tab_reader.browser_comments)

        self.tab_reader.layout.addWidget(self.read_split)

        self.tab_reader.setLayout(self.tab_reader.layout)

    def article_clicked(self):
        item = self.tab_main.article_list.currentItem()

        self.set_reader_tab(self.tab_main.article_list.row(item) + 1)

    def set_reader_tab(self, article_index):
        article = self.articles.get(article_index)

        self.tab_reader.browser_comments.load(QUrl(f"https://news.ycombinator.com/item?id={article['id']}"))

        if article.get("url"):
            self.tab_reader.browser_article.load(QUrl(article['url']))
        else:
            self.tab_reader.browser_article.load(QUrl("https://i.imgur.com/cr2ml4j.gif"))

        try:
            self.tabs.addTab(self.tab_reader, "Reader")
        except:
            pass

        self.tabs.setCurrentIndex(1)

    def add_tabs_to_widget(self):
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

    @pyqtSlot()
    def on_click(self):
        print("\n")
        for currentQTableWidgetItem in self.tableWidget.selectedItems():
            print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())


from tkinter import *

class Toolbar:
  def __init__(
    self,
    master,
    root,
    on_add_new_node,
    on_sizes_click,
    on_degrees_click,
    on_remove_min_click,
    on_min_root_click,
    on_reset_click,
  ):
    # validate inputs
    vcmd = master.register(self.validate_num)
    self.vcmd = vcmd

    root.grid_columnconfigure(0, minsize=80)
    root.grid_columnconfigure(1, minsize=20)
    root.grid_columnconfigure(2, minsize=80)
    root.grid_columnconfigure(3, minsize=80)

    for i in range(0, 6):
      root.grid_rowconfigure(i, minsize=30)

    self.make_entry_field(
      root,
      label="Add nodes",
      btn_label="Add",
      submit_handler=on_add_new_node,
      row=0,
      column=0
    )

    # Sizes
    size_btn = Button(root, text="Sizes", command=on_sizes_click)
    size_btn.grid(row=1, column=2, sticky="WE")

    # Degrees
    size_btn = Button(root, text="Degrees", command=on_degrees_click)
    size_btn.grid(row=2, column=2, sticky="WE")

    # Min
    min_btn = Button(root, text="Min root", command=on_min_root_click)
    min_btn.grid(row=3, column=2, sticky="WE")

    # Remove min
    size_btn = Button(root, text="Remove min", command=on_remove_min_click)
    size_btn.grid(row=1, column=3, sticky="WE")

    # Reset
    reset_btn = Button(root, text="Reset", command=on_reset_click)
    reset_btn.grid(row=2, column=3, sticky="WE")

  def make_entry_field(
    self,
    root,
    label,
    btn_label,
    submit_handler,
    row,
    column,
  ):
    Label(root, text=label).grid(row=row, column=column, sticky="W")
    entry = Entry(root, validate='all', validatecommand=(self.vcmd, '%P'), width=10)
    entry.grid(row=row+1, column=column, sticky="WENS")
    btn = Button(
      root,
      text=btn_label,
      command=self.on_entry_submit(entry, submit_handler),
    )
    btn.grid(row=row+2, column=column, sticky="WENS")

  def validate_num(self, str):
    return all(
      item == '' or item.isdigit() for item in str.split(",")
    )

  def on_entry_submit(self, entry, callback):
    def handle():
      entry_value = entry.get()
      if entry_value:
        str_values = filter(lambda x: x.isdigit(), entry_value.split(","))
        values = [int(item) for item in str_values]
        callback(values)
        entry.delete(0, END)

    return handle


import pika, os, logging
logging.basicConfig()

url = os.environ.get('CLOUDAMQP_URL','amqp://fnfdxokx:EPwMQFxwqZU4fHV3JY1VgsxXaVBdUsXn@mosquito.rmq.cloudamqp.com/fnfdxokx')
params = pika.URLParameters(url)
params.socket_timeout = 5

connection = pika.BlockingConnection(params)
channel = connection.channel()
channel.queue_declare(queue = 'sesdata')

channel.basic_publish(exchange='',routing_key='sesdata',body='yoyoyo\n')
print("[x] Message sent")
connection.close()


# 5*5 격자판에 다음과 같이 숫자가 적혀있다.
# 10 13 10 12 15
# 12 39 30 23 11
# 11 25 50 53 15
# 19 27 29 37 27
# 19 18 30 13 19
# n*n 격자판이 주어지면 각 행의 합, 각 열의 합, 두 대각선의 합 중 가장 큰 합을 출력한다.

n = int(input())
a = [list(map(int, input().split())) for _ in range(n)] # 2차원 list 생성 : map으로 한줄을 읽어오는데, for문을 통해 n번 반복해서 list를 생성한다.
maximum = -214700000

# 각 행, 열의 합 : 행과 열을 하나씩 고정하면서 격자판 전체를 훑는다.
for i in range(n):
    sum_row = sum_col = 0 # row : 행, col : 열
    for j in range(n):
        sum_row += a[i][j] # 행(고정)의 합
        sum_col += a[j][i] # 열(고정)의 합
    # maximum에 행과 열의 최대합 저장
    if sum_row > maximum:
        maximum = sum_row
    if sum_col > maximum:
        maximum = sum_col

# 두 대각선의 합
sum_row = sum_col = 0 # 대각선 계산을 위한 초기화
for i in range(n):
    sum_row += a[i][i]
    sum_col += a[i][n - i - 1]
    if sum_row > maximum:
        maximum = sum_row
    if sum_col > maximum:
        maximum = sum_col

print(maximum)

'''
5
10 13 10 12 15
12 39 30 23 11
11 25 50 53 15
19 27 29 37 27
19 18 30 13 19
'''


import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
    'Object':["phone","charger","cable","dock","box","others"],
    'Price':[12000,4000,2000,1500,500,2500]
})
plt.pie(df["Price"],labels=df["Object"])
plt.show()


#!/usr/bin/env python3

import auctioneers
import bidder
import synchronisation
import threading
import queue
import sys
import time
import multiprocessing
import signal
import logging

def handler(signum, frame):
    a1.change_state(4)
    a2.change_state(4)
    sys.exit()

if __name__ == "__main__":
    signal.signal(signal.SIGINT, handler)
    if len(sys.argv) < 5:
        sys.exit('Usage: %s configuration_file database_info run_configuration log_file' % sys.argv[0])
    conf = sys.argv[1]
    db_info = sys.argv[2]
    run_conf = sys.argv[3]
    log_file = sys.argv[4]

    if len(sys.argv) == 6 and sys.argv[5] == '-d':
        logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-3s) %(message)s')
    else:
        logging.basicConfig(filename=log_file, filemode='w', level=logging.DEBUG, format='(%(threadName)-3s) %(message)s')

    (db1,db2) = auctioneers.prepare_database_connection(db_info)
    sync = synchronisation.Synchronisation()
    qbid = queue.Queue()
    log = open(log_file,'w')
    f1=open('auct_num_1','w')
    f2=open('auct_num_2','w')

    a1 = auctioneers.Auctioneer(8888,f1,'advdb1',sync,conf,db1)
    a2 = auctioneers.Auctioneer(8889,f2,'advdb2',sync,conf,db2)

    sync.addObservers(a1,a2)
    t1 = threading.Thread(target=a1.serviceloop,name="auctioneer1")
    t2 = threading.Thread(target=a2.serviceloop,name="auctioneer2")
    t1.start()
    t2.start()

    fd = open(run_conf,'r')
    N = int(fd.readline().split()[0])
    bidders = []
    for i in range(0,N):
        line = fd.readline()
        line = line.split()
        ip = line[0]
        port = int(line[1])
        name = line[2]
        budget = float(line[3])
        bidr = bidder.Bidder(ip,port,name,budget,qbid)
        bidders.append(bidr)
        t1 = threading.Thread(target=bidr.cmdloop,name=name)
        t1.start()
        time.sleep(1)
        if qbid.qsize() > 0:
            data = qbid.get()
            if data == 2:
                bidders.remove(bidr)

    while True:
        msg = 0
        for i in bidders:
            data = qbid.get()
            if data == 3:
                quit += 3
            msg += data
        if msg == 0:
            interested_list = []
            line = fd.readline()
            line = line.split()
            for i in line:
                interested_list.append(int(i))
            for bidid in interested_list:
                time.sleep(1)
                bidders[bidid].i_am_interested()
        msg = 0
        for i in interested_list:
            data = qbid.get()
            if data == 3:
                quit += 3
            msg += data
        if msg == len(interested_list):
            bid_list = []
            while line != []:
                line = fd.readline()
                line = line.split()
                if line != []:
                    bid_list.append([int(line[0]),int(line[1]),float(line[2])])
            for b in bid_list:
                time.sleep(b[0])
                bidders[b[1]].bid(bidders[b[1]].sock,b[2])


import asyncio
from typing import List

from aiogram import Bot

from db.sql_facade import DAO
from db.types import DAOVacancyData
from keyboards.inline.auto_posting import get_url_keyboard_fab

async def __send_message_2_channel(bot: Bot, vacancy: DAOVacancyData, tg_channel_id: int) -> int:
    result = await bot.send_message(tg_channel_id,
                                    f"Условия {vacancy.name}\n"
                                    f"График {vacancy.work_schedule.value}\n"
                                    f"Оплата {vacancy.salary}",
                                    reply_markup=await get_url_keyboard_fab(vacancy.id, bot))
    return result.message_id

async def auto_posting(bot: Bot, db: DAO):
    vacancies = await db.get_vacancy_by_geolocation()
    for vacancy in vacancies:
        channels = await db.get_channels_id_by_audience(vacancy.audience_id)
        for channel_id in channels:
            await asyncio.sleep(0.3)
            post_id = await __send_message_2_channel(bot, vacancy, channel_id)
            print(f"channel_id {channel_id}, message_id{post_id}, vacancy_id {vacancy.id}")
            await db.insert_post(channel_id=channel_id, message_id=post_id, vacancy_id=vacancy.id)


import smtplib
try:
    #Create your SMTP session
    smtp = smtplib.SMTP('smtp.gmail.com', 587)

   #Use TLS to add security
    smtp.starttls()

    #User Authentication
    smtp.login("faddhackathon@gmail.com","fadd1234")

    #Defining The Message
    message = "Hello"

    #Sending the Email
    smtp.sendmail("faddhackathon@gmail.com", "dmaiya@umass.edu", message)

    #Terminating the session
    smtp.quit()
    print ("Email sent successfully!")

except Exception as ex:
    print("Something went wrong....",ex)


from photJules import *
import pylab as plt

self = photosynthesis()

def test1(self,n=100,name='a',ipar=200.,Tc=None,x=None,xlabel=None,\
          omega=None,co2_ppmv=390,C3=True,type='C3 grass',plot=True):
    '''
    low light level, span a temperature range, normal CO2
    '''

    self.data = np.zeros(n)

    # set plant type to C3
    self.C3 = np.zeros([n]).astype(bool) + C3

    self.Lcarbon = np.ones([n]) * 1
    self.Rcarbon = np.ones([n]) * 1
    self.Scarbon = np.ones([n]) * 1

    # set pft type
    # options are:
    # 'C3 grass', 'C4 grass', 'Needleleaf tree', 'Shrub'
    # 'Broadleaf tree'
    # Note that if C4 used, you must set the array
    # self.C3 to False

    self.pft = np.array([type]*n)

    # set up Ipar, incident PAR in (mol m-2 s-1)
    self.Ipar = np.ones_like(self.data) * ipar * 1e-6

    # set co2 (ppmv)
    self.co2_ppmv = co2_ppmv*np.ones_like(self.data)

    # set up a temperature range (C)
    try:
        if Tc == None:
            self.Tc = Tc or np.arange(n)/(1.*n) * 100. - 30.
        else:
            self.Tc = Tc
    except:
        self.Tc = Tc
    # initialise
    self.initialise()
    # reset defaults
    self.defaults()

    # omega
    if omega != None:
        self.omega = self.omega*0 + omega
    # calculate leaf and canopy photosynthesis
    self.photosynthesis()

    if plot == True:
        # plot
        plt.clf()
        if x == None:
            x = self.Tc
        plt.plot(x,self.Wc * 1e6,label='Wc')
        plt.plot(x,self.Wl * 1e6,label='Wl')
        plt.plot(x,self.We * 1e6,label='We')
        plt.plot(x,self.W * 1e6,label='W')
        plt.plot(x,self.Al* 1e6,label='Al')
        plt.plot(x,self.Rd* 1e6,label='Rd')

        plt.ylabel('assimilation rate (umol CO2 m-2 s-1)')
        if xlabel == None:
            plt.xlabel('temperature (C))')
        else:
            plt.xlabel(xlabel)
        plt.legend(loc='upper right')
        plt.savefig('figures/test1%s.png'%name)

# make sure can access pyephem
import sys
sys.path.append ("/home/ucfajlg/Data/python_libs/pyephem-3.7.5.1-py2.7-linux-x86_64.egg/" )

class sunInfo():
    '''
    A utility to work out some solar information
    '''
    def __init__(self,julianOffset=None):
        '''
        Initialise class

        options:
            julianOffset: set to report Julian day with an offset subtracted
                          Format, 'YYYY/M/D' e.g. '2012/1/1'
        '''
        # use the python library ephem
        import ephem
        self.gatech = ephem.Observer()
        if julianOffset != None:
            self.julianOffset = ephem.julian_date(julianOffset)
        else:
            self.julianOffset  = 0.

        # http://acrim.com/TSI%20Monitoring.htm
        self.solar = 1361 #W/m2

        # PPFD is measured in micromoles/m2/sec
        # (Photosynthetic Photon Flux Density)

        # astronomical unit
        # http://neo.jpl.nasa.gov/glossary/au.html
        # we dont need this, but its interesting to know
        self.AU = 149597870.691 * 1e3 # m

        # energy content of PAR quanta
        self.EPAR = 220.e-3 # MJmol-1

    def sun(self,secs,mins,hours,days,months,years,lats,lons):
        '''
        Utility to set days, months, years, lats, lons
        and calculate max_solar_flux
        '''
        import ephem
        self.julian = []
        self.sza = []
        self.earth_distance = []
        for lon in np.nditer(lons):
            self.gatech.lon = str(lon)
            for lat in np.nditer(lats):
                self.gatech.lat = str(lat)
                for year in np.nditer(years):
                    for month in np.nditer(months):
                        for day in np.nditer(days):
                            for hour in np.nditer(hours):
                                for min in np.nditer(mins):
                                    for sec in np.nditer(secs):
                                        self.gatech.date = '%4d/%d/%d %d:%d:%d'%\
                                            (year,month,day,hour,min,int(sec))
                                        v = ephem.Sun(self.gatech)
                                        alt = np.max([0,v.alt * 180./np.pi])
                                        self.sza.append(90. - alt)
                                        jd = ephem.julian_date('%4d/%d/%d'%(year,month,day)) \
                                                 - self.julianOffset
                                        jd += hour/24. + min/60./24. + sec/60./60./24.
                                        self.julian.append(jd)
                                        self.earth_distance.append(v.earth_distance)
        self.julian = np.array(self.julian)
        self.sza = np.array(self.sza)
        self.earth_distance = np.array(self.earth_distance)
        self.solarRad = self.solar/(self.earth_distance*self.earth_distance)
        # Express radiation in mol(photons) / (m^2 s)
        self.solarRad_mol = self.solarRad/self.EPAR

    def plot(self,x,y,xname,yname,plotname='sunplot.png'):
        '''
        Plot utility
        '''
        plt.clf()
        plt.xlabel(xname)
        plt.ylabel(yname)
        plt.plot(x,y)
        plt.savefig('figures/' + plotname)


"""minres+mg is the most efficient solver on these isotropic problems

Note that these relative benchmarks are very sensitive to the rhs;
making it very smooth favors pure minres, and simplifies amg restriction
with high bandwidth, mg wins.

still many surprising things happening; pure mg is fastest by far on the sphere,
followed by minres+amg, and minres+amg by far the best on regular complex
differences by machine are likely related to the number of cores and parralelization differences
"""

import numpy as np
import scipy.sparse
from cached_property import cached_property

from examples.multigrid.equation import SymmetricEquation
from pycomplex.sparse import normalize_l1, inv_diag

class Poisson(SymmetricEquation):
    """Wrap complex with poisson equation methods and state

    Poisson logic for primal 0-forms, or 0-laplace-beltrami

    A * x = B * y, or laplacian(x) = mass(y)

    Notes
    -----
    need to think of clear interface to extend this to multicomplex as well.
    what do we truly expect as interface from the complex that we bind to here?
    at what level do we translate from possible block system to simple monolithic matrices?
    """

    def __init__(self, complex, k=0):
        """

        Parameters
        ----------
        complex : BaseComplex
        k : int
            laplace order

        """
        self.complex = complex
        self.k = k

    @cached_property
    def operators(self):
        """Construct laplace-beltrami on primal k-forms

        Returns
        -------
        A : Linear operator
            symmetric;
            maps primal k-form to dual k-form
        B : Linear operator
            symmetric diagonal;
            maps primal k-form to dual k-form
        BI :
            inverse of B
        """
        k = self.k
        DP = [scipy.sparse.diags(h) for h in self.complex.hodge_DP]
        PD = [scipy.sparse.diags(h) for h in self.complex.hodge_PD]

        DPl, DPm, DPr = ([0] + DP + [0])[k:][:3]
        PDl, PDm, PDr = ([0] + PD + [0])[k:][:3]
        Dl, Dr = ([0] + self.complex.topology.matrices + [0])[k:][:2]
        Pl, Pr = np.transpose(Dl), np.transpose(Dr)

        A = DPm * Pl * PDl * Dl * PDm + Dr * DPr * Pr

        # FIXME: is mass just hodge for non-scalar forms? seems like
        B = DPm
        BI = inv_diag(B)

        return A.tocsr(), B.tocsc(), BI.tocsc()

    @cached_property
    def null_space(self):
        """Return null space of the equations"""
        A, B, BI = self.operators

        return np.ones((B.shape[1], 1))

    def solve(self, y):
        """Solve poisson linear system in eigenbasis

        Parameters
        ----------
        y : ndarray

        Returns
        -------
        x : ndarray
        """
        A, B, BI = self.operators

        def poisson(y, v):
            x = np.zeros_like(y)
            # poisson linear solve is simple division in eigenspace. skip nullspace
            null_rank = self.null_space.shape[1]
            # swivel dimensions to start binding broadcasting dimensions from the left
            x[null_rank:] = (y[null_rank:].T / v[null_rank:].T).T
            return x

        return self._solve_eigen(B * y, poisson)

    # FIXME: mg operators belong to the complexes themselves
    @cached_property
    def transfer(self):
        """Transfer operator of state variables between fine and coarse representation

        Returns
        -------
        sparse matrix
            entry [c, f] is the overlap between fine and coarse dual n-cells

        Notes
        -----
        only available for SphericalTriangularComplex; implementation on regular grids should be easy tho
        """
        try:
            # triangular 0-form special case
            fine = self.complex
            coarse = fine.parent
            return self.complex.multigrid_transfer_dual(coarse, fine).T
        except:
            return self.complex.multigrid_transfers[self.k]

    @cached_property
    def restrictor(self):
        """Maps primal 0-form from fine to coarse"""
        # return self.interpolator.T
        A, B, BI = self.operators
        # FIXME: need a link to parent equation; this is hacky. should be coarse.BI
        # convert to dual; then transfer, then back to primal. why again?
        fine = scipy.sparse.diags(self.complex.hodge_DP[0])
        coarse = scipy.sparse.diags(self.complex.parent.hodge_PD[0])
        return coarse * normalize_l1(self.transfer.T, axis=0) * fine
    def restrict(self, fine):
        """Restrict solution from fine to coarse"""
        return self.restrictor * fine
    @cached_property
    def interpolator(self):
        """Maps primal 0-form from coarse to fine"""
        A, B, BI = self.operators
        return normalize_l1(self.transfer, axis=1)
    def interpolate(self, coarse):
        """Interpolate solution from coarse to fine"""
        return self.interpolator * coarse

    def petrov_galerkin(self):
        A, B, BI = self.operators
        return self.restrictor * A * self.interpolator

# class PoissonDual(Equation):
#     """Wrap complex with poisson equation methods and state
#
#     Poisson logic for dual n-forms, or n-laplace-beltrami
#
#     A * x = B * y, or laplacian(x) = mass(y)
#
#     """
#
#     def __init__(self, complex, k, dual=True):
#         """
#
#         Parameters
#         ----------
#         complex : BaseComplex
#         k : int
#             degree of the laplacian
#         dual : bool
#             if true, dual boundary terms are included in the unknowns
#             if false, these are implicitly zero and only primal topology is used
#         """
#         self.complex = complex
#         self.k = k
#         self.dual = dual
#
#     @cached_property
#     def operators(self):
#         """Construct laplace-beltrami on dual k-forms
#
#         Returns
#         -------
#         A : Linear operator
#             symmetric;
#             maps dual k-form to primal k-form
#         B : Linear operator
#             symmetric diagonal;
#             maps dual k-form to primal k-form
#         BI :
#             inverse of B
#         """
#         k = self.k
#         DPl, DPm, DPr = ([0] + self.complex.hodge_DP + [0])[k:][:3]
#         PDl, PDm, PDr = ([0] + self.complex.hodge_PD + [0])[k:][:3]
#         if self.dual:
#             Dl, Dr = ([0] + self.complex.topology.dual.matrices_2 + [0])[k:][:2]
#             Pl, Pr = np.transpose(Dl), np.transpose(Dr)
#         else:
#             Pl, Pr = ([0] + self.complex.topology.matrices + [0])[k:][:2]
#             Dl, Dr = np.transpose(Pl), np.transpose(Pr)
#
#         A = Pl * PDl * Dl + \
#             PDm * Dr * DPr * Pr * PDm
#
#         # FIXME: is mass just hodge for non-scalar forms?
#         B = scipy.sparse.diags(PDm)
#         BI = inv_diag(B)
#
#         return A.tocsr(), B.tocsc(), BI.tocsc()
#
#     def solve(self, y):
#         """Solve poisson linear system in eigenbasis
#
#         Parameters
#         ----------
#         y : ndarray
#
#         Returns
#         -------
#         x : ndarray
#         """
#         A, B, BI = self.operators
#
#         def poisson(y, v):
#             x = np.zeros_like(y)
#             # poisson linear solve is simple division in eigenspace. skip nullspace
#             x[1:] = y[1:] / v[1:]
#             return x
#
#         return self._solve_eigen(B * y, poisson)
#
#     # FIXME: mg operators belong to the complexes themselves
#     @cached_property
#     def transfer(self):
#         """Transfer operator of state variables between fine and coarse representation
#
#         Returns
#         -------
#         sparse matrix
#             entry [c, f] is the overlap between fine and coarse dual n-cells
#
#         Notes
#         -----
#         might switch to special case for triangular complex and 0-forms
#         """
#         if False:
#             # triangular 0-form special case
#             fine = self.complex
#             coarse = fine.parent
#             return self.complex.multigrid_transfer_dual(coarse, fine).T
#         else:
#             return self.complex.multigrid_transfers[self.k]
#
#     @cached_property
#     def restrictor(self):
#         A, B, BI = self.operators
#         # FIXME: need a link to parent equation; this is hacky. should be coarse.BI
#         # note: is this the same for vector equations?
#         coarse = scipy.sparse.diags(self.complex.parent.hodge_PD[0])
#         return coarse * normalize_l1(self.transfer.T, axis=0) * B
#     def restrict(self, fine):
#         """Restrict solution from fine to coarse; dual to dual"""
#         return self.restrictor * fine
#     @cached_property
#     def interpolator(self):
#         A, B, BI = self.operators
#         coarse = scipy.sparse.diags(self.complex.parent.hodge_DP[0])
#         return BI * normalize_l1(self.transfer, axis=0) * coarse
#     def interpolate(self, coarse):
#         """Interpolate solution from coarse to fine; dual to dual"""
#         return self.interpolator * coarse

class GeometricMultiGrid(object):
    """Perhaps use this to cache the MG-specific data?"""
    def __init__(self, complex, equation):
        self.complex = complex
        self.equation = equation

class Hierarchy(object):
    def __init__(self, hierarchy, equation):
        self.hierarchy = hierarchy
        self.equations = [equation(l) for l in hierarchy]

    def solve(self, y):
        pass

    def as_preconditioner(self):
        pass

if __name__ == '__main__':
    from examples.multigrid import multigrid
    from time import clock
    from examples.diffusion.perlin_noise import perlin_noise

    from pycomplex import synthetic
    import matplotlib.pyplot as plt

    complex_type = 'regular'
    print(complex_type)

    if complex_type == 'sphere':
        sphere = synthetic.icosahedron().copy(radius=30).subdivide_fundamental()
        hierarchy = [sphere]
        for i in range(5):
            hierarchy.append(hierarchy[-1].subdivide_loop())

    if complex_type == 'regular':
        # test if multigrid operators on primal-0-forms work correctly on regular grids
        root = synthetic.n_cube(n_dim=2).as_22().as_regular()
        root = root.copy(vertices=root.vertices * 30)
        hierarchy = [root]
        for i in range(6):
            hierarchy.append(hierarchy[-1].subdivide_cubical())

    # set up hierarchy of equations
    equations = [Poisson(l, k=0) for l in hierarchy]

    # test transfer operators
    if True:
        R = equations[-1].restrictor
        I = equations[-1].interpolator
        T = R * I
        # this T is far from identity. i suppose this is normal; roundtrip on high frequency component does lead to smoothing, if R=I.T
        ones = np.ones((T.shape[1], 1))
        q = T * ones
        print(q)
        assert np.allclose(q, 1)

        T = I * R
        ones = np.ones((T.shape[1], 1))
        q = T * ones
        print(q)
        assert np.allclose(q, 1)

    if False:
        # monkey patch this dumb assert
        from scipy.sparse.linalg.eigen.lobpcg import lobpcg
        lobpcg._assert_symmetric = lambda x: None

        # test eigen solve; seems to work just fine
        # V, v = equations[-1].eigen_basis(K=100, preconditioner='amg')
        V, v = equations[-1].eigen_basis(K=201, preconditioner=multigrid.as_preconditioner(equations[2:]), tol=1e-6)

        print(equations[-1].largest_eigenvalue)
        hierarchy[-1].plot_primal_0_form(V[:, -1])
        plt.show()

    # now test multigrid; what is a good testcase?
    # visually not that obvious; but we can focus on numbers first
    # if we can solve poisson with perlin input using mg,
    # we should be good, since it contains all frequency components

    p0 = perlin_noise(hierarchy[-1])
    p0 -= p0.mean()
    # p0 = np.random.normal(size=p0.size)

    x0 = np.zeros_like(p0)
    print('initial res')
    print(np.linalg.norm(equations[-1].residual(x0, p0)))

    t = clock()
    x_minres = equations[-1].solve_minres(p0, preconditioner=None)
    print('minres time: ', clock() - t)
    print('minres resnorm', np.linalg.norm(equations[-1].residual(x_minres, p0)))

    # warm up cache
    x = multigrid.solve_full_cycle(equations, p0, iterations=1)
    t = clock()
    x = multigrid.solve_full_cycle(equations, p0, iterations=4)
    print('mg full time: ', clock() - t)
    print('mg full resnorm', np.linalg.norm(equations[-1].residual(x, p0)))

    # from examples.multigrid.krylov import krylov_cycle
    # t = clock()
    # x = krylov_cycle(equations, p0)
    # print('krylov full time: ', clock() - t)
    # print('krylov full resnorm', np.linalg.norm(equations[-1].residual(x, p0)))

    # # warm up amg
    # x_minres = equations[-1].solve_minres(p0, preconditioner='amg')
    # t = clock()
    # x_minres = equations[-1].solve_minres(p0, preconditioner='amg')
    # print('minres+amg time: ', clock() - t)
    # print('minres+amg resnorm', np.linalg.norm(equations[-1].residual(x_minres, p0)))

    # warm up mg
    x_minres = equations[-1].solve_minres(p0, preconditioner=multigrid.as_preconditioner(equations[1:]))
    t = clock()
    # x_minres = equations[-1].solve_minres(p0, amg=True)
    x_minres = equations[-1].solve_minres(p0, preconditioner=multigrid.as_preconditioner(equations[1:]))
    print('minres+mg time: ', clock() - t)
    print('minres+mg resnorm', np.linalg.norm(equations[-1].residual(x_minres, p0)))

    # t = clock()
    # x_amg = equations[-1].solve_amg(p0)
    # print('amg time: ', clock() - t)
    # print('amg resnorm', np.linalg.norm(equations[-1].residual(x_amg, p0)))

    t = clock()
    x_eigen = equations[-1].eigen_basis(K=100, preconditioner=None, tol=1e-6)
    print('eigen time: ', clock() - t)

    # t = clock()
    # x_eigen = equations[-1].eigen_basis(K=100, preconditioner='amg', tol=1e-6)
    # print('eigen amg time: ', clock() - t)

    t = clock()
    x_eigen = equations[-1].eigen_basis(K=100, preconditioner=multigrid.as_preconditioner(equations[1:]), tol=1e-6)
    print('eigen mg time: ', clock() - t)

    if True:
        v = x
        vmin, vmax = v.min(), v.max()
        if complex_type == 'sphere':

            hierarchy[-1].as_euclidian().plot_primal_0_form(v, vmin=vmin, vmax=vmax)
        if complex_type == 'regular':
            hierarchy[-1].plot_primal_0_form(v, vmin=vmin, vmax=vmax)

        # hierarchy[-2].as_euclidian().plot_primal_0_form(equations[-1].restrict(p0), vmin=vmin, vmax=vmax)
        # hierarchy[-1].as_euclidian().plot_primal_0_form(equations[-1].interpolate(equations[-1].restrict(p0)), vmin=vmin, vmax=vmax)

        plt.show()


from tonguetwister.disassembler.chunkparser import EntryMapChunkParser, InternalEntryParser
from tonguetwister.lib.stream import ByteBlockIO

class LingoNamelist(EntryMapChunkParser):
    @classmethod
    def parse_header(cls, stream: ByteBlockIO):
        header = {}
        header['u1'] = stream.uint32()
        header['u2'] = stream.uint32()
        header['chunk_length'] = stream.uint32()
        header['chunk_length_2'] = stream.uint32()
        header['header_length'] = stream.uint16()
        header['n_records'] = stream.uint16()

        return header

    @classmethod
    def parse_entries(cls, stream: ByteBlockIO, header):
        return [NameEntry.parse(stream) for _ in range(header['n_records'])]

    def __getitem__(self, i):
        return self.records[i].text

class NameEntry(InternalEntryParser):
    public_data_attrs = ['text']

    @classmethod
    def _parse(cls, stream: ByteBlockIO):
        data = {}
        data['text_length'] = stream.uint8()
        data['text'] = stream.string_raw(data['text_length'])

        return data


from Bio.KEGG import REST
from Bio.KEGG import Enzyme
import xlsxwriter

# Create a workbook and add a worksheet.
workbook = xlsxwriter.Workbook('LegpneumoPh463_693_Enzymes.xlsx')
worksheet = workbook.add_worksheet("KEGG Enzymes")
# Add a bold format to use to highlight cells.
bold = workbook.add_format({'bold': True})
# Initiate the workbook by filling the first row with headers
worksheet.write("A1", "Gene ID (NCBI, KEGG)", bold)
worksheet.write("B1", "Locus Tag", bold)
worksheet.write("C1", "EC Number", bold)
worksheet.write("D1", "KEGG Orthologs", bold)
worksheet.write("E1", "KEGG Reactions IDs", bold)
worksheet.write("F1", "KEGG Pathways", bold)
# Start from the first cell below the headers.
row = 1
col = 0

ec = open("ecnums.txt", "r")
ec_nums = []
for line in ec.readlines():
    line = line.strip()
    ec_nums.append(line)

for ec_num in ec_nums:
    if "-" in ec_num:
        continue
    print(ec_num)
    res = []
    request = REST.kegg_get("ec:"+ec_num)
    open(r"enzymes\ec_"+ec_num+".txt", 'w').write(request.read())
    records = Enzyme.parse(open(r"enzymes\ec_"+ec_num+".txt"))
    record = list(records)[0]

    # locus_tag
    gene = ""
    for g in record.genes:
        if "LPN" in g:
            gene = g
    if gene != "":
        gene = ''.join(gene[1])
    res.append(gene)
    # EC Number
    ec_number = record.entry
    res.append(ec_number)
    # KEGG Ortholog
    f = open("ec_4.2.1.10.txt", 'r')
    orthologs = []
    for line in f.readlines():
        if line[:12] != "            ":
            keyword = line[:12]
        data = line[12:].strip()
        if "ORTHOLOGY" in keyword:
            orthologs.append(data)
    f.close()
    orth_str = ""
    for ortholog in orthologs:
        orth_str += ortholog + ", "
    res.append(orth_str)
    # KEGG Reaction
    reactions = record.reaction
    if len(reactions) > 1:
        reac_list = ""
        for reaction in reactions:
            reac_list += reaction + ', '
        res.append(reac_list)
    else:
        res.append(''.join(reactions))
    # Kegg Pathways
    pathways = record.pathway
    path_str = ""
    for pathway in pathways:
        id = pathway[1]
        path = pathway[2]
        path_str += id + ": " + path + ", "
    res.append(path_str)

    for i in range(len(res)):
        worksheet.write(row, col+i+1, res[i])
    row += 1

workbook.close() # close the workbook


import PythonBasics
from enum import Enum, unique
from abc import ABC, ABCMeta, abstractmethod

from PythonBasics.Classes import Engine
from PythonBasics.Enums import IgnitionConstants, VehicleConstants

class Vehicle:

    def __init__(self,
    bodyType: VehicleConstants.BodyType,
    vehicleType: VehicleConstants.VehicleType,
    engineType: Engine.EngineConstants.EngineType,
    fuelType: Engine.EngineConstants.FuelType ):
        self.Wheels = 1
        self.Gear = 1
        self.BodyType = VehicleConstants.BodyType.Nothing
        self.VehicleType = vehicleType
        self.EngineType = engineType
        self.FuelType = fuelType

        self.Engine = Engine.Engine(engineType,fuelType)

        print("Factory Setting for Power : {} HP".format(self.Engine.power))

        if (isinstance (bodyType,VehicleConstants.BodyType)):
            self.bodyType = bodyType

        if (isinstance(vehicleType, VehicleConstants.VehicleType)):
            self.vehicleType = vehicleType

   # @abstractmethod
    def startEngine(self):
        self.Engine.crankIgnition()
        print("{} has started".format(self.VehicleType.name))

# if __name__ == "__main__":

#     vehicle = Vehicle(BodyType.Fiber,
#     VehicleType.Nothing,
#     Engine.EngineConstants.EngineType.ThermalEngine,
#     Engine.EngineConstants.FuelType.Petrol)

#     vehicle.Wheels = 4
#     print(vehicle.Engine.FuelType)