import csv
import json
import logging
import os
import re
import signal
import tkinter as tk
import tkinter.font as tkFont
import uuid
from datetime import datetime, timedelta
from tkinter import Toplevel
from tkinter import messagebox
from tkinter.messagebox import showerror
import time
import matplotlib.pyplot as plt
import requests
import socketio
from PIL import Image, ImageTk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
# from ttkbootstrap.constants import *
import datetime

from operator_module.operator_dashboard import OperatorDashboard
from technician_module.technician_dashboard import TechnicianDashboard
from utils.quantity_data import QuantityData
from utils.status_update import StatusUpdate
from utils.time_data import TimeData
from utils.ticket_status import TicketChecker
# from utils.trigger_downtime import TriggerDowntime
from socketio_utils.socketio_manager import SocketIOManager

class UserPermissions:
    def __init__(self, config_path):
        self.config_path = config_path
        self.employee_departments = []
        self.employee_positions = []
        self.technician = []
        self.operator = []

    def load_permissions(self):
        try:
            with open(self.config_path) as json_file:
                data = json.load(json_file)
                self.employee_departments = data["allowed_users"]["employee_department"]
                self.employee_positions = data["allowed_users"]["employee_position"]
                self.operator = data["allowed_users"]["operator"]
                self.technician = data["allowed_users"]["technician"]
        except FileNotFoundError as e:
            print(e)

            self.employee_departments = []
            self.employee_positions = []
            self.technician = []
            self.operator = []

    def is_department_allowed(self, department):
        return department in self.employee_departments

    def is_position_allowed(self, position):
        return position in self.employee_positions

    def is_technician(self, position):
        return position in self.technician

    def is_operator(self, position):
        return position in self.operator

class App:
    def __init__(self, root):
        # setting title
        root.title("EEMS_IOT - © 2023")
        # setting window size

        ## GLOBAL VARIABLES##

        self.quantity_data = QuantityData("../data")
        self.get_data = TimeData('../data')

        # self.receiver = ReceiveAndRequest(self.socketio_path())
        self.total_running_qty = self.quantity_data.total_running_qty()
        self.calculate_oee = self.get_data.calculate_oee
        self.total_remaining_qty_value = self.quantity_data.total_remaining_qty()
        self.get_available_hrs = self.get_data.get_available_hrs()
        self.get_productive_hrs = self.get_data.calculate_total_productive_time()
        self.get_downtime_hrs = self.get_data.calculate_total_downtime()
        self.get_idle_hrs = self.get_data.calculate_total_idle()
        self.last_ticket_status = None
        # self.downtime_started = False
        self.downtime_started = self.load_downtime_state()
        self.update_interval = 50000
        self.root = root

        # self.root = root

        ## FUNCTIONS##

        self.makeCenter()
        self.mainGui()
        self.init_logging()
        self.update_clock()
        self.update_status()
        self.time_data()
        self.update_logs()
        self.create_total_qty_graph()
        self.create_oee_graph()
        self.charts()
        self.verify_ticket_status()
        self.auto_update()
        self.save_downtime_state()
        # self.downtime_trigger_record()
        # self.continuously_check_tickets()

        ## END##

    def makeCenter(self):
        self.width = 1800
        self.height = 1013
        self.screenwidth = self.root.winfo_screenwidth()
        self.screenheight = self.root.winfo_screenheight()
        alignstr = '%dx%d+%d+%d' % (self.width, self.height, (self.screenwidth -
                                                              self.width) / 2, (self.screenheight - self.height) / 2)
        self.root.geometry(alignstr)
        self.root.resizable(width=False, height=False)

    def mainGui(self):
        self.cpk_graph = tk.Label(self.root)
        self.cpk_graph["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=10)
        self.cpk_graph["font"] = ft
        self.cpk_graph["fg"] = "#333333"
        self.cpk_graph["justify"] = "center"
        self.cpk_graph["text"] = "CPK"
        self.cpk_graph.place(x=20, y=130, width=580, height=550)

        self.oee_graph = tk.Label(self.root)
        self.oee_graph["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=10)
        self.oee_graph["font"] = ft
        self.oee_graph["fg"] = "#333333"
        self.oee_graph["justify"] = "center"
        self.oee_graph["text"] = "label"
        self.oee_graph.place(x=610, y=130, width=580, height=550)

        self.quantity_graph = tk.Label(self.root)
        self.quantity_graph["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=10)
        self.quantity_graph["font"] = ft
        self.quantity_graph["fg"] = "#333333"
        self.quantity_graph["justify"] = "center"
        self.quantity_graph["text"] = "QTY GRAPH"
        self.quantity_graph.place(x=1200, y=130, width=580, height=550)

        self.productive_hrs = tk.Label(self.root)
        self.productive_hrs["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=22)
        self.productive_hrs["font"] = ft
        self.productive_hrs["fg"] = "#333333"
        self.productive_hrs["justify"] = "center"
        self.productive_hrs.place(x=20, y=700, width=580, height=90)

        self.available_hrs = tk.Label(self.root)
        self.available_hrs["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=22)
        self.available_hrs["font"] = ft
        self.available_hrs["fg"] = "#333333"
        self.available_hrs["justify"] = "left"
        self.available_hrs.place(x=20, y=800, width=580, height=90)

        self.total_quantity_to_process = tk.Label(self.root)
        self.total_quantity_to_process["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=22)
        self.total_quantity_to_process["font"] = ft
        self.total_quantity_to_process["fg"] = "#333333"
        self.total_quantity_to_process["justify"] = "left"
        self.total_quantity_to_process.place(x=610, y=700, width=580, height=90)

        self.total_remaining_qty = tk.Label(self.root)
        self.total_remaining_qty["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=22)
        self.total_remaining_qty["font"] = ft
        self.total_remaining_qty["fg"] = "#333333"
        self.total_remaining_qty["justify"] = "left"
        self.total_remaining_qty.place(x=20, y=900, width=580, height=90)

        self.downtime = tk.Label(self.root)
        self.downtime["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=22)
        self.downtime["font"] = ft
        self.downtime["fg"] = "#333333"
        self.downtime["justify"] = "center"
        self.downtime.place(x=610, y=900, width=580, height=90)

        self.idle = tk.Label(self.root)
        self.idle["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=22)
        self.idle["font"] = ft
        self.idle["fg"] = "#333333"
        self.idle["justify"] = "center"
        self.idle.place(x=610, y=800, width=580, height=90)

        self.statusHere = tk.Label(self.root)
        ft = tkFont.Font(family='Times', size=58)
        self.statusHere["font"] = ft
        self.statusHere["justify"] = "center"
        self.statusHere.place(x=20, y=10, width=359, height=106)

        self.employee_id = tk.Entry(self.root)
        self.employee_id["bg"] = "#ffffff"
        self.employee_id["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times', size=83)
        self.employee_id["font"] = ft
        self.employee_id["fg"] = "#333333"
        self.employee_id["justify"] = "center"
        self.employee_id["text"] = "10450"
        self.employee_id.bind(
            '<KeyRelease>', self.validate_employee_number)
        self.employee_id.place(x=650, y=10, width=500, height=106)

        self.logs_message = tk.Message(self.root)
        self.logs_message["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=15)
        self.logs_message["font"] = ft
        self.logs_message["fg"] = "#333333"
        self.logs_message["justify"] = "left"
        self.logs_message['width'] = 580
        self.logs_message.place(x=1200, y=700, width=580, height=290)

        self.date_time = tk.Label(self.root)
        self.date_time["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times', size=15)
        self.date_time["font"] = ft
        self.date_time["fg"] = "#333333"
        self.date_time["justify"] = "center"
        self.date_time.place(x=1480, y=10, width=300, height=60)

        self.ticket = tk.Label(root)
        self.ticket["bg"] = "#ffb800"
        self.ticket["cursor"] = "circle"
        ft = tkFont.Font(family='Times', size=9)
        self.ticket["font"] = ft
        self.ticket["fg"] = "#000000"
        self.ticket["justify"] = "left"
        self.ticket.place(x=1199, y=73, width=581, height=43)

    def get_script_directory(self):
        return os.path.dirname(os.path.abspath(__file__))

    def socketio_path(self):
        path_here = os.path.join(
            self.get_script_directory(), "data", 'main.json')
        return path_here

    def check_internet_connection_requests(self):
        try:
            response = requests.get("http://www.google.com", timeout=5)
            return response.status_code == 200
        except requests.ConnectionError:
            return False

    def validate_employee_number(self, event):
        employee_number = self.employee_id.get()
        if len(employee_number) == 5:
            if self.check_internet_connection_requests():
                self.validate_online_employee(employee_number)
            else:
                self.validate_offline_employee(employee_number)
        elif len(employee_number) == 4:
            if self.check_internet_connection_requests():
                self.validate_online_employee(employee_number)
            else:
                self.validate_offline_employee(employee_number)

    def validate_online_employee(self, employee_number):
        try:
            employee_number = int(employee_number)
            hris_url = f'http://hris.teamglac.com/api/users/emp-num?empno={employee_number}'
            response = requests.get(hris_url)

            if response.status_code == 200:
                try:
                    data = json.loads(response.text)['result']

                    # Check if data is a dictionary before accessing its values
                    if isinstance(data, dict):
                        user_department = data.get('employee_department')
                        fullname = data.get('fullname')
                        user_position = data.get('employee_position')
                        employee_no = data.get('employee_no')
                        employee_department = data.get('employee_department')
                        photo_url = data.get('photo_url')
                        username = data.get('username')

                        data = [
                            user_department,
                            fullname,
                            employee_no,
                            employee_department,
                            photo_url,
                            user_position,
                            username
                        ]
                        dataJson = {'data': data}

                        if user_department and user_position:
                            self.validate_permissions(
                                user_department, user_position, dataJson)
                        else:
                            pass
                            # print(
                            #     "Employee data doesn't contain department or position.")
                    else:
                        pass
                        # print(
                        #     "Response data is not in the expected format (dictionary).")
                except KeyError:
                    pass
                    # print("Response data doesn't have expected keys.")
            else:
                print("Error accessing HRIS API:", response.status_code)
        except ValueError:
            tk.messagebox.showerror(
                "Invalid Input", "Please enter a valid integer employee number.")

    def validate_offline_employee(self, employee_number):
        log_file_path = os.path.join(
            self.get_script_directory(), "config", 'hris.json')

        with open(log_file_path, "r") as json_file:
            data = json.load(json_file)['result']

        matching_employee = None
        for employee in data:
            if employee.get('employee_id_no') == employee_number:
                matching_employee = employee
                break

        if matching_employee:
            user_department = matching_employee.get('employee_department')
            user_position = matching_employee.get('employee_position')
            # user_empNo = matching_employee.get('employee_id_no')

            self.validate_permissions(user_department, user_position)
        else:
            print("Employee not found.")

    def validate_permissions(self, user_department, user_position, dataJson):
        employee_number = self.employee_id.get()

        permissions = self.load_permissions()
        if permissions.is_department_allowed(user_department) and permissions.is_position_allowed(user_position):
            if permissions.is_technician(user_position):
                self.show_tech_dashboard(
                    user_department, user_position, dataJson)
            elif permissions.is_operator(user_position):
                print(f"{user_position} is an operator.")
                self.show_operator_dashboard(
                    user_department, user_position, dataJson)
                self.log_activity(
                    logging.INFO, f'User login successful. ID NUM: {employee_number}')

            else:
                self.log_activity(
                    logging.INFO, f'User login unsuccessful. ID NUM: {employee_number}')

                showerror(title='Login Failed',
                          message=f"User's department or position is not allowed. Please check, Current Department / Possition  {user_department + ' ' + user_position}")

        else:
            self.log_activity(
                logging.INFO, f'User login unsuccessful. ID NUM: {employee_number}')
            showerror(title='Login Failed',
                      message=f"User's department or position is not allowed. Please check, Current Department / Possition  {user_department + ' ' + user_position}")

    def load_permissions(self):
        log_file_path = os.path.join(
            self.get_script_directory(), "config", 'settings.json')
        permissions = UserPermissions(log_file_path)
        permissions.load_permissions()
        return permissions

    def checking_allowed_user(self):
        script_directory = os.path.dirname(os.path.abspath(__file__))
        log_folder = os.path.join(script_directory, "config")
        log_file_path = os.path.join(log_folder, 'settings.json')
        try:
            with open(log_file_path, 'r') as file:
                log_content = file.read()
                result = log_content['allowed_users']
        except FileNotFoundError as e:
            print(e)

    def init_logging(self):
        log_file = 'data/logs/activity_log.txt'
        logging.basicConfig(filename=log_file, level=logging.INFO,
                            format='[%(asctime)s] %(levelname)s: %(message)s',
                            datefmt='%Y-%m-%d %H:%M:%S', filemode='a')
        # print(f'Logging to {log_file}')-

    def log_activity(self, level, message):
        logging.log(level, message)

    def show_operator_dashboard(self, user_department, user_position, data_json):
        OpeDashboard = tk.Toplevel(root)
        ope_dashboard = OperatorDashboard(
            OpeDashboard, user_department, user_position, data_json)
        root.withdraw()

    def show_tech_dashboard(self, user_department, user_position, dataJson):
        techDashboard = Toplevel(root)
        tech_dashboard = TechnicianDashboard(
            techDashboard, user_department, user_position, dataJson)
        root.withdraw()

    def update_clock(self):
        current_time = time.strftime('%H:%M:%S')
        current_date = time.strftime('%Y-%m-%d')

        dateNTime = current_date + ' ' + current_time
        self.date_time["text"] = 'DATETIME: ' + dateNTime
        root.after(1000, self.update_clock)

    def update_status(self):
        statusHere = StatusUpdate('data/logs/logs.csv')
        getStatus = statusHere.get_last_log_value()
        if getStatus is None or False:
            self.statusHere["bg"] = "#ffffff"
            self.statusHere["text"] = ''
        elif getStatus == 'ONLINE':
            self.statusHere["bg"] = "#4CAF50"
            self.statusHere["fg"] = "#ffffff"
            self.statusHere["text"] = getStatus
        else:
            self.statusHere["bg"] = "#cc0000"
            self.statusHere["fg"] = "#ffffff"
            self.statusHere["text"] = getStatus
        #     self.status_card()
        # self.root.after(1000, self.update_status)

    def status_card(self):
        self.time_data()
        self.get_data.calculate_oee
        self.charts()
        self.delete_file_data()
        self.get_data.calculate_total_productive_time()

    def delete_file_data(self):
        filename = os.path.join(
            self.get_script_directory(), "data", 'time.csv')
        try:
            with open(filename, 'w') as file:
                file.truncate(0)

        except IOError:
            print(f"Error deleting data in '{filename}'.")

    def update_logs(self):
        log_file_path = os.path.join(
            self.get_script_directory(), 'data/logs', 'activity_log.txt')
        try:
            with open(log_file_path, 'r') as file:
                log_content = file.read()
            lines = log_content.split('\n')
            last_5_logs = '\n'.join(lines[-6:])
            self.logs_message["text"] = last_5_logs

        except FileNotFoundError:
            self.logs["text"] = "Log file not found."
        # root.after(50000, self.update_logs)

    def time_data(self):
        self.total_remaining_qty["text"] = f"TOTAL PROCESS : {self.total_running_qty}"
        self.productive_hrs["text"] = f"PRODUCTIVE HRS : {self.get_productive_hrs}"
        self.available_hrs["text"] = f"AVAILABLE HRS : {self.get_available_hrs}"
        self.total_quantity_to_process[
            "text"] = f"QUANTITY PROCESSED : {self.total_remaining_qty_value}"

    def create_total_qty_graph(self):
        if self.total_running_qty == 0 and self.total_remaining_qty_value == 0:
            return None

        result_qty = self.total_running_qty - self.total_remaining_qty_value
        data = [self.total_remaining_qty_value, result_qty]
        labels = ['QUANTITY COMPLETED', 'PROCESS QUANTITY']
        colors = ['#4CAF50', '#e74c3c']
        explode = (0.05, 0)

        figure = Figure(figsize=(5, 4), dpi=100)
        plot = figure.add_subplot(1, 1, 1)
        plot.pie(data, labels=labels, colors=colors, autopct='%1.1f%%',
                 startangle=90, pctdistance=0.85, explode=explode)

        centre_circle = plt.Circle((0, 0), 0.70, fc='white')
        plot.add_artist(centre_circle)

        center_text = 'QUANTITY'
        plot.text(0, 0, center_text, va='center', ha='center', fontsize=12)

        plot.axis('equal')
        # plot.set_title('QUANTITY GRAPH')

        plot.legend(loc='upper center', labels=labels, fontsize='small')

        canvas = FigureCanvasTkAgg(figure, master=self.root)
        canvas_widget = canvas.get_tk_widget()

        canvas.draw()
        pil_image = Image.frombytes(
            'RGB', canvas.get_width_height(), canvas.tostring_rgb())
        img = ImageTk.PhotoImage(image=pil_image)
        # self.root.after(50000, self.create_total_qty_graph)
        return img

    def create_oee_graph(self):
        calculated_oee = self.calculate_oee()
        calculated_oee = max(0, min(calculated_oee, 100))

        total = 100 - calculated_oee
        data = [calculated_oee, total]
        labels = ['EFFECTIVENESS', 'INEFFECTIVENESS']
        colors = ['#4CAF50', '#e74c3c']
        explode = (0.05, 0)

        figure = Figure(figsize=(5, 4), dpi=100)
        plot = figure.add_subplot(1, 1, 1)
        plot.pie(data, labels=labels, colors=colors, autopct='%1.1f%%',
                 startangle=90, pctdistance=0.85, explode=explode)

        centre_circle = plt.Circle((0, 0), 0.70, fc='white')
        plot.add_artist(centre_circle)

        center_text = 'OEE'
        plot.text(0, 0, center_text, va='center', ha='center', fontsize=12)
        plot.legend(loc='upper center', labels=labels, fontsize='small')

        plot.axis('equal')
        # plot.set_title('OEE GRAPH')

        canvas = FigureCanvasTkAgg(figure, master=self.root)
        canvas_widget = canvas.get_tk_widget()

        canvas.draw()
        pil_image = Image.frombytes(
            'RGB', canvas.get_width_height(), canvas.tostring_rgb())
        img = ImageTk.PhotoImage(image=pil_image)
        # self.root.after(50000, self.create_oee_graph)
        return img

    def create_line_chart(self):
        fig = Figure(figsize=(6, 4), dpi=100)
        ax = fig.add_subplot(1, 1, 1)

        days = np.arange(1, 8)
        values = [10, 0, 2, 11, 4, 2, 15]

        ax.plot(days, values, marker='o', label="7-Day Data")
        ax.set_xlabel("Day")
        ax.set_ylabel("Value")
        ax.set_title("CPK GRAPH")
        ax.legend()

        canvas = FigureCanvasTkAgg(fig, master=self.root)
        canvas.draw()
        img = self.convert_figure_to_photoimage(canvas)
        return img

    def convert_figure_to_photoimage(self, fig_canvas):
        buf = fig_canvas.buffer_rgba()
        img_data = buf.tobytes()  # Convert memoryview to bytes
        img = Image.frombytes("RGBA", fig_canvas.get_width_height(), img_data)
        return ImageTk.PhotoImage(image=img)

    def time_data(self):
        self.total_remaining_qty["text"] = f"TOTAL TO PROCESS : {self.total_running_qty}"
        self.productive_hrs["text"] = f"PRODUCTIVE HOURS : {self.get_productive_hrs}"
        self.available_hrs["text"] = f"AVAILABLE HOURS : {self.get_data.get_available_hrs()}"
        self.total_quantity_to_process[
            "text"] = f"QUANTITY PROCESSED : {self.total_remaining_qty_value}"
        self.downtime["text"] = f"DOWNTIME : {self.get_downtime_hrs}"
        self.idle["text"] = f"TOTAL IDLETIME : {self.get_idle_hrs}"
        # self.root.after(50000, self.time_data)

        self.label_update_id = self.root.after(self.update_interval, self.time_data)

    def charts(self):
        self.chart_img = self.create_oee_graph()
        self.total_img = self.create_total_qty_graph()
        self.line_img = self.create_line_chart()
        if self.oee_graph is not None:
            self.oee_graph.configure(image=self.chart_img)
        if self.quantity_graph is not None:
            self.quantity_graph.configure(image=self.total_img)
        if self.cpk_graph is not None:
            self.cpk_graph.configure(image=self.line_img)

        self.chart_update_id = self.root.after(self.update_interval, self.charts)

    def auto_update(self):
        """
        CAN BE ENABLED, BUT IT CAN EAT A LOT OF RESOURCES
        """
        pass
        # self.time_data()
        # self.get_data.calculate_oee
        # self.create_oee_graph()
        # self.create_line_chart()
        # self.root.after(50000, self.auto_update)

    def verify_ticket_status(self):
        ticket_inspector = TicketChecker()
        ticket_present = ticket_inspector.checking()
        if ticket_present:
            self.ticket["text"] = "VALID TICKET AVAILABLE. ACCESS ONLY FOR CHECKING, NO TRANSACTIONS. CLOSE TO PROCEED."
            if not self.downtime_started:
                self.downtime_started = True
                self.log_event("DOWNTIME_START")
        else:
            if self.downtime_started:
                self.downtime_started = False
                self.log_event("DOWNTIME_STOP")
            self.ticket.destroy()

    def log_event(self, msg):
        current_time = datetime.datetime.now()
        date = current_time.strftime("%Y-%m-%d")
        time = current_time.strftime("%H:%M:%S")

        with open('data/logs/downtime.csv', mode="a", newline="") as csv_file:
            csv_writer = csv.writer(csv_file)
            csv_writer.writerow([msg, date, time])

    def load_downtime_state(self):
        try:
            with open('config/downtime_state.json', 'r') as state_file:
                state = json.load(state_file)
                return state.get('downtime_started', False)
        except FileNotFoundError:
            return False

    def save_downtime_state(self):
        with open('config/downtime_state.json', 'w') as state_file:
            json.dump({'downtime_started': self.downtime_started}, state_file)

# receiver.sio.wait()
if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.iconbitmap("config/ico/favicon.ico")
    root.mainloop()


'''
    6.1A The Golden Ratio HW

    Author: Sam Sit
'''

import arrays
import turtle
import random

#6.1.1
def fibonacci(n):
    n = int(n)
    if n <= 0:
        return None
    if n == 1:
        return 0
    if n == 2:
        return 1
    if n > 2:
        return fibonacci(n-1) + fibonacci(n-2)

#6.1.2
def fill_fibonacci_array(array, index = 0):
    if index < len(array):
        array[index] = fibonacci(index+1)
        fill_fibonacci_array(array, index+1)
    return array

#6.1.4
def print_ratios(array, index = 0):
    a = array[index]
    b = array[index+1]

    if index < (len(array)-2):

        try:
            print(f"{a:>4n} {b:>4n}  {(b/a):.5f}  {((a+b)/b):.5f}")

        except:
            print(f"{a:>4n} {b:>4n}  undefined")

        print_ratios(array, index+1)

#6.1.6
def draw_fibonacci_spiral():
    size = 15
    scale = 2
    #can do size = 12, scale = 5
    array = fill_fibonacci_array(arrays.Array(size))

    #turtle.tracer(0)
    initialize()
    squares(array, size, scale)
    initialize()
    turtle.right(90)
    circles(array, size, scale)

def initialize():
    turtle.setheading(0)
    turtle.colormode(255)
    turtle.up()
    turtle.goto(-800, -500)
    turtle.down()

def squares(array, depth, scale):
    if depth > 1:
        square(array[depth-1], random_color(), scale)
        squares(array, depth-1, scale)

def square(size, color, scale):
    size *= scale
    turtle.fillcolor(color)
    turtle.begin_fill()
    turtle.left(90)
    turtle.forward(size)
    turtle.right(90)
    turtle.forward(size)
    turtle.right(90)
    turtle.forward(size)
    turtle.right(90)
    turtle.forward(size)
    turtle.end_fill()
    turtle.up()
    turtle.right(90)
    turtle.forward(size)
    turtle.right(90)
    turtle.forward(size)
    turtle.right(90)
    turtle.down()

def circles(array, depth, scale):
    if depth > 1:
        circle(array[depth-1], scale)
        circles(array, depth-1, scale)

def circle(size, scale):
    size *= scale
    turtle.pensize(3)
    turtle.circle(size, -90)

def random_color():
    r = random.randint(0,255)
    g = random.randint(0,255)
    b = random.randint(0,255)
    return (r, g, b)

def main():
    '''
    #6.1.1
    n = 9
    #print(fibonacci(n))

    #6.1.3
    size = 20
    array = arrays.Array(size)
    print(fill_fibonacci_array(array))

    #6.1.5
    size = 21
    array = arrays.Array(size)
    print_ratios(fill_fibonacci_array(array))
    '''

    #6.1.6
    draw_fibonacci_spiral()
    input()

main()


#!/usr/bin/python
#Contact: emanuelvalente@gmail.com

import urllib2
import json

#Data to be send
ourdict = {'email': "emanuelvalente@gmail.com", \
	'github': "https://github.com/lbull/Code2040APIChallenge"}

#convert our data in JSON format
jdata = json.dumps(ourdict)
#Send it
response = urllib2.urlopen("http://challenge.code2040.org/api/register", jdata)
#get the content
page_content = response.read()
#print it (our token)
print(page_content)


from collections import Counter
def solution(N):
    binary = bin(N)[2:]
    c = Counter(binary)
    if c["1"] == len(binary) or c["1"] < 1:
        return 0

    res = 0
    for _ in range(c["1"]):
        f = binary.find("1")

        if binary[f+1:].find("1") == -1:
            return res

        l = binary[f+1:].find("1")-f+1
        res = max(res, l-f-1)

        binary = binary[l:]

    return res

print(solution(529))
print(solution(1041))


"""input=4
input=3 2 1 3
output=2"""
n = int(input())
ar = list(map(int, input().split()[:n]))

def diagonalDifference(ar):
    c = 0
    temp = ar[0]
    for i in range(1, len(ar)):
        if ar[i] > temp:
            temp = ar[i]
    for i in range(0, len(ar)):
        if ar[i] == temp:
            c = c + 1
    return c

result = diagonalDifference(ar)
print(result)

""""exeeded time limit"""
# n = int(input())
# ar = list(map(int, input().split()[:n]))

# def diagonalDifference(ar):
#     c = 0
#     for i in range(0, len(ar)):
#         ar.sort()

#         a = ar[n - 1]
#         if ar[i] == a:
#             c = c + 1
#         else:
#             pass
#     print(c)

# diagonalDifference(ar)


import pygame

pygame.init()

"""

==========

WIDTH -
	ширина,

HEIGHT -
	высота
-
	окна игры

	используется в:

		draw_blocks()

		классах:

			Tank

			Bullet

----------

FPS -
	частота кадров в секунду

	используется в PLAYING
				    (game)

----------

TILE -
	размер стороны блоков

	используется в:

		draw_blocks()

		классе Tank

----------

CLOCK -
	экземпляр pygame

	используется в PLAYING
				    (game)

----------

Favorite Tanks -
	установленное название окна игры

	изменяется в DRAW_INTRO
				(draw_intro)

----------

block_brick.png -
	установленная иконка окна игры

----------

WINDOW -
	экран с размерами ширины и высоты

	используется в:

		классах:

			Bullet

			UI

		MAIN

----------

CURSOR -
	курсор,
		взятый из
			IMAGE_OF_CURSOR

PALM -
	тоже самое, что и CURSOR,
		но с другой картинкой
				( IMAGE_OF_PALM )

CURSOR и PALM -
	чередуются в зависимости от расположения курсора

	используется в:

		draw_intro()

		images()

		rules()

----------

IMAGES_OF_BLOCKS -
	список с загруженными картинками блоков

	используется в:

		images()

		BLOCKS

----------

IMAGE_OF_BLUE_TANK -
	загруженная картинка синего танка

	используется в:

		images()

		draw_blocks()

----------

IMAGE_OF_RED_TANK -
	загруженная картинка красного танка

	используется в:

		images()

		draw_blocks()

----------

IMAGE_OF_INTRO_TANK -
	загруженная картинка демонстрационного танка,
		для загрузочного экрана

	используется в:

		images()

		draw_intro()

----------

IMAGES_OF_BANGS -
	список картинок взрывов

	используется в:

		images()

		draw_intro()

---------

SURF -
	объект класса pygame.Surface -
		с размерами, равными стороне блоков
									 (TILE)

	изменяется в DRAW_INTRO
				(draw_intro)

----------

BULLETS -
	список снарядом

	изменяется при выстреле
			(инициализации класса Bullet)

----------

OBJECTS -
	список экземпляров классов

	как-либо используется везде

----------

SCORE -
	количество загрузок в игру,

		может равняться 0,
			если был заход в игру первый раз
		или 1

			если был заход в бой хотя бы один раз

	изменяется в DRAW_INTRO
				(draw_intro)

----------

WIN_FLAG -
	флаг проверки в игровом цикле,
	    произошла ли победа

	изменяется в TANK
		Tank ( damage() )

	используется в PLAYING и UI
				   game()  draw()

----------

SCORE_BLUE -
	счёт количества очков у "синего" игрока

	изменяется в момент победы
					UI ( draw() )

----------

SCORE_RED -
	счёт количества очков у "красного" игрока

	изменяется в момент победы
					UI ( draw() )

----------

DIRECTS -
	список списков,
		откуда берутся значения в TANK,
								 (Tank)
			для определения направления векторов
				полёта снарядов

==========

"""

WIDTH = 800
HEIGHT = 608

FPS = 60

TILE = 32

CLOCK = pygame.time.Clock()

pygame.display.set_caption(
	'Favorite Tanks'
)

pygame.display.set_icon(
	pygame.image.load(
		"../images/block_brick.png"
	)
)

WINDOW = pygame.display.set_mode(
	(
		WIDTH,
		HEIGHT
	)
)

IMAGE_OF_CURSOR = pygame.image.load(
	'../images/arrow.png'
)
CURSOR = pygame.cursors.Cursor(
	(
		16,
		16
	),
	IMAGE_OF_CURSOR
)

IMAGE_OF_PALM = pygame.image.load(
 	'../images/palm.png'
)
PALM = pygame.cursors.Cursor(
	(
		16,
		16
	),
	IMAGE_OF_PALM
)

IMAGES_OF_BLOCKS = [
	pygame.image.load(
		'../images/block_armor2.0.png'
	),

	pygame.image.load(
		'../images/block_brick2.0.png'
	),

	pygame.image.load(
		'../images/block_bushes2.0.png'
	),

	pygame.image.load(
		'../images/block_water.png'
	)

]

IMAGE_OF_BLUE_TANK = pygame.image.load(
	'../images/tank1.png'
)

IMAGE_OF_RED_TANK = pygame.image.load(
	'../images/tank2.png'
)

IMAGE_OF_INTRO_TANK = pygame.image.load(
		'../images/intro_tank2.0.png'
)

IMAGES_OF_BANGS = [
	pygame.image.load(
		'../images/bang1.png'
	),

	pygame.image.load(
		'../images/bang2.png'
	),

	pygame.image.load(
		'../images/bang3.png'
	),

]

SURF = pygame.Surface(
	(
		TILE,
		TILE
	)
)

DIRECTS = [
	[
		0,
		-1
	],

	[
		1,
		0
	],
	[
		0,
		1
	],

	[
		-1,
		0
	]
]

BULLETS = list()
OBJECTS = list()

SCORE = 0

WIN_FLAG = False

SCORE_BLUE = 0
SCORE_RED = 0


import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import itertools
import math

def plot_history(model_history, model_name):
    # Code copied from Phil Harrissons pbseq lab and then adapted
    fig = plt.figure(figsize=(15, 5), facecolor='w')
    ax = fig.add_subplot(131)
    ax.plot(model_history.history['loss'])
    ax.plot(model_history.history['val_loss'])
    ax.set(title = model_name + ': Model loss', ylabel='Loss', xlabel='Epoch')
    ax.legend(['train', 'valid'], loc='upper right')

    # ax = fig.add_subplot(132)
    # ax.plot(np.log(model_history.history['loss'])) # THIS IS wrong
    # ax.plot(np.log(model_history.history['val_loss']))
    # ax.set(title=model_name + ': Log model loss', ylabel='Log loss', xlabel='Epoch')
    # ax.legend(['Train', 'Test'], loc='upper right')

    ax = fig.add_subplot(133)
    ax.plot(model_history.history['accuracy'])
    ax.plot(model_history.history['val_accuracy'])
    ax.set(title=model_name + ': Model accuracy', ylabel='Accuracy', xlabel='Epoch')
    ax.legend(['train', 'valid'], loc='upper right')
    plt.show()
    plt.close()

def show_random_images(data_directory, df_labels, file_column):
    figure, ax = plt.subplots(2, 3, figsize=(14, 10))
    figure.suptitle("Examples of images", fontsize=20)
    axes = ax.ravel()

    df_images_to_show = df_labels.sample(8)

    for i in range(len(axes)):
        row = df_images_to_show.iloc[[i]]
        random_image = Image.open(data_directory + row["Filenames"].values[0])
        axes[i].set_title(row["Class"].values[0], fontsize=14)
        axes[i].imshow(random_image)
        axes[i].set_axis_off()

    plt.subplots_adjust(wspace=0.05, hspace=0.05)
    plt.show()
    plt.close()

def plot_confusion_matrix(confusion_matrix, classes, title='Confusion matrix', save = False, cmap=plt.cm.Blues, scale_colours = False):
    thresh = 0.5
    vmin=0
    vmax=1
    if scale_colours:
        thresh = confusion_matrix.max() / 2.
        vmin = confusion_matrix.min()
        vmax = confusion_matrix.max()

    plt.close('all')
    plt.imshow(confusion_matrix, interpolation='nearest', cmap=cmap, vmin=vmin, vmax=vmax)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=90)
    plt.yticks(tick_marks, classes)

    for row, column in itertools.product(range(confusion_matrix.shape[0]), range(confusion_matrix.shape[1])):
        value = confusion_matrix[row, column]
        plt.text(column, row, '{:.0f} %'.format(100*value), horizontalalignment="center", color="white" if value > thresh else "black")
        # plt.txt wants x then y coordinates

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')

    if save == True:
        plt.savefig(title + '.png')

    plt.show()

def plot_2d_layer(weights, plot_title= "Layer visualized in 2D", number_of_rows = 2):
    # weights shape: (weights_in_a_node, number_of_nodes)
    # code based on:https://thispointer.com/python-convert-a-1d-array-to-a-2d-numpy-array-or-matrix/
    number_of_nodes = int(weights.shape[1])
    side_of_image = int(math.sqrt(weights.shape[0]))
    image_stack = np.reshape(weights, (side_of_image, side_of_image,number_of_nodes))

    number_of_rows = 2
    number_of_columns = (number_of_nodes // number_of_rows) + (1 if number_of_nodes % number_of_rows > 0 else 0)

    figure, ax = plt.subplots(number_of_rows,number_of_columns , figsize=(14, 10))
    figure.suptitle(plot_title, fontsize=20)
    axes = ax.ravel()

    for i in range(0,number_of_nodes):
        image = image_stack[:,:,i:i+1]
        image = image[:,:,0]
        axes[i].set_title("Node" + str(i+1), fontsize=14)
        axes[i].imshow(image)
        axes[i].set_axis_off()

    plt.subplots_adjust(wspace=0.05, hspace=0.05)
    plt.show()

def plot_1d_layer(weights, plot_title= "Layer visualized in 1d", number_of_rows = 2):
    # weights shape: (weights_in_a_node, number_of_nodes)
    number_of_nodes = int(weights.shape[1])
    image_stack = weights

    number_of_columns = (number_of_nodes // number_of_rows) + (1 if number_of_nodes % number_of_rows > 0 else 0)

    figure, ax = plt.subplots(number_of_rows,number_of_columns , figsize=(14, 10))
    figure.suptitle(plot_title, fontsize=20)
    axes = ax.ravel()

    for i in range(0,number_of_nodes):
        image = image_stack[:,i:i+1]
        image = image[:,0]
        axes[i].set_title("Node" + str(i+1), fontsize=14)
        axes[i].plot(image)
        axes[i].set_axis_off()

    plt.subplots_adjust(wspace=0.05, hspace=0.05)
    plt.show()


import turtle
import time

class Polygon:
    def __init__(self, side, name='non-set', linecolor='black', linewidth=1, stepsize=100, speed=3):
        try:
            if side < 3:
                self.side = -1
                raise ValueError
            else:
                self.side = side
        except:
            print('ValueError: The amount of sides must be greater than 2')

        self.name = name
        self.angle = (self.side-2)*180/self.side
        self.linecolor = linecolor
        self.linewidth = linewidth
        self.color = linecolor
        self.stepsize = stepsize
        self.speed = speed

    def get_name(self):
        return self.name

    def draw(self):

        if self.side == -1: # Handles error: self.side < 3
            return
    # Initialize everything
        # turtle.color(self.color)
        turtle.getscreen()
        t = turtle.Turtle()
        t.width(self.linewidth)
        t.pencolor(self.linecolor)
        t.speed(self.speed)

        for i in range(self.side):
            t.forward(self.stepsize)
            t.left(180-self.angle)

        time.sleep(1)
        t.clear()

class Triangle(Polygon):
    def __init__(self, linecolor='black', linewidth=1):
        super().__init__(3,'triangle', linecolor, linewidth)

class Square(Polygon):
    def __init__(self, linecolor='black', linewidth=1):
        super().__init__(4,'square', linecolor, linewidth)

class Pentagon(Polygon):
    def __init__(self, linecolor='black', linewidth=1):
        super().__init__(5,'pentagon', linecolor, linewidth)

class Circle(Polygon):
    def __init__(self, radius = 50, linecolor='black', linewidth=1, stepsize=5, speed='fastest'):
        super().__init__(1, 'circle', linecolor, linewidth,stepsize,speed)
        self.radius = radius

    def draw(self):
        t = turtle.Turtle()
        t.circle(self.radius)

def draw_example():
    p1 = Triangle('red')
    p1.draw()

    p2 = Square('red')
    p2.draw()

    p3 = Circle(linecolor='red')
    p3.draw()

if __name__ == '__main__':
    draw_example()


import torch
import torch.nn as nn
import torch.nn.functional as F
from typing  import Union, Callable
from model.utils.layer import DecoderLayer
from model.utils.postion import PositionalEncoding
device = torch.device('cuda' if torch.cuda.is_available() else "cpu")

class Decoder(nn.Module):
    def __init__(self, token_size: int, n: int, embedding_dim: int, heads: int, d_ff: int, dropout_rate: float, eps: float, activation: Union[str, Callable[[torch.Tensor], torch.Tensor]]):
        super().__init__()
        self.embedding_layer = nn.Embedding(num_embeddings=token_size, embedding_dim=embedding_dim)
        self.positional_encoding = PositionalEncoding(embedding_dim=embedding_dim)
        self.decoder_layers = [DecoderLayer(embedding_dim=embedding_dim, heads=heads, d_ff=d_ff, dropout_rate=dropout_rate, eps=eps, activation=activation) for _ in range(n)]

        self.linear = nn.Linear(in_features=embedding_dim, out_features=token_size)

        self.embedding_dim = embedding_dim
        self.to(device)

    def forward(self, x: torch.Tensor, mask: torch.Tensor) -> torch.Tensor:
        x = self.positional_encoding(x)
        for layer in self.decoder_layers:
            x = layer(x, mask)

        x = self.linear(x)

        return x


from _context import former
from former import util, GTransformer

from util import d, here

import torch
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
import torch.distributions as dist

import numpy as np

from argparse import ArgumentParser
from torch.utils.tensorboard import SummaryWriter

import random, tqdm, sys, math, gzip

# NB, the enwik8 data contains tokens from 9 to 240, but well round up to the nearest
# power of two.
NUM_TOKENS = 256
# Used for converting between nats and bits
LOG2E = math.log2(math.e)

def sample(lnprobs, temperature=1.0):
    """
    Sample an element from a categorical distribution
    :param lnprobs: Outcome log-probabilities
    :param temperature: Sampling temperature. 1.0 follows the given distribution,
        0.0 returns the maximum probability element.
    :return: The index of the sampled element.
    """

    if temperature == 0.0:
        return lnprobs.argmax()

    p = F.softmax(lnprobs / temperature, dim=0)
    cd = dist.Categorical(p)

    return cd.sample()

def enwik8(path, n_train=int(90e6), n_valid=int(5e6), n_test=int(5e6)):
    """
    Load the enwik8 dataset from the Hutter challenge.

    Adapted from https://github.com/openai/blocksparse/blob/master/examples/transformer/enwik8.py
    :param path:
    :param n_train:
    :param n_valid:
    :param n_test:
    :return:
    """
    with gzip.open(path) if path.endswith('.gz') else open(path) as file:
        X = np.fromstring(file.read(n_train + n_valid + n_test), dtype=np.uint8)
        trX, vaX, teX = np.split(X, [n_train, n_train + n_valid])
        return torch.from_numpy(trX), torch.from_numpy(vaX), torch.from_numpy(teX)

def go(arg):

    if arg.seed < 0:
        seed = random.randint(0, 1000000)
        print('random seed: ', seed)
    else:
        torch.manual_seed(arg.seed)

    tbw = SummaryWriter(log_dir=arg.tb_dir) # Tensorboard logging

    # load the data (validation unless arg.final is true, then test)
    arg.data = here('data/enwik8.gz') if arg.data is None else arg.data

    data_train, data_val, data_test = enwik8(arg.data)
    data_train, data_test = (torch.cat([data_train, data_val], dim=0), data_test) \
                            if arg.final else (data_train, data_val)

    # create the model
    model = GTransformer(emb=arg.embedding_size, heads=arg.num_heads, depth=arg.depth, seq_length=arg.context, num_tokens=NUM_TOKENS, wide=arg.wide)
    if torch.cuda.is_available():
        model.cuda()

    opt = torch.optim.Adam(lr=arg.lr, params=model.parameters())
    # linear learning rate warmup
    sch = torch.optim.lr_scheduler.LambdaLR(opt, lambda i: min(i / (arg.lr_warmup / arg.batch_size), 1.0))

    # training loop
    # - note: we don't loop over the data, instead we sample a batch of random subsequences each time.
    for i in tqdm.trange(arg.num_batches):

        opt.zero_grad()

        # sample a batch of random subsequences
        starts = torch.randint(size=(arg.batch_size, ), low=0, high=data_train.size(0) - arg.context - 1)
        seqs_source = [data_train[start  :start+arg.context  ] for start in starts]
        seqs_target = [data_train[start+1:start+arg.context+1] for start in starts]
        source = torch.cat([s[None, :] for s in seqs_source ], dim=0).to(torch.long)
        target = torch.cat([s[None, :] for s in seqs_target ], dim=0).to(torch.long)
        # - target is the same sequence as source, except one character ahead

        if torch.cuda.is_available():
            source, target = source.cuda(), target.cuda()
        source, target = Variable(source), Variable(target)

        output = model(source)

        loss = F.nll_loss(output.transpose(2, 1), target, reduction='mean')
        tbw.add_scalar('transformer/train-loss', float(loss.item()) * LOG2E, i * arg.batch_size)

        loss.backward()

        # clip gradients
        # - If the total gradient vector has a length > 1, we clip it back down to 1.
        if arg.gradient_clipping > 0.0:
            nn.utils.clip_grad_norm_(model.parameters(), arg.gradient_clipping)

        opt.step()
        sch.step()

        # - validate every {arg.test_every} steps. First we compute the
        #   compression on the validation (or a subset)
        #   then we generate some random text to monitor progress
        if i != 0 and (i % arg.test_every == 0 or i == arg.num_batches - 1):

            upto = data_test.size(0) if i == arg.num_batches - 1 else arg.test_subset
            data_sub = data_test[:upto]

            with torch.no_grad():
                bits, tot = 0.0, 0
                batch = [] # buffer, every time it fills up, we run it through the model

                for current in range(data_sub.size(0)):

                    fr = max(0, current - arg.context)
                    to = current + 1

                    context = data_sub[fr:to].to(torch.long)
                    if context.size(0) < arg.context + 1:
                        pad = torch.zeros(size=(arg.context + 1 - context.size(0),), dtype=torch.long)
                        context = torch.cat([pad, context], dim=0)

                        assert context.size(0) == arg.context + 1

                    if torch.cuda.is_available():
                        context = context.cuda()

                    batch.append(context[None, :])

                    if len(batch) == arg.test_batchsize or current == data_sub.size(0) - 1:

                        # batch is full, run it through the model
                        b = len(batch)

                        all = torch.cat(batch, dim=0)
                        source = all[:, :-1] # input
                        target = all[:, -1]  # target values

                        output = model(source)

                        lnprobs = output[torch.arange(b, device=d()), -1, target]
                        log2probs = lnprobs * LOG2E # convert from nats to bits

                        bits += - log2probs.sum()
                        batch = [] # empty buffer

                bits_per_byte = bits / data_sub.size(0)

                # print validation performance. 1 bit per byte is (currently) state of the art.
                print(f'epoch{i}: {bits_per_byte:.4} bits per byte')
                tbw.add_scalar(f'transformer/eval-loss', bits_per_byte, i * arg.batch_size)

                # generate some random text
                GENSIZE = 600
                TEMP = 0.5
                seedfr = random.randint(0, data_test.size(0) - arg.context)
                input = data_test[seedfr:seedfr + arg.context].to(torch.long)

                if torch.cuda.is_available():
                    input = input.cuda()

                input = Variable(input)

                print('[', end='', flush=True)
                for c in input:
                    print(str(chr(c)), end='', flush=True)
                print(']', end='', flush=True)

                for _ in range(GENSIZE):
                    output = model(input[None, :])
                    c = sample(output[0, -1, :], TEMP)
                    print(str(chr(max(32, c))), end='', flush=True)

                    input = torch.cat([input[1:], c[None]], dim=0)

                print()

if __name__ == "__main__":

    ## Parse the command line options
    parser = ArgumentParser()

    parser.add_argument("-N", "--num-batches",
                        dest="num_batches",
                        help="Number of batches to train on. Each batch contains randomly sampled subsequences of the data.",
                        default=1_000_000, type=int)

    parser.add_argument("-b", "--batch-size",
                        dest="batch_size",
                        help="The batch size.",
                        default=32, type=int)

    parser.add_argument("-D", "--data", dest="data",
                        help="Data file. Will be read as a string of 8-bit characters.",
                        default=None)

    parser.add_argument("-l", "--learn-rate",
                        dest="lr",
                        help="Learning rate",
                        default=0.0001, type=float)

    parser.add_argument("-T", "--tb_dir", dest="tb_dir",
                        help="Tensorboard logging directory",
                        default='./runs')

    parser.add_argument("-f", "--final", dest="final",
                        help="Whether to run on the real test set (if not included, the validation set is used).",
                        action="store_true")

    parser.add_argument("-E", "--embedding", dest="embedding_size",
                        help="Size of the character embeddings.",
                        default=128, type=int)

    parser.add_argument("-H", "--heads", dest="num_heads",
                        help="Number of attention heads.",
                        default=8, type=int)

    parser.add_argument("-C", "--context", dest="context",
                        help="Length of the sequences extracted from the corpus (and the context used during inference).",
                        default=256, type=int)

    parser.add_argument("-d", "--depth", dest="depth",
                        help="Depth of the network (nr of self-attention layers)",
                        default=12, type=int)

    parser.add_argument("-r", "--random-seed",
                        dest="seed",
                        help="RNG seed. Negative for random",
                        default=1, type=int)

    parser.add_argument("--test-every",
                        dest="test_every",
                        help="How many batches between tests.",
                        default=1500, type=int)

    parser.add_argument("--test-subset",
                        dest="test_subset",
                        help="A subset for the validation tests.",
                        default=100000, type=int)

    parser.add_argument("--test-batchsize",
                        dest="test_batchsize",
                        help="Batch size for computing the validation loss. This can be a bit bigger than the training batch size.",
                        default=64, type=int)

    parser.add_argument("--gradient-clipping",
                        dest="gradient_clipping",
                        help="Gradient clipping.",
                        default=1.0, type=float)

    parser.add_argument("--lr-warmup",
                        dest="lr_warmup",
                        help="Learning rate warmup.",
                        default=5000, type=int)

    parser.add_argument("--wide", dest="wide",
                        help="Use wide self attention instead of narrow self attention.",
                        action="store_true")

    options = parser.parse_args()

    print('OPTIONS ', options)

    go(options)


import math
import os
import random
import re
import sys

def beautifulTriplets(d, arr):
    nums = set(arr)
    return sum(n + d in nums and n + d + d in nums for n in arr)

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    nd = input().split()

    n = int(nd[0])

    d = int(nd[1])

    arr = list(map(int, input().rstrip().split()))

    result = beautifulTriplets(d, arr)

    fptr.write(str(result) + '\n')

    fptr.close()

Problem solving/Beautiful Triplets/Beautiful Triplets.py


# import modules
from tkinter import *
import sys

main_window = Tk()
main_window.geometry("400x300")

# variables
FONT=("Verdana", 16)
FG_COLOUR="#eeeeee"
BG_COLOUR="#777777"

# command functions
def calculate():
    temp = float(temperature_input.get())
    temp = (temp * 9 / 5) + 32
    display_temperature.configure(text = "{:.1f} degrees F".format(temp))
    temperature_input.delete(0, END)

def close_cmd():
    sys.exit()

# create widgets
display_title = Label(text="temperature converter", font=FONT, fg=FG_COLOUR, bg=BG_COLOUR)
get_temperature = Label(text="enter temperature", font=FONT, fg=FG_COLOUR, bg=BG_COLOUR)
temperature_input = Entry(font=FONT, fg=FG_COLOUR, bg=BG_COLOUR)
convert_button = Button(text="[ enter ]", font=FONT, fg=FG_COLOUR, bg=BG_COLOUR, bd=4, relief=RAISED, command=calculate)
display_temperature = Label(font=FONT, fg=FG_COLOUR, bg=BG_COLOUR)

# display widgets
display_title.place(x=0, y=0, width=400, height=60)
get_temperature.place(x=0, y=60, width=400, height=60)
temperature_input.place(x=0, y=120, width=400, height=60)
convert_button.place(x=0, y=180, width=400, height=60)
display_temperature.place(x=0, y=240, width=400, height=60)

# create menu
top = Menu(main_window)
file = Menu(top)
file.add_command(label="Close", command=close_cmd)
top.add_cascade(label="File", menu=file)
main_window.config(menu=top)

main_window.mainloop()


'''
DNAA Boxes

The aim of this script is to find the origin of replication for a given genome

Given:
string = a region of a genome where the supposed origin of replication is located as
suggested by finding the minimum of the skew for the genome.
k = an estimated size of dnaA string for genome being tested.
d = an estimated number of mismatches to find the neighborhoods of the dnaA boxes

Return:
a list of kmers of length k that are the potential dnaA boxes in the given region

'''

import time
from collections import defaultdict
import itertools

def get_data():
	#Load genome Data
	with open('...test_genome.txt') as file:
		title=file.readline().replace('\n','')
		seq_list=file.readlines()
		file.close()

	string=''.join(seq_list).replace('\n','')
	return string

def rev_comp(text):
	#output the reverse complement of the given string
	output_forward=[]
	output=[]
	output_list=[]
	for i in text:
		if i=='C':
			output_forward.append('G')
		if i=='T':
			output_forward.append('A')
		if i=='G':
			output_forward.append('C')
		if i=='A':
			output_forward.append('T')

	for j in range(1,len(text)+1):
		output_list.append(output_forward[-j])

	output=''.join(let for let in output_list)

	return output

def HammDist(seq1,seq2):
	#The hamming distance between two strings is the
	#number of mismatches between the two strings
	count=0
	for i in range(len(seq1)):
		if seq1[i]!=seq2[i]:
			count=count+1

	return count

def Neighbors(pattern,d):
	'''
	finds the neighbors with hamm dist < d recursively
	'''
	if d==0:
		return [pattern]
	if len(pattern)==1:
		return ['A','C','G','T']
	neighborhood=[]
	SuffixNeighbors=Neighbors(pattern[1:],d)
	for kmer in SuffixNeighbors:
		if HammDist(kmer,pattern[1:]) < d:
			for x in ['A','C','G','T']:
				neighborhood.append(x+kmer)
		else:
			neighborhood.append(pattern[0]+kmer)
	return neighborhood

def find_kmer(string,k,d):
	'''
	In an effort to speed up the process of finding the most frequent kmers,
	With this version, we will generate the neighborhood for each kmer in sequence,
	reducing the number of computations significantly.

	This function outputs a list of the kmers with the maximum number of neighbors
	that have a hamming distance < d
	'''
	#First create a list of all the kmers of length k in string and rev complement of string
	kmer_dict=[]
	for i in range(len(string)-k+1):
		kmer_dict.append(string[i:i+k])

	#Create an array of all possible kmers of length k, store in dictionary
	arrays=list(itertools.product(['A','C','G','T'],repeat=k))
	outs={}
	outs=defaultdict(lambda:0,outs)
	for item in arrays:
		string=''.join(let for let in item)
		outs[string]

	#Next find the neighborhood with hamm dist<d for each kmer in string
	#save the kmers that meet hamm dist to the dictionary
	for kmer in kmer_dict:
		#add rev comp of kmer here to get neighbors of both.
		nbrs=Neighbors(kmer,d)+Neighbors(rev_comp(kmer),d)
		for item in nbrs:
			outs[item] += 1

	#find maximum value of kmers with hamm dist<d
	maxi=0
	for key in outs.keys():
		if outs[key]>maxi:
			maxi=outs[key]

	#create list of kmers with that maximum value
	kmers_out=[]
	for key in outs.keys():
		if outs[key]==maxi:
			kmers_out.append(key)

	return kmers_out

def save_output_str(output_list):
	''' Convert a list of strings to a string with each item in list seperated by newline
		save string to text file
	'''
	string=' '.join(str for str in output_list)
	with open('dna_boxes_output.txt','w') as newfile:
		newfile.write(string)
		newfile.close()

def main():
	start_time = time.time()
	string=get_data()

	#test a subset of the genome string with a given window size
	#minimum skew for E. coli is found at position 3923620
	start=3923620
	window=1000
	test_str=string[start-window//2:start+window//2]

	#find_kmer returns a list of the kmers of length k with the
	#maximum number of neighbors and that have a hamming distance < d
	#bacterial DnaA boxes are usually 9 nucleotides long, so use k=9 for bacteria
	kmers=find_kmer(test_str,9,1)
	print(kmers)
	save_output_str(kmers)
	print('%f seconds' % (time.time() - start_time))

main()


p = (1, 4)
x, y = p
print(x, y)

data = ["ACME", 50, 90.1, (2021, 4, 27)]
name, shares, price, date = data
print(name, date)
name, shares, price, (y, m, d) = data
print(shares, m)

word = "Hello"
a, b, c, d, e = word
print(a, d)
# Throwaway vars
data = ["ACME", 50, 90.1, (2021, 4, 27)]
_, shares, price, date = data

def drop_first_last(*grades):
    first, *middle, last = grades
    print(sum(middle) / len(middle))

drop_first_last(1, 5, 5, 5, 100)
record = ["Dave", "dave@test.com", 6, 5, 1977, "Halcom"]
name, mail, *rest, company = record
print(name, mail, rest, company)

records = [
    ("plus", 1, 2),
    ("minus", 3, 4),
    ("plus", 4, 5),
]

def plus(x, y):
    print("seštevam", x + y)

def minus(x, y):
    print("odštevam", x - y)

for tag, *args in records:
    if tag == "plus":
        plus(*args)
    elif tag == "minus":
        minus(*args)

line = "nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false"
uname, *fields, homedir, sh = line.split(":")
print(uname, fields, homedir, sh)

items = list(range(13))
head, *tail = items
print(head, tail)

def sum(items):
    head, *tail = items
    return head + sum(tail) if tail else head

print(sum(items))

from collections import deque

print("Keep latest n items history")

def search(lines, pattern, history=5):
    previous_lines = deque(maxlen=history)
    for line in lines:
        if pattern in line:
            yield line, previous_lines
        previous_lines.append(line)

with open("/home/rado/sw/python/PythonCookBook/test.txt") as f:
    for line, prevlines in search(f, "Lorem"):
        for pline in prevlines:
            print("HI" * 20)
            print(pline, end="")
            print("ST" * 20)

        print(line, end="")
        print("-" * 20)

print("Find n largest, smallest items in collection")

import heapq

nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

portfolio = [
    {"name": "IBM", "shares": 100, "price": 91.1},
    {"name": "AAPL", "shares": 50, "price": 543.22},
    {"name": "FB", "shares": 200, "price": 21.09},
    {"name": "HPQ", "shares": 35, "price": 31.75},
    {"name": "YHOO", "shares": 45, "price": 16.35},
    {"name": "ACME", "shares": 75, "price": 115.65},
]

print("cheap", heapq.nsmallest(3, portfolio, key=lambda s: s["price"]))
print("expensive", heapq.nlargest(3, portfolio, key=lambda s: s["price"]))

print(nums)
(heapq.heapify(nums))
print(nums)
print(heapq.heappop(nums))
print(heapq.heappop(nums))

print("Priority Queue")

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)[-1]

class Item:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "Item({!r})".format(self.name)

q = PriorityQueue()
q.push(Item("foo"), 1)
q.push(Item("bar"), 5)
q.push(Item("spam"), 4)
q.push(Item("grok"), 1)
print(q.pop())
print(q.pop())
print(q.pop())
print(q.pop())
print("To make items comparable use touples or they cannot be compared")
print((1, Item("foo")) < (2, Item("test")))
print((1, 1, Item("foo")) < (1, 0, Item("test")))

print("Multidict")
zivila = {
    "pijace": ["pivo", "vino", "voda"],
    "hrana": ["burger", "kruh", "zelje", "klobase"],
}

import pprint

pprint.pprint(zivila)

from collections import defaultdict

zivila = defaultdict(list)
zivila["pijace"].append("pivo")
zivila["pijace"].append("vino")
zivila["pijace"].append("voda")
zivila["hrana"].append("burger")
zivila["hrana"].append("kruh")
zivila["hrana"].append("zelje")
zivila["hrana"].append("klobase")
zivila["hrana"].append("zelje")

pprint.pprint(zivila)

zivila = defaultdict(set)
zivila["pijace"].add("pivo")
zivila["pijace"].add("vino")
zivila["pijace"].add("voda")
zivila["hrana"].add("burger")
zivila["hrana"].add("kruh")
zivila["hrana"].add("zelje")
zivila["hrana"].add("klobase")
zivila["hrana"].add("zelje")

pprint.pprint(zivila)

pairs = [
    ["pijace", "pivo"],
    ["pijace", "vino"],
    ["pijace", "voda"],
    ["hrana", "burger"],
    ["hrana", "kruh"],
    ["hrana", "zelje"],
    ["hrana", "klobase"],
    ["hrana", "zelje"],
]

zivila = defaultdict(list)
for key, value in pairs:
    zivila[key].append(value)

pprint.pprint(zivila)

print("1.7 Keeping dictionary in order")

from collections import OrderedDict
import json

d = OrderedDict()
d["foo"] = 1
d["bar"] = 2
d["spam"] = 3
d["grok"] = 4

for key, value in d.items():
    print(key, value)
print(json.dumps(d))

print("1.8 Calculating wiht dictionaries")
prices = {"ACME": 45.23, "AAPL": 612.78, "IBM": 205.55, "HPQ": 37.20, "FB": 10.75}
print(min(prices))  # Not ok is searchig min key)
print(min(prices.values()))  # Not ok finds only the smallest value
print(min(zip(prices.values(), prices.keys())))
print(sorted(zip(prices.values(), prices.keys())))

print("1.9. Finding Commonalities in Two Dictionaries")
a = {"x": 1, "y": 2, "z": 3}
b = {"w": 10, "x": 11, "y": 2}

print(a.keys() & b.keys())
print(a.keys() - b.keys())
print(a.items() & b.items())
print("Make a new dict wiht certain keys removed")
c = {key: a[key] for key in a.keys() - {"z", "w"}}
print(c)

print("1.10. Removing Duplicates from a Sequence while Maintaining Order")

def dedupe(items, key=None):
    seen = set()
    for item in items:
        val = item if key is None else key(item)
        if val not in seen:
            yield item
            seen.add(val)

a = [1, 5, 2, 1, 9, 1, 5, 10]
print(list(dedupe(a)))

a = [{"x": 1, "y": 2}, {"x": 1, "y": 3}, {"x": 1, "y": 2}, {"x": 2, "y": 4}]
print(list(dedupe(a, key=lambda d: (d["x"], d["y"]))))

print("1.11. Naming a Slice")
record = "....................100.......513.25.........."
cost = int(record[20:23]) * float(record[30:36])
print(record)
print(cost)

SHARES = slice(20, 23)
PRICE = slice(30, 36)
cost = int(record[SHARES]) * float(record[PRICE])
print(cost)
a = slice(5, 50, 2)
print(a.start, a.stop, a.step)
s = "HelloWorld"
print(a.indices(len(s)))
for i in range(*a.indices(len(s))):
    print(s[i])
print("1.12. Determining the Most Frequently Occurring Items in a Sequence")


# -*- coding: utf-8 -*-
###############################################################################
#
# Copyright (c) 2005 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
###############################################################################
"""RML-to-PDF View

$Id$
"""
__docformat__ = "reStructuredText"

import cStringIO
from zope.publisher.browser import BrowserPage
from z3c.rml import rml2pdf

class RML2PDFView(BrowserPage):

    template = None
    encoding = u'iso-8859-1'

    def __call__(self):
        rml = self.template(self).encode(self.encoding)
        self.request.response.setHeader('content-type', 'application/pdf')
        return rml2pdf.parseString(rml).read()


"""Development configuration."""
import pathlib
# Root of this application, useful if it doesn't occupy an entire domain
APPLICATION_ROOT = '/'
# Secret key for encrypting cookies
SECRET_KEY = (b'\x8a\xac\xb5\xd4\x19\xe6\xef',
              '\x18\xe7\xd4\x11\x05\xf3\x95\x9b\xbeD~-\xdf@[\xf8k')
SESSION_COOKIE_NAME = 'login'
SITE_ROOT = pathlib.Path(__file__).resolve().parent.parent
# File Upload to static/img/
UPLOADS_FOLDER = SITE_ROOT/"porto"/"static"/"img"/"upload"
# Database file is var/resume.sqlite3
DATABASE_FILENAME = SITE_ROOT/'var'/'porto.sqlite3'


from collections import Counter
import nltk

def stemmize(token, stem_reference=None):
    token = token.casefold()
    stemmer = nltk.stem.RSLPStemmer()
    stemmed = stemmer.stem(token)

    if stem_reference is not None:
        reference = stem_reference.get(stemmed, Counter())
        reference.update([token])
        stem_reference[stemmed] = reference

    return stemmed


from django.shortcuts import render, redirect
# from importlib_metadata import re
from .forms import *
from .models import *
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from product.models import Products
from django.db.models import Sum
from restock.models import Inventory
from accounts.models import Account_Receivables, General_Ledger, All_Transaction,Accumulated_fund, Sub_Accounts,Revenue

def manage_orders(request):
    orders = Orders.objects.all()

    if request.method == 'POST':
        form = OrderForm(request.POST)
        if form.is_valid():
            stock=form.save()
            messages.success(request,'Please Select items for this order')
            return redirect('orders:add_orders',stock.id)

    else:
        form = OrderForm()

    template = 'orders/manage_order.html'

    context = {
        'orders': orders,
        'form':form,
    }

    return render(request,template,context)

def manage_car(request):
    cars = Car.objects.all()

    if request.method == 'POST':
        form = CarForm(request.POST)
        if form.is_valid():
            stock=form.save()
            messages.success(request,'Car Saved')
            return redirect('orders:manage_car')

    else:
        form = CarForm()

    template = 'orders/manage_car.html'

    context = {
        'cars': cars,
        'form':form,
    }

    return render(request,template,context)

def edit_car(request,pk):
    cars = Car.objects.all()
    car = Car.objects.get(id=pk)

    if request.method == 'POST':
        form = CarForm(request.POST,instance=car)
        if form.is_valid():
            stock=form.save()
            messages.success(request,'Car Updated')
            return redirect('orders:manage_car')

    else:
        form = CarForm(instance=car)

    template = 'orders/manage_car.html'

    context = {
        'cars': cars,
        'form':form,
    }

    return render(request,template,context)

def add_orders(request,pk):
    order = Orders.objects.get(id=pk)
    details = Order_details.objects.filter(order=order)
    if details:
        gross_total = details.aggregate(cc=Sum('gross_price'))
        tt = gross_total['cc']

    else:
        tt = 0.00

    if request.method =='POST':
        form = OrderDetailForm(request.POST)
        if form.is_valid():
            product = form.cleaned_data.get("item")
            print(product)
            pro = Products.objects.get(name=product)
            cc = form.save(commit=False)
            cc.order = order
            cc.unit_price = pro.unit_price
            cc.save()
            messages.success(request,'Item Selected')
            return redirect('orders:add_orders', order.id)

    else:
        form = OrderDetailForm()

    template = 'orders/add_order.html'

    context = {
        'order': order,
        'details':details,
        'form':form,
        'tt':tt
    }

    return render(request,template,context)

def order_summery(request,pk):
    order = Orders.objects.get(id=pk)
    general_ledger = Revenue.objects.filter(transactionref=order.id)
    details = Order_details.objects.filter(order=order)
    if details:
        gross_total = details.aggregate(cc=Sum('gross_price'))
        tt = gross_total['cc']

    else:
        tt = 0.00

    template = 'orders/order_summery.html'

    context = {
        'order': order,

        'tt':tt,
        'details':details,
        'general_ledger':general_ledger
    }

    return render(request,template,context)

def remove_item(request,pk):
    item = Order_details.objects.get(id=pk)
    ff=item.order.id
    item.delete()
    messages.success(request,'Item Removed')
    return redirect('orders:add_orders', ff)

def approve_order(request,pk):
    item = Orders.objects.get(id=pk)
    item.status = 'approved'
    item.save()
    messages.success(request,'Order Approved , Kindly comfirm the Supply')
    return redirect('orders:order_summery', item.id)

def comfirm_order(request,pk):
    order = Orders.objects.get(id=pk)
    details = Order_details.objects.filter(order=order)
    order.status = 'comfirmed'
    order.save()
    messages.success(request,'Supply Comfirmed')
    return redirect('orders:order_summery', order.id)

def add_return_saless(request,pk):
    details = Order_details.objects.get(id=pk)
    order = Orders.objects.get(id=details.order.id)
    if request.method =='POST':
        form = ReturnForm(request.POST)
        if form.is_valid():
            qty = form.cleaned_data.get("quantity")
            details.quantity_returned = qty
            details.save()
            messages.success(request,'Quantity Returned Added')
            return redirect('orders:order_summery', order.id)
    else:
        form = ReturnForm()

    template = 'orders/sales_retun.html'

    context = {

        'details':details,
        'form':form,

    }

    return render(request,template,context)

def add_sales_amount(request,pk):
    order = Orders.objects.get(id=pk)
    if request.method =='POST':
        form = SaleAmountForm(request.POST)
        if form.is_valid():
            sales_posted = form.cleaned_data.get("sales_posted")
            order.sales_posted = sales_posted
            order.save()
            messages.success(request,'Distribution Sales Entered')
            return redirect('orders:order_summery', order.id)
    else:
        form = SaleAmountForm()

    template = 'orders/sales_amount.html'

    context = {

        'order':order,
        'form':form,

    }

    return render(request,template,context)

def close_shitf_sales(request,pk):
    order = Orders.objects.get(id=pk)
    details = Order_details.objects.filter(order=order)
    sub_code = Sub_Accounts.objects.get(sub_description='SALES')
    ff = Accumulated_fund.objects.all().order_by('id').last()
    if ff is None :
        messages.success(request,'You cannot comfirm a supply until you start an accounting year')
        return redirect('orders:order_summery', order.id)
    elif ff.status == 'Closed':
        messages.success(request,'You cannot comfirm a supply until you start an accounting year')
        return redirect('orders:order_summery', order.id)
    else:
        if details:
            gross_total = details.aggregate(cc=Sum('gross_price'))
            tt = gross_total['cc']

        else:
            tt = 0.00

        for item in details:
            try:
                if Inventory.objects.filter(product = item.item).exists():
                    item_inventroy = Inventory.objects.get(product=item.item)
                    item_inventroy.outgoing += item.atual_quantity
                    item_inventroy.save()
                else:
                    pass

            except Inventory.DoesNotExist:
                pass
        Revenue.objects.create(account_period=ff,transaction_date=order.order_date,sub_code=sub_code,description="Supply of Water" ,amount=tt,car=order.car,transactionref=order.id)
    order.status = 'posted'
    order.save()
    messages.success(request,'Daily Shift Closed')
    return redirect('orders:order_summery', order.id)


from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_request_type, is_intent_name
from ask_sdk_model.ui.link_account_card import LinkAccountCard

from services.States import States
from services.Utils import getChatName, formatMessages

class RepeatIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_request_type("IntentRequest")(handler_input) and is_intent_name('AMAZON.RepeatIntent')(handler_input)

    def handle(self, handler_input):
        sessionAttributes = handler_input.attributes_manager.session_attributes

        if not sessionAttributes['isAuthorized']:
            speech_text = handler_input.i18n.t('Errors.noAccountLinked')
            handler_input.response_builder.speak(speech_text).set_should_end_session(True)
        elif 'read' in sessionAttributes and 'current' in sessionAttributes['read']:
            chats = sessionAttributes['read']['chats']
            currentChat = sessionAttributes['read']['current']
            messages = currentChat.get('messages')
            unread = len(messages)

            speech_text = handler_input.i18n.t('ReadMessageIntent.speech.chat',
                                               count = unread,
                                               messages = formatMessages(chat = currentChat, i18n = handler_input.i18n))

            if currentChat.get('canReply'):
                canReply = handler_input.i18n.t('ReadMessageIntent.speech.canReply')
                sessionAttributes['state'] = States.REPLY
            else:
                canReply = ''  # handler_input.i18n.t('ReadMessageIntent.speech.cantReply')
                if len(chats) > 0:
                    names = list(map(lambda chat: getChatName(chat), chats))
                    comma = ', '
                    chatNames = comma.join(names[:-1])
                    fistChat = names[0]
                    lastChat = names[-1]
                    canReply = canReply + handler_input.i18n.t('ReadMessageIntent.speech.middleRecap',
                                                               count = len(chats),
                                                               chats = chatNames, lastChat = lastChat,
                                                               fistChat = fistChat)
                else:
                    sessionAttributes['state'] = States.SEND
                    canReply = canReply + handler_input.i18n.t('ReadMessageIntent.speech.middleRecap', count = 0)

            speech_text = speech_text + canReply

            handler_input.response_builder.speak(speech_text).ask(speech_text)

        else:
            speech_text = handler_input.i18n.t('RepeatIntent.speech.noMessage')
            handler_input.response_builder.speak(speech_text).ask(speech_text)

        return handler_input.response_builder.response


import copy

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

    def set_next(self, new_next):
        self.next = new_next

    def get_next(self):
        return self.next

    def set_data(self, new_data):
        self.data = new_data

    def get_data(self):
        return self.data

class StackEmptyException(Exception):
    pass

class StackWithLinkedList:
    def __init__(self):
        self.top = None
        self.size = 0

    def is_empty(self):
        return self.top is None

    def peek(self):
        if self.is_empty():
            raise StackEmptyException("Stack is empty")
        return self.top.data

    def push(self, data):
        new_node = Node(data)
        new_node.next = self.top
        self.top = new_node
        self.size += 1

    def pop(self):
        if self.is_empty():
            raise StackEmptyException("Stack is empty")
        data = self.top.data
        next_head = self.top.next
        self.top.next = None
        self.top = next_head
        self.size -= 1
        return data

    def display(self):
        cur = self.top
        while cur is not None:
            print(cur.data, end=" -> ")
            cur = cur.next
        print("None")

    def delete_all(self):
        while self.top is not None:
            print(f"Freeing: {self.top.data}")
            next = self.top.next
            self.top.next = None
            del self.top
            self.top = next

    def insert_nth(self, data, nth):
        new_node = Node(data)
        index = 0
        prev = None
        cur = self.top

        while cur is not None and index < nth:
            prev = cur
            cur = cur.next
            index += 1
        # insert at the beginning
        if prev is None:
            self.top = new_node
        else:
            prev.next = new_node
        new_node.next = cur
        self.size += 1

    def insert_sorted(self, data):
        new_node = Node(data)
        prev = None
        cur = self.top

        while cur is not None and cur.data < data:
            prev = cur
            cur = cur.next

        if prev is None:
            self.top = new_node
        else:
            prev.next = new_node
        new_node.next = cur

    def remove_duplicates(self):
        if self.is_empty():
            return

        prev = self.top
        cur = self.top.next

        while cur is not None:
            if prev.data == cur.data:
                prev.next = cur.next
                cur.next = None
                cur = prev.next
                continue
            prev = cur
            cur = cur.next

def merge_sorted_list(lista, listb):
    if lista is None: return listb
    if listb is None: return lista

    if lista.data < listb.data:
        head = lista
        lista = lista.next
    else:
        head = listb
        listb = listb.next

    head.next = None
    cur = head
    while lista is not None and listb is not None:
        if lista.data < listb.data:
            cur.next = lista
            lista = lista.next

        else:
            cur.next = listb
            listb = listb.next
        cur = cur.next

    if lista is not None:
        cur.next = lista
    else:
        cur.next = listb

    return head

def reverse_iter(head):
    prev = None
    cur = head

    while cur is not None:
        next = cur.next
        cur.next = prev
        prev = cur
        cur = next
    return prev

if __name__ == "__main__":
    s = StackWithLinkedList()
    # s.display()
    # s.push(3)
    # s.push(4)
    # s.push(5)
    # s.display()
    # s.pop()
    # s.display()
    # s.pop()
    # s.display()
    # s.push(2)
    # s.display()
    #
    # for x in range(10):
    #     s.push(x**2)
    #
    # s.display()
    # s.delete_all()
    # print(s.top)
    # s.display()
    #
    # s.insert_nth(1, 5)
    # s.display()
    # s.insert_nth(2, 11)
    # s.display()
    # s.insert_nth(2, -11)
    # s.display()
    # s.insert_nth(20, 1)
    # s.display()
    # s.insert_nth(50, 3)
    # s.display()

    # s.insert_sorted(4)
    # s.display()
    # s.insert_sorted(10)
    # s.display()
    # s.insert_sorted(2)
    # s.display()
    # s.insert_sorted(5)
    # s.display()
    # s.insert_sorted(20)
    # s.display()
    # s.push(1)
    # s.push(1)
    # # s.insert_nth(2, 33)
    # # s.insert_nth(2, 33)
    # # s.insert_nth(2, 33)
    # # s.insert_nth(3, 33)
    # s.remove_duplicates()
    # s.display()
    s.insert_sorted(1)
    s.insert_sorted(3)
    s.insert_sorted(5)
    s.display()

    v = StackWithLinkedList()
    v.insert_sorted(2)
    v.insert_sorted(4)
    v.insert_sorted(6)
    v.display()

    final = merge_sorted_list(s.top, v.top)
    #
    # while final is not None:
    #     print(final.data, sep=" -> ")
    #     final = final.next

    final = reverse_iter(final)
    while final is not None:
        print(final.data, sep=" -> ")
        final = final.next


#
# The following code liberally taken from the OpenAI gym/examples/random_agent.py source
#

import argparse
import logging
import sys

import numpy as np
import nengo

import gym
import universe
from gym import wrappers

#from nengo.processes import WhiteSignal #replace this with input from Env.()

class NengoUniverse(object):

    def __init__(self):
        #super(NengoGymLunarLander, self).__init__(self.step)
        #self.name = name
        print("*** Universe Init****")

        self.env = gym.make('flashgames.DuskDrive-v0') # any Universe environment ID here
        self.env.configure(remotes=1)  # automatically creates a local docker container
        self.observation = self.env.reset()
        self.action = [[('KeyEvent', 'ArrowUp', True)] for ob in self.observation]
        self.actionstate = 0
        # print("Action Space:")
        # print(self.env.action_space)
        #
        # print("Observation Space:")
        # print(self.env.observation_space)
        # print(self.env.observation_space.high)
        # print(self.env.observation_space.low)

        self.reward = 0
        self.total_reward = 0
        self.steps = 0
        # self.output = []
    #handles the environment state and possible reward value passed back
    #reinforce heuristics based on reward
    def handle_input(values):
        return 0 #nothing for now

    def handle_output(self):
        return 0 #nothing for now

    def heuristic(self,state):

        return 0 #nothing for now

    def __call__(self, t, action_temp):

        #action_n = [[('KeyEvent', 'ArrowUp', True)] for _ in observation_n]

        # if action_temp[0] < -0.3 and self.actionstate != 0:
        #     self.actionstate = 0
        #     self.action = [[('KeyEvent', 'ArrightRight', False)]]
        #     self.env.step(self.action)
        #     self.action = [[('KeyEvent', 'ArrowUp', False)]]
        #     self.env.step(self.action)
        #     self.action = [[('KeyEvent', 'ArrowLeft', True)]  for ob in self.observation]
        #     self.observation, reward, done, info = self.env.step(self.action)
        # elif action_temp[0] > 0.3 and self.actionstate != 1:
        #     self.actionstate = 1
        #     self.action = [[('KeyEvent', 'ArrowLeft', False)]]
        #     self.env.step(self.action)
        #     self.action = [[('KeyEvent', 'ArrowUp', False)]]
        #     self.env.step(self.action)
        #     self.action = [[('KeyEvent', 'ArrowRight', True)] for ob in self.observation]
        #     self.observation, reward, done, info = self.env.step(self.action)
        # else: #default to gas
        #     self.actionstate = 2
        #     self.action = [[('KeyEvent', 'ArrowRight', False)]]
        #     self.env.step(self.action)
        #     self.action = [[('KeyEvent', 'ArrowLeft', False)]]
        #     self.env.step(self.action)
        #
        self.action = [[('KeyEvent', 'ArrowUp', True)] for ob in self.observation]
        self.observation, reward, done, info = self.env.step(self.action)

        self.env.render() #one frame

        #tally reward for epoch updates
        self.total_reward += self.reward
        #total_reward += 1

        self.steps += 1

        #check to see if we have crashed, landed, etc
        # if done:
        #     env.render(close=True)
        #     raise Exception("Simulation done")
        #     self.state = self.env.reset()
        #

        return self.observation

class NengoGymNode(nengo.Node):

    def __init__(self, **kwargs):
        self.env = NengoGymLunarLander(**kwargs)

        def func(t, x):
            return self.env.step(x[0])

        super(NengoGymNode, self).__init__(size_in=1, size_out=1)

def heuristic(state):

#     type(state)

#     #PID controller for trajectory optimizatio
#     #Engine control based on Pontryagin's maximum principle (full thrust on/off)

#     angle_targ = state[0]*0.5 + state[2]*1.0         # angle should point towards center (state[0] is horizontal coordinate, state[2] hor speed)
#     #if angle_targ >  0.4: angle_targ =  0.4  # more than 0.4 radians (22 degrees) is bad
#     #if angle_targ < -0.4: angle_targ = -0.4

#     if angle_targ >  0: angle_targ =  0.4  # more than 0.4 radians (22 degrees) is bad
#     if angle_targ < -0: angle_targ = -0.4

#     hover_targ = 0.55*np.abs(state[0])           # target y should be proporional to horizontal offset

#     # PID controller: state[4] angle, state[5] angularSpeed
#     angle_todo = (angle_targ - state[4])*0.5 - (state[5])*1.0
#     #print("angle_targ=%0.2f, angle_todo=%0.2f" % (angle_targ, angle_todo))

#     # PID controller: state[1] vertical coordinate state[3] vertical speed
#     hover_todo = (hover_targ - state[1])*0.5 - (state[3])*0.5
#     #print("hover_targ=%0.2f, hover_todo=%0.2f" % (hover_targ, hover_todo))

#     if state[6] or state[7]: # legs have contact
#         angle_todo = 0
#         hover_todo = -(state[3])*0.5  # override to reduce fall speed, that's all we need after contact

#     # # analog feedback
#     # action = np.array( [hover_todo*20 - 1, -angle_todo*20] )
#     # #action = np.clip(action, -1, +1)
#     #
#     # #action = np.array([hover_todo,angle_todo])
#     # action = np.array([angle_todo,hover_todo])

#     action = [hover_todo,angle_todo]
#     #digital feedback
#     # if hover_todo > np.abs(angle_todo) and hover_todo > 0.05:
#     #     action[1] = 1
#     #     #action[0] = -1
#     # if angle_todo < -0.05:
#     #     action[0] = -1
#     #     #action[1] = -1
#     # if angle_todo > +0.05:
#     #     action[0] = 1
     action = 0
     return action

model = nengo.Network()

with model:

   #pid = PIDNode(dimensions=1)
    environment = NengoUniverse()

    env = nengo.Node(environment, size_in=1, size_out=4)
    correction = nengo.Node(None, size_in=1, size_out=4)

    sensors = nengo.Ensemble(n_neurons=1, dimensions=4, neuron_type=nengo.Direct())
    controls = nengo.Ensemble(n_neurons=1, dimensions=1)

    nengo.Connection(env, sensors)
    nengo.Connection(sensors, controls, function=heuristic, synapse=0)
    nengo.Connection(controls, correction)
    #nengo.Connection(correction, env)

    manual = nengo.Node(0)
    #nengo.Connection(manual,env)

sim = nengo.Simulator(model)
sim.run(5)


#!/usr/bin/env python

import hotshot
import sys

import aptBackend

def main():
    prof = hotshot.Profile("%s.prof" % sys.argv[1])
    backend = aptBackend.PackageKitAptBackend(sys.argv[1:])
    prof.runcall(backend.run_command)
    prof.close()

if __name__ == '__main__':
    main()

# vim: ts=4 et sts=4


#!/usr/bin/env python

#AUTHOR: Jason Yatfai Zhang
#GITHUB: risingjason

import discord
import commands
import asyncio
import enum
import os
import sys

#NEW UPDATE TO DISCORD NO LONGER ALLOWS BOT TO BE LOGGED IN THROUGH EMAIL AND PASSWORD
#Copy and paste your bot's token into infos.txt
#Bot tokens are obtained through the Discord Developer website
fp_token = open("token.txt", "r")
token = fp_token.read()
fp_token.close()

client = discord.Client()

online_message = "`Bot v2.0 Currently in Development`"

# added text channels filter list to avoid spamming multiple text channels , "169666525404463105"
allowed_text_channels = ["93456386729451520"]
# allowed_users = ["91115380646354944", "93610826346266624"]
master_user = "91115380646354944"
# in case i need to ban people
# <@153142506014507008> <@292941873956257792> <@153753304751538176> <@93610826346266624>
@client.event
async def on_ready():
	print("Bot is running as the user '{}'".format(client.user.name))
	channel = client.get_all_channels()
	for channel in client.get_all_channels():
		if channel.type is discord.ChannelType.text: #notifies all registered text channels that the bot is online
			if channel.id in allowed_text_channels:
				#utf-8 compatibility paste .encode("utf-8") after channel.name
				print("Bot is running on server: {}, name: {}, id: {}, type: {}".format(channel.server, channel.name, channel.id, channel.type))

				#if channel.name == "general": # use this to only send to specifil text channels
				# prints a Bot Online status too all text channels in every server
				#await client.send_message(channel, online_message)

@client.event
async def on_message(msg):
	cmds = [x.lower() for x in msg.content.split(" ")] # parses string and makes them lowercase
	cmd = cmds[0] # first word is always !command; used to access commands.py module
	mentions = msg.raw_mentions # might be of use in the future
	# print(cmds)
	#waits for any of the commands in commands.py to be called upon
	#if msg.channel.id in allowed_text_channels:

	if cmd in commands.commands:
		await commands.commands[cmd](client, msg, cmds)

print("Starting bot...")
client.run(token)


import urllib.request, urllib.parse, urllib.error
import json
import ssl

def getGeoJson():
    api_key = 42
    serviceurl = 'http://py4e-data.dr-chuck.net/json?'

    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE

    while True:
        address = input('Enter location: ')
        if len(address) < 1: break

        params = dict()
        params['address'] = address
        params['key'] = api_key
        url = serviceurl + urllib.parse.urlencode(params)
        print('Retrieving url:', url)

        uh = urllib.request.urlopen(url, context=ctx)
        data = uh.read().decode()

        try:
            js = json.loads(data)
        except:
            js = None

        if not js or 'status' not in js or js['status'] != 'OK':
            print('==== Failure To Retrieve ====')
            print(data)
            continue

        print(js["results"][0]["place_id"])

if __name__ == '__main__':
    getGeoJson()


for _ in range(int(input())):
    buf = { color: ['0'] * 100 for color in 'rgby'}
    M = int(input())
    tiles = input().split()
    for tile in tiles:
        num, color = int(tile[:-1]) - 1, tile[-1]
        buf[color][num] = '1'
    if any('111' in ''.join(color) for color in buf.values()):
        print('YES')
    elif any(nums.count('1') >= 3 for nums in zip(*buf.values())):
        print('YES')
    else:
        print('NO')


import torch
import numpy as np
import os
from matplotlib import  pyplot as plt

def plot_hist_sequence_length():
    ROOT = '/data/cossu/quickdraw'

    classes = [ el for el in os.listdir(ROOT) \
                if (not os.path.isdir(el)) and (not el.endswith('.full.npz'))]

    for cls in classes:
        print(f'Reading {cls}')
        data = np.load(os.path.join(ROOT, cls), encoding='latin1', allow_pickle=True)
        data = data['train']
        plt.figure()
        plt.hist([p.shape[0] for p in data])
        cls_f = os.path.splitext(os.path.basename(cls))[0]
        print(f'Saving {cls_f}')
        plt.title(cls_f)
        plt.savefig(os.path.join(ROOT, 'histograms', f'{cls_f}_lengths.png'))
        plt.close()

def plot_pattern_occurences_scr():
    ROOT = '/data/cossu/speech_words/pickled'

    classes = [ el.split('.')[0] for el in os.listdir(ROOT) if (not os.path.isdir(el))]

    occurrences = {}
    for classname in classes:
        feature = torch.load(os.path.join(ROOT, f"{classname}.pt"))
        occurrences[classname] = feature.size(0)

    for k,v in occurrences.items():
        print(f"{k}: {v}")

if __name__ == '__main__':
    #plot_hist_sequence_length()
    plot_pattern_occurences_scr()