import json
import time
import os
import sys
from tabulate import tabulate
import add_question as aq

aq.top_list()#tworzy globalną listę tematów

class AskModule:
    def __init__(self, name):
        self.name = name
        self.score = 0
        print("\nWitam {}!\n\nWybierz dziedzinę pytań:".format(name))
        self.play_quiz()

    @staticmethod
    def zapytaj(dane, flag = True):
        if flag:
            print(tabulate([[x] for x in dane["odpowiedzi"]],
                headers = ['#',dane["pytanie"]],tablefmt="fancy_grid",
                showindex=range(1,len(dane["odpowiedzi"])+1)))

        try:
            choice = int(input("Wpisz swoją odpowiedź: "))
            if choice < 1 or choice > len(dane["odpowiedzi"]):
                raise ValueError
        except:
            print("Niepoprawna wartość."
                "Wprowadź naturalną liczbę od 1 do {}\n"
                .format(len(dane["odpowiedzi"])))
            return AskModule.zapytaj(dane, flag = False)
            # zaczyna od razu od miejsca gdzie rzucono Error

        if choice == dane['poprawna_odp']:
            return 2
        else:
            return -1

    def test(self,questions):
        print('\nKrótkie wprowadzenie:\n1. Wprowadzaj tylko numer (1/2/...) '
            'odpowiadający poprawnej odpowiedzi.\n2. Poprawna odpowiedź daje'
            ' 2 pkt.\n3. Za złą odpowiedź dostajesz -1 pkt.\nTest zaraz się zacznie.\n'
            'Powodzenia!')
        time.sleep(3)
        for key, meta in questions.items():
            if key in ("Ilość pytań",):
                continue
            else:
                print("\nPytanie {}:".format(key))
                self.score += self.zapytaj(meta)
        print('\n{:_^80s}\n'.format("KONIEC"))
        print('{} twój wynik: {}'.format(self.name, self.score))
        self.rebegin_prompt()

    @staticmethod
    def load_question(filename):
        """
        Wczytuje pytania z wybranego pliku JSON
        """
        qs = None
        with open(filename, "r", encoding='utf8') as read_file:
            qs = json.load(read_file)
        return (qs)

    def play_quiz(self, flag_2 = 1):
        flag = 1
        try:
            if flag_2:
                for x in range(len(aq.TOPICS_LIST)):
                    print("({})-> {}".format(x+1,aq.TOPICS_LIST[x]))
                print("(+)-> Dodać pytanie")
            choice = input("Wprowadź numer tematu:")
            if choice == '+':
                aq.dodanie_pytanie_dziedzina()
                flag = 0
            else:
                choice = int(choice)
                if choice > len(aq.TOPICS_LIST) or choice < 1:
                    print("Niepoprawna wartość. Wprowadź od nowa.\n")
                    flag = -1
        except ValueError as e:
            print("Niepoprawna wartość. Wprowadź od nowa.\n")
            flag = -1

        if flag == 1:
            self.test(self.load_question(os.path.join(sys.path[0],
                'Pytania',aq.TOPICS_LIST[choice-1]+'.json')))
        elif flag == -1:
            self.play_quiz(0) # od nowa jeżeli flaga = True
        elif flag == 0:
            self.rebegin_prompt()

    def rebegin_prompt(self):
        print("\nCzy chcesz kontynuować?\nTak - [Enter]\nNie - [0]")
        play = input()
        if play.lower() in ['0', 'n','nie']:
            return print('{:~^80s}'.format("ZAPRASZAM PONOWNIE"))

        if play.lower() in ['', 't', 'tak']:
            print("\nWybierz dziedzinę pytań:")
            self.play_quiz()
        else:
            print("Niepoprawna wartość. Wprowadź od nowa.\n"
                "Poprawne wartości: Enter/Tak/T lub 0/Nie/N")
            self.rebegin_prompt()


import tkinter as tk
from tkinter import ttk
from tkinter import Entry
from tkinter import Scrollbar
from tkinter.font import Font
from tkinter import Label
from tkinter import Button
from tkinter import END
from tkinter import RIDGE
from tkinter import Toplevel
from utils import *

# Global variables
num_days = 0
num_clients = 0
centrales = ["Nuclear", "Hidroeléctrica", "Térmica"]
g = 0
pago = []
capacidad = []
costo = []
demanda = []

# Methods

def set_container_color(container, color):
    container.configure(bg=color)

def init_tb_payments(num_clients: int):
    columnas = []
    # cleanup container4
    container4.delete("all")
    lb_clients_c4 = tk.Label(
        container4, text="Clientes", font=('Times New Roman', 12))
    lb_pago_c4 = tk.Label(container4, text="Pago",
                          font=('Times New Roman', 12))
    container4.create_window(
        (50, 30), window=lb_clients_c4, anchor="nw")
    container4.create_window(
        (200, 30), window=lb_pago_c4, anchor="nw")

    for i in range(2):
        filas = []
        for j in range(num_clients):
            data = f'Cliente {j+1}' if i == 0 else ""
            e = Entry(container4, relief=RIDGE)
            e.insert(END, data)
            e.configure(validate="key", validatecommand=(
                e.register(validate_float_input), "%P")
            )
            container4.create_window(
                (4+i*160, 50+j*20), window=e, anchor="nw")
            filas.append(e)
        columnas.append(filas)
    pago.append(columnas)

def init_tb_demanda(num_clients: int, num_days: int):
    columnas = []
    # cleanup container4
    container6.delete("all")
    lb_clients_c6 = tk.Label(
        container6, text="Clientes", font=('Times New Roman', 12))
    container6.create_window(
        (50, 50), window=lb_clients_c6, anchor="nw")

    for i in range(num_days + 1):
        filas = []
        data = f'Día {i}' if i >= 1 else ""
        lb_days_c6 = tk.Label(
            container6, text=data, font=('Times New Roman', 12))
        container6.create_window(
            (160*i, 50), window=lb_days_c6, anchor="nw")
        for j in range(num_clients):
            data = f'Cliente {j+1}' if i == 0 else ""
            e = Entry(container6, relief=RIDGE)
            e.insert(END, data)
            container6.create_window(
                (4+i*160, 70+j*20), window=e, anchor="nw")
            filas.append(e)
        columnas.append(filas)
    demanda.append(columnas)

def init_tb_capacidad():
    columnas = []
    container5.delete("all")
    lb_centrales_c5 = tk.Label(
        container5, text="Centrales", font=('Times New Roman', 20))
    container5.create_window(
        (50, 0), window=lb_centrales_c5, anchor="nw")
    lb_capacidad_c5 = tk.Label(
        container5, text="Capacidad", font=('Times New Roman', 20))
    container5.create_window(
        (200, 0), window=lb_capacidad_c5, anchor="nw")
    lb_costo_c5 = tk.Label(
        container5, text="Costo", font=('Times New Roman', 20))
    container5.create_window(
        (350, 0), window=lb_costo_c5, anchor="nw")

    for i in range(len(centrales)):
        filas = []
        lb_central_c5 = tk.Label(
            container5, text=centrales[i], font=('Times New Roman', 12))
        container5.create_window(
            (50, 35 + i * 30), window=lb_central_c5, anchor="nw")

        e_capacidad = Entry(container5, relief=RIDGE)
        e_capacidad.insert(END, "")
        container5.create_window(
            (200, 30 + i * 30), window=e_capacidad, anchor="nw")
        filas.append(e_capacidad)

        e_costo = Entry(container5, relief=RIDGE)
        e_costo.insert(END, "")
        container5.create_window(
            (350, 30 + i * 30), window=e_costo, anchor="nw")
        filas.append(e_costo)

        columnas.append(filas)
    capacidad.append(columnas)

def disable_button():
    if num_days > 0 or num_clients > 0:
        boton_solve.config(state="normal")
    else:
        boton_solve.config(state="disabled")

def create_table(ganancia, producion, num_clientes, num_dias):

    window = tk.Toplevel(root)
    window.title("resultados")

    columns = ["Clientes / Plantas"] + [f"Día {i+1}" for i in range(num_dias)]
    columns.append("Producción Total (MW)")
    table = ttk.Treeview(window, columns=columns)

    for col in columns:
        table.heading(col, text=col)

    nuclear_totals = [0.0] * num_dias
    hydro_totals = [0.0] * num_dias
    thermal_totals = [0.0] * num_dias

    for i in range(num_clientes):
        start = i * num_dias * 3
        end = start + num_dias * 3

        if end <= len(producion):  # Verifica que haya suficientes elementos en data
            client_data = [producion[j:j+3] for j in range(start, end, 3)]
            client_num = i + 1

            # Formatear la lista de tuplas como cadenas
            formatted_data = [str(tuple) for tuple in client_data]

        # Calcular las sumas para las plantas
            for j in range(num_dias):
                nuclear_totals[j] += client_data[j][0]
                hydro_totals[j] += client_data[j][1]
                thermal_totals[j] += client_data[j][2]

            table.insert("", "end", values=[
                f"Cliente {client_num}"] + formatted_data)
        else:
            print(
                f"No hay suficientes datos en 'data' para el cliente")

    nuclear_totals.append(sum(nuclear_totals))
    hydro_totals.append(sum(hydro_totals))
    thermal_totals.append(sum(thermal_totals))

    # Insertar filas para las sumas de plantas
    table.insert("", "end", values=["Nuclear"] +
                 [f"{total:.1f}" for total in nuclear_totals])
    table.insert("", "end", values=[
                 "Hidroeléctrica"] + [f"{total:.1f}" for total in hydro_totals])
    table.insert("", "end", values=["Térmica"] +
                 [f"{total:.1f}" for total in thermal_totals])

    # Insertar la fila de Ganancia Total
    table.insert("", "end", values=["Ganancia Total", ganancia])

    table.pack()

def clickStart():
    global num_clients, num_days, g
    try:
        num_clients = int(input_clients.get(), 10)
        num_days = int(input_days.get(), 10)
        g = float(input_g.get())
        # Agregar entradas a container4
        init_tb_payments(num_clients)
        init_tb_demanda(num_clients, num_days)
        init_tb_capacidad()
        disable_button()
    except IndexError:
        pass  # Manejo de excepción

def clickSolve():
    global num_clients, num_days, g

    num_clients = int(input_clients.get(), 10)
    num_days = int(input_days.get(), 10)
    g = float(input_g.get())
    capacidad_values = []
    costo_values = []
    demanda_values = []
    pago_values = []

    try:
        for i in range(1, len(demanda[0])):
            lista = demanda[0][i]
            temp = []
            for j in range(len(lista)):
                temp.append(float(lista[j].get()))
            demanda_values.append(temp)

        demanda_values = [list(x) for x in zip(*demanda_values)]

        for i in range(len(pago[0][1])):
            value = pago[0][1][i].get()
            pago_values.append(float(value))

        for i in range(len(capacidad[0])):
            value = capacidad[0][i][0].get()
            capacidad_values.append(float(value))
            value = capacidad[0][i][1].get()
            costo_values.append(float(value))

        data = solve(g, num_clients, num_days, costo_values,
                     capacidad_values, pago_values, demanda_values)
        ganancia = data[0]
        producion = data[1]

        create_table(ganancia, producion, num_clients, num_days)

    except ValueError:
        t = Toplevel(root)
        t.wm_title("Error")
        t.geometry("480x40")
        t.resizable(False, False)
        label_t = Label(t, text="Complete los datos o inserte datos validos", font=(
            'Times New Roman', 20), fg="red")
        label_t.place(relx=0, y=0)

    # solve(g, num_clients, num_days, costo, capacidad,
    #       pago, demanda)

def on_horizontal_scroll(event):
    container = event.widget
    if event.delta > 0:
        container.xview_scroll(-1, "units")
    else:
        container.xview_scroll(1, "units")

root = tk.Tk()
root.title("Plantas de Energı́a")

# Setup rows and columns for distribution
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=19)
root.grid_rowconfigure(2, weight=35)
root.grid_rowconfigure(3, weight=45)  # container6
root.grid_columnconfigure(0, weight=50)
root.grid_columnconfigure(1, weight=50)

# Create containers
container1 = tk.Frame(root)
container2 = tk.Frame(root)

container4 = tk.Canvas(root)
scrollbar4_y = Scrollbar(container4, orient="vertical")
container4.config(yscrollcommand=scrollbar4_y.set)
scrollbar4_y.config(command=container4.yview)
container4.bind("<MouseWheel>", on_horizontal_scroll)

container5 = tk.Canvas(root)
scrollbar5_y = Scrollbar(container5, orient="vertical")
scrollbar5_x = Scrollbar(container5, orient="horizontal")
container5.config(yscrollcommand=scrollbar5_y.set,
                  xscrollcommand=scrollbar5_x.set)
scrollbar5_y.config(command=container5.yview)
scrollbar5_x.config(command=container5.xview)

container6 = tk.Canvas(root)
scrollbar6_y = Scrollbar(container6, orient="vertical")
scrollbar6_x = Scrollbar(container6, orient="horizontal")
container6.config(yscrollcommand=scrollbar6_y.set,
                  xscrollcommand=scrollbar6_x.set)
scrollbar6_y.config(command=container6.yview)
scrollbar6_x.config(command=container6.xview)

container1.grid(row=0, column=0, columnspan=2, sticky="nsew")
container2.grid(row=1, column=0, sticky="nsew")

container4.grid(row=2, column=0, sticky="nsew")
scrollbar4_y.pack(side="right", fill="y")

container5.grid(row=2, column=1, sticky="nsew")
scrollbar5_y.pack(side="right", fill="y")
scrollbar5_x.pack(side="bottom", fill="x")

container6.grid(row=3, column=0, columnspan=2, sticky="nsew")
scrollbar6_y.pack(side="right", fill="y")
scrollbar6_x.pack(side="bottom", fill="x")

# Containers data

# container1
title_font = Font(family="Arial", size=20, weight="bold")
title_label = tk.Label(container1, text="Plantas de Energía", font=title_font)
title_label.pack(fill="both", expand=True)

# container2
lb_clients = Label(container2, text="Ingrese el número de clientes =>")
lb_clients.place(x=20, y=10)

lb_days = Label(container2, text="Ingrese el número de días =>")
lb_days.place(x=20, y=30)

lb_clients = Label(container2, text="Porcentaje mínimo demanda =>")
lb_clients.place(x=20, y=50)

input_clients = Entry(container2, width=10)
input_clients.place(x=230, y=10)
input_clients.configure(validate="key", validatecommand=(
    input_clients.register(validate_int_input), "%P"))

input_days = Entry(container2, width=10)
input_days.place(x=230, y=30)
input_days.configure(validate="key", validatecommand=(
    input_days.register(validate_int_input), "%P"))

input_g = Entry(container2, width=10)
input_g.place(x=230, y=50)
input_g.configure(validate="key", validatecommand=(
    input_g.register(validate_float_input), "%P"))

boton_cargar = Button(
    container2, text="Iniciar carga de datos", command=clickStart, width=25)
boton_cargar.place(x=50, y=80)

boton_solve = Button(
    container2, text="Calcular", command=clickSolve, width=20, state="disabled")
boton_solve.place(x=400, y=30)

# Set scrollregion to update scrollbars
container4.update_idletasks()
container5.update_idletasks()
container6.update_idletasks()

container4.config(scrollregion=container4.bbox("all"))
container5.config(scrollregion=container5.bbox("all"))
container6.config(scrollregion=container6.bbox("all"))

# Start the application
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry(f"{screen_width}x{screen_height}")
root.mainloop()


import discord,asyncio,DiscordUtils
from discord.ext import commands, tasks
from discord.ext.commands import *
from discord_components import *

music = DiscordUtils.Music()

class Music(Cog):

    def __init__(self,bot):
        self.bot = bot

    @command(aliases=["j",])
    async def join(self,ctx):

        if not ctx.voice_client:

            if ctx.author.voice is None:

                await ctx.send("You are not in a Voice Channel yet.")
                return

            elif ctx.guild.me.voice == ctx.author.voice:

                pass

            await ctx.author.voice.channel.connect()

        else:
            try:
                await ctx.author.voice.channel.connect()
            except Exception as e:
                print(e)

    @command(aliases=["l",])
    async def leave(self,ctx):

        if not ctx.voice_client:

            await ctx.send("I\'m not in a Voice Channel yet.")

        else:

            await ctx.voice_client.disconnect()
            """
    @command()
    async def play(self,ctx,*urls):

        url = str(" ".join(urls))

        await ctx.invoke(self.bot.get_command("join"))

        if not ctx.voice_client:
            return

        player = music.get_player(guild_id = ctx.guild.id)

        if not player:
            player = music.create_player(ctx,ffmpeg_error_betterfix = True)

        if not ctx.voice_client.is_playing():
            await player.queue(url,search=True)

            song = await player.play()
            await ctx.send(f"Started Playing {song.name}.")

        else:
            song = await player.queue(url,search=True)
            await ctx.send(f"Added {song.name} to queue.")"""

    @command(aliases=["pl","play"])
    async def playlist(self,ctx,*uri):

        urls = str(" ".join(uri))

        try:
            url = urls.split(",")
        except:
            url = uri

        await ctx.invoke(self.bot.get_command("join"))
        player = music.get_player(guild_id = ctx.guild.id)

        if not ctx.voice_client is None:
            if not player:
                player = music.create_player(ctx,ffmpeg_error_betterfix = True)

            if not ctx.voice_client.is_playing():

                await player.queue(url[0],search=True)
                song = await player.play()
                await ctx.send(f"Started Playing {song.name}.")
                url.pop(0)

            if len(url) > 0:

                for i in url:

                    await player.queue(i,search=True)

            await ctx.send("Added Playlist!")
            await ctx.invoke(self.bot.get_command("queue"))

    @command()
    async def queue(self,ctx):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        embed = discord.Embed(title="Queue", description="Songs in Queue :" , color = discord.Color.random())
        msg = ""
        num = 1
        time = 0
        for i in player.current_queue():
            dur = i.duration
            minutes = dur//60
            seconds = dur%60
            time += dur
            msg += f"{num}. {i.name} {minutes}:{seconds}"
            msg += "\n"
            num += 1
        if len(player.current_queue()) == 0:
            msg = "None"
        minutes = time//60
        seconds = time%60
        embed.add_field(name=msg,value="\u200b")
        embed.set_footer(icon_url=ctx.author.avatar_url,text=f"Total time - {minutes}:{seconds}")
        await ctx.send(embed=embed)

    @command()
    async def resume(self,ctx):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        song = await player.resume()
        await ctx.send(f"Resumed Playing {song.name}")

    @command()
    async def pause(self,ctx):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        song = await player.pause()
        await ctx.send(f"Paused Playing {song.name}")

    @command(aliases=["r",])
    async def remove(self,ctx,num : int):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        num -= 1
        if num == 0:
            return await ctx.invoke(self.bot.get_command("skip"))
        elif num > 0:
            try:
                song = await player.remove_from_queue(num)
                if len(player.current_queue()) == 1:
                    name = song.name
                else:
                    name = song[0].name
                await ctx.send(f"Removed {name} from queue.")
            except IndexError:
                await ctx.send("Invalid number provided. Check the number from queue command.")

    @command(aliases=["s",])
    async def skip(self,ctx):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        song = await player.skip(force=True)
        await ctx.send(f"Skipped {song[0].name}")

    @command()
    async def loop(self,ctx):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        song = await player.toggle_song_loop()

        if song.is_looping:
            await ctx.send(f"{song.name} is now looping.")

        else:
            await ctx.send(f"Stopped looping {song.name}.")

    @command(aliases=["vol",])
    async def volume(self,ctx,num : int = None):

        if not ctx.voice_client:
            return
        player = music.get_player(guild_id = ctx.guild.id)
        if num:
            vol = num/100
            await player.change_volume(vol)
            await ctx.send(f"Volume changed to {num}%")
        else:
            msg = await ctx.send("> Volume :",components=[[Button(style=1,custom_id="0",label="0"),Button(style=1,custom_id="25",label="25"),Button(style=1,custom_id="50",label="50"),Button(style=1,custom_id="75",label="75"),Button(style=1,custom_id="100",label="100"),]])
            def check(res):
                return res.user == ctx.author and res.message.id == msg.id
            self.bot.flag = True
            while self.bot.flag:
                res = await self.bot.wait_for("button_click",check = check)
                vol = int(res.component.custom_id)
                await player.change_volume(vol)
                await res.respond(content="https://cdn.discordapp.com/emojis/803643669323972638.gif?v=1")

    @volume.before_invoke
    async def kk(self,ctx):

        self.bot.flag = False

    @command()
    async def stop(self,ctx):

        if ctx.voice_client is not None:

            try:
                player = music.get_player(guild_id = ctx.guild.id)
                await player.stop()
                await ctx.send("Stopped!")
            except Exception as e:
                print(e)

    @command(aliases=["p",])
    async def player(self,ctx):

        if not ctx.voice_client:

            return

        player = music.get_player(guild_id=ctx.guild.id)
        msg = await ctx.send("> Player :", components=[[Button(style=1,emoji="🔁",custom_id="loop"),Button(style=1,emoji="⏸",custom_id="pause"),Button(style=3,emoji="▶",custom_id="resume"),Button(style=4,emoji="⏹",custom_id="stop"),Button(style=4,emoji="⏭",custom_id="skip")]])

        self.bot.flag = True
        while self.bot.flag:
            def check(res):

                return res.user == ctx.author and res.message.id == msg.id

            res = await self.bot.wait_for("button_click",check=check)
            m1 = await ctx.send("Done.")
            await asyncio.sleep(1)
            await m1.delete()
            await ctx.invoke(self.bot.get_command(res.component.custom_id))

    @player.before_invoke
    async def playe(self,ctx):

        self.bot.flag = False

    @Cog.listener()
    async def on_voice_state_update(self,user,bfr,aftr):

        try:
            if aftr.channel is None:
                voice = discord.utils.get(self.bot.voice_clients,guild = bfr.channel.guild)
                if bfr.channel == voice.channel and len(bfr.channel.members) == 1 and self.bot.user in bfr.channel.members:
                    if not voice.is_connected():
                        return
                    try:
                        player = music.get_player(guild_id=bfr.channel.guild.id)
                        await player.stop()
                    except Exception as e:
                        print(e)
                    await voice.disconnect()

        except AttributeError as e:

            print(e)

    @Cog.listener()
    async def on_command_error(self,ctx,error):

        if isinstance(error,CommandNotFound):
            pass
        else:
            raise(error)

def setup(bot):
    bot.add_cog(Music(bot))


# Problem 24
# ==========
#
#
#    A permutation is an ordered arrangement of objects. For example, 3124 is
#    one possible permutation of the digits 1, 2, 3 and 4. If all of the
#    permutations are listed numerically or alphabetically, we call it
#    lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
#
#                        012   021   102   120   201   210
#
#    What is the millionth lexicographic permutation of the digits 0, 1, 2, 3,
#    4, 5, 6, 7, 8 and 9?
import itertools as it

gen = it.permutations(range(0, 10))

count = 0
for i in gen:
   count += 1
   if count == 1000000:
      print(i)

#       Congratulations, the answer you gave to problem 24 is correct.
#
# You are the 80878th person to have solved this problem.
#
# Return to Problems page.


from sentence_transformers.losses import CosineSimilarityLoss

from setfit import SetFitModel, SetFitTrainer
from setup_utils import seed_everything, MODEL_SEED

def do_setfit(args, train_ds, val_ds, config_dict=None):
    if len(set(train_ds['labels'])) != 2:
        metric = 'f1'
    else:
        metric = 'ap'
    if not config_dict:
        config_dict = {'batch_size':16,
                       'model_seed':MODEL_SEED,
                       'metric': metric,
                       'num_iterations':20,
                       'num_epochs':1}
        seed_everything(MODEL_SEED)
        model = SetFitModel.from_pretrained("sentence-transformers/{}".format(args.st_model))
    else:
        seed_everything(config_dict['model_seed'])
        model = SetFitModel.from_pretrained("sentence-transformers/{}".format(config_dict['st_model']))

    trainer = SetFitTrainer(
    model=model,
    train_dataset=train_ds,
    eval_dataset=val_ds,
    loss_class=CosineSimilarityLoss,
    metric=config_dict['metric'], #was f1
    batch_size=config_dict['batch_size'],
    seed=config_dict['model_seed'],
    num_iterations=config_dict['num_iterations'], # The number of text pairs to generate for contrastive learning
    num_epochs=config_dict['num_epochs'], # The number of epochs to use for constrastive learning
    column_mapping={"text": "text", "labels": "label"} # Map dataset columns to text/label expected by trainer
    )

    trainer.train()
    return trainer

def predict_with_setfit(X, y, sbert_trainer):
    print('predicting with setfit')
    clf = sbert_trainer.model
    y_logit = clf.predict_proba(X)
    if len(y_logit.shape) == 2:
        y_logit = y_logit[:, 1]
    y_pred = clf.predict(X)
    predictions = (y_logit, y_pred, y)

    return predictions


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.stats.multitest import multipletests
from matplotlib.patches import Rectangle
from matplotlib.colors import ListedColormap
from matplotlib.colors import BoundaryNorm

from get_dfs import get_metabs, get_md
from metabs_utils import run_DA

def figures_2AD():

	def make_heatmap(ifn, conds, title, ofn, df=None, y_ticks=True, x_ticks=False, title_on=False, cbar_on=True, cbar_pos='left',  full=True, p_05_to_q=0.5):

		res_all = df
		res_sig = res_all[res_all.heatmap_q < 0.1]
		res_sig = res_sig[res_sig['Cond'].isin(conds)]
		res_all = res_all[res_all.index.get_level_values(0).isin(res_sig.index)]

		q_bins = [.01, .05, .1, p_05_to_q, 1.00001]
		res_all['q_discrete'] = res_all.heatmap_q.apply(lambda p: [b for b in q_bins if p < b][0])
		res_all['slogq'] = res_all.stat.apply(np.sign) * res_all.heatmap_q.apply(np.log10)

		conds = list(res_all.Cond.unique())
		x = res_all.set_index('Cond', append=True).slogq.unstack(1)[conds] ## new
		x = x.assign(m = x.mean(1)).sort_values('m').drop('m', axis = 1)
		sns.set_context('talk')
		x.columns = conds
		sns.set(font="Calibri", font_scale = .9, style = 'whitegrid', context = 'talk')

		color_bins = ['#1d50a3', '#6a7bbb', '#abb1d8', '#e9eaf1', 'white', '#f3e8e2', '#f9896c', '#f76449', '#ff0013']
		cmap = ListedColormap(color_bins[1:-1])#.with_extremes(over = bins[-1], under = bins[1])
		cmap.set_over(color_bins[-1])
		cmap.set_under(color_bins[0])
		bounds = list(np.log10(q_bins[:-1])) + list(-np.log10(q_bins)[:-1][::-1])

		norm = BoundaryNorm(bounds, cmap.N)
		plt.close('all')
		x.index = x.index.to_series().str.capitalize().str.replace('*', '')

		N_metabs = len(set(res_all.index))
		N_conds = len(res_all['Cond'].unique())
		fig = plt.figure(figsize = (N_metabs, 2*N_conds))
		g = sns.heatmap(x[x.columns[::-1]].T, cmap=cmap, norm = norm, yticklabels = y_ticks, xticklabels = x_ticks, cbar=cbar_on, linewidths=2, linecolor='gray')

		##remove colorbar tick labels
		cax = plt.gcf().axes[-1]
		cax.set_yticklabels([])

		_=g.set_xticklabels(g.get_xticklabels(), rotation=60, ha='right', fontsize = min(10, 10*(32/x[x.columns[::-1]].shape[0])), fontweight=10)

		if title_on == True:
			plt.title(title)

		height = x[x.columns[::-1]].T.shape[0]
		width = x[x.columns[::-1]].T.shape[1]
		g.add_patch(Rectangle((0, 0), width, height, fill=False, edgecolor='gray', lw=3))

		plt.savefig(f"{ofn}.png", dpi = 600, bbox_inches = 'tight')
		plt.savefig(f"{ofn}.pdf", dpi = 600, bbox_inches = 'tight')
		plt.close()

	### Fig 2A - ptb DA heatmap
	metabs = get_metabs(min_pres = 0, min_impute = False, rzscore=True)
	md = get_md().loc[metabs.index]
	all_race_conds = list(zip((pd.Series(True, index = md.index), md.race == 1, md.race == 0), ('All', 'AA', 'White')))
	black_cond = [all_race_conds[1]]

	all_ptb_vs_tb_strict_q = run_DA(metabs, md, ['extreme_sPTB', 'very_sPTB', 'moderate_sPTB'], ['TB'], False, all_race_conds)
	all_ptb_vs_tb_strict_q['heatmap_q'] = multipletests(all_ptb_vs_tb_strict_q['p'], method='fdr_bh')[1]
	make_heatmap(None, ['All', 'AA', 'White'], "all sPTB vs TB", "./figurePanels/2A",
		df=all_ptb_vs_tb_strict_q, y_ticks=False, x_ticks=False, cbar_on=False, p_05_to_q=0.5)
	make_heatmap(None, ['All', 'AA', 'White'], "all sPTB vs TB", "./figurePanels/2A_xticks",
		df=all_ptb_vs_tb_strict_q, y_ticks=False, x_ticks=True, cbar_on=False, p_05_to_q=0.5)

	### Fig 2D
	extremely_ptb_vs_rest = run_DA(metabs, md, ['extreme_sPTB'], ['very_sPTB', 'moderate_sPTB', 'TB'], False, black_cond)
	extremely_ptb_vs_rest['Cond'] = 'Below 28 (AA) vs 28 and above (AA)'
	very_and_extreme_ptb_vs_rest = run_DA(metabs, md, ['extreme_sPTB', 'very_sPTB'], ['moderate_sPTB', 'TB'], False, black_cond)
	very_and_extreme_ptb_vs_rest['Cond'] = 'Below 32 (AA) vs 32 and above (AA)'
	merged = pd.concat([very_and_extreme_ptb_vs_rest, extremely_ptb_vs_rest])
	merged['heatmap_q'] = multipletests(merged['p'], method='fdr_bh')[1]
	make_heatmap(None, list(merged.Cond.unique()), "Above GA thresh vs below GA thresh", "./figurePanels/2D",
		df=merged, y_ticks=False, x_ticks=False, title_on=False, cbar_on=False, p_05_to_q=0.3)
	make_heatmap(None, list(merged.Cond.unique()), "Above GA thresh vs below GA thresh", "./figurePanels/2D_xticks",
		df=merged, y_ticks=False, x_ticks=True, title_on=False, cbar_on=False, p_05_to_q=0.3)


# -*- coding: utf-8 -*-
from twisted.internet.protocol import DatagramProtocol
from c2w.main.lossy_transport import LossyTransport
import c2w.main.constants as c2w_constants
import c2w.protocol.constants as constants
from twisted.internet import reactor
from c2w.protocol.message import Message
from c2w.protocol.format_type import FormatType
import logging

logging.basicConfig()
moduleLogger = logging.getLogger('c2w.protocol.udp_chat_client_protocol')

class c2wUdpChatClientProtocol(DatagramProtocol):

    def __init__(self, serverAddress, serverPort, clientProxy, lossPr):
        """
        :param serverAddress: The IP address (or the name) of the c2w server,
            given by the user.
        :param serverPort: The port number used by the c2w server,
            given by the user.
        :param clientProxy: The clientProxy, which the protocol must use
            to interact with the Graphical User Interface.

        Class implementing the UDP version of the client protocol.

        .. note::
            You must write the implementation of this class.

        Each instance must have at least the following attributes:

        .. attribute:: serverAddress

            The IP address of the c2w server.

        .. attribute:: serverPort

            The port number of the c2w server.

        .. attribute:: clientProxy

            The clientProxy, which the protocol must use
            to interact with the Graphical User Interface.

        .. attribute:: lossPr

            The packet loss probability for outgoing packets.  Do
            not modify this value!  (It is used by startProtocol.)

        .. note::
            You must add attributes and methods to this class in order
            to have a working and complete implementation of the c2w
            protocol.
        """

        #: The IP address of the c2w server.
        self.serverAddress = serverAddress
        #: The port number of the c2w server.
        self.serverPort = serverPort
        #: The clientProxy, which the protocol must use
        #: to interact with the Graphical User Interface.
        self.clientProxy = clientProxy
        self.lossPr = lossPr

        self.format = FormatType()

        # Dictionary of Type Message
        self.waitingMessages = {}

        # Emission counter
        self.emissionCounter = 0
        # Received counter
        self.receivedCounter = 0
        # Message number in the header of the messages
        self.numMessage = 0

        # Users list
        self.usersConnected = {}
        self.room = None
        self.movies = []

        self.mainRoom = True
        self.firstLogin = True
        self.userName = None

    def startProtocol(self):
        """
        DO NOT MODIFY THE FIRST TWO LINES OF THIS METHOD!!

        If in doubt, do not add anything to this method.  Just ignore it.
        It is used to randomly drop outgoing packets if the -l
        command line option is used.
        """
        self.transport = LossyTransport(self.transport, self.lossPr)
        DatagramProtocol.transport = self.transport

    def sendLoginRequestOIE(self, userName):
        """
        :param string userName: The user name that the user has typed.

        The client proxy calls this function when the user clicks on
        the login button.
        """
        moduleLogger.debug('loginRequest called with username=%s', userName)
        self.userName = userName
        pack = self.format.msg_connexion(self.numMessage, userName)

        self.sendPackage(pack, 1)

    def sendChatMessageOIE(self, message):
        """
        :param message: The text of the chat message.
        :type message: string

        Called by the client proxy  when the user has decided to send
        a chat message

        .. note::
           This is the only function handling chat messages, irrespective
           of the room where the user is.  Therefore it is up to the
           c2wChatClientProctocol or to the server to make sure that this
           message is handled properly, i.e., it is shown only by the
           client(s) who are in the same room.
        """
        self.numMessage += 1
        pack = self.format.msg_chat(self.numMessage, self.userName, message)
        self.sendPackage(pack, 9)

    def sendJoinRoomRequestOIE(self, roomName):
        """
        :param roomName: The room name (or movie title.)

        Called by the client proxy  when the user
        has clicked on the watch button or the leave button,
        indicating that she/he wants to change room.

        .. warning:
            The controller sets roomName to
            c2w.main.constants.ROOM_IDS.MAIN_ROOM when the user
            wants to go back to the main room.
        """

        self.numMessage += 1
        if roomName == c2w_constants.ROOM_IDS.MAIN_ROOM:
            message = self.format.msg_quitter_salon(self.numMessage)
            self.sendPackage(message, 4)

        else:
            message = self.format.msg_selection_film(self.numMessage, roomName)
            self.sendPackage(message, 3)
            self.room = roomName

    def sendLeaveSystemRequestOIE(self):
        """
        Called by the client proxy  when the user
        has clicked on the leave button in the main room.
        """
        self.numMessage += 1
        message = self.format.msg_quitter_app(self.numMessage)
        self.sendPackage(message, 2)

    def datagramReceived(self, datagram, host_port):
        """
        :param string datagram: the payload of the UDP packet.
        :param host_port: a touple containing the source IP address and port.

        Called **by Twisted** when the client has received a UDP
        packet.
        """

        [longueur, num_sequence, type, message] = self.format.datagram_received(datagram)

        # If the client receives a different type than 0 -> Always send the ACK
        if type != 0:
            pack = self.format.msg_acquittemen(num_sequence)
            self.transport.write(pack, host_port)

        if type == 0:
            if num_sequence == self.emissionCounter:
                # Set the message as sended
                self.waitingMessages[num_sequence].sended = True
                self.emissionCounter += 1

                # Format Type 2 : Quitter Application
                if self.waitingMessages[self.numMessage].type == 2:
                    self.clientProxy.leaveSystemOKONE()

                # Format 3: Selection du Film
                if self.waitingMessages[self.numMessage].type == 3:
                    self.clientProxy.joinRoomOKONE()
                    self.mainRoom = False

                # Format 4 : Quitter salon Film
                if self.waitingMessages[self.numMessage].type == 4:
                    self.clientProxy.joinRoomOKONE()
                    self.mainRoom = True

                # Delete message if it was sent
                del self.waitingMessages[num_sequence]
                if bool(self.waitingMessages):
                    self.controlPackages(self.emissionCounter)

        if num_sequence == self.receivedCounter and type != 0:
            self.receivedCounter += 1
            # Format Type 7 : Acceptation connexion
            if type == 7:
                self.room = c2w_constants.ROOM_IDS.MAIN_ROOM
                self.usersConnected[host_port] = []

            # Type 5: liste des films
            if type == 5:
                self.movies = self.format.get_movie_list(message)

            # Type 6: liste Utilisateurs
            if type == 6:
                self.usersConnected[host_port] = self.format.get_user_list(message)
                # I have the movies and users!

                if self.mainRoom:  # The user is in the main room
                    self.clientProxy.setUserListONE([])
                    if not self.firstLogin:
                        self.clientProxy.setUserListONE(self.usersConnected[host_port])
                    else:
                        self.clientProxy.initCompleteONE(self.usersConnected[host_port], self.movies)
                        self.firstLogin = False

                else:  # The user is in the movie room
                    self.clientProxy.setUserListONE([])
                    for user in self.usersConnected[host_port]:
                        self.clientProxy.userUpdateReceivedONE(user[0], self.room)

            # Format Type 8 : Refus de connexion
            if type == 8:
                self.clientProxy.connectionRejectedONE("Un utilisateur avec ce nom existe déjà")

            # Format 9 : Chat
            if type == 9:
                self.clientProxy.chatMessageReceivedONE(message[0], message[1])

    def sendPackage(self, pack, type):
        message = Message(pack, type)
        self.waitingMessages[self.numMessage] = message

        self.controlPackages(self.numMessage)

    def controlPackages(self, num_sequence):
        if num_sequence == self.emissionCounter:
            # Send the message
            self.transport.write(self.waitingMessages[num_sequence].data, (self.serverAddress, self.serverPort))
            # Increase emission counter
            self.waitingMessages[num_sequence].attempsCounter += 1
            # Reemission message
            reactor.callLater(1, self.resendPackage, num_sequence)

    def resendPackage(self, num_sequence):
        if num_sequence in self.waitingMessages:
            message = self.waitingMessages[num_sequence]
            # If the message is set as not sended
            if message.sended is False:
                # If attemps counter <= 7
                if message.attempsCounter <= constants.MAX_ATTEMPS_RESEND:
                    self.transport.write(message.data, (self.serverAddress, self.serverPort))
                    # Increase attemps counter
                    message.attempsCounter += 1

                    # Call this method again
                    reactor.callLater(1, self.resendPackage, num_sequence)
                else:
                    self.clientProxy.connectionRejectedONE("Connection rejected")
                    self.clientProxy.applicationQuit()


import functions as f
import matplotlib.pyplot as plt
import numpy as np

# Program used to carry out the baseline study analysis

scenarios = ['5MW', '10MW', '15MW']
inertia = ['5s', '2.5s']

for h in inertia:

    filesF = [f'frequency {scenario} {h}.mat' for scenario in scenarios]
    filesR = [f'rocof {scenario} {h}.mat' for scenario in scenarios]

    dsF = f.importData(filesF, 'data/v2-data/2-baseline-study')
    dsR = f.importData(filesR, 'data/v2-data/2-baseline-study')

    print(f'Generator Inertia = {h}')

    i = 0
    for key in dsF.keys():

        t0_index = dsF[key]['Time'].index(0.0)
        index = range(t0_index)

        ds = np.delete(dsF[key]['Value'], index)

        f_min = round(min(ds), 4)
        f_delta = round(f_min - 50, 4)
        f_ss = round(ds[-1], 4)
        print(f'Case {scenarios[i]}: Minimum frequency = {f_min}, delta = {f_delta}')
        print(f'Case {scenarios[i]}: Steady-State frequency = {f_ss}')
        i += 1

    i = 0
    for key in dsR.keys():

        t0_index = dsR[key]['Time'].index(0.0)
        index = range(t0_index)

        ds = np.delete(dsR[key]['Value'], index)

        r_max = round(max(abs(ds)), 4)
        print(f'Case {scenarios[i]}: Maximum RoCoF = {r_max}')
        i += 1


import numpy as np
import pandas as pd

class YieldByFrequency:

    def process(self, dataframe, vtype):
        ar = np.zeros((int((dataset.shape[0]) / 5) + 1))
        for j in range(len(dataset.columns)):
            parray = np.array([])
            i = 0
            while i <= dataset.shape[0] - div:
                wyield = 1 + dataset.iloc[i, j]
                for count in range(1, div):
                    i += 1
                    wyield = wyield * (1 + dataset.iloc[i, j])
                    count += 1
                parray = np.append(parray, wyield)
                i += 1

            numleft = dataset.shape[0] - i
            wyield = 1 + dataset.iloc[i, j]

            while numleft > 1:
                i += 1
                wyield = wyield * (1 + dataset.iloc[i, j])
                numleft -= 1
            parray = np.append(parray, wyield)

            ar = np.column_stack((ar, parray))

            j += 1

        ar = np.delete(ar, 0, 1)
        newframe = pd.DataFrame(ar, columns=["A", "B", "C", "D", "E"])
        print(newframe)

dataset = pd.read_excel('/Users/lizongyun/Desktop/中信建投/投研/Test.xls', sheet_name=0, header=0)
print(dataset)
voltype = input("Please enter the type of volatility(weekly/monthly):\n")
if voltype == "weekly":
    div = 5
elif voltype == "monthly":
    div = 20


from flask import Blueprint, request, current_app
from libs.awsservice import *
from libs.awsclient import awsTempToken
from libs.awss3service import *
from libs.awssupport import awssupport
from libs.defResponse import success, nonauthorization
from models.Company import CompanyControl
from models.AwsTokenRecord import AwsRecordControl
from views.auth import auth
from datetime import datetime
from uuid import uuid4
import mimetypes
import os

makeImage = Blueprint("makeImage", __name__)

import boto3

@makeImage.route("/make_image", methods = ["POST"])
@auth.login_required
def image():
    if not request.json or not request.json.get("CompanyId") or not request.json.get("service_list") or not request.json.get("StartTime") or not request.json.get("EndTime") or not request.json.get("Unit") or not request.json.get("Region"):
        return success(20002, msg="缺少必要参数")
    service_list = request.json.get("service_list")

    aksk = CompanyControl().getAwsSecret(request.json.get("CompanyId"))
    if not aksk:
        return success(20007, msg="客户id不正确")

    dict_result = {}
    startTime = datetime.strptime(request.json.get("StartTime"), '%Y, %m, %d')
    endTime = datetime.strptime(request.json.get("EndTime"), '%Y, %m, %d')
    dict_result['Unit'] = request.json.get("Unit")
    P = []
    MetricName = ''
    for i in service_list:
        if not i.get("Namespace") or not i.get("Dimensions") or not i.get("ServiceType") or not i.get("Statistics") or not i.get("MetricName"):
            return success(20003, msg="缺少必要参数")
        service_dict = {}
        service_dict['serviceType'] = i.get("ServiceType")
        MetricName = i.get("MetricName")
        dict_result['type'] = MetricName
        # s3_client = boto3.client('s3', aws_access_key_id=aksk[0],
        #                          aws_secret_access_key=aksk[1],
        #                          region_name=request.json.get("Region"))
        # s3_client.download_file('bositool.file', '1.PNG', 'test.png')
        client = boto3.client('cloudwatch', aws_access_key_id=aksk[0],
                              aws_secret_access_key=aksk[1],
                              region_name=request.json.get("Region"))

        response = client.get_metric_statistics(
            Namespace=i.get("Namespace"),
            MetricName=i.get("MetricName"),
            Dimensions=i.get("Dimensions"),
            StartTime=startTime,
            EndTime=endTime,
            Period=int((endTime - startTime).total_seconds()),
            # Period=i.json.get("Period"),
            Statistics=i.get("Statistics"),
            Unit=request.json.get("Unit")
            # Unit='Percent'
        )
        p = {}
        j = response['Datapoints'][0]
        a = 1
        for en in i.get("Statistics"):
            k = j[en]
            p['k'+str(a)] = en
            p['v'+str(a)] = k
            a += 1
        service_dict['p'] = p
        P.append(service_dict)
    dict_result['P'] = P

    '''
     {
        'type':'cpu',
        'Unit':'Percent',
        'P': [
            {
                'serviceType':'ec2',
                'p': {
                    'k1': 'max',
                    'k2': 'avg',
                    'v1': '95',
                    'v2': '90'
                }
            }, {
                'serviceType':'rds',
                'p': {
                    'k1': 'max',
                    'k2': 'avg',
                    'v1': '94',
                    'v2': '91'
                }
            }, {
                'serviceType':'redis',
                'p': {
                    'k1': 'max',
                    'k2': 'avg',
                    'v1': '93',
                    'v2': '90'
                }
            }
        ]
     }
    '''
    print(111)
    print(dict_result)
    print(111)
    file_path = make_image(dict_result)

    s3_client = boto3.client('s3', aws_access_key_id=aksk[0],
                              aws_secret_access_key=aksk[1],
                              region_name=request.json.get("Region"))
    CompanyName = CompanyControl().getCompanyName(request.json.get("CompanyId"))
    dir = CompanyName + '/' + request.json.get("Region") + '/' + request.json.get("StartTime") + '-' + request.json.get("EndTime") + '/' + MetricName
    s3_client.upload_file(str(file_path), 'bositool.file', dir + '/test.png')
    return success(20000, msg="更新成功")

@makeImage.route("/list_image", methods=["POST"])
@auth.login_required
def list_image():
    if not request.json or not request.json.get("CompanyId") or not request.json.get("Region"):
        return success(20002, msg="缺少必要参数")
    aksk = CompanyControl().getAwsSecret(request.json.get("CompanyId"))
    if not aksk:
        return success(20007, msg="客户id不正确")
    s3_client = boto3.client('s3', aws_access_key_id=aksk[0],
                              aws_secret_access_key=aksk[1])
    CompanyName = CompanyControl().getCompanyName(request.json.get("CompanyId"))
    response = s3_client.list_objects(
        Bucket='bositool.file',
        Marker=CompanyName
    )
    k = []
    for i in response['Contents']:
        d = {}
        key = i['Key']
        if not key.startswith(CompanyName):
            continue
        # k.append(key)
        d['key'] = key
        d['url'] = 'https://s3.{}.amazonaws.com.cn/{}/{}'.format(request.json.get("Region"), 'bositool.file', key)
        k.append(d)
    return {
        "image": k
    }

from unittest import mock
from os.path import *

def get_chrome_driver():
    from selenium import webdriver
    options = webdriver.ChromeOptions()
    options.add_argument("headless")
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-gpu')
    options.add_argument('--disable-dev-shm-usage')
    return webdriver.Chrome(options=options)

from snapshot_selenium import snapshot as driver
from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.render import make_snapshot

def make_image(data):
    print("make in")
    metric = data["type"]
    unit = data['Unit']
    name_list = []
    for i in data["P"]:
        name_list.append(i["serviceType"])

    png = png_bar_chart(metric, unit, name_list, data)
    with mock.patch('snapshot_selenium.snapshot.get_chrome_driver', get_chrome_driver):
        make_snapshot(driver, png.render(), "{}.png".format(metric), 2, 2, True)
    file_path = os.path.abspath("/app") + "/{}.png".format(metric)
    print(file_path)
    return file_path

def png_bar_chart(metric, unit, x_name, data):
    bar = Bar(init_opts=opts.InitOpts(theme="white", bg_color="#c4ccd3"))
    bar.add_xaxis(x_name)

    k_list = []
    v_list = []
    for j in range(int((len(data['P'][0]['p'].keys()) / 2))):
        key = 'k' + str(j + 1)
        k_list.append(key)
        val = 'v' + str(j + 1)
        v_list.append(val)

    V = []
    a = 0
    for _ in range(len(v_list)):
        v = []
        for k in data['P']:
            v.append(k['p'][v_list[a]])
        V.append(v)
        a += 1
    print(V)

    a = 0
    for i in k_list:
        bar.add_yaxis(data['P'][0]['p'][i], V[a])
        a += 1

    bar.reversal_axis()
    bar.set_series_opts(label_opts=opts.LabelOpts(position="right"))
    bar.set_global_opts(title_opts=opts.TitleOpts(title="{}".format(metric),
                                                  pos_right="40%",
                                                  pos_top="15"),
                        legend_opts=opts.LegendOpts(pos_top="20",
                                                    pos_right="20",
                                                    orient="vertical"),
                        xaxis_opts=opts.AxisOpts(name="{}".format(unit)),
                        yaxis_opts=opts.AxisOpts(name="服务类型"))
    return bar


from project.helpers.pydantic_typo import ObjectId
from project.infrastructure.drivers.mongo.connector import Mongo
from project.infrastructure.data_layer.abstract_datalayer import AbstractDataLayer

class MongoAdapter(AbstractDataLayer):
    """
    Mongo adapter class
    """

    def __init__(self, resource_name: str) -> None:
        self.resource_name = resource_name
        super().__init__(resource_name=resource_name)

    async def get_buildinfo(self) -> bool:
        client = Mongo().client()
        buildinfo = await client.command("buildinfo")
        return bool(buildinfo["ok"])

    async def get_one(self, id: ObjectId) -> dict:

        client = Mongo().client()
        result = await client[self.resource_name].find_one({"_id": id})
        if not result:
            raise Exception("document not found!")
        return result

    async def get_many(self, filter, *args: any, **kwargs: any) -> dict:

        client = Mongo().client()
        cursor = client[self.resource_name].find(filter=filter)
        result = await cursor.to_list(None)
        await cursor.close()

        if not result:
            raise Exception("result not found!")

        return result

    async def insert_one(self, item: dict) -> ObjectId:
        try:
            client = Mongo().client()
            result = await client[self.resource_name].insert_one(item)
            return result.inserted_id
        except Exception as error:
            raise error

    async def insert_many(self, itens: list[dict]) -> list[ObjectId]:
        try:
            client = Mongo().client()
            result = await client[self.resource_name].insert_many(itens)
            return result.inserted_ids
        except Exception as error:
            raise error

    async def update_one(self, id: ObjectId, data: dict) -> tuple:
        try:
            client = Mongo().client()
            result = await client[self.resource_name].update_one(
                {"_id": id}, {"$set": data}
            )
            acknowledged, modified_count = result.acknowledged, result.modified_count
            return acknowledged, modified_count
        except Exception as error:
            raise error

    async def update_many(self, criteria: dict, data: dict) -> tuple:
        try:
            client = Mongo().client()
            result = await client[self.resource_name].update_many(
                criteria, {"$set": data}
            )
            acknowledged, modified_count = result.acknowledged, result.modified_count
            return acknowledged, modified_count
        except Exception as error:
            raise error

    async def delete(self, criteria: dict) -> tuple:
        try:
            client = Mongo().client()
            result = await client[self.resource_name].delete_many(criteria)
            acknowledged, deleted_count = result.acknowledged, result.deleted_count
            return acknowledged, deleted_count
        except Exception as error:
            raise error


# EXERCICIO 53 - Informando se uma frase é palindromo ou não

frase = input('Digite uma frase: ').strip().upper().split()
frase1 = ''.join(frase)
frase2 = frase1[::-1]

# for l in range(len(frase1) -1, -1, -1):
#     frase2 += frase1[l]

if frase1 == frase2:
    print('Yes, your sentence is a palindromo')
else:
    print('No, you are wrong')


import os
from datetime import datetime, timedelta

import pandas as pd
import streamlit as st
from streamlit.elements.widgets.time_widgets import DateWidgetReturn

from req.param import ReqParam
from utils.gh import (
    get_commit_author_weekly_num,
    get_commit_weekly_num,
    get_issues_weekly_num,
)
from utils.reshape import get_dict_val_by_key_order, get_year_week_list

date_now: datetime = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
date_this_week_end: datetime = (date_now - timedelta(days=date_now.weekday())
                                + timedelta(days=6))
date_week_ago: datetime = date_this_week_end - timedelta(weeks=4)

st.title('OSS Insight Lite')
st.subheader('Some metric not including in https://ossinsight.io')

st.subheader('Options')

option_repo = st.selectbox(
    'Which repository do you like to insight',
    ('apache/dolphinscheduler', 'apache/seatunnel')
)

date_range: DateWidgetReturn = st.date_input(
    label="Select the start date",
    value=(date_week_ago, date_this_week_end),
)

# to avoid UI index error: https://discuss.streamlit.io/t/date-input-range-index-error-while-selecting/22499
if len(date_range) != 2:
    st.stop()

st.subheader('Information')

st.write(f"For more metric of this project please see in ossinsight [{option_repo}](https://ossinsight.io/analyze/{option_repo}#overview)")
st.write("For important issue track, please see our [notion database](https://zhongjiajie.notion.site/DolphinScheduler-a03f7c3cccd142248193b12837f18a8f?pvs=4)")

start_date = datetime.combine(date_range[0], datetime.min.time())
end_date = datetime.combine(date_range[1], datetime.min.time())
year_week_list = get_year_week_list(start_date, end_date)
try:
    github_token = st.secrets["GITHUB_TOKEN"]
except FileNotFoundError:
    github_token = os.environ.get("GITHUB_TOKEN", None)

req_param = ReqParam(
    token=github_token,
    repo=option_repo,
    since=start_date,
    until=end_date,
    today=date_now,
)

@st.cache_data
def data_commits(req: ReqParam) -> list[int]:
    return get_dict_val_by_key_order(
        get_commit_weekly_num(req)
    )

@st.cache_data
def data_commits_author(req: ReqParam) -> list[int]:
    return get_dict_val_by_key_order(
        get_commit_author_weekly_num(req)
    )

@st.cache_data
def data_issues(req: ReqParam) -> [dict, list[int]]:
    return get_issues_weekly_num(req)

@st.cache_data
def data_issues_update(req: ReqParam) -> list[int]:
    return data_issues(req).get('update')

@st.cache_data
def data_issues_open(req: ReqParam) -> list[int]:
    return data_issues(req).get('open')

@st.cache_data
def data_issues_close(req: ReqParam) -> list[int]:
    return data_issues(req).get('close')

st.subheader('Metric')

st.write("Weekly Commits")
df_contributors = pd.DataFrame(
    data={
        'commits': data_commits(req_param),
        'commits-authors': data_commits_author(req_param),
    },
    index=year_week_list,
)
st.line_chart(df_contributors)

st.write("Weekly Issues")
df_issues = pd.DataFrame(
    data={
        'issues-open': data_issues_open(req_param),
        'issues-close': data_issues_close(req_param),
        'issues-update': data_issues_update(req_param),
    },
    index=year_week_list,
)
st.line_chart(df_issues)


from typing import Dict
from string import Template
from enum import Enum
from g_code_parsing.g_code_functionality_defs.g_code_functionality_def_base import (
    GCodeFunctionalityDefBase,
)

class SetTempGCodeFunctionalityDef(GCodeFunctionalityDefBase):
    # Using this list to output string in specific order
    EXPECTED_ARGS = ["S", "P", "I", "D"]

    class ValDefinedMessage(str, Enum):
        S = "Temperature: ${val}C"
        P = "Kp: $val"
        I = "Ki: $val"  # noqa: E741
        D = "Kd: $val"

    @classmethod
    def _generate_command_explanation(cls, g_code_args: Dict[str, str]) -> str:
        message_list = []
        for arg in cls.EXPECTED_ARGS:
            g_code_arg_val = g_code_args.get(arg)
            if g_code_arg_val is not None:
                message_temp = Template(cls.ValDefinedMessage[arg].value)
                message = message_temp.substitute(val=g_code_arg_val)
                message_list.append(message)

        return "Setting temperature values to the following:\n\t" + "\n\t".join(
            message_list
        )


#!/usr/bin/env python3
"""
Why shell=True can be dangerous

echo '%an\' > /tmp/wuzhere #'
"""
import argparse
import subprocess
import sys

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("-u", "--unsafe", action="store_true")
    args = parser.parse_args()

    # get desired log format
    default = "%an|%ae"
    fmt = input(f"git-log format (default: {default}): ")
    fmt = fmt.strip()
    if not fmt:
        fmt = default

    if args.unsafe:
        subprocess.run(f"git log -n1 --format='{fmt}'", shell=True)
    else:
        subprocess.run(["git", "log", "-n1", f"--format={fmt}"])

if __name__ == "__main__":
    sys.exit(main())


import speech_recognition as sr

#use the microphone as source for input. Here, we also specify
#which device ID to specifically look for incase the microphone
#is not working, an error will pop up saying "device_id undefined"
sample_rate = 48000
chunk_size = 2048

#Initialize the recognizer
r = sr.Recognizer()

with sr.Microphone(device_index = 2, sample_rate = sample_rate,
                        chunk_size = chunk_size) as source:
    #wait for a second to let the recognizer adjust the
    #energy threshold based on the surrounding noise level
    r.adjust_for_ambient_noise(source)
    print("Listen Started")
    #listens for the user's input

    audio = r.record(source, duration=4)
    print("Listen Done")
    try:
        print("Recognition started")
        text = r.recognize_google(audio)
        print ("you said: " + text)

    #error occurs when google could not understand what was said

    except sr.UnknownValueError:
        print("Google Speech Recognition could not understand audio")

    except sr.RequestError as e:
        print("Could not request results from Google Speech Recognition service; {0}".format(e))


def median(nums1, nums2):
    m = len(nums1)
    n = len(nums2)
    if m > n:
        return median(nums2, nums1)
    low = 0
    high = m
    medianPos = (m+n+1)//2
    while low <= high:
        cut1 = (low+high)//2
        cut2 = medianPos - cut1

        l1 = float('-inf') if cut1 == 0 else nums1[cut1-1]
        l2 = float('-inf') if cut2 == 0 else nums2[cut2-1]
        r1 = float('inf') if cut1 == m else nums1[cut1]
        r2 = float('inf') if cut2 == n else nums2[cut2]

        if l1 <= r2 and l2 <= r1:
            if (m+n) % 2 != 0:
                return float(max(l1, l2))
            else:
                return (max(l1, l2)+min(r1, r2))/2.0
        elif l1 > r2:
            high = cut1-1
        else:
            low = cut1+1
    return 0.0


from django.conf.urls import patterns, url

# sighting specific url patterns
urlpatterns = patterns('bushlog.apps.sighting.views',
    url(r'^search/$', 'search', name='search'),
    url(r'^create/$', 'create', name='create'),
    url(r'^create/image/$', 'create_image', name='create_image'),
    url(r'^forms/(?P<type>\w+)/$', 'forms', name='forms'),
    url(r'^activate/(?P<pk>\d+)/$', 'activate', name='activate'),
    url(r'^deactivate/(?P<pk>\d+)/$', 'deactivate', name='deactivate'),
    url(r'^latest/$', 'latest', name='latest'),
    url(r'^(?P<reserve_slug>\S+)/(?P<species_slug>\S+)/(?P<pk>\d+)/$', 'detail', name='detail'),
    url(r'^(?P<reserve_slug>\S+)/(?P<species_slug>\S+)/$', 'list', name='list')
)


""" Copyright 2012, August 05
	Written by Pattarapol (Cheer) Iamngamsup
	E-mail:  IAM.PATTARAPOL@GMAIL.COM

	Counting Sundays
	Problem 19

	You are given the following information,
	but you may prefer to do some research for yourself.

	1 Jan 1900 was a Monday.
	Thirty days has September, April, June and November.

	All the rest have thirty-one, Saving February alone,
	Which has twenty-eight, rain or shine. And on leap years, twenty-nine.

	A leap year occurs on any year evenly divisible by 4,
	but not on a century unless it is divisible by 400.

	How many Sundays fell on the first of the month
	during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
"""

#################################################
#   Importing libraries & modules
import datetime

#################################################
#   Global variables

#################################################
#   Functions

#################################################
#   Classes

#################################################
#   Main function
def main():

	count = 0
	for year in range( 1901, 2001 ):
		for month in range( 1, 13 ):
			if datetime.datetime( year, month, 1 ).weekday() == 6:
				count += 1
	print( 'answer = {0}'.format( count ) )

#################################################
#   Main execution
if __name__ == '__main__':
	#   get starting date time
	startingDateTime = datetime.datetime.utcnow()
	print( 'startingDateTime = {0} UTC'.format( startingDateTime ) )

	#   call main function
	main()

	#   get ending date time
	endingdateTime = datetime.datetime.utcnow()
	print( 'endingdateTime = {0} UTC'.format( endingdateTime ) )

	#   compute delta date time
	deltaDateTime = endingdateTime - startingDateTime
	print( 'deltaDateTime = {0}'.format( deltaDateTime ) )


from bin.service import Info, Logger

class AutoComplete:

    def __init__(self):
        self.info = Info.Info()
        self.logger = Logger.Logger()

    def run(self, query, include_jira):

        if include_jira == 'True':
            include_jira = True
        else:
            include_jira = False

        result = {
            'items': [],
            'success': True,
            'error': None
        }
        try:
            suggestions = self.info.get_query_suggestions(query, include_jira)
            result['items'].append({
                'suggestions': suggestions
            })

        except Exception as e:
            result['error'] = str(e)
            result['success'] = False
            self.logger.add_entry(self.__class__.__name__, e)

        return result


#!/usr/bin/env python
"""
# License: GNU Affero General Public License v3 or later
# A copy of GNU AGPL v3 should have been included in this software package in LICENSE.txt.

File containing definition of the NCBI class and containing functions useful for handling NCBI taxonomy databases
"""

import gzip
import logging
import os
import string
import sys

from typing import Dict, Set, Tuple
from itertools import chain

import pandas as pd

from tqdm import tqdm

from autometa.common.utilities import file_length
from autometa.common.exceptions import DatabaseOutOfSyncError
from autometa.config.utilities import DEFAULT_CONFIG
from autometa.taxonomy.database import TaxonomyDatabase

logger = logging.getLogger(__name__)

NCBI_DIR = DEFAULT_CONFIG.get("databases", "ncbi")
# For cases where autometa has not been configured, attempt to find ncbi directory via source
NCBI_DIR = NCBI_DIR if not "None" in NCBI_DIR else NCBI_DIR.replace("None", ".")

class NCBI(TaxonomyDatabase):
    """Taxonomy utilities for NCBI databases."""

    def __init__(self, dbdir, verbose=False):
        """
        Instantiates the NCBI class

        Parameters
        ----------

        dbdir : str
            Path to the database directory

        verbose : bool, optional
            log progress to terminal, by default False

        """
        self.dbdir = dbdir
        self.verbose = verbose
        self.disable = not self.verbose
        self.names_fpath = os.path.join(self.dbdir, "names.dmp")
        self.nodes_fpath = os.path.join(self.dbdir, "nodes.dmp")
        self.merged_fpath = os.path.join(self.dbdir, "merged.dmp")
        self.delnodes_fpath = os.path.join(self.dbdir, "delnodes.dmp")
        # Set prot.accession2taxid filepath
        self.accession2taxid_fpath = os.path.join(self.dbdir, "prot.accession2taxid")
        acc2taxid_gz = ".".join([self.accession2taxid_fpath, "gz"])
        if not os.path.exists(self.accession2taxid_fpath) and os.path.exists(
            acc2taxid_gz
        ):
            self.accession2taxid_fpath = acc2taxid_gz
        # Set prot.accession2taxid.FULL.gz filepath
        self.accession2taxidfull_fpath = os.path.join(
            self.dbdir, "prot.accession2taxid.FULL"
        )
        acc2taxid_gz = ".".join([self.accession2taxidfull_fpath, "gz"])
        if not os.path.exists(self.accession2taxidfull_fpath) and os.path.exists(
            acc2taxid_gz
        ):
            self.accession2taxidfull_fpath = acc2taxid_gz
        # Set dead_prot.accession2taxid filepath
        self.dead_accession2taxid_fpath = os.path.join(
            self.dbdir, "dead_prot.accession2taxid"
        )
        acc2taxid_gz = ".".join([self.dead_accession2taxid_fpath, "gz"])
        if not os.path.exists(self.dead_accession2taxid_fpath) and os.path.exists(
            acc2taxid_gz
        ):
            self.dead_accession2taxid_fpath = acc2taxid_gz
        # Check formatting for nr database
        self.nr_fpath = os.path.join(self.dbdir, "nr.gz")
        nr_bname = os.path.splitext(os.path.basename(self.nr_fpath))[0]
        nr_dmnd_fname = ".".join([nr_bname, "dmnd"])
        nr_dmnd_fpath = os.path.join(self.dbdir, nr_dmnd_fname)
        if os.path.exists(nr_dmnd_fpath):
            self.nr_fpath = nr_dmnd_fpath
        if "dmnd" not in os.path.basename(self.nr_fpath):
            # This check should probably be in the dependencies/databases file...
            logger.warning(
                f"DatabaseWarning: {self.nr_fpath} needs to be formatted for diamond!"
            )
        # Setup data structures from nodes.dmp, names.dmp and merged.dmp
        self.nodes = self.parse_nodes()
        self.names = self.parse_names()
        self.merged = self.parse_merged()
        self.delnodes = self.parse_delnodes()

    def __repr__(self):
        """
        Operator overloading to return the string representation of the class object

        Returns
        -------
        str
            String representation of the class object
        """
        return str(self)

    def __str__(self):
        """
        Operator overloading to return the directory path of the class object

        Returns
        -------
        str
            Directory path of the class object
        """
        # Perhaps should place summary here of files that do or do not exist?
        return self.dbdir

    def parse_names(self) -> Dict[int, str]:
        """
        Parses through names.dmp database and loads taxids with scientific names

        Returns
        -------
        dict
            {taxid:name, ...}
        """
        if self.verbose:
            logger.debug(f"Processing names from {self.names_fpath}")
        names = {}
        fh = open(self.names_fpath)
        for line in tqdm(fh, disable=self.disable, desc="parsing names", leave=False):
            taxid, name, __, classification = line.strip("\t|\n").split("\t|\t")[:4]
            taxid = int(taxid)
            name = name.lower()
            # Only add scientific name entries
            if classification == "scientific name":
                names.update({taxid: name})
        fh.close()
        if self.verbose:
            logger.debug("names loaded")
        return names

    def parse_nodes(self) -> Dict[int, str]:
        """
        Parse the `nodes.dmp` database to be used later by :func:`autometa.taxonomy.ncbi.NCBI.parent`, :func:`autometa.taxonomy.ncbi.NCBI.rank`
        Note: This is performed when a new NCBI class instance is constructed

        Returns
        -------
        dict
            {child_taxid:{'parent':parent_taxid,'rank':rank}, ...}
        """
        if self.verbose:
            logger.debug(f"Processing nodes from {self.nodes_fpath}")
        fh = open(self.nodes_fpath)
        __ = fh.readline()  # root line
        nodes = {1: {"parent": 1, "rank": "root"}}
        for line in tqdm(fh, disable=self.disable, desc="parsing nodes", leave=False):
            child, parent, rank = line.split("\t|\t")[:3]
            parent, child = [int(node) for node in [parent, child]]
            rank = rank.lower()
            nodes.update({child: {"parent": parent, "rank": rank}})
        fh.close()
        if self.verbose:
            logger.debug("nodes loaded")
        return nodes

    def parse_merged(self) -> Dict[int, int]:
        """
        Parse the merged.dmp database
        Note: This is performed when a new NCBI class instance is constructed

        Returns
        -------
        dict
            {old_taxid: new_taxid, ...}
        """
        if self.verbose:
            logger.debug(f"Processing nodes from {self.merged_fpath}")
        fh = open(self.merged_fpath)
        merged = {}
        for line in tqdm(fh, disable=self.disable, desc="parsing merged", leave=False):
            old_taxid, new_taxid = [
                int(taxid) for taxid in line.strip("\t|\n").split("\t|\t")
            ]
            merged.update({old_taxid: new_taxid})
        fh.close()
        if self.verbose:
            logger.debug("merged loaded")
        return merged

    def parse_delnodes(self) -> Set[int]:
        """
        Parse the delnodes.dmp database
        Note: This is performed when a new NCBI class instance is constructed

        Returns
        -------
        set
            {taxid, ...}
        """
        if self.verbose:
            logger.debug(f"Processing delnodes from {self.delnodes_fpath}")
        fh = open(self.delnodes_fpath)
        delnodes = set()
        for line in tqdm(
            fh, disable=self.disable, desc="parsing delnodes", leave=False
        ):
            del_taxid = int(line.strip("\t|\n"))
            delnodes.add(del_taxid)
        fh.close()
        if self.verbose:
            logger.debug("delnodes loaded")
        return delnodes

    def convert_taxid_dtype(self, taxid: int) -> int:
        """
        1. Converts the given `taxid` to an integer and checks whether it is positive.
        2. Checks whether `taxid` is present in both nodes.dmp and names.dmp.
        3a. If (2) is false, will check for corresponding `taxid` in merged.dmp and convert to this then redo (2).
        3b. If (2) is true, will return converted taxid.
        4. If (3a) is false will look for `taxid` in delnodes.dmp. If present will convert to root (taxid=1)

        Parameters
        ----------
        taxid : int
            identifier for a taxon in NCBI taxonomy databases - nodes.dmp, names.dmp or merged.dmp

        Returns
        -------
        int
            `taxid` if the `taxid` is a positive integer and present in either nodes.dmp or names.dmp or
            taxid recovered from merged.dmp

        Raises
        ------
        ValueError
            Provided `taxid` is not a positive integer
        DatabaseOutOfSyncError
            NCBI databases nodes.dmp, names.dmp and merged.dmp are out of sync with each other
        """
        #  Step 1 Converts the given `taxid` to an integer and checks whether it is positive.
        # Checking taxid instance format
        # This checks if an integer has been added as str, eg. "562"
        if isinstance(taxid, str):
            invalid_chars = set(string.punctuation + string.ascii_letters)
            invalid_chars.discard(".")
            if set(taxid).intersection(invalid_chars) or taxid.count(".") > 1:
                raise ValueError(f"taxid contains invalid character(s)! Given: {taxid}")
            taxid = float(taxid)
        # a boolean check is needed as they will evaluate silently to 0 or 1 when cast as ints. FALSE=0, TRUE=1
        # float(taxid).is_integer() checks if it is something like 12.0 vs. 12.9
        # is_integer only takes float as input else raises error, thus isinstance( ,float) is used before it to make sure a float is being passed
        if isinstance(taxid, bool) or (
            isinstance(taxid, float) and not taxid.is_integer()
        ):
            raise ValueError(f"taxid must be an integer! Given: {taxid}")
        taxid = int(taxid)
        if taxid <= 0:
            raise ValueError(f"Taxid must be a positive integer! Given: {taxid}")
        # Checking databases
        #  Step 2: Check whether taxid is present in both nodes.dmp and names.dmp.
        if taxid not in self.names and taxid not in self.nodes:
            # Step 3a. Check for corresponding taxid in merged.dmp
            if taxid not in self.merged:
                # Step 4: look for taxid in delnodes.dmp. If present will convert to root (taxid=1)
                if taxid in self.delnodes:
                    # Assign deleted taxid to root...
                    if self.verbose:
                        logger.debug(
                            f"Found {taxid} in delnodes.dmp, converting to root (taxid=1)"
                        )
                    taxid = 1
                else:
                    err_message = f"Databases out of sync. {taxid} not in found in nodes.dmp, names.dmp, merged.dmp or delnodes.dmp"
                    raise DatabaseOutOfSyncError(err_message)
            else:
                # Step 3b. convert taxid from merged.
                if self.verbose:
                    logger.debug(
                        f"Converted {taxid} to {self.merged[taxid]} from merged.dmp"
                    )
                taxid = self.merged[taxid]
                if taxid not in self.names and taxid not in self.nodes:
                    # NOTE: Do not check delnodes.dmp here, as at this point it appears the databases are indeed out of sync.
                    # i.e. The taxid should either be in merged.dmp or in delnodes.dmp if not in nodes.dmp or names.dmp
                    err_message = f"Databases out of sync. Merged taxid ({taxid}) not found in nodes.dmp or names.dmp!"
                    raise DatabaseOutOfSyncError(err_message)
        return taxid

    def search_prot_accessions(
        self,
        accessions: set,
        sseqids_to_taxids: Dict[str, int] = None,
        db: str = "live",
    ) -> Dict[str, int]:
        """Search prot.accession2taxid.gz and dead_prot.accession2taxid.gz

        Parameters
        ----------
        accessions : set
            Set of subject sequence ids retrieved from diamond blastp search (sseqids)

        sseqids_to_taxids : Dict[str, int], optional
            Dictionary containing sseqids converted to taxids

        db : str, optional
            selection of one of the prot accession to taxid databases from NCBI. Choices are live, dead, full

            * live: prot.accession2taxid.gz
            * full: prot.accession2taxid.FULL.gz
            * dead: dead_prot.accession2taxid.gz

        Returns
        -------
        Dict[str, int]
            Dictionary containing sseqids converted to taxids
        """
        if not sseqids_to_taxids:
            sseqids_to_taxids = {}
        if not isinstance(db, str):
            raise ValueError(f"db must be a string! Type Given: {type(db)}")
        db = db.lower()
        choices = {
            "live": self.accession2taxid_fpath,
            "dead": self.dead_accession2taxid_fpath,
            "full": self.accession2taxidfull_fpath,
        }
        if db not in choices:
            raise ValueError(f"db must be one of live, full or dead. Given: {db}")
        fpath = choices.get(db)

        # Revert to accession2taxid if FULL is not present
        if db == "full" and (not os.path.exists(fpath) or not os.path.getsize(fpath)):
            logger.warn(
                "prot.accession2taxid.FULL.gz was not found. Reverting to prot.accession2taxid.gz"
            )
            logger.warn(
                "To achieve greater resolution of your metagenome taxonomy, considering downloading the prot.accession2taxid.FULL.gz database file"
            )
            fpath = choices.get("live")
            db = "live"

        if not os.path.exists(fpath) or not os.path.getsize(fpath):
            raise FileNotFoundError(fpath)

        # "rt" open the database in text mode instead of binary to be handled like a text file
        fh = gzip.open(fpath, "rt") if fpath.endswith(".gz") else open(fpath)
        filename = os.path.basename(fpath)
        # skip the header line
        __ = fh.readline()
        logger.debug(
            f"Searching for {len(accessions):,} accessions in {filename}. This may take a while..."
        )
        n_lines = file_length(fpath, approximate=True) if self.verbose else None
        desc = f"Parsing {filename}"
        converted_sseqid_count = 0
        for line in tqdm(
            fh, disable=self.disable, desc=desc, total=n_lines, leave=False
        ):
            if db == "full":
                # FULL format is accession.version\ttaxid\n
                acc_num = None  # Just in case
                acc_ver, taxid = line.strip().split("\t")
            else:
                # dead and live formats are accession\taccession.version\ttaxid\tgi\n
                acc_num, acc_ver, taxid, _ = line.strip().split("\t")

            taxid = int(taxid)
            if acc_ver in accessions:
                sseqids_to_taxids[acc_ver] = taxid
                converted_sseqid_count += 1

            # So prog will not have to search through the accessions set
            if db == "full":
                continue

            # Search for base accession if using live or dead accession2taxid databases
            if acc_num in accessions:
                sseqids_to_taxids[acc_num] = taxid
                converted_sseqid_count += 1

        fh.close()
        logger.debug(f"sseqids converted from {filename}: {converted_sseqid_count:,}")
        return sseqids_to_taxids

    def convert_accessions_to_taxids(
        self, accessions: set
    ) -> Tuple[Dict[str, Set[int]], pd.DataFrame]:
        # We first get all unique accessions that were retrieved from the blast output
        recovered_accessions = set(
            chain.from_iterable(
                [qseqid_sseqids for qseqid_sseqids in accessions.values()]
            )
        )
        # Check for sseqid in dead_prot.accession2taxid.gz in case an old db was used.
        # Any accessions not found in live prot.accession2taxid db *may* be here.
        # This *attempts* to prevent accessions from being assigned root (root taxid=1)
        try:
            sseqids_to_taxids = self.search_prot_accessions(
                accessions=recovered_accessions,
                db="dead",
                sseqids_to_taxids=None,
            )
            dead_sseqids_found = set(sseqids_to_taxids.keys())
        except FileNotFoundError as db_fpath:
            logger.warn(f"Skipping taxid conversion from {db_fpath}")
            sseqids_to_taxids = None
            dead_sseqids_found = set()

        # Now build the mapping from sseqid to taxid from the full/live accession2taxid dbs
        # Possibly overwriting any merged accessions to live accessions
        sseqids_to_taxids = self.search_prot_accessions(
            accessions=recovered_accessions,
            db="full",
            sseqids_to_taxids=sseqids_to_taxids,
        )

        # Remove accessions: Ignore any accessions already found
        live_sseqids_found = set(sseqids_to_taxids.keys())
        live_sseqids_found -= dead_sseqids_found
        recovered_accessions -= live_sseqids_found
        if recovered_accessions:
            logger.warn(
                f"accessions without corresponding taxid: {len(recovered_accessions):,}"
            )
        root_taxid = 1
        taxids = {}
        sseqid_not_found = pd.NA
        sseqid_to_taxid_df = pd.DataFrame(
            [
                {
                    "qseqid": qseqid,
                    "sseqid": sseqid,
                    "raw_taxid": sseqids_to_taxids.get(sseqid, sseqid_not_found),
                }
                for qseqid, qseqid_sseqids in accessions.items()
                for sseqid in qseqid_sseqids
            ]
        )
        # Update taxids if they are old.
        sseqid_to_taxid_df["merged_taxid"] = sseqid_to_taxid_df.raw_taxid.map(
            lambda tid: self.merged.get(tid, tid)
        )
        # If we still have missing taxids, we will set the sseqid value to the root taxid
        # fill missing taxids with root_taxid
        sseqid_to_taxid_df["cleaned_taxid"] = sseqid_to_taxid_df.merged_taxid.fillna(
            root_taxid
        )
        root_taxid = 1
        for qseqid, qseqid_sseqids in accessions.items():
            # NOTE: we only want to retrieve the set of unique taxids (not a list) for LCA query
            qseqid_taxids = {
                sseqids_to_taxids.get(sseqid, root_taxid) for sseqid in qseqid_sseqids
            }
            taxids[qseqid] = qseqid_taxids
        return taxids, sseqid_to_taxid_df

if __name__ == "__main__":
    print("file containing Autometa NCBI utilities class")
    import sys

    sys.exit(1)


# This file contains utility-type of functions to assist with the creation
# of a histogram graph, e.g., for preparing
# the input data before plotting them as a histogram.

from typing import List

import pandas as pd

from .constants import COL_NAME_BUCKETS, COL_NAME_FREQS, PRECISION_VAL

def create_df_w_lats_ranges_and_freqs(
    list_of_buckets: List[List[float]], list_of_frequencies: List[int]
) -> pd.DataFrame:
    """
    Create a dataframe of latency buckets' ranges and frequencies given two
    lists containing a list of buckets of
    latencies and a list of frequencies.

    Args:
        list_of_buckets: List[List[float]]
                        a list of lists containing latencies (floats), wherein
                         each sub-list is a bucket.
        list_of_frequencies: List[int]
                            a list of frequencies (integers).

    Returns:
        a dataframe of latency buckets' ranges (strings)
        and frequencies (integers).
    """

    list_of_min_and_max = []
    for bucket in list_of_buckets:
        list_of_min_and_max.append(
            f"{str(round(min(bucket), PRECISION_VAL))}{'-'}"
            f"{str(round(max(bucket), PRECISION_VAL))}"
        )

    df_w_lats_ranges_and_freqs = pd.DataFrame(
        {COL_NAME_BUCKETS: list_of_min_and_max, COL_NAME_FREQS: list_of_frequencies}
    )

    return df_w_lats_ranges_and_freqs


__author__ = 'Nick Sarris'

import numpy as np
import pandas as pd

Predictions_Ensemble = pd.read_csv('~/Desktop/Massey Predictor/Final_Submissions/Final Predictions (Ensemble 2016).csv', encoding = "ISO-8859-1")
Predictions_Model = pd.read_csv('~/Desktop/Massey Predictor/Final_Submissions/Final Predictions (Model 2016).csv', encoding = "ISO-8859-1")
Bracket_Teams = pd.read_csv('~/Desktop/Massey Predictor/Bracket_Data/Bracket Teams.csv', encoding = "ISO-8859-1")

Teams_Array = np.asarray(Bracket_Teams)
Teams_List_1 = list(Teams_Array[:,0])
Teams_List_2 = list(Teams_Array[:,1])

Team_Dictionary = dict(zip(Teams_List_1, Teams_List_2))
ID_Dictionary = dict(zip(Teams_List_2, Teams_List_1))

Predictions_Model = np.asarray(Predictions_Model)
Predictions_Model_Keys = Predictions_Model[:,0]
Predictions_Model_Values = Predictions_Model[:,1]
Predictions_Model = dict(zip(Predictions_Model_Keys, Predictions_Model_Values))

Predictions_Ensemble = np.asarray(Predictions_Ensemble)
Predictions_Ensemble_Keys = Predictions_Ensemble[:,0]
Predictions_Ensemble_Values = Predictions_Ensemble[:,1]
Predictions_Ensemble = dict(zip(Predictions_Ensemble_Keys, Predictions_Ensemble_Values))

def Predictions(Team_Dictionary, ID_Dictionary, Predictions_Model, Predictions_Ensemble):

    Team_1 = ID_Dictionary[input("Enter Team 1: ")]
    Team_2 = ID_Dictionary[input("Enter Team 2: ")]

    print ('')

    try:
        Match_1 = ('2016_%d_%d' % (Team_1, Team_2))
        print ('Model Prediction = %s (%.1f%%) vs %s (%.1f%%).' % (Team_Dictionary[Team_1], (100 * (Predictions_Model[Match_1])), Team_Dictionary[Team_2], (100 * (1 - Predictions_Model[Match_1]))))

    except:
        Match_1 = ('2016_%d_%d' % (Team_2, Team_1))
        print ('Model Prediction = %s (%.1f%%) vs %s (%.1f%%).' % (Team_Dictionary[Team_2], (100 * (Predictions_Model[Match_1])), Team_Dictionary[Team_1], (100 * (1 - Predictions_Model[Match_1]))))

    try:
        Match_1 = ('2016_%d_%d' % (Team_1, Team_2))
        print ('Ensemble Prediction = %s (%.1f%%) vs %s (%.1f%%).' % (Team_Dictionary[Team_1], (100 * (Predictions_Ensemble[Match_1])), Team_Dictionary[Team_2], (100 * (1 - Predictions_Ensemble[Match_1]))))

    except:
        Match_1 = ('2016_%d_%d' % (Team_2, Team_1))
        print ('Ensemble Prediction = %s (%.1f%%) vs %s (%.1f%%).' % (Team_Dictionary[Team_2], (100 * (Predictions_Ensemble[Match_1])), Team_Dictionary[Team_1], (100 * (1 - Predictions_Ensemble[Match_1]))))

Predictions(Team_Dictionary, ID_Dictionary, Predictions_Model, Predictions_Ensemble)


class Student:
    def __init__(self, id, name, surname, phone, email, number, room):
        self.id = id
        self.name = name
        self.surname = surname
        self.phone = phone
        self.email = email
        self.number = number
        self.room = room

class Teacher:
    def __init__(self, id, name, surname, phone, email, position):
        self.id = id
        self.name = name
        self.surname = surname
        self.phone = phone
        self.email = email
        self.position = position

class Lesson:
    def __init__(self, id, name):
        self.id = id
        self.name = name

class Room:
    def __init__(self, id, name, lessons, teachers):
        self.id = id
        self.name = name
        self.lessons = lessons
        self.teachers = teachers


''' This is used to plot the results from the pitch detector.
	To change which sound file you're looking at, modify the 'testing' variable.
	To change which note you're looking at, modify the 'ii' variable.
	To change if you're looking at a single note or the entire melody,
		modify the 'sung_note' variable, and 'timestamps', and axarr[0].scatter
'''

#import pitch detectors:
from helpers import *
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
np.set_printoptions(threshold='nan')

hopSize = 128 #units: samples
frameSize = 2048 #units: samples
sr = 44100 #sample rate: 44100 samples per second
guessUnvoiced = True # read the algorithm's reference for more details
run_predominant_melody = PitchMelodia(guessUnvoiced=guessUnvoiced,
                                      frameSize=frameSize,
                                      hopSize=hopSize)
methods = ['yinfft']

indir = '/Users/asdfang/Desktop/YEAR3/17SPRING/399EECSindependentstudy/HarmonizeMe/PitchOnsetTrackerTests'

''' MODIFY testing AND ii BASED ON WHAT TEST AND WHICH LABEL YOU'RE LOOKING AT: '''
testing = 'Male_1a'
ii = 0 #looking at the ii-th label, starting from 0

sound_file = testing + '.wav'
label_file = testing + '_Labels.txt'

sound_path = indir + '/' + testing + '/' + sound_file
label_path = indir + '/' + testing + '/' + label_file

sound_path = './totest/original.wav'
label_path = './totest/original_Labels.txt'

#testing from specific file
# sound_path = 'tests/1a/original.wav'
# label_path = 'tests/1a/original_Labels.txt'

#loading full sound file into a mono array of dtype=numpy.float32
audio_array, dummy_var = librosa.core.load(sound_path, sr=sr)

# test_onsets = aubio_onsets(audio_array)
# for ii in range(0, len(test_onsets)):
# 	test_onsets[ii] = test_onsets[ii]/44100.0
# print test_onsets

#parsing text file
full_labels = open(label_path)
lines = full_labels.readlines()
label_info = [] #parsed file
for l in lines:
	label_info.append(l.strip().split('\t')) #split with spaces as separation; strip() takes care of the \t's
#label_info[x] holds the xth label; elements are strings
#label[x][0] holds the start time, label[x][1] holds the end time, label[x][2] holds the info for the xth label

#parsing ground truths
ground_truth_onsets_seconds = []
ground_truth_onsets_samps = []
lines = []
with open(label_path) as input:
    lines = zip(*(line.strip().split('\t') for line in input))

for midi, onset in zip(lines[2], lines[0]):
	ground_truth_onsets_seconds.append(float(onset))
# convert onsets to samples
for onset in ground_truth_onsets_seconds:
	ground_truth_onsets_samps.append(int(numpy.around(onset*sr)))

#start and end in terms of seconds
s_time = float(label_info[ii][0])
e_time = float(label_info[ii][1])
#start and end in terms of samples
start = int(np.rint(s_time * float(sr)))
end = int(np.rint(e_time * float(sr)))
lbl = label_info[ii][2]

#making midi arrays
ground_truth_midis = []
for l in label_info:
	if l[2].strip() == "SIL":
		ground_truth_midis.append(90.0)
	else:
		ground_truth_midis.append(float(l[2]))

''' MODIFY THIS BASED ON ISOLATED NOTE VS. FULL MELODY: '''
# ISOLATED NOTE:
# sung_note = audio_array[start:end]

#FULL MELODY:
sung_note = audio_array
s_time = 0.0
e_time = librosa.get_duration(audio_array, sr=sr)

#feeding it into the pitch detector; first pad
#pad with zeros to make it divisible by hopSize
# audio_length = sung_note.size
# num_padded_zeros = 128 - (audio_length % 128)
# sung_note = np.concatenate([sung_note, np.zeros(num_padded_zeros, dtype=np.float32)])
detector_result_midi_verbose = aubio_pitches(audio_array)
detector_result_midis = verbose_to_detected_midi(detector_result_midi_verbose, ground_truth_onsets_samps, hopSize)

'''
matplot time!
'''
''' MODIFY THIS BASED ON ISOLATED NOTE VS. FULL MELODY: '''
dur = librosa.get_duration(sung_note, sr=sr)
# if full melody:
timestamps = np.linspace(s_time, e_time, len(detector_result_midi_verbose))
#if sliced note:
# num_times = len(detector_result_midi_verbose[int(np.around(start/hopSize)):int(np.around(end/hopSize))])
# timestamps = np.linspace(s_time, e_time, num_times) #+1 because of padding

#plotting
f, axarr = plt.subplots(2, figsize=(15, 9))
green_patch = mpatches.Patch(color='green', label='Ground Truth Onsets')
black_patch = mpatches.Patch(color='black', label='Ground Truth Pitch')
red_patch = mpatches.Patch(color='red', label='Pitch Detector Result')
axarr[0].legend(handles=[green_patch, black_patch, red_patch])
''' MODIFY THIS BASED ON ISOLATED NOTE VS. FULL MELODY: '''
#full melody:
axarr[0].scatter(timestamps, detector_result_midi_verbose)
#spliced note:
# axarr[0].scatter(timestamps, detector_result_midi_verbose[int(np.around(start/hopSize)):int(np.around(end/hopSize))])
axarr[0].set_title('Pitch Detector')
axarr[0].set_ylabel('MIDI Note Number')
axarr[0].set_xlabel('Time (s)')
xmin = s_time
xmax = e_time
ymin = 50.0
ymax = 80.0
axarr[0].axis([xmin, xmax, ymin, ymax]) #xmin, xmax, ymin, ymax
axarr[0].vlines(ground_truth_onsets_seconds, ymin, ymax, colors='green')

''' MODIFY THIS BASED ON ISOLATED NOTE VS. FULL MELODY: '''
#if visualizing one note
'''
if label_info[ii][2].strip() == 'SIL':
	axarr[0].text((e_time-s_time)/2.5, (ymax-ymin)*0.75, "SIL", color='black')
else:
	axarr[0].hlines(ground_truth_midis[ii], s_time, e_time, color='black')
	axarr[0].text(s_time+(e_time-s_time)/2.0, ground_truth_midis[ii]+5, str(ground_truth_midis[ii]), color='black')
	axarr[0].hlines(detector_result_midis[ii], s_time, e_time, color='red')
	axarr[0].text(s_time+(e_time-s_time)/2.0, detector_result_midis[ii]-5, str(round(float(detector_result_midis[ii]), 1)), color='red')
'''

#if visualizing full melody
for ii in range(0, len(ground_truth_midis)):
	if label_info[ii][2].strip() == 'SIL':
		continue
	s = float(label_info[ii][0])
	e = float(label_info[ii][1])
	axarr[0].hlines(ground_truth_midis[ii], s, e, colors='black')
	axarr[0].text(s+(e-s)/3.5, ground_truth_midis[ii]+5, str(ground_truth_midis[ii]), color='black')
	axarr[0].hlines(detector_result_midis[ii], s, e, colors='red')
	axarr[0].text(s+(e-s)/3.5, detector_result_midis[ii]-5, str(round(float(detector_result_midis[ii]), 1)), color='red')

f.subplots_adjust(hspace=0.5)
plt.show()


import math
import random

class Node:
	def __init__(self, element,right,down):
		self.value= element
		self.right = right
		self.down= down

class SkipList:
	def __init__(self):
		#head of the highest list
		self.head = Node (-math.inf,None,None)
		self.tail= Node(math.inf,None,None)
		self.head.right=self.tail

	def coinFlip(self):
		return  random.randint(0,1)

	def printAllLevels(self):
		tmp_head=self.head
		tmp_head_down=self.head.down
		while tmp_head:
			print(tmp_head.value, end=" ")
			tmp_head=tmp_head.right
			if(tmp_head==None):
				tmp_head=tmp_head_down
				if(tmp_head_down):
					tmp_head_down=tmp_head_down.down
				print(" ")

	def createNewLevel(self):
		#Create a new level
		# -inf  ------------> +inf
		#-inf  is the new head of the skip list
		head_tmp = Node (-math.inf,None,self.head)
		#inf is the new tail of the skip list
		tail_tmp= Node(math.inf,None,self.tail)
		head_tmp.right=self.tail
		self.head=head_tmp
		self.tail=tail_tmp

	def insert(self,key):

		#Search Path until level 0
		tmp = self.head
		path = []
		while(tmp):
			#move right
			if (tmp.right.value <=key):
				tmp = tmp.right
			else:
				#Store the nodes that yields the algorithm to
				#move one level down
				if(tmp.down!=None):
					path.append(tmp)
				# When it reaches the level  0 --> stop
				if(tmp.down==None):
					break
				else:
					#move down
					tmp=tmp.down
		#if key already exists
		if(tmp.value==key):
			print('Key ', key, 'already exists')
			return

		#Add new node at level 0 and flip a coin. If coin gives '1'
		#then promote the node at level i+1, where i is the current level.
		#If the promoting exceeds the current max height create a new level
		#and add the new node.
		prevNode=None
		pointer= len(path)-1
		while True:
			newNode=Node(key, tmp.right,prevNode)
			tmp.right=newNode
			prevNode=newNode
			if(self.coinFlip()==1):
				if(pointer<0):
					self.createNewLevel()
					tmp=self.head
				else:
					tmp=path[pointer]
					pointer=pointer-1

			else:
				break

if __name__ == '__main__':
	list = SkipList()
	#Insert all elements
	for i in range (0,1024):
		list.insert(i)
	#Print all levels top-down
	list.printAllLevels()