import tkinter as tk
import tkinter.messagebox
from tkinter import ttk
from Control import database_creator as dc
from Control import get_, validation

# Placeholder Function: Allow sample input to be shown
def on_focus_in(entry):
    if entry.cget('state') == 'disabled':
        entry.configure(state='normal')
        entry.delete(0, 'end')

def on_focus_out(entry, placeholder):
    if entry.get() == "":
        entry.insert(0, placeholder)
        entry.configure(state='disabled')

# Driver window
def driver(window, system):
    def load_data():
        head_driver = ("id", "name", "phone_num", "vehicle_id", "salary", "gender", "age")
        for heading_name in head_driver:
            treeview.heading(heading_name, text=heading_name)
        for driver in system.get_list("driver"):
            treeview.insert('', tk.END, values=(
                driver.get_id(), driver.get_name(), driver.get_phone_num(), driver.get_vehicle_id(),
                driver.get_salary(),
                driver.get_gender(), driver.get_age()))

        head_vehicle = "unassigned_vehicle_id"
        treeview_vehicle.heading(head_vehicle, text=head_vehicle)
        for vehicle in dc.create_unassigned_vehicle_list(system):
            treeview_vehicle.insert('', tk.END, values=vehicle)

    def delete_driver_data():
        id = id_entry.get()
        if id not in get_.driver_id_list(system):
            tkinter.messagebox.showerror("Error", "Driver ID not found", parent=window)
            id_entry.delete(0, tk.END)
            return
        driver_name, driver_phone_num, driver_vehicle_id, driver_salary, driver_gender, driver_age = get_.driver_data(
            system, id)
        system.delete_object("driver", id)
        get_.vehicle_assignment(system, driver_vehicle_id, "unassigned")
        for row in treeview.get_children():
            if treeview.item(row) == {'text': '', 'image': '',
                                      'values': [id, driver_name, driver_phone_num, str(driver_vehicle_id),
                                                 driver_salary,
                                                 driver_gender, driver_age], 'open': 0, 'tags': ''}:
                treeview.delete(row)
                if str(driver_vehicle_id) == 'None':
                    id_entry.delete(0, tk.END)
                    return
                else:
                    treeview_vehicle.insert('', tk.END, values=driver_vehicle_id)
                    id_entry.delete(0, tk.END)

    def enter_driver_data():
        name = name_entry.get()
        phone_num = phone_num_entry.get()
        vehicle_id = vehicle_id_entry.get()

        salary = salary_entry.get()
        gender = gender_combobox.get()
        age = age_spinbox.get()
        if vehicle_id == '#S###':
            vehicle_id = "None"
        if not validation.is_valid_name(name) or name == "Enter name":
            tkinter.messagebox.showwarning(title="Error", message="Invalid name", parent=window)
        elif not validation.is_valid_phone_number(phone_num) or phone_num == "0### ### ###":
            tkinter.messagebox.showwarning(title="Error", message="Invalid Phone Number", parent=window)
        elif not validation.is_valid_gender(gender):
            tkinter.messagebox.showwarning(title="Error", message="Invalid Gender", parent=window)
        elif not validation.is_valid_vehicle_id(vehicle_id):
            tkinter.messagebox.showwarning(title="Error", message="Invalid Vehicle ID", parent=window)
        elif validation.exist_vehicle_id(system, vehicle_id) == 1:
            tkinter.messagebox.showwarning(title="Error", message="Vehicle already assigned", parent=window)
        elif validation.exist_vehicle_id(system, vehicle_id) == 0:
            tkinter.messagebox.showwarning(title="Error", message="Vehicle doesn't exist", parent=window)
        elif not validation.is_valid_age(age):
            tkinter.messagebox.showwarning(title="Error", message="Invalid Age", parent=window)
        else:
            driver_id = dc.create_driver_id(system)
            # appending the value into
            if vehicle_id in dc.create_unassigned_vehicle_list(system):
                for row in treeview_vehicle.get_children():
                    if treeview_vehicle.item(row) == {'text': '', 'image': '', 'values': [vehicle_id], 'open': 0,
                                                      'tags': ''}:
                        treeview_vehicle.delete(row)
                        break
            if vehicle_id != 'None':
                get_.vehicle_assignment(system, vehicle_id, "assign")
            row_values = [driver_id, name, phone_num, vehicle_id, salary, gender, age]
            system.set_new_driver(row_values)

            treeview.insert('', tk.END, values=row_values)

            name_entry.delete(0, "end")
            phone_num_entry.delete(0, "end")
            vehicle_id_entry.delete(0, "end")
            salary_entry.delete(0, "end")
            gender_combobox.delete(0, "end")

    def select_driver_data():
        # Disable placeholder
        name_entry.configure(state='normal')
        phone_num_entry.configure(state='normal')
        vehicle_id_entry.configure(state='normal')
        salary_entry.configure(state='normal')
        gender_combobox.configure(state='normal')
        age_spinbox.configure(state='normal')

        # Clear boxes
        name_entry.delete(0, "end")
        phone_num_entry.delete(0, "end")
        vehicle_id_entry.delete(0, "end")
        salary_entry.delete(0, "end")
        gender_combobox.delete(0, "end")
        age_spinbox.delete(0, "end")

        # Grab row to update
        selected = treeview.focus()

        # Grab data
        values = treeview.item(selected, 'values')

        # Output data to boxes
        name_entry.insert(0, values[1])
        phone_num_entry.insert(0, values[2])
        vehicle_id_entry.insert(0, values[3])
        salary_entry.insert(0, values[4])
        gender_combobox.insert(0, values[5])
        age_spinbox.insert(0, values[6])

    def update_driver_data():
        name = name_entry.get()
        phone_num = phone_num_entry.get()
        vehicle_id = vehicle_id_entry.get()
        salary = salary_entry.get()
        gender = gender_combobox.get()
        age = age_spinbox.get()
        if not validation.is_valid_name(name) or name == "Enter name":
            tkinter.messagebox.showwarning(title="Error", message="Invalid name", parent=window)
        elif not validation.is_valid_phone_number(phone_num) or phone_num == "0### ### ###":
            tkinter.messagebox.showwarning(title="Error", message="Invalid Phone Number", parent=window)
        elif not validation.is_valid_vehicle_id(vehicle_id) or vehicle_id == "#S###":
            # need to check whether the vehicle actually exist or available for assignment also bug
            tkinter.messagebox.showwarning(title="Error", message="Invalid Vehicle ID", parent=window)
        elif validation.exist_vehicle_id(system, vehicle_id) == 2:
            tkinter.messagebox.showwarning(title="Error", message="Vehicle already assigned", parent=window)
        elif validation.exist_vehicle_id(system, vehicle_id) == 0:
            tkinter.messagebox.showwarning(title="Error", message="Vehicle doesn't exist", parent=window)
        elif validation.exist_vehicle_id(system, vehicle_id) == 1:
            tkinter.messagebox.showwarning(title="Error", message="Vehicle already assigned", parent=window)
        elif not validation.is_valid_gender(gender):
            tkinter.messagebox.showwarning(title="Error", message="Invalid Gender", parent=window)
        elif not validation.is_valid_age(age):
            tkinter.messagebox.showwarning(title="Error", message="Invalid Age", parent=window)
        else:
            # To get the values[0] == id, not other values
            selected = treeview.focus()
            values = treeview.item(selected, 'values')
            if vehicle_id != values[3]:
                get_.vehicle_assignment(system, values[3], "unassigned")
                get_.vehicle_assignment(system, vehicle_id, "assign")

            updated_data = [values[0], name, phone_num, vehicle_id, salary, gender, age]
            system.update_driver(updated_data)
            treeview.item(selected, text="", values=(values[0], name, phone_num, vehicle_id, salary, gender, age))

            # if the treeview_vehicle is empty, and the value[3] is not None, then insert the value[3] into the
            # treeview_vehicle
            if values[3] != vehicle_id and vehicle_id != 'None' and values[3] != 'None':
                for row in treeview_vehicle.get_children():
                    print(treeview_vehicle.item(row))
                    if treeview_vehicle.item(row) == {'text': '', 'image': '', 'values': [vehicle_id], 'open': 0,
                                                      'tags': ''}:
                        treeview_vehicle.delete(row)
                        treeview_vehicle.insert('', tk.END, values=[values[3]])
            elif values[3] != vehicle_id and vehicle_id == 'None' and values[3] != 'None':
                treeview_vehicle.insert('', tk.END, values=[values[3]])
            elif values[3] != vehicle_id and vehicle_id != 'None' and values[3] == 'None':
                for row in treeview_vehicle.get_children():
                    print(treeview_vehicle.item(row))
                    if treeview_vehicle.item(row) == {'text': '', 'image': '', 'values': [vehicle_id], 'open': 0,
                                                      'tags': ''}:
                        treeview_vehicle.delete(row)

                # treeview_vehicle.insert('', tk.END, values=[vehicle_id])

            name_entry.delete(0, "end")
            phone_num_entry.delete(0, "end")
            vehicle_id_entry.delete(0, "end")
            salary_entry.delete(0, "end")
            gender_combobox.delete(0, "end")
            age_spinbox.delete(0, "end")

    def clear_driver_data():
        # Disable placeholder
        name_entry.configure(state='normal')
        phone_num_entry.configure(state='normal')
        vehicle_id_entry.configure(state='normal')
        salary_entry.configure(state='normal')
        gender_combobox.configure(state='normal')
        age_spinbox.configure(state='normal')

        # Clear boxes
        name_entry.delete(0, "end")
        phone_num_entry.delete(0, "end")
        vehicle_id_entry.delete(0, "end")
        salary_entry.delete(0, "end")
        gender_combobox.delete(0, "end")
        age_spinbox.delete(0, "end")

    def search_driver_data():
        search_by = search_by_combobox.get()
        if search_by == "":
            tkinter.messagebox.showwarning(title="Error", message="Please select a search option", parent=window)
            # delete input in search entry
            search_ent_var.set("")
            return
        else:
            items_on_treeview = treeview.get_children()
            search_phone_num = search_ent_var.get()
            if search_by == "Driver ID":
                for item in items_on_treeview:
                    if search_phone_num in str(treeview.item(item)['values'][0]):
                        # Put the search result on the top of the treeview and highlight it
                        treeview.move(item, '', 0)
                        treeview.selection_set(item)
            if search_by == "Name":
                for item in items_on_treeview:
                    if search_phone_num in str(treeview.item(item)['values'][1]):
                        # Put the search result on the top of the treeview and highlight it
                        treeview.move(item, '', 0)
                        treeview.selection_set(item)
            if search_by == "Vehicle ID":
                for item in items_on_treeview:
                    if search_phone_num in str(treeview.item(item)['values'][3]):
                        # Put the search result on the top of the treeview and highlight it
                        treeview.move(item, '', 0)
                        treeview.selection_set(item)
            if search_by == "Phone Number":
                for item in items_on_treeview:
                    if search_phone_num in str("0" + str(treeview.item(item)['values'][2])):
                        # Put the search result on the top of the treeview and highlight it
                        treeview.move(item, '', 0)
                        treeview.selection_set(item)

    def search_unassigned_vehicle_data():
        items_on_treeview = treeview_vehicle.get_children()
        search_vehicle_id = search_ent_unassigned_vehicle_id.get()
        for item in items_on_treeview:
            if search_vehicle_id in str(treeview_vehicle.item(item)['values'][0]):
                # Put the search result on the top of the treeview and highlight it
                treeview_vehicle.move(item, '', 0)
                treeview_vehicle.selection_set(item)

    # ============== Main window and Frames  ============== #
    # check if a frame already exists in the window grid in position 0,1 (row 0, column 1) and destroy it
    if len(window.grid_slaves(row=0, column=1)) > 0:
        window.grid_slaves(row=0, column=1)[0].destroy()

    # Main frame
    driver_frame = ttk.Frame(window)
    driver_frame.grid(row=0, column=1, padx=20, pady=10)

    # Frame for adding and modifying information
    driver_info_frame = tk.LabelFrame(driver_frame, text="Driver info")
    driver_info_frame.grid(row=0, column=0, padx=20, pady=10)

    # Frame for deleting the data
    delete_driver_info_frame = tk.LabelFrame(driver_frame, text="Delete Driver")
    delete_driver_info_frame.grid(row=1, column=0, pady=10)

    # Frame for searching the driver phone number
    search_driver_info_frame = tk.LabelFrame(driver_frame, text="Search Customer by Phone Number")
    search_driver_info_frame.grid(row=1, column=1, pady=10)

    # Frame for searching unassigned vehicle
    search_unassigned_vehicle_frame = tk.LabelFrame(driver_frame, text="Search Unassigned Vehicle")
    search_unassigned_vehicle_frame.grid(row=1, column=2, pady=10)

    # ============== Basic information ============== #
    # name
    name_label = tk.Label(driver_info_frame, text="Name")
    name_label.grid(row=0, column=0)
    name_entry = tk.Entry(driver_info_frame)
    name_entry.configure(state='disabled')
    name_entry.grid(row=1, column=0)

    # phone number
    phone_num_label = tk.Label(driver_info_frame, text="Phone Number")
    phone_num_label.grid(row=0, column=1)
    phone_num_entry = tk.Entry(driver_info_frame)
    phone_num_entry.insert(0, "0### ### ###")
    phone_num_entry.configure(state='disabled')
    phone_num_entry.grid(row=1, column=1)

    # vehicle_id
    vehicle_id_label = tk.Label(driver_info_frame, text="Vehicle ID")
    vehicle_id_label.grid(row=0, column=2)
    vehicle_id_entry = tk.Entry(driver_info_frame)
    vehicle_id_entry.insert(0, "#S###")
    vehicle_id_entry.configure(state='disabled')
    vehicle_id_entry.grid(row=1, column=2)

    # salary
    salary_label = tk.Label(driver_info_frame, text="Salary")
    salary_label.grid(row=2, column=0)
    salary_entry = tk.Entry(driver_info_frame)
    salary_entry.grid(row=3, column=0)

    # gender
    gender_combo_list = ["Male", "Female", "Other"]
    gender_label = tk.Label(driver_info_frame, text="Gender")
    gender_label.grid(row=2, column=1)
    gender_combobox = ttk.Combobox(driver_info_frame, values=gender_combo_list)

    gender_combobox.grid(row=3, column=1)

    # age
    age_label = tk.Label(driver_info_frame, text="Age")
    age_label.grid(row=2, column=2)
    age_spinbox = tk.Spinbox(driver_info_frame, from_=18, to=200)
    age_spinbox.grid(row=3, column=2)

    # Id
    id_label = tk.Label(delete_driver_info_frame, text="Driver ID")
    id_label.grid(row=0, column=0)
    id_entry = tk.Entry(delete_driver_info_frame)
    id_entry.insert(0, "D#")
    id_entry.configure(state='disabled')
    id_entry.grid(row=1, column=0)

    # Search by
    search_by_combo_list = ["Driver ID", "Name", "Phone Number", "Vehicle ID"]
    search_by_label = tk.Label(search_driver_info_frame, text="Search by")
    search_by_label.grid(row=0, column=0)
    search_by_combobox = ttk.Combobox(search_driver_info_frame, values=search_by_combo_list)
    search_by_combobox.grid(row=1, column=0)

    # Search box
    search_label = tk.Label(search_driver_info_frame, text="Search")
    search_label.grid(row=0, column=1)
    search_ent_var = tk.Variable()
    search_entry = tk.Entry(search_driver_info_frame, textvariable=search_ent_var)
    search_entry.grid(row=1, column=1)
    search_ent_var.trace("w", lambda name, index, mode, sv=search_ent_var: search_driver_data())

    # Search unassigned vehicles
    search_unassigned_vehicle_id_label = tk.Label(search_unassigned_vehicle_frame, text="Search")
    search_unassigned_vehicle_id_label.grid(row=0, column=0)
    search_ent_unassigned_vehicle_id = tk.Variable()
    search_unassigned_vehicle_id_entry = tk.Entry(search_unassigned_vehicle_frame,
                                                  textvariable=search_ent_unassigned_vehicle_id)
    search_unassigned_vehicle_id_entry.grid(row=1, column=0)
    search_ent_unassigned_vehicle_id.trace("w", lambda name, index, mode,
                                           sv=search_ent_unassigned_vehicle_id: search_unassigned_vehicle_data())

    # ============== Modification Buttons ============== #
    # Add button
    add_button = ttk.Button(driver_info_frame, text="Enter data", command=enter_driver_data, style="Accent.TButton")
    add_button.grid(row=4, column=0, sticky="news", padx=20, pady=10)

    # Select button
    select_button = ttk.Button(driver_info_frame, text="Select data", command=select_driver_data,
                               style="Accent.TButton")
    select_button.grid(row=5, column=0, sticky="news", padx=20, pady=10)

    # Update button
    update_button = ttk.Button(driver_info_frame, text="Update data", command=update_driver_data,
                               style="Accent.TButton")
    update_button.grid(row=5, column=1, sticky="news", padx=20, pady=10)

    # Clear button
    clear_button = ttk.Button(driver_info_frame, text="Clear data", command=clear_driver_data, style="Accent.TButton")
    clear_button.grid(row=5, column=2, sticky="news", padx=20, pady=10)

    # Delete button
    delete_button = ttk.Button(delete_driver_info_frame, text="Delete data", command=delete_driver_data,
                               style="Accent.TButton")
    delete_button.grid(row=1, column=1, sticky="news", padx=20, pady=10)

    # Regridding widgets
    for widget in driver_info_frame.winfo_children():
        widget.grid_configure(padx=10, pady=5)

    for widget in search_unassigned_vehicle_frame.winfo_children():
        widget.grid_configure(padx=10, pady=5)

    for widget in search_driver_info_frame.winfo_children():
        widget.grid_configure(padx=10, pady=5)

    # ============== Others ============== #
    # Disable placeholder
    name_entry.bind('<Button-1>', lambda x: on_focus_in(name_entry))
    name_entry.bind('<FocusOut>', lambda x: on_focus_out(name_entry, 'Enter name'))

    phone_num_entry.bind('<Button-1>', lambda x: on_focus_in(phone_num_entry))
    phone_num_entry.bind('<FocusOut>', lambda x: on_focus_out(phone_num_entry, '0### ### ###'))

    vehicle_id_entry.bind('<Button-1>', lambda x: on_focus_in(vehicle_id_entry))
    vehicle_id_entry.bind('<FocusOut>', lambda x: on_focus_out(vehicle_id_entry, '#S###'))

    id_entry.bind('<Button-1>', lambda x: on_focus_in(id_entry))
    id_entry.bind('<FocusOut>', lambda x: on_focus_out(id_entry, 'D#'))

    treeFrame = ttk.Frame(driver_frame)
    treeFrame.grid(row=0, column=1, pady=10)
    treeScroll = ttk.Scrollbar(treeFrame)
    treeScroll.pack(side="right", fill="y")
    cols = ("id", "name", "phone_num", "vehicle_id", "salary", "gender", "age")
    treeview = ttk.Treeview(treeFrame, show="headings", yscrollcommand=treeScroll.set, columns=cols, height=13)
    treeview.column("id", width=70)
    treeview.column("name", width=100)
    treeview.column("phone_num", width=130)
    treeview.column("vehicle_id", width=100)
    treeview.column("salary", width=110)
    treeview.column("gender", width=70)
    treeview.column("age", width=50)
    treeview.pack()
    treeScroll.config(command=treeview.yview())

    # ============== Treeview to show available vehicle ============== #
    treeFrame_vehicle = ttk.Frame(driver_frame)
    treeFrame_vehicle.grid(row=0, column=2, pady=10)
    treeScroll_vehicle = ttk.Scrollbar(treeFrame_vehicle)
    treeScroll_vehicle.pack(side="right", fill="y")
    cols_vehicle = "unassigned_vehicle_id"
    treeview_vehicle = ttk.Treeview(treeFrame_vehicle, show="headings", yscrollcommand=treeScroll_vehicle.set,
                                    columns=cols_vehicle, height=13)
    treeview_vehicle.column("unassigned_vehicle_id", width=155)
    treeview_vehicle.pack()
    treeScroll_vehicle.config(command=treeview_vehicle.yview())

    load_data()


import json
import threading
import time
import traceback
from base64 import b64decode
from urllib.parse import quote_plus
from zlib import decompress, MAX_WBITS

import requests
import websocket

NAME = 'Bittrex'

class BittrexWebsocket:

    def __init__(self, symbol):
        """Constructor"""
        self.__symbol = symbol
        self.__token = ""
        self.__orderbook_bid = {}
        self.__orderbook_ask = {}
        self.__ws = None

        # Constants
        self.__NAME = 'Bittrex'
        self.__REST_ENDPOINT = "https://socket.bittrex.com/signalr/"
        self.__WS_ENDPOINT = "wss://socket.bittrex.com/signalr/"
        self.__TRANSPORT = "webSockets"
        self.__CLIENT_PROTOCOL = "1.5"
        self.__CONNECTION_DATA = "%5B%7B%22name%22%3A%22c2%22%7D%5D"

    def __get_conn_token(self):
        r = requests.get(f'{self.__REST_ENDPOINT}negotiate?'
                         f'clientProtocol={self.__CLIENT_PROTOCOL}&'
                         f'connectionData={self.__CONNECTION_DATA}'
                         f'&_={time.time()}')
        if r is not None:
            self.__token = quote_plus(json.loads(r.text)['ConnectionToken'])
        self.__TID = "3"

    def __start_ws(self):
        self.__get_conn_token()
        r = requests.get(
            f'{self.__REST_ENDPOINT}start?'
            f'transport={self.__TRANSPORT}&'
            f'clientProtocol={self.__CLIENT_PROTOCOL}&'
            f'connectionToken={self.__token}&'
            f'connectionData={self.__CONNECTION_DATA}&'
            f'_={time.time()}'
        )
        if r is not None:
            if json.loads(r.text)['Response'] == 'started':
                return True
        return False

    @staticmethod
    def __process_message(message):
        try:
            deflated_msg = decompress(b64decode(message, validate=True), -MAX_WBITS)
        except SyntaxError:
            deflated_msg = decompress(b64decode(message, validate=True))
        return json.loads(deflated_msg.decode())

    def __on_message(self, message):
        message = json.loads(message)
        # print(message)

        if "R" in message:
            message = self.__process_message(message['R'])
            # print(message)
            self.__orderbook_bid = dict((x['R'], x['Q']) for x in message['Z'])
            self.__orderbook_ask = dict((x['R'], x['Q']) for x in message['S'])

        if "M" in message and len(message['M']) > 0:
            message = message["M"][0]
            if 'A' in message and len(message['A']) > 0:
                message = self.__process_message(message['A'][0])
                # print(message)

                for x in message['Z']:
                    if x['TY'] == 0 or x['TY'] == 2:
                        self.__orderbook_bid.update({x['R']: x['Q']})
                    if x['TY'] == 1:
                        self.__orderbook_bid.pop(x['R'])
                for x in message['S']:
                    if x['TY'] == 0 or x['TY'] == 2:
                        self.__orderbook_ask.update({x['R']: x['Q']})
                    if x['TY'] == 1:
                        self.__orderbook_ask.pop(x['R'], None)

                ask = list(sorted(self.__orderbook_ask.keys()))[0]
                bid = list(sorted(self.__orderbook_bid.keys(), reverse=True))[0]
                bid_amount = self.__orderbook_bid[bid]
                ask_amount = self.__orderbook_ask[ask]

                print(self.__symbol, json.dumps({
                    'bid': bid,
                    'ask': ask,
                    'bid_amount': bid_amount,
                    'ask_amount': ask_amount,
                    'timestamp': int(time.time() * 1000)
                }))

                # print(self.__orderbook_bid)
                # print(self.__orderbook_ask)

    def __on_error(self, error):
        print(f'ws{self.__NAME}: {error}')

    def __on_close(self):
        print(f'ws{self.__NAME}: {"closed"}')

    def __on_open(self):
        print(f'ws{self.__NAME} subscribe {self.__symbol}')

        symbol = self.__symbol.split('_')[1] + '-' + self.__symbol.split('_')[0]
        self.__ws.send(json.dumps({"H": "c2", "M": "SubscribeToExchangeDeltas", "A": [symbol], "I": 3}))
        self.__ws.send(json.dumps({"H": "c2", "M": "QueryExchangeState", "A": [symbol], "I": 7}))

    def run(self):
        if self.__start_ws():
            self.__ws = websocket.WebSocketApp(
                f"{self.__WS_ENDPOINT}connect?"
                f"transport={self.__TRANSPORT}&"
                f"clientProtocol={self.__CLIENT_PROTOCOL}&"
                f"connectionToken={self.__token}&"
                f"connectionData={self.__CONNECTION_DATA}",
                on_open=self.__on_open,
                on_message=self.__on_message,
                on_error=self.__on_error,
                on_close=self.__on_close)

            self.__ws.run_forever()

def run_ws(symbol):
    bittrex = BittrexWebsocket(symbol)
    bittrex.run()

if __name__ == "__main__":
    try:
        SYMBOLS = ['ETH_BTC',
                   'ETH_USDT',
                   'BTC_USDT',
                   'LTC_BTC',
                   'LTC_ETH',
                   'LTC_USDT'
                   ]

        print(f'ws{NAME}: start')

        for s in SYMBOLS:
            th = threading.Thread(target=run_ws, kwargs={'symbol': s})
            th.start()
    except KeyboardInterrupt:
        exit()
    except:
        print(traceback.format_exc())


import ctypes

#dlls

kernel32 = ctypes.windll.kernel32

#process permissions

PROCESS_QUERY_INFORMATION = (0x0400)
PROCESS_VM_OPERATION = (0x0008)
PROCESS_VM_READ = (0x0010)
PROCESS_VM_WRITE = (0x0020)
PROCESS_ALL_ACCESS = (0x1F0FFF)

#win apis

OpenProcess = kernel32.OpenProcess
CloseHandle = kernel32.CloseHandle
GetLastError = kernel32.GetLastError
ReadProcessMemory = kernel32.ReadProcessMemory
WriteProcessMemory = kernel32.WriteProcessMemory

class ReadWriteMem:

    def OpenProcess(self, processPID):
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, processPID)

        return hProcess

    def CloseHandle(self, hProcess):
        CloseHandle(hProcess)

    def GetLastError(self):
        GetLastError()

        return GetLastError()

    def ReadProcessMemory(self, hProcess, MemAddress):
        try:
            MemValue = ctypes.c_uint()
            MemValueSize = ctypes.sizeof(MemValue)

            ReadProcessMemory(hProcess, MemAddress, ctypes.byref(MemValue), MemValueSize, None)

            return MemValue.value

        except(BufferError, ValueError, TypeError):
            CloseHandle(hProcess)
            error = "Handle closed. Error:", hProcess, GetLastError()

            return error

    def WriteProcessMemory(self, hProcess, MemAddress, Value):
        try:
            ValueBuffer = ctypes.c_int(Value)
            ValueBufferSize = ctypes.sizeof(ValueBuffer)

            WriteProcessMemory(hProcess, MemAddress, ctypes.byref(ValueBuffer), ValueBufferSize, None)

        except(BufferError, ValueError, TypeError):
            CloseHandle(hProcess)
            error = "Handle closed. Error:", hProcess, GetLastError()

            return error

rwm = ReadWriteMem()


# %%
from concurrent import futures
import os
import time
import grpc
import json
import uuid
import shutil
import grpc.basic_pb2 as basic_pb2
import grpc.basic_pb2_grpc as basic_pb2_grpc
from ner.trainer import NERTrainer

# %%
class Task(basic_pb2_grpc.TaskServicer):

    def createTrain(self, request, context):
        guid = str(uuid.uuid1()).split('-')[0]
        save_dir = './tmp/{}'.format(guid)
        os.makedirs(save_dir)
        required_list = {
            'bert_config_file': False,
            'pretrained_file': False,
            'train_file': False,
            'vocab_file': False,
            'tags_file': False,
            'eval_file': False
        }
        for r in request:
            cur_name = r.name
            required_list[r.name] = True
            with open(os.path.join(save_dir, cur_name), 'ab') as f:
                f.write(r.file)
        for key in required_list.keys():
            if not required_list[key]:
                shutil.rmtree(save_dir)
                return basic_pb2.Response(status='failed', result='missing {}'.format(required_list[key]))
        return basic_pb2.Response(status='success', result=guid)

    def getModel(self, request, context):
        guid = request.guid
        model_id = request.model_id
        save_dir = './tmp/{}'.format(guid)
        model_dir = './save_model'
        if not os.path.isfile(os.path.join(model_dir, 'bert', '{}_bert.pth'.format(model_id))):
            yield basic_pb2.FileBody(file=None, name='missing model file')
        common_files = os.listdir(save_dir)
        for fi in common_files:
            with open(os.path.join(save_dir, fi), mode='rb') as f:
                lines = f.readlines()
            for line in lines:
                yield basic_pb2.FileBody(file=line, name=fi)
        with open(os.path.join(model_dir, 'bert', '{}_bert.pth'.format(model_id)), mode='rb') as f:
                lines = f.readlines()
        for line in lines:
            yield basic_pb2.FileBody(file=line, name=fi)
        with open(os.path.join(model_dir, 'lstm_crf', '{}_lstm_crf.pth'.format(model_id)), mode='rb') as f:
                lines = f.readlines()
        for line in lines:
            yield basic_pb2.FileBody(file=line, name=fi)

    def createPredict(self, request, context):
        guid = request.guid
        return basic_pb2.Response(status='success', result=guid)

class Train(basic_pb2_grpc.TrainServicer):

    def train(self, request, context):
        save_dir = './tmp/{}'.format(request.guid)
        trainer = NERTrainer(request.num_epochs, request.num_gpus,
            bert_config_file_name= os.path.join(save_dir, 'bert_config_file'),
            pretrained_file_name= os.path.join(save_dir, 'pretrained_file'),
            hidden_dim= request.hidden_dim,
            train_file_name= os.path.join(save_dir, 'train_file'),
            vocab_file_name= os.path.join(save_dir, 'vocab_file'),
            tags_file_name= os.path.join(save_dir, 'tags_file'),
            eval_file_name= os.path.join(save_dir, 'eval_file'),
            batch_size=request.batch_size,
            eval_batch_size=request.eval_batch_size)
        for info in trainer():
            yield basic_pb2.Response(status='training', result=json.dumps(info))

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    basic_pb2_grpc.add_TaskServicer_to_server(Task(), server)
    basic_pb2_grpc.add_TrainServicer_to_server(Train(), server)
    server.add_insecure_port('[::]:8088')
    server.start()

    try:
        while True:
            time.sleep(60*60*24)
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    serve()

# %%


from django import template
from ..models import BlogTag, Blog
import datetime
import math

register = template.Library()

@register.inclusion_tag('blog/blog_tag_list.html')
def blog_tag_list():
    tags = list(set(BlogTag.objects.all()))
    for article in Blog.objects.all():
        for tag in article.get_all_tags():
            if not tag in tags:
                tags.append(tag)
    return {
        'tags': tags,
    }

@register.inclusion_tag('blog/blog_archive.html')
def blog_archive():
    m_list = []

    def add2m_list(dt):
        ndt = datetime.datetime(dt.year, dt.month, 1)
        if ndt not in m_list:
            m_list.append(ndt)

    for m in Blog.objects.values_list('date'):
        add2m_list(m[0])

    cs = int(math.ceil(len(m_list) / 2))
    m_lists = [
        m_list[:cs],
        m_list[cs:],
    ]

    return {
        'month_lists': m_lists
    }


"""
4▹ Napisz funkcję, która sprawdzi, czy liczba występuje w podanym przez użytkownika zakresie.
Powinna zwrócić komunikat: “tak, liczba x znajduje się w zadanym zakresie”, “nie, liczba x jest z poza zakresu”.
"""

def ask():
    q1 = int(input('Podaj zakres dolny: \n'))
    q2 = int(input('Podaj zakres górny \n'))
    szukana = int(input('Podaj liczbę \n'))
    return q1, q2, szukana

def test(a, b):
    return (a, b) if (a < b) else ((b, a))

def group(a, b, x):
    (a, b) = test(a, b)
    if (x >= a and x <= b):
        print('Dolny zakres', a, 'Górny zakres', b)
        print('Tak, liczba x znajduje się w zadanym zakresie. \n')

    else:
        print('Dolny zakres', a, 'Górny zakres', b)
        print('Nie, liczba x jest z poza zakresu. \n')

(m, n, x) = ask()
sprawdzenie = group(m, n, x)


from mainLibrary import CompleteModelReview, EvaluateModel , CompareModels, RetrainModels

# set properties
enviroment_name = 'Seaquest-v4'
policy = 'CnnPolicy'
algorithm = 'PPO'
n_envs=4
n_stack=4
total_timesteps=1000000
seed=0
verbose=1
environment_type = "Atari"
learning_rate = None
gamma = None
is_image_based = True
eval_episodes = 10

algorithms = ["PPO","A2C"]

# model_save_path2 = 'models/PPO_Atlantis-v4_CnnPolicy_timestepes:300000_gamma_None_learningRate_None'
# model_save_path = 'models/PPO_CnnPolicy_timestepes:300000_gamma:None_learningRate_None'

# evaluateModel= EvaluateModel(model_save_path, enviroment_name,
#                              eval_episodes,algorithm,n_envs, environment_type , is_image_based, seed, n_stack)
# evaluateModel.evaluateModel()

newModel = CompleteModelReview(enviroment_name, algorithm, policy, n_envs, n_stack, seed,
                 verbose,total_timesteps,environment_type, learning_rate, gamma, is_image_based,eval_episodes)
is_imageBased = newModel.analyzeEnv()
newModel.is_image_based = is_imageBased
newModel.trainModel()
newModel.evaluateModel()

# compareModels = CompareModels(enviroment_name, algorithm, policy, n_envs, n_stack, seed,
#                  verbose,total_timesteps,environment_type, learning_rate, gamma, is_image_based,eval_episodes, algorithms)

# compareModels.Compare()

# model = RetrainModels(total_timesteps,algorithm, model_save_path, environment_type,
#                       enviroment_name, n_envs, seed, is_image_based, n_stack,eval_episodes)

# model.Retrain()


import os
import sys
import pandas

from framework.module import Module
from framework.sources.profiler import Profiler

class Profiler_module(Module):

    def __init__(self):

        super().__init__()

        self.pickle_file = None

    def get_name(self):

        return 'profiler'

    def get_desc(self):

        return 'Qualcomm Snapdragon Profiler data'

    def get_help(self):

        text = '''
    半自动方式抓取、解析SnapdragonProfiler提供的所有数据
    (需要PC端安装高通Profiler工具)

    > tracecat "trace:profiler(cpu_branch_miss),profiler(cpu_cache_miss)"
      抓取cpu_branch_miss, cpu_cache_miss，开始后命令行会进入等待，请手动运行
      profiler，并在profiler中启动这些数据的抓取，然后在命令行按y继续。抓取结束
      后，命令行再次进入等待，请手动停止profiler，并将结果导出到./runs/xxx/prof
      iler/profiler.csv，然后按y继续。
    > tracecat "parse:profiler(cpu_branch_miss),profiler(cpu_cache_miss)"
      解析出cpu_branch_miss, cpu_cache_miss, cpu_clock
    > tracecat "chart:profiler(cpu_branch_miss)"
      显示cpu_branch_miss的图表

    当前支持的Metrics:
    ------------------------\n'''

        for metric, params in Profiler.metrics.items():

            text += '    ' + metric.ljust(24) + params['matcher'].replace('^', '').replace('$', '') + '\n'

        return text.rstrip()

    def invoke_sources(self):

        self.profiler = self.invoke_source('profiler')

    # Hijack module::save
    def save(self, pickle_file = None):

        return super().save(self.pickle_file)

    # Hijack module::export
    def export(self, excel_file = None):

        return super().export(self.excel_file)

    # Hijack module::load
    def load(self, pickle_file = None):

        if not pickle_file:

            self.results = pandas.DataFrame(['dummy'])

            return self.results

        return super().load(pickle_file)

    def do_parse(self, params):

        if not params:

            sys.exit('Please spicify a metrics for profiler module')

        metrics = params[0]

        self.pickle_file = self.workspace + self.get_name() + '_' + metrics + '.pkl'

        self.excel_file = self.workspace + self.get_name() + '_' + metrics + '.xlsx'

        results = self.profiler.get_metrics(metrics)

        return pandas.DataFrame(results)

    def do_chart(self, params, df):

        # load pickle file

        if not params:

            sys.exit('Please spicify a metrics for profiler module')

        metrics = params[0]

        pickle_file = self.workspace + self.get_name() + '_' + metrics + '.pkl'

        df = self.load(pickle_file)

        # draw chart

        if 'index' in df.columns:

            self.plotter.plot_index_chart(params[1:], df, metrics, index='index', x='timestamp', y=metrics, kind='line', marker='.')

        else:

            self.plotter.plot(df, metrics, x='timestamp', y=metrics, kind='line', marker='.')


# /**
# * @author Rajat Verma
# * https://www.linkedin.com/in/rajat-v-3b0685128/
# * https://github.com/rajatt95
# * https://rajatt95.github.io/
# *
# * Course: Learn API Automation Testing with Python & BDD Framework (https://www.udemy.com/course/python-sdet-rest-api-automation/)
# * Tutor: Rahul Shetty (https://www.udemy.com/user/rahul445/)
# */
#
# /***************************************************/

# https://realpython.com/python-requests/
# https://docs.python-requests.org/en/latest/
# Requests is an elegant and simple HTTP library for Python, built for human beings.
import requests
from PayLoad import *

# POST request
response_AddBook = requests.post('http://216.10.245.166/Library/Addbook.php',
                                 # Request Body
                                 json=addBookPayLoad("123f23221"),
                                 # 3rd argument takes information like Header
                                 headers={'Content-Type': 'application/json'},
                                 # 4th argument - Optional
                                 )

response_AddBook_InJSON = response_AddBook.json()
print(response_AddBook_InJSON['ID'])
book_ID = response_AddBook_InJSON['ID']

# DELETE request
response_deleteBook = requests.post('http://216.10.245.166/Library/DeleteBook.php',
              # Request Body
              json={"ID": book_ID},
              # 3rd argument takes information like Header
              headers={'Content-Type': 'application/json'},
              # 4th argument - Optional
              )
print(response_deleteBook.status_code)
response_deleteBook_InJSON = response_deleteBook.json()
print(response_deleteBook_InJSON['msg'])


import urllib.request as urlR
import time, re

###  Searching for new users  ###
def check( ):
    f_Old = open("old", 'r+');
    f_New = open("new", 'r');
    nowe = [];
    stare = [];
    test = [];

    ###  Add new and old users to arrays  ###
    for lineO in f_Old:
        stare.append(lineO)
    for lineN in f_New:
        nowe.append(lineN)

    '''  If in 'old' array element != 'new' array element pushing
        this new user to 'test' array  '''
    for i in range(0,len(nowe)):
        if nowe[i] not in stare:
            test.append(nowe[i])

    ###  Writing new users to 'old' file  ###
    for i in range(0,len(test)):
        f_Old.write(test[i]);

    ###  Showing new users  ###
    for i in range(0,len(test)):
        print(test[i])

    ###  Closing all files  ###
    f_New.close();
    f_Old.close();

def __main__():
    ###  Opening all needed files  ###
    urlString = open('source.txt','r')
    time.sleep(1);
    f_New = open("new", 'w+');

    ###  Reading a page  ###
    data = urlR.urlopen(urlString.read());
    nicks = re.findall(r'<a href="/+\w*', str(data.read()));
    i=0;
    for nick in nicks:
        if(i%2==0):
            f_New.write(nick[10:]+"\n");
        i=i+1;

    ###  Closing all files  ###
    f_New.close();

    check()

__main__();


class Solution:
    def isValid(self, s: str) -> bool:
        # use a stack
        # loop thru the entire input string
        # push every open bracket onto the stack
        # if you encounter a closing bracket, pop top off stack and
        # make a comparison. If valid pair, then continue.
        # Else return false.
        #
        # Edge cases:
        # 1) You encounter a closing bracket but the stack is empty. Return false.
        # 2) You loop thru the entire input string but the stack still
        # contains open brackets. Return false.
        #
        # Runtime: O(N) b/c the worst case is an input string with only
        # open brackets. You have to loop thru the entire input string.
        # Space used: O(N). Same worst case - input string contains only
        # open brackets. You use extra space proportional to the size of
        # this input string.

        my_stack = []
        for char in s:
            if char == '(' or char == '[' or char == '{':
                my_stack.append(char)
            else:
                # must be a closing bracket, b/c prompt says the string
                # contains only open or closing brackets.
                if len(my_stack) == 0:
                    return False
                top = my_stack.pop()
                if top == '(' and char != ')' or\
                top == '{' and char != '}' or\
                top == '[' and char != ']':
                    return False
        return False if len(my_stack) > 0 else True


from typing import *
from .Letters import *
from .SpecificPositions import SpecificPositions
from typing import Literal

Colors = Literal["red", "blue"]
MotionTypes = Literal["pro", "anti", "dash", "static"]
Locations = Literal["n", "e", "s", "w", "ne", "se", "sw", "nw"]
RotationDirections = Literal["cw", "ccw"]
Turns = float | Literal["fl", "0", "0.5", "1", "1.5", "2", "2.5", "3"]

### STAFF ATTRIBUTES ###

PropAttributes = Literal[
    "color", "prop_type", "location", "layer", "axis", "orientation"
]
PropTypes = Literal[
    "staff",
    "bigstaff",
    "buugeng",
    "club",
    "fan",
    "minihoop",
    "triad",
    "bigtriad",
    "bighoop",
    "doublestar",
    "bigdoublestar",
    "quiad",
    "sword",
    "guitar",
    "ukulele",
    "chicken",
]
Layers = Literal[1, 2]
Axes = Literal["vertical", "horizontal"]
Orientations = Literal[
    "in",
    "clock-in",
    "clock",
    "clock-out",
    "out",
    "counter-out",
    "counter",
    "counter-in",
]

OrientationCombinations = Literal[
    "in_vs_in",
    "in_vs_clock-in",
    "in_vs_clock",
    "in_vs_clock-out",
    "in_vs_out",
    "in_vs_counter-out",
    "in_vs_counter",
    "in_vs_counter-in",
    "clock-in_vs_clock-in",
    "clock-in_vs_clock",
    "clock-in_vs_clock-out",
    "clock-in_vs_out",
    "clock-in_vs_counter-out",
    "clock-in_vs_counter",
    "clock-in_vs_counter-in",
    "clock_vs_clock",
    "clock_vs_clock-out",
    "clock_vs_out",
    "clock_vs_counter-out",
    "clock_vs_counter",
    "clock_vs_counter-in",
    "clock-out_vs_clock-out",
    "clock-out_vs_out",
    "clock-out_vs_counter-out",
    "clock-out_vs_counter",
    "clock-out_vs_counter-in",
    "out_vs_out",
    "out_vs_counter-out",
    "out_vs_counter",
    "out_vs_counter-in",
    "counter-out_vs_counter-out",
    "counter-out_vs_counter",
    "counter-out_vs_counter-in",
    "counter_vs_counter",
    "counter_vs_counter-in",
    "counter-in_vs_counter-in",
]

RotationAngles = Literal[0, 90, 180, 270]
Positions = Literal["alpha", "beta", "gamma"]
Direction = Literal["right", "left", "down", "up"]
ColorsHex = Literal["#ED1C24", "#2E3192"]
LetterType = Literal[
    "Dual-Shift", "Shift", "Cross-Shift", "Dash", "Dual-Dash", "Static"
]

GridModes = Literal["Box", "Diamond"]

class SpecificStartEndPositionsDicts(TypedDict):
    start_position: SpecificPositions
    end_position: SpecificPositions

OptimalLocationsEntries = Dict[Literal["x", "y"], float]

class OptimalLocationsDicts(TypedDict):
    optimal_red_location: OptimalLocationsEntries
    optimal_blue_location: OptimalLocationsEntries

class PropAttributesDicts(TypedDict):
    color: Colors
    prop_type: PropTypes
    prop_location: Locations
    layer: Layers
    orientation: Orientations

### MOTION ATTRIBUTES ###
class MotionAttributesDicts(TypedDict):
    color: Colors
    motion_type: MotionTypes
    rotation_direction: RotationDirections
    location: Locations
    turns: Turns

    start_location: Locations
    start_orientation: Orientations
    start_layer: Layers

    end_location: Locations
    end_orientation: Orientations
    end_layer: Layers

class ArrowAttributesDicts(TypedDict):
    color: Colors
    location: Locations
    motion_type: MotionTypes
    turns: Turns

class MotionAttributesDicts(TypedDict):
    color: Colors
    motion_type: MotionTypes
    rotation_direction: RotationDirections
    turns: Turns
    start_location: Locations
    end_location: Locations
    start_orientation: Orientations
    end_orientation: Orientations
    start_layer: Layers
    end_layer: Layers

MotionTypesCombinations = Literal[
    "pro_vs_pro",
    "anti_vs_anti",
    "static_vs_static",
    "pro_vs_anti",
    "static_vs_pro",
    "static_vs_anti",
    "dash_vs_pro",
    "dash_vs_anti",
    "dash_vs_static",
    "dash_vs_dash",
]

StartEndLocationsTuple = Tuple[Locations, Locations]
PreprocessedStartEndCombinations = Dict[
    SpecificStartEndPositionsDicts,
    List[Tuple[Letters, List[MotionAttributesDicts]]],
]
OptimalLocationsDicts = Dict[str, OptimalLocationsEntries]
DictVariants = (
    MotionAttributesDicts | SpecificStartEndPositionsDicts | OptimalLocationsDicts
)
DictVariantsLists = List[DictVariants]
LetterDictionary = Dict[Letters, List[DictVariantsLists]]

Mode = Optional[Literal["TS", "TO", "SS", "SO", "QTS", "QTO"]]

class PictographAttributesDict(TypedDict):
    start_position: Positions
    end_position: Positions
    letter_type: LetterType
    mode: Mode
    motion_type_combination: MotionTypesCombinations

HybridCombinations = Literal[
    "pro_vs_anti",
    "static_vs_pro",
    "static_vs_anti",
    "dash_vs_pro",
    "dash_vs_anti",
    "dash_vs_static",
]

### LETTER GROUPS ###

LetterGroupsByMotionTypes = Literal[
    "ADGJMPS",
    "BEHKNQT",
    "CFILORUV",
    "WYΣθ",
    "XZΔΩ",
    "W-Y-Σ-θ-",
    "X-Z-Δ-Ω-",
    "ΦΨΛ",
    "Φ-Ψ-Λ-",
    "αβΓ",
]

MotionTypesLetterGroupMap = Dict[MotionTypesCombinations, LetterGroupsByMotionTypes]
ParallelCombinationsSet = Set[Tuple[str, str, str, str]]


import time
import pickle
from dolfin import *
set_log_level(LogLevel.ERROR)
import numpy as np
import numba

# import required functions from twoDim
from statFEM_analysis.twoDim import mean_assembler, kernMat, cov_assembler
from scipy.linalg import sqrtm
from tqdm import tqdm

# set up mean and kernel functions
f_bar = Constant(1.0)

σ_f = 0.1
κ = 4

@numba.jit
def c_f(x,y):
    return (σ_f**2)*np.exp(-κ*np.abs(x-y))

@numba.jit
def k_f(x):
    return (σ_f**2)*np.exp(-κ*np.abs(x))

def fem_prior(h,f_bar,k_f,grid):
    J = int(np.round(1/h))
    μ = mean_assembler(h,f_bar)
    Σ = cov_assembler(J,k_f,grid,False,True)
    return μ,Σ

N = 41
x_range = np.linspace(0,1,N)
grid = np.array([[x,y] for x in x_range for y in x_range])

def compute_cov_diff(C1,C2,tol=1e-10):
    N = np.sqrt(C1.shape[0])
    C1_sqrt = np.real(sqrtm(C1))
    rel_error_1 = np.linalg.norm(C1_sqrt @ C1_sqrt - C1)/np.linalg.norm(C1)
    assert rel_error_1 < tol

    C12 = C1_sqrt @ C2 @ C1_sqrt
    C12_sqrt = np.real(sqrtm(C12))
    rel_error_12 = np.linalg.norm(C12_sqrt @ C12_sqrt - C12)/np.linalg.norm(C12)
    assert rel_error_12 < tol

    hSq = (1/(N-1))**2
    return hSq*(np.trace(C1) + np.trace(C2) - 2*np.trace(C12_sqrt))

def W(μ_1,μ_2,Σ_1,Σ_2):
    mean_error = errornorm(μ_1,μ_2,'L2')
    cov_error = compute_cov_diff(Σ_1,Σ_2)
    cov_error = np.sqrt(np.abs(cov_error))
    error = mean_error + cov_error
    return error

def refine(h,n,f_bar,k_f,grid):
    # set up empty lists to hold h-values and errors (this being the ratios)
    h_range = []
    errors = []
    # get the statFEM prior for h and h/2
    μ_1, Σ_1 = fem_prior(h,f_bar,k_f,grid)
    μ_2, Σ_2 = fem_prior(h/2,f_bar,k_f,grid)
    # compute the distance between these and store in numerator variable
    numerator = W(μ_1,μ_2,Σ_1,Σ_2)
    # succesively refine the mesh by halving and do this n times
    for i in tqdm(range(n), desc="inner loop", position=1, leave=False):
    # for i in range(n):
        # print(f"inner loop iteration #{i} out of {n}")
        # store mean and cov for h/2 in storage for h
        μ_1, Σ_1 = μ_2, Σ_2
        # in storage for h/2 store mean and cov for h/4
        μ_2, Σ_2 = fem_prior(h/4,f_bar,k_f,grid)
        # compute the distance between the priors for h/2 and h/4
        # and store in denominator variable
        denominator = W(μ_1,μ_2,Σ_1,Σ_2)
        # compute the ratio and store in error
        error = numerator/denominator
        # append the current value of h and the ratio
        h_range.append(h)
        errors.append(error)
        # store denominator in numerator and halve h
        numerator = denominator
        h = h/2
    # return the list of h-values together with the ratios for these values
    return h_range,errors

my_list = [(0.25,4),(0.2,3),(0.175,3),(0.22,4),(0.176,3),(0.177,3),(0.178,3),(0.179,3),(0.18,3),(0.21,3),(0.215,3),(0.1,2),(0.3,4),(0.31,4),(0.315,4),(0.24,4),(0.245,4),(0.25,4),(0.14,2),(0.16,2),(0.15,2),(0.18,2)]

set_log_level(LogLevel.ERROR)

n_outer=len(my_list)

h_range = []
errors = []
print("Starting computation.")
start = time.time()
# for i,(h,n) in enumerate(my_list):
    # print(f"outer loop iteration #{i} out of {n_outer}")
for (h, n) in tqdm(my_list, desc="outer", position=0):
    h_range_tmp, errors_tmp = refine(h,n,f_bar,k_f,grid)
    h_range.extend(h_range_tmp)
    errors.extend(errors_tmp)

end = time.time()
print("Finished computation.")
print(f"time elapsed: {end - start}")

results = {'my_list': my_list, 'h_range': h_range, 'errors': errors}
with open('results/twoDim_prior_matern_results', 'wb') as f:
    pickle.dump(results, f)


import kachery_client as kc
from sortingview.workspace import Workspace
from ..workspace import Workspace

# Obsolete, but needed for now for the migration script to work
class WorkspaceList:
    def __init__(self, *, list_name: str):
        print(f'WARNING: WorkspaceList is obsolete (except when migrating to new system). Instead, use get_workspace_list(), set_workspace_list(), and add_workspace_to_list().')
        self._list_name = list_name
        self._workspaces = {}
        sf = kc.load_subfeed(self.get_subfeed_uri())
        messages = sf.get_next_messages()
        for m in messages:
            a = m.get('action', {})
            type0 = a.get('type', None)
            if type0 == 'add':
                w = a.get('workspace')
                self._workspaces[w['name']] = w
            elif type0 == 'remove':
                name = a.get('workspaceName')
                if name in self._workspaces:
                    del self._workspaces[name]
    @property
    def workspace_names(self):
        return [name for name in list(self._workspaces.keys())]
    def get_workspace(self, name):
        w = self._workspaces[name]
        return Workspace(workspace_uri=w['uri'], label=w['name'])
    def add_workspace(self, *, name: str, workspace: Workspace):
        if name in self.workspace_names:
            raise Exception(f'Workspace with name already exists: {name}')
        sf = kc.load_subfeed(self.get_subfeed_uri())
        w = {
            'name': name,
            'uri': workspace.uri
        }
        sf.append_message({
            'action': {
                'type': 'add',
                'workspace': w
            }
        })
        self._workspaces[name] = w
    def remove_workspace(self, name: str):
        if name not in self.workspace_names:
            raise Exception(f'Workspace not found: {name}')
        sf = kc.load_subfeed(self.get_subfeed_uri())
        sf.append_message({
            'action': {
                'type': 'remove',
                'workspaceName': name
            }
        })
        del self._workspaces[name]
    def get_subfeed_uri(self):
        k = {'name': 'sortingview-workspace-list'}
        feed_uri = kc.get(k)
        if feed_uri is None:
            feed_uri = kc.create_feed().uri
            kc.set(k, feed_uri)
        f = kc.load_feed(feed_uri)
        return f.load_subfeed(self._list_name).uri


import threading
from multiprocessing import Queue

results = []
results2 = []

def take_numbers(q):
    print('Enter the numbers:')
    for i in range(0,3):
        num1 = int(input('Enter first number: '))
        num2 = int(input('Enter second number: '))
        q.put(num1)
        q.put(num2)

def add_num(q):
    for i in range(0,3):
        num1 = q.get()
        num2 = q.get()
        results.append(num1+num2)
        results2.append(num1-num2)

q = Queue()
t2 = threading.Thread(target=add_num, args=(q, ))
t1 = threading.Thread(target=take_numbers, args=(q, ))

t2.start()
t1.start()
t2.join()
t1.join()
q.close()

for result in results:
    print ("adunare =",  result)

for result in results2:
    print ("scadere =",  result)


import sys, os, re, datetime, json
from utils import read_transactions, read_alfa, named_dict, read_ofx
import argparse, logging
from collections import namedtuple, defaultdict
from typing import List, DefaultDict, Dict, Union
# from mypy_extensions import TypedDict
from tabulate import tabulate
import numpy as np
import xlsxwriter
import itertools
from mako.template import Template
import sqlalchemy as sq
from table_defs import trs_t
import yaml

class _uni_t:
    def __init__(self):
        self.account = None
        self.date = None
        self.amount = None
        self.currency = None
        self.category = None
        self.src = None

uni_t : _uni_t = named_dict('uni_t', ['account', 'date', 'amount', 'currency', 'category', 'src'])

class float_and_list_t(dict):
    def __init__(self, v=0., trs=[]):
        self.v : float = v
        self.trs : List[uni_t] = trs
        super().__init__(self.__dict__)

    def __add__(self, o):
        return float_and_list_t(self.v + o.v, self.trs + o.trs)

class Main:
    @staticmethod
    def make_parser():
        parser = argparse.ArgumentParser()
        group = parser.add_mutually_exclusive_group()
        group.add_argument('--csvdir')
        group.add_argument('--db')
        parser.add_argument('--debug', action='store_true')
        parser.add_argument('--days_after', type=int)
        parser.add_argument('--days_before', type=int)
        parser.add_argument('--after', required=True,  type=lambda s: datetime.datetime.strptime(s, '%d.%m.%Y'))
        parser.add_argument('--before', required=True, type=lambda s: datetime.datetime.strptime(s, '%d.%m.%Y'))
        parser.add_argument('--allout', default="transactions.json")
        parser.add_argument('--sumout', default="summary.txt")
        parser.add_argument('--bydayout', default="expenses_by_day.json")
        parser.add_argument('--xlsout', help="summary.xlsx")
        parser.add_argument('--htmlout', default="summary.html")

        return parser

    def  __init__(self, args):
        self.args = args
        if hasattr(self.args, 'config_file'):
            try:
                with open(self.args.config_file,'r') as f:
                    new_conf = yaml.safe_load(f)
                    for k,v in new_conf.items():
                        setattr(self.args, k, v)
            except Exception:
                logging.exception('')

        self.logger = logging.getLogger(self.__class__.__name__)

    def read_datadir(self):
        for f in os.listdir(self.args.csvdir):
            if f.endswith('.csv'):
                try:
                    fullpath = os.path.join(self.args.csvdir,f)
                    if 'rub' in f:
                        trs = read_alfa(fullpath)
                        yield 'rub', trs
                    elif 'credit' in f:
                        trs = read_alfa(fullpath)
                        yield 'credit', trs
                    elif 'byn' in f:
                        trs = read_transactions(fullpath)
                        yield 'byn', trs
                    elif 'usd' in f:
                        trs = read_transactions(fullpath)
                        yield 'usd', trs
                    else:
                        self.logger.warning(f"{fullpath} is not recognized")
                except Exception:
                    self.logger.exception(fullpath)
                    raise

            if f.endswith('.ofx'):
                fullpath = os.path.join(self.args.csvdir,f)
                trs = read_ofx(fullpath)
                yield 'raif', trs

    def read_database(self):
        # def regexp(expr, item):
        #     reg = re.compile(expr)
        #     return reg.search(item) is not None

        db = sq.create_engine(self.args.db)
        Session = sq.orm.sessionmaker(db)

        # with sqlite3.connect(self.args.db) as conn:
        with Session() as session:
            items = session.query(trs_t) \
                .filter(trs_t.adate.between(self.args.after, self.args.before)) \
                .order_by(trs_t.adate)
            # vc = {
            #     'after' : self.args.after,
            #     'before' : self.args.before
            # }
            # cursor.execute("SELECT account, adate, amount, currency, cat, descr FROM trsv WHERE adate between :after and :before", vc)
            # items = cursor.fetchall()
            for it in items:
                tr = uni_t(
                    it.account, # account
                    it.adate,
                    # datetime.datetime.strptime(it[1],'%Y-%m-%d %H:%M:%S'), # date
                    it.amount, # amount
                    it.currency, # currency
                    it.descr, # descr as cat
                    None
                    )
                cat = self.get_category(tr)
                yield uni_t(tr.account, tr.date, tr.amount, tr.currency, cat, tr)

                # yield uni_t(
                #     it.account, # account
                #     # datetime.datetime.strptime(it[1],'%Y-%m-%d %H:%M:%S'), # date
                #     it.adate,
                #     it.amount, # amount
                #     it.currency, # currency
                #     it.descr, # cat
                #     src
                #     )

    def to_unified_rec(self, en):
        for _type, trs in en:
            #['date', 'amount', 'currency', 'category', 'src']
            for tr in trs:
                # if _type in ['rub', 'credit']:
                #     cat = tr.category
                # else:
                #     cat = tr.op + tr.category
                # _tr = uni_t(_type, tr.date, tr.amount, tr.currency, cat, tr)
                cat = self.get_category(tr)
                tr = uni_t(_type, tr.date, tr.amount, tr.currency, cat, tr)
                yield tr

    def filter_by_date(self, en : List[_uni_t]):
        min_date = None
        max_date = None
        if self.args.days_after is not None:
            min_date = datetime.datetime.today() - datetime.timedelta(days=self.args.days_after)
        if self.args.after is not None:
            min_date = self.args.after

        if self.args.days_before is not None:
            max_date = datetime.datetime.today() - datetime.timedelta(days=self.args.days_before)
        if self.args.before is not None:
            max_date = self.args.before

        if min_date is not None:
            self.logger.info(f"min_date {min_date}")
        if max_date is not None:
            self.logger.info(f"max_date {max_date}")

        for tr in en:
            if min_date is not None:
                if tr.date <= min_date:
                    continue
            if max_date is not None:
                if tr.date >= max_date:
                    continue
            yield tr

    def filter_transfers(self, en):
        for tr in en:
            if tr.category not in ['income','to BYN', 'to RUB', 'to CREDIT']:
                yield tr

    def get_category(self, tr : _uni_t):

        if tr.amount > 0:
            return 'income'

        if hasattr(self.args,'cat_defs'):
            cat_defs = self.args.cat_defs
        else:
            self.logger.warning('using default cat_defs')
            cat_defs = {
                'sadik' : [r'Парфенов\s+Сергей'],
                'kv' : [r'в пользу"ЧЕЛЯБИНВЕСТБАНК"'],
                'kv_otop' : [r'RU GOROD74.RU'],
                'cash' : [r'Alfa Iss'],
                'dolina' : [r'DOLINA'],
                'molnia' : [r'MOLNIA'],
                'taxi' : [r'TAXI'],
                'eats' : [r'MAGNIT', r'PYATEROCHKA',r'Магазины продуктовые'],
                'to KATE' : [r'на \+79511286005'],
                'gas' : [r'GAZPROMNEFT',r'AZS', r'АЗС'],
                'to RUB' : [r'CH Debit BLR MINSK P2P_SDBO_INTERNATIONAL'],
                'to BYN' : [r'CH Debit BLR MINSK P2P SDBO NO FEE'],
                'to CREDIT' : [r'Внутрибанковский перевод между счетами'],
                'Kate eats' : [r'STOLOVAYA VILKA', r'Ресторация'],
            }

        for cat, regs in cat_defs.items():
            for reg in regs:
                # print(reg)
                ret = re.search(reg, tr.category)
                # print(ret, tr.category == ss)
                if ret:
                    return cat
        return 'other'

    def group_by_category(self, en : List[_uni_t]):
        # ValueOrlistDict = TypedDict('ValueOrlistDict', {
        #         'v'   : float,
        #         'trs' : List[uni_t]
        #     })

        summary : DefaultDict[str,DefaultDict[str, DefaultDict[str, float_and_list_t]]] = \
            defaultdict(lambda: defaultdict(lambda: defaultdict(float_and_list_t)))

        for tr in en:
            summary[tr.category][tr.account][tr.currency] += float_and_list_t(tr.amount, [tr])

        cat_totals : DefaultDict[str,DefaultDict[str,float_and_list_t]] = defaultdict(lambda: defaultdict(float_and_list_t))
        acc_totals : DefaultDict[str,DefaultDict[str,float_and_list_t]] = defaultdict(lambda: defaultdict(float_and_list_t))
        spent_total : DefaultDict[str,float_and_list_t] = defaultdict(float_and_list_t)

        for tr in self.filter_transfers(en):
            cat_totals[tr.category][tr.currency] += float_and_list_t(tr.amount, [tr])
            acc_totals[tr.account][tr.currency] += float_and_list_t(tr.amount, [tr])
            spent_total[tr.currency] += float_and_list_t(tr.amount, [tr])

        return {
            'summary' : summary,
            'cat_totals' : cat_totals,
            'acc_totals' : acc_totals,
            'spent_total' : spent_total
            }

    def tr_format_html(self, trs):
        html = """

            % for tr in data['trs']:

                    ${data['self'].tr_format(tr)}

            % endfor

        """
        tm = Template(html)
        return tm.render(data={'self':self, 'trs':trs})

        # return f"{tr.account}-{tr.category} {tr.amount:6.2f} {tr.src.category}"

    def printable_summary(self, by_cat, printable=True):
        by_acc_cur = {
            cat : {
                f"{acc}_{cur}" : f"{v.v:6.2f}" for acc, curd in accd.items() for cur, v in curd.items()
            } for cat, accd in by_cat['summary'].items()
        }
        for cat, curd in by_cat['cat_totals'].items():
            by_acc_cur[cat]['total'] = ",".join([f"{v.v:6.2f} {cur}" for cur, v in curd.items() ])

        total_by_acc = {f"{acc}_{cur}" : f"{v.v:6.2f}" for acc, accd in by_cat['acc_totals'].items() for cur, v in accd.items()}
        total_by_acc['total'] = ",".join([f"{v.v:6.2f} {cur}" for cur, v in by_cat['spent_total'].items()])

        acc_curs = ['usd_USD','usd_BYN', 'byn_BYN','usd_RUB','byn_RUB','rub_RUB','raif', 'total']
        headers = ['cat'] + acc_curs
        _sum = [
            ['income'] + [by_acc_cur.get('income',{}).get(acc_cur, '') for acc_cur in acc_curs]
        ]
        _sum += [
            [cat] + [accurd.get(acc_cur, '') for acc_cur in acc_curs] \
                for cat, accurd in sorted([(k,v) for k,v in by_acc_cur.items() if k != 'income'], key=lambda kv: kv[0])
        ]
        _sum += [['total'] + [total_by_acc.get(acc_cur, '') for acc_cur in acc_curs]]

        by_acc_cur_c = {
            cat : {
                f"{acc}_{cur}" : self.tr_format_html(sorted(v.trs, key=lambda tr: tr.amount)) \
                    for acc, curd in accd.items() for cur, v in curd.items()
            } for cat, accd in by_cat['summary'].items()
        }

        _com = [
            ['income'] + [by_acc_cur_c.get('income',{}).get(acc_cur, None) for acc_cur in acc_curs]
        ]
        _com += [
            [None] + [accurd.get(acc_cur, None) for acc_cur in acc_curs] \
                for cat, accurd in sorted([(k,v) for k,v in by_acc_cur_c.items() if k != 'income'], key=lambda kv: kv[0])
        ]

        return tabulate(_sum, headers=headers) if printable else (_sum, headers, acc_curs, by_acc_cur, by_acc_cur_c, _com)

    def write_summary_to_excel(self, worksheet, by_cat, printable, row_offset=0):

        rows, headers, acc_curs, by_acc_cur, by_acc_cur_c, _com = printable

        for i,h in enumerate(headers):
            worksheet.write(*self.xlsaddr(i,row_offset+0), h)

        for r, (row, row_c) in enumerate(itertools.zip_longest(rows, _com)):
            for c,(v, com) in enumerate(itertools.zip_longest(row, row_c if row_c is not None else [])):
                worksheet.write(*self.xlsaddr(c,row_offset+r+1), v)
                if com is not None:
                    worksheet.write_comment(*self.xlsaddr(c,row_offset+r+1), str(com))

    def expenses_by_day(self, en):
        ret = defaultdict(list)
        for tr in en:
            ret[tr.date.date()] += [tr]
        return ret

    def printable_speed(self, expenses_by_day, printable=True):

        headers = [''] + [d.day for d in sorted(expenses_by_day.keys())] + ['avg_7']
        all_curs = {tr.currency for d, trs in expenses_by_day.items() for tr in trs}

        def _make_row(_cur):
            by_day_sums = [sum([tr.amount for tr in trs if tr.currency == _cur]) for d,trs in sorted(expenses_by_day.items(), key=lambda kv: kv[0])]
            return [f'by day,{_cur}'] + by_day_sums + [np.mean(by_day_sums[-7:])]

        rows = [ _make_row(_cur) for _cur in all_curs]

        def _make_row_c(_cur):
            return [[self.tr_format(tr) for tr in sorted(trs, key=lambda kv: kv.amount) \
                if tr.currency == _cur] for d,trs in sorted(expenses_by_day.items(), key=lambda kv: kv[0])]

        rows_c = [ _make_row_c(_cur) for _cur in all_curs]

        return tabulate(rows, headers=headers) if printable else (rows, headers, all_curs, rows_c)

    def xlsaddr(self,c,r):
        # return str(chr(ord('A')+c))+str(r+1)
        return r,c

    def tr_format(self, tr):
        return f"{tr.date}-{tr.account}-{tr.category} {tr.amount:6.2f} {tr.currency} {tr.src.category}"

    def write_spd_to_excel(self, worksheet, expenses_by_day, printable):

        rows, headers, all_curs, rowsc = printable
        # def _make_row(_cur):
        #     return [[self.tr_format(tr) for tr in sorted(trs, key=lambda kv: kv.amount) \
        #         if tr.currency == _cur] for d,trs in sorted(expenses_by_day.items(), key=lambda kv: kv[0])]

        # rowsc = [ _make_row(_cur) for _cur in all_curs]

        for i,h in enumerate(headers):
            # print(i,self.xlsaddr(i,0),h)
            worksheet.write(*self.xlsaddr(i,0), h)
        for r, row in enumerate(rows):
            for c,v in enumerate(row):
                worksheet.write(*self.xlsaddr(c,r+1), v)
        for r, row in enumerate(rowsc):
            for c,trs in enumerate(row):
                worksheet.write_comment(*self.xlsaddr(c+1,r+1), str(trs))
        return len(rows)

    def do_htmlout(self, expenses_by_day_printable, by_cat_printable):
        rows, headers, acc_curs, by_acc_cur, by_acc_cur_c, _com = by_cat_printable
        data = {
            'rows':rows,
            'headers':headers,
            'acc_curs':acc_curs,
            'by_acc_cur':by_acc_cur,
            'by_acc_cur_c':by_acc_cur_c,
            '_com':_com
            }

        # for i,h in enumerate(headers):
        #     worksheet.write(*self.xlsaddr(i,row_offset+0), h)

        # for r, (row, row_c) in enumerate(itertools.zip_longest(rows, _com)):
        #     for c,(v, com) in enumerate(itertools.zip_longest(row, row_c if row_c is not None else [])):
        #         worksheet.write(*self.xlsaddr(c,row_offset+r+1), v)
        #         if com is not None:
        #             worksheet.write_comment(*self.xlsaddr(c,row_offset+r+1), str(com))

        html = """
<%! import itertools %>
<!DOCTYPE HTML>

    <title>summary</title>

    Summary

            % for h in data['headers']:
                ${h}
            % endfor

            % for row, row_c in itertools.zip_longest(data['rows'], data['_com']):

                % for v, com in itertools.zip_longest(row, row_c if row_c is not None else []):
                ${v}
                    % if com is not None:
                    ${com}
                    % endif

                % endfor

            % endfor

        """

        tm = Template(html)
        return tm.render(data=data)

    def sterilize(self, obj):
        if isinstance(obj, datetime.datetime):
            return str(obj)
        assert False, str(type(obj))

    def go(self):
        if self.args.db is None:
            en = self.read_datadir()
            en = self.to_unified_rec(en)
            en = self.filter_by_date(en)
            en = list(en)
            en = sorted(en, key=lambda tr: tr.date)
        else:
            en = self.read_database()
            en = list(en)

        with open(self.args.allout, 'w') as f:
            json.dump(en, f, indent=4, default=self.sterilize, ensure_ascii=False)

        en_no_tr = self.filter_transfers(en)
        en_no_tr = list(en_no_tr)

        expenses_by_day = self.expenses_by_day(en_no_tr)
        # expenses_by_day = [(str(d),trs) for d, trs in sorted(expenses_by_day.items(), key=lambda kv: kv[0])]

        # with open(self.args.bydayout, 'w') as f:
        #     json.dump(expenses_by_day, f, indent=4, default=self.sterilize, ensure_ascii=False)

        print(self.printable_speed(expenses_by_day))
        print('\n')

        by_cat = self.group_by_category(en)
        print(self.printable_summary(by_cat))

        if self.args.xlsout is not None:
            workbook = xlsxwriter.Workbook(self.args.xlsout)
            worksheet = workbook.add_worksheet()

            row_offset = self.write_spd_to_excel(worksheet, expenses_by_day,
                self.printable_speed(expenses_by_day, printable=False))

            self.write_summary_to_excel(worksheet, by_cat,
                self.printable_summary(by_cat, printable=False), row_offset=row_offset + 2)
            workbook.close()

        if self.args.htmlout is not None:
            html = self.do_htmlout(
                self.printable_speed(expenses_by_day, printable=False),
                self.printable_summary(by_cat, printable=False)
                )
            with open(self.args.htmlout, 'w') as out:
                out.write(html)

        printable_sum = self.printable_summary(by_cat, printable=True)
        with open(self.args.sumout, 'w') as f:
            # json.dump(printable_sum, f, indent=4, default=self.sterilize, ensure_ascii=False)
            f.write(printable_sum)

    @staticmethod
    def main(args):
        # logging.basicConfig(level=logging.INFO if not args.debug else logging.DEBUG)
        root = logging.getLogger()
        root.setLevel(logging.INFO if not args.debug else logging.DEBUG)

        handler = logging.StreamHandler(sys.stdout)
        handler.setLevel(logging.INFO if not args.debug else logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        root.addHandler(handler)

        Main(args).go()

if __name__ == "__main__":
    Main.main(Main.make_parser().parse_args())


def process_photo(file):
    """convert image to jpg format"""
    from PIL import Image
    image = Image.open(file)
    width, height = image.size
    image = image.crop((0, 0, width, width / 290 * 418))
    image.thumbnail((290, 418))
    image.save("./export.jpg", "JPEG", quality=90)

import sys

process_photo(sys.argv[1])


# imports
import yake
import spacy
from rake_nltk import Rake
from gensim.summarization import keywords
from utility import *

bill_data = "Sample_Bill_Data.txt"

# Wordcount seems to have some use but we would need
# to filter out some of the most used words that are
# generic or irrelevant
def wordcount_exploration(string):
    print(get_word_counts(string))

# YAKE: yet another keyword extractor
# Takes a statistical approach to keyword extraction
# Works pretty good, high level of customizability (e.g. n-gram specification)
# Some filtering would still be good
def yake_exploration(string):
    custom_kw_extractor = yake.KeywordExtractor(lan="en", n=3, dedupLim=0.9, top=20, features=None)
    keywords = custom_kw_extractor.extract_keywords(string)

    for word in keywords:
        print(word)

# spacy
# need to run "python3 -m spacy download en_core_web_lg" to get model
# can get smaller models using "en_core_web_md" and "en_core_web_sm"
# Not bad, still gets too many keywords
def spacy_exploration(string):
    nlp = spacy.load("en_core_web_lg")
    doc = nlp(string)
    print(doc.ents)

# NON-FUNCTIONAL CURRENTLY
# RAKE: Rapid Automatic Keyword Extraction
# uses nltk stopwords and cannot download
def rake_exploration(string):
    rake_nltk_var = Rake()

    rake_nltk_var.extract_keywords_from_text(string)
    keyword_extracted = rake_nltk_var.get_ranked_phrases()

    print(keyword_extracted)

# Gensim
# Way too broad
# maybe useful for filtering keywords in other methods?
def gensim_exploration(string):
    print(keywords(string))

# Graph based approach to find keywords? (Textrank?)

# Can find keywords with BERT. A lot of work :(

# list of keywords to exclude - WIP
bad_keywords = ["united states", "act", "section", "united", "states", "united states of america", "secretary", "federal", "federal government", "government", "congressional", "congress", "bill", "bills", "congress", "senate", "america", "state", "agency", "federal agency", "military", "spending", "healthcare"]

def cleanup(my_list: list):
    # remove confidence scores
    my_list = list(map(lambda x: x[0], my_list))

    # remove any monograms
    my_list = filter(lambda x: len(x.split(" ")) > 1, my_list)

    # remove unuseful keywords
    my_list = [word for word in my_list if word not in bad_keywords]

    return my_list[:10] if len(my_list) > 9 else my_list

def remove_dups(my_list: list):
    """ Returns a set of tuples with unique first values (keyword) """

    unique_results = []
    for element in my_list:
        unique_words = list(map(lambda word: word[0], unique_results))
        if element[0] not in unique_words:
            unique_results.append(element)
    return unique_results

def yake_extraction(summary: str, full_text: str):
    # YAKE keyword extraction parameters
    language = "en"
    max_ngram_size = 3
    deduplication_thresold = 0.25
    deduplication_algo = 'seqm'
    windowSize = 1
    numOfKeywords = 20

    # get keywords
    extractor = yake.KeywordExtractor(lan=language, n=max_ngram_size, dedupLim=deduplication_thresold, dedupFunc=deduplication_algo, windowsSize=windowSize, top=numOfKeywords, features=None)
    keywords = extractor.extract_keywords(summary + " " + full_text)

    return cleanup(keywords)

if __name__ == "__main__":
    bill_num = "2"

    bill_data = "/Users/ianwu/Desktop/Senior Design/SeniorDesign/app/machine_learning/keyword_extraction/ian/tests/Sample_Bill_Data.txt"
    data = load_json_from_file(bill_data)
    summary = data[bill_num]["summary"].replace("\n", '')
    full_text = data[bill_num]["full_text"].replace("\n", '')
    # string = remove_stopwords(string)

    words = yake_extraction(summary, full_text)

    for i in words:
        print(i)


'''
Even Count

You are provided with an integer array where each number is present either odd number of times or even number of times.
You have to find and return the number which is present even number of times.
If multiple numbers are present even number of times, then return that number which occurs first among these numbers
in the given array. If no such number exists, then return -1.

Note : You may take extra space but solve this problem in O(n) time.

Input Format:
        Line 1 : An Integer N i.e. size of array
        Line 2 : N integers which are elements of the array, separated by spaces
Output Format:
        Array element occurring even no. of times

Constraints :   1 <= N <= 10^5

Sample Input:   6                       Sample Output:  5
                2 5 3 5 3 4
'''

def evenCount(arr):

    mydict = {}

    for ele in arr:
        if ele in mydict:
            mydict[ele] += 1
        else:
            mydict[ele] = 1

    # ----------------------------- My Soln.
    # count = []
    # for key, val in mydict.items():
    #     if val % 2 == 0:
    #         count.append(key)
    # return count[0]
    #-----------------------------

    #----------------------------- CN Soln. (better)
    for val in arr:
        if mydict[val] % 2 == 0:
            return val
    #------------------------------

# Main
n=int(input())
arr=list(int(i) for i in input().strip().split(' '))
print(evenCount(arr))

12. Tuples, Dictionary _ Sets/Ele occuring Even Times.py


#!/usr/bin/env python3

import struct
import sys
from os import listdir
from os.path import isfile, join, isdir

# You can specify a list of names that are used to filter the stream names. The filter is case-insensitive.
filter_list = []

if len(sys.argv) > 1:
    filter_list = sys.argv[1:]

stream_manager_directory = "greengrass/v2/work/aws.greengrass.StreamManager"

if not isdir(stream_manager_directory):
    print("Stream Manager directory not found: " + stream_manager_directory)
    sys.exit(1)

streams = [f for f in listdir(stream_manager_directory) if isdir(join(stream_manager_directory, f))]

def filter_matches(filters, stream_name):
    for current_filter in filters:
        # If any filter term matches, return true
        if stream_name.lower().find(current_filter.lower()) != -1:
            return True

    # Nothing matched
    return False

for stream in streams:
    # If any filters are specified, only print streams that match
    if len(filter_list) != 0 and not filter_matches(filter_list, stream):
        continue

    # Found a stream directory
    print("Processing stream: " + stream)
    # Get the relative path from the directory name
    stream_directory = join(stream_manager_directory, stream)
    # Get all of the files in this stream's directory that end in .log
    stream_files = [f for f in listdir(stream_directory) if isfile(join(stream_directory, f)) and f.endswith(".log")]

    # Loop through a sorted list of files
    for stream_file in sorted(stream_files):
        print("Processing file: " + stream_file)
        # Get the relative path from the file name
        stream_file_path = join(stream_directory, stream_file)

        # Open the file in binary mode
        with open(stream_file_path, "rb") as file:
            # Loop until the end of the file
            while True:
                # The first 28 bytes are part of the header that we don't need
                throwaway = file.read(28)

                if not throwaway:
                    # If we hit EOF then we're done
                    break

                # Read the next 4 bytes which is the length of the current payload
                # Struct unpack to convert the 4 bytes to a number
                #   NOTE: Exclamation point to read the value in network/big-endian byte order
                payload_length = struct.unpack('!i', file.read(4))[0]

                # Read the data and decode it as a UTF-8 string so we can print it cleanly
                data = file.read(payload_length).decode('utf-8')
                print(data)


#!/usr/bin/python -u
#
# this tests the basic APIs of the XmlTextReader interface
#
import libxml2
import sys
try:
    import StringIO
    str_io = StringIO.StringIO
except:
    import io
    str_io = io.StringIO

# Memory debug specific
libxml2.debugMemory(1)

def tst_reader(s):
    f = str_io(s)
    input = libxml2.inputBuffer(f)
    reader = input.newTextReader("tst")
    res = ""
    while reader.Read():
        res=res + "%s (%s) [%s] %d\n" % (reader.NodeType(),reader.Name(),
				      reader.Value(), reader.IsEmptyElement())
        if reader.NodeType() == 1: # Element
            while reader.MoveToNextAttribute():
                res = res + "-- %s (%s) [%s]\n" % (reader.NodeType(),
						   reader.Name(),reader.Value())
    return res

expect="""1 (test) [None] 0
1 (b) [None] 1
1 (c) [None] 1
15 (test) [None] 0
"""

res = tst_reader("""<test><b/><c/></test>""")

if res != expect:
    print("Did not get the expected error message:")
    print(res)
    sys.exit(1)

# Memory debug specific
libxml2.cleanupParser()
if libxml2.debugMemory(1) == 0:
    print("OK")
else:
    print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
    libxml2.dumpMemory()


lista = []
for p in range (0,5):
    x = int(input('Digite um valor'))
    if p == 0 or x > lista[-1]:
        print('Adicionado ao final da lista')
        lista.append(x)
    else:
        contador = 0
        while contador < len(lista):
            if x <= lista[contador]:
                lista.insert(contador,x)
                print(f'Adicionado na posiçao {p}')
                break
            contador += 1

print(lista)


import tensorflow as tf
import numpy as np
VGG_MEAN = [103.939, 116.779, 123.68]

#template borrowed from https://github.com/machrisaa/tensorflow-vgg/blob/master/vgg19.py
def build_part_vgg19(img_input, model_dir='vgg19.npy'):
    '''
    input tensor: input image with shape of [batch, height, width, colors=3]
    params_dir: Directory of vgg19 model
    '''

    def conv(x, name):
        with tf.variable_scope(name):
            f = tf.constant(params[name][0], dtype='float32')
            b = tf.constant(params[name][1], dtype='float32')
            conv = tf.nn.conv2d(input=x, filter=f, strides=[1, 1, 1, 1], padding='SAME')
            bias = tf.nn.bias_add(conv, b)
            relu = tf.nn.relu(bias)
            return relu

    def max_pool(x, name):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)

    def avg_pool(x, name):
        return tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)

    #convert RGB to BGR
    params = np.load(model_dir, encoding='latin1').item()
    red, green, blue = tf.split(axis=3, value=img_input, num_or_size_splits=3)
    bgr = tf.concat(axis=3, values=[
        blue - VGG_MEAN[0],
        green - VGG_MEAN[1],
        red - VGG_MEAN[2],
    ])

    pool = lambda x, name: avg_pool(x, name)

    conv1_1 = conv(bgr, 'conv1_1')
    conv1_2 = conv(conv1_1, 'conv1_2')
    pool1 = pool(conv1_2, 'pool1')

    conv2_1 = conv(pool1, 'conv2_1')
    conv2_2 = conv(conv2_1, 'conv2_2')
    pool2 = pool(conv2_2, 'pool2')

    conv3_1 = conv(pool2, 'conv3_1')
    conv3_2 = conv(conv3_1, 'conv3_2')
    conv3_3 = conv(conv3_2, 'conv3_3')
    conv3_4 = conv(conv3_3, 'conv3_4')
    pool3 = pool(conv3_4, 'pool3')

    conv4_1 = conv(pool3, 'conv4_1')
    conv4_2 = conv(conv4_1, 'conv4_2')
    conv4_3 = conv(conv4_2, 'conv4_3')
    conv4_4 = conv(conv4_3, 'conv4_4')
    pool4 = pool(conv4_4, 'pool4')

    conv5_1 = conv(pool4, 'conv5_1')

    # print(conv1_1.shape)
    # print(conv2_1.shape)
    # print(conv3_1.shape)
    # print(conv4_1.shape)
    # print(conv5_1.shape)

    return conv1_1, conv2_1, conv3_1, conv4_1, conv5_1, conv4_2


from 宽度优先遍历 import BFS
from DFS import DFS
from 拓扑排序 import sortedTopology
from 克鲁斯卡算法 import kruskalMST
from 普里姆算法 import Prim
from 迪克斯特拉算法 import Dijkstra2

class Graph:
    def __init__(self):
        self.nodes = {}  # 存放每一个节点的名字和其对应的节点
        self.edges = set()  # 是一个集合类型，保存边

class Node:
    def __init__(self, value, ins=0, outs=0):
        self.value = value
        self.ins = ins
        self.outs = outs
        self.nexts = []
        self.edges = []

class Edge:
    def __init__(self, weight, fromnode, tonode):
        self.weight = weight
        self.fromnode = fromnode
        self.tonode = tonode

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

# 接口函数，根据具体题目给出的数据格式转化为我们熟悉的格式。然后利用熟悉格式的算法进行解题
# 输入矩阵N*3形状的
# 每一行表示一条边，[0]位置表示起点，[1]表示终点，[2]表示权重
def createGraph(matrix):
    graph = Graph()
    for i in range(len(matrix)):
        fromname = matrix[i][0]
        toname = matrix[i][1]
        weight = matrix[i][2]
        if fromname not in graph.nodes:
            graph.nodes[fromname] = Node(fromname)
        if toname not in graph.nodes:
            graph.nodes[toname] = Node(toname)
        fromnode = graph.nodes[fromname]
        tonode = graph.nodes[toname]
        newedge = Edge(weight, fromnode, tonode)
        fromnode.nexts.append(tonode)
        fromnode.outs += 1
        tonode.ins += 1
        fromnode.edges.append(newedge)
        graph.edges.add(newedge)
    return graph

if __name__ == "__main__":
    print("------宽度优先遍历测试-------")
    graphmatrix = [[0, 3, 2],
                   [3, 0, 2],
                   [2, 0, 5],
                   [0, 2, 5],
                   [1, 0, 3],
                   [0, 1, 3],
                   [2, 1, 2],
                   [1, 2, 2]]
    graph1 = createGraph(graphmatrix)  # 无向图
    BFS(graph1.nodes[1])
    print("-------深度(广度)优先遍历测试--------")
    graphmatrix2 = [[1, 2, 1],
                    [2, 1, 1],
                    [1, 3, 1],
                    [3, 1, 1],
                    [1, 5, 1],
                    [5, 1, 1],
                    [2, 4, 1],
                    [4, 2, 1],
                    [2, 3, 1],
                    [3, 2, 1],
                    [2, 5, 1],
                    [5, 2, 1],
                    [4, 3, 1],
                    [3, 4, 1],
                    [4, 5, 1],
                    [5, 4, 1]]
    graph2 = createGraph(graphmatrix2)  # 无向图
    DFS(graph2.nodes[3])
    # print("------宽度优先遍历测试-------")
    # BFS(graph2.nodes[4])
    print("-------拓扑排序测试-------")
    graphmatrix3 = [[1, 2, 1],
                    [1, 3, 1],
                    [2, 3, 1],
                    [2, 4, 1],
                    [3, 4, 1]]
    graph3 = createGraph(graphmatrix3)
    nodes = sortedTopology(graph3)
    print([node.value for node in nodes])
    print("-------K算法测试-------")
    graphmatrix4 = [[1, 2, 3],
                    [2, 1, 3],
                    [1, 3, 100],
                    [3, 1, 100],
                    [1, 4, 7],
                    [4, 1, 7],
                    [2, 3, 5],
                    [3, 2, 5],
                    [2, 4, 2],
                    [4, 2, 2],
                    [4, 3, 10000],
                    [3, 4, 10000]]
    graph4 = createGraph(graphmatrix4)
    edges = kruskalMST(graph4)
    print([edge.weight for edge in edges])
    print("-------P算法测试-------")
    edgesp = Prim(graph4)
    print([edge.weight for edge in edgesp])
    print("-------迪克斯塔拉算法测试-------")
    graphmatrix5 = [[1, 2, 3],
                    [2, 1, 3],
                    [1, 3, 15],
                    [3, 1, 15],
                    [1, 4, 9],
                    [4, 1, 9],
                    [2, 3, 2],
                    [3, 2, 2],
                    [4, 3, 7],
                    [3, 4, 7],
                    [2, 5, 200],
                    [5, 2, 200],
                    [5, 3, 14],
                    [3, 5, 14],
                    [4, 5, 16],
                    [5, 4, 16]]
    graph5 = createGraph(graphmatrix5)
    distancemap = Dijkstra2(graph5.nodes[1],5)
    print("正确值:0,3,5,9,19")
    print([distance for distance in distancemap.values()])