import uproot
import os
import pandas as pd
import numpy as np
import awkward
from tqdm import tqdm

def extract_scalar_data(events, branches, entrystop=None, progressbar=False):
    data = {}

    data["event"] = events.array("event", entrystop=entrystop)

    for br in tqdm(branches, disable=not progressbar):
        data[br] = events.array(br, entrystop=entrystop).flatten()

    return pd.DataFrame(data)

def extract_vector_data(events, branches, entrystop=10, progressbar=False):
    def get(branch, flat=True):
        a = events.array(branch, entrystop=entrystop)
        if flat:
            return a.flatten()
        else:
            return a

    if len(branches) == 0:
        return {}

    first_branch_jagged = get(branches[0], flat=False)
    first_branch_flat = first_branch_jagged.flatten()

    event_jagged = get("event") + awkward.JaggedArray(
        first_branch_jagged.starts, first_branch_jagged.stops, np.zeros(len(first_branch_flat), dtype=np.int)
    )

    data = {}

    data["event"] = event_jagged.flatten()

    data[branches[0]] = first_branch_flat

    for br in tqdm(branches, disable=not progressbar):
        if br == branches[0]:
            continue

        if br in events:
            data[br] = get(br)
        else:
            print('Warning! Branch "' + br + '" not found in input file and skipped.')

    return pd.DataFrame(data)

def nanoaod_to_parquet(input_files, out_dir, entrystop=None, input_prefix="", progressbar=False):
    def save_parquet(df, name):
        df.to_parquet(os.path.join(out_dir, name + ".parquet.gzip"), compression="gzip", index=False)

    out_dir = os.path.expanduser(out_dir)

    if not os.path.exists(out_dir):
        os.makedirs(out_dir)

    n_input_files = len(input_files)

    for i, input_file in enumerate(input_files):

        log_prefix = ""
        if i > 0:
            log_prefix = f"[{i+1}/{n_input_files}] "

        def log(s):
            print(log_prefix + s)

        log("Opening input file " + input_file)
        root_file = uproot.open(input_prefix + input_file)

        events = root_file["Events"]

        branches = [br.decode("ascii") for br in events.keys()]

        n_events = len(events[branches[0]])

        prefixes = list(set([b.split("_")[0] for b in branches]))

        vector_groups_present = [p for p in prefixes if "n" + p in events]

        scalar_branches = ["n" + s for s in vector_groups_present]

        for br in branches:
            if br == "event":
                continue
            if not br.split("_")[0] in vector_groups_present:
                scalar_branches.append(br)

        basename = os.path.basename(input_file)[:-5]

        log("Loading DataFrame for scalar branches")
        df_scalar = extract_scalar_data(events, scalar_branches, entrystop=entrystop, progressbar=progressbar)
        log("Saving DataFrame parquet Scalar")
        save_parquet(df_scalar, basename + "_Scalar")
        del df_scalar

        processed_branches = scalar_branches + ["event"]

        for group in vector_groups_present:
            log("Loading DataFrame for object group " + group)
            filtered_branches = list(filter(lambda br: br == group or br.startswith(group + "_"), branches))
            df = extract_vector_data(events, filtered_branches, entrystop=entrystop, progressbar=progressbar)
            log("Saving DataFrame parquet " + group)
            save_parquet(df, basename + "_" + group)
            processed_branches += filtered_branches
            del df

        # make sure we considered all the branches
        assert [b for b in branches if not b in processed_branches] == []

from geeksw.nanocache import list_files

import os
import subprocess

def convert_files_to_parquet(input_files, base_out_dir=".", server="root://polgrid4.in2p3.fr/"):

    n = len(input_files)

    for i, input_file in enumerate(input_files):

        out_dir = base_out_dir + os.path.dirname(input_file)

        tmp_file_name = os.path.join("/tmp", os.path.basename(input_file))

        if os.path.exists(tmp_file_name):
            subprocess.call(["rm", tmp_file_name])

        print(f"File {i+1} of {n}: copying " + input_file + " to " + tmp_file_name)
        subprocess.call(["xrdcp", server + input_file, tmp_file_name])

        nanoaod_to_parquet([tmp_file_name], out_dir, entrystop=None, progressbar=False)

        subprocess.call(["rm", tmp_file_name])
        print("Deleted " + tmp_file_name)

def convert_dataset_to_parquet(dataset, base_out_dir=".", server="root://polgrid4.in2p3.fr/"):

    input_files = list_files(dataset)

    convert_files_to_parquet(input_files, base_out_dir=base_out_dir, server=server)


import tensorflow as tf
import collect
import numpy as np

#from tensorflow.examples.tutorials.mnist import input_data

#mnist = input_data.read_data_sets("/tmp/data/", one_hot = True)

'''
10 classes, 0-9
'''

#Setting up neural network
n_nodes_hl1 = 100
n_nodes_hl2 = 150
n_nodes_hl3 = 125

n_classes = 2
batch_size = 80 #setup batches, batches of 100 images, up this to compare more at one time
data_num = 8000

#height x width
x = tf.placeholder(tf.float32, [batch_size, 500]) # don't know what the fixed width is
y = tf.placeholder(tf.float32, [batch_size,2]) # temporary values

def neural_network_model(data):
    #input_data * weights + biases

    #Biases exist to make the neural network a bit more dynamic
    hidden_1_layer = {'weights' : tf.Variable(tf.random_normal([500, n_nodes_hl1])),
                      'biases' : tf.Variable(tf.random_normal([n_nodes_hl1]))}

    hidden_2_layer = {'weights' : tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])),
                      'biases' : tf.Variable(tf.random_normal([n_nodes_hl2]))}

    hidden_3_layer = {'weights' : tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])),
                      'biases' : tf.Variable(tf.random_normal([n_nodes_hl3]))}

    output_layer = {'weights' : tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])),
                      'biases' : tf.Variable(tf.random_normal([n_classes]))}

    l1 = tf.add(tf.matmul(data, hidden_1_layer['weights']) , hidden_1_layer['biases'])
    l1 = tf.nn.relu(l1)

    l2 = tf.add(tf.matmul(l1, hidden_2_layer['weights']) , hidden_2_layer['biases'])
    l2 = tf.nn.relu(l2)

    l3 = tf.add(tf.matmul(l2, hidden_3_layer['weights']) , hidden_3_layer['biases'])
    l3 = tf.nn.relu(l3)

    output = tf.matmul(l3, output_layer['weights']) + output_layer['biases']
    return output

def train_neural_network(x):
    prediction = neural_network_model(x)
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y, logits = prediction))

    optimizer = tf.train.AdamOptimizer().minimize(cost)

    #Cycles feed forward +  back prop
    hm_epochs = 2
    saver = tf.train.Saver()

    with tf.Session() as sess:
        sess.run(tf.initialize_all_variables())

        for epoch in range(hm_epochs):
            epoch_loss = 0
            for _ in range(int(data_num/batch_size)):
                epoch_x, epoch_y = collect.nextbatch(batch_size) #Lol it aint this easy :)

                print('New batch beginning!')

                #print(np.shape(x), np.shape(y))
                #print(len(np.array(epoch_x)))
                #print(len(np.array(epoch_y)))
                _, c, predictnumpy = sess.run([optimizer, cost, prediction], feed_dict = {x: np.array(epoch_x), y: np.array(epoch_y)})
                epoch_loss += c
                saver.save(sess, 'checkpoints/the-best.ckpt')
            print('Epoch ', epoch, ' completed out of ', hm_epochs, ' loss: ', epoch_loss)
            correct = np.equal(np.argmax(predictnumpy,0), np.argmax(y,0))
            accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
            print('Accuracy: ', sess.run(accuracy.eval()))

train_neural_network(x)


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

# In[1]:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Dropout,BatchNormalization
from keras.callbacks import EarlyStopping,ModelCheckpoint
import keras
import pickle
import numpy as np
import tensorflow as tf
import glob
from tensorflow.keras import layers
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from pickle import dump
import pandas as pd
from collections import Counter

# ETL Standarization

def Scaler(df,direction):
    # Mediante esta funcion creamos y transfromamos los datos mediante un normalizador
# Standardizing the features
    scaler=StandardScaler()
    final_data = scaler.fit_transform(df)
# Download scaler
    dump(scaler, open(direction+'model_scaler.pkl', 'wb'))
    return final_data

# ETL to sequences

# Create model

def model_autoencoder(data,dim_1,dim_2,dim_3,dp):
    model = Sequential()
    model.add(Dense(dim_1, input_dim=data.shape[1], activation='relu'))
    model.add(BatchNormalization())
    model.add(Dense(dim_2, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dense(dim_3, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dense(dim_3, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dense(dim_2, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dense(dim_1, activation='relu'))
    model.add(Dense(data.shape[1]))
    model.compile(optimizer='adam', loss='mse')
    return model

    # Data, es data en forma de create_sequences
    # time_steps, es la cantidad de datos de sequencia que se quiere meter
    # dim out & dim in, dimensionalidad  de la red neuronalde lstm
    # dp is drop_out

# Training

def training(data,val,model,patience,direccion,bs,n_epochs,verbose):
    # data, model
    # patience, cantidad de epochs que no avanza para meteler checkpoints
    # bs es la cantidad de batch & n_epochs, es la cantidad maxima de epcohs que se pueden dar

    es = EarlyStopping(monitor='val_loss', mode='min', verbose=verbose, patience=patience)
    mc = ModelCheckpoint(direccion+'model_autoencoder.h5', monitor='val_loss', mode='min', verbose=verbose, save_best_only=True)
    model.fit(data,data,batch_size=bs,epochs=n_epochs,verbose=verbose,callbacks=[es,mc],validation_data=(val,val))

# Calculate P_Value
def P_value_calculate(model_dir,data_array,porcentaje_max,direction):
	model=keras.models.load_model(model_dir)
	data_array_pred=model.predict(data_array)
	resta=np.abs(data_array_pred - data_array)
	resta_global_total=resta.mean(axis=1)
	value_limited=sorted(resta_global_total,reverse=True)[int(len(resta_global_total)*porcentaje_max)]
	np.save(direction+'p_value.npy', np.array(value_limited))
	return resta_global_total

def Export_results_xlsx(resta_global_total,value_limited,data_select_dataframe,direccion):

# Calculate id (del array) out/in
	resta_global_binary=[]
	for r in resta_global_total:
    		if r>value_limited:
        		resta_global_binary.append(1)
    		else:
        		resta_global_binary.append(0)

	Final=pd.DataFrame(resta_global_binary)
	Final.columns=['Out/In']
	result = pd.merge(data_select_dataframe, Final, how="left",left_index=True, right_index=True).fillna(0)

	result.to_excel(direccion+"_resultados.xlsx")
	return result

def graphs(direccion,result):
	for prop in result.columns[1:-1]:
    		fig,ax=plt.subplots(figsize=(20, 16))
    		plt.plot(result['index'],result[prop],marker="o",label=prop)
    		plt.plot(result[result['Out/In']==1]['index'],result[result['Out/In']==1][prop],marker="o",color="red",linestyle='')
    		plt.title(prop, fontdict=None, loc='center', pad=None,fontsize=30)
    		plt.savefig(direccion+'Grap_'+prop+'.png', bbox_inches='tight', pad_inches=0.0)


from tkinter import *
from tkinter import ttk
import pandas as pd
import numpy as np
import traceback

class CurrencyCard:

    def __init__(self, parent, BG_COLOR, WIDGET_COLOR, index:int, s_api, symbol_from="", symbol_to=""):
        self.parent = parent
        self.index = index
        self.cdata = s_api.cdata

        if (index % 2) == 0:
            bg = BG_COLOR[1]
        else:
            bg = BG_COLOR[0]

        self.frame = Frame(parent.frame, bg=bg)
        cols = 0
        #self.in_label = Label(self.frame, text=f"Conversion {index}", bg=bg, fg=WIDGET_COLOR[0])
        #self.in_label.grid(row=0, column=0)

        Button(self.frame, text="-", fg=WIDGET_COLOR[0], command=self.remove_ccard).grid(row=0, column=cols, sticky="w")
        cols += 1
        Label(self.frame, text=" ", bg=bg).grid(row=0, column=cols)
        cols += 1

        self.in_label = Entry(self.frame, bg=bg, fg=WIDGET_COLOR[0])
        self.in_label.insert(0, f"Conversion {index}")
        self.in_label.grid(row=0, column=cols); cols += 1

        self.in_entry = Entry(self.frame)
        self.in_entry.grid(row=0, column=cols); cols += 1

        self.in_currency_cbox = ttk.Combobox(self.frame, values=s_api.currency_strs)
        if symbol_from != "":
            try:
                self.in_currency_cbox.current(s_api.currency_str_index(symbol_from))
            except:
                self.in_currency_cbox.current(1)
        else:
            self.in_currency_cbox.current(1)

        self.in_currency_cbox.grid(row=0, column=cols); cols += 1

        Label(self.frame, text="    ===>    ", bg=bg, fg=WIDGET_COLOR[0]).grid(row=0, column=cols)
        cols += 1

        self.out_entry = Entry(self.frame, textvariable="")
        self.out_entry.grid(row=0, column=cols); cols += 1

        self.out_currency_cbox = ttk.Combobox(self.frame, values=s_api.currency_strs)

        if symbol_to != "":
            try:
                self.out_currency_cbox.current(s_api.currency_str_index(symbol_to))
            except:
                self.out_currency_cbox.current(0)
        else:
            self.out_currency_cbox.current(0)

        self.out_currency_cbox.grid(row=0, column=cols); cols +=1

        self.calc_btn = Button(self.frame, text="Calculate", bg=WIDGET_COLOR[0], fg=WIDGET_COLOR[1], command=self.calculate)
        self.calc_btn.grid(row=0, column=cols); cols += 1

    def calculate(self):
        try:
            self.out_entry.delete(0, END)
            in_cdata = self.cdata.iloc[self.in_currency_cbox.current()].to_numpy()
            out_cdata = self.cdata.loc[self.out_currency_cbox.current()].to_numpy()
            in_usd = float(in_cdata[2])
            out_usd = float(out_cdata[2])
            self.exchange_rate = np.divide(in_usd, out_usd)
            self.result = np.multiply(float(self.in_entry.get()), self.exchange_rate)
            self.result_usd = np.multiply(self.result, out_usd)
            self.out_entry.insert(0, '{:.20f}'.format(self.result).rstrip("0"))
            #print(f"Calculated {in_cdata[2]} USD worth of {in_cdata[1]} to {out_cdata[2]} USD worth of {out_cdata[1]}\nWith exchange rate: {self.exchange_rate}%")
        except Exception as e:
            print(f"Could not calculate values for {self.in_label.get()}:\n{e}")

    def remove_ccard(self):
        self.parent.ccard_list.remove(self)
        self.frame.destroy()

    def get_calculated(self):
        self.calculate()
        return [self.result, self.result_usd, self.exchange_rate]

    def update_cdata(self, s_api):
        self.cdata = s_api.cdata

    def get_log_data(self):
        self.calculate()
        return [self.in_label.get(), self.result_usd]


from django.db import transaction
from django.utils.translation import ugettext, ugettext_lazy as _
from django import forms

from gf.gas.forms.order.plan import AddPlannedOrderForm
from gf.gas.forms.order.base import AddOrderForm

from gf.gas.models import GAS, GASSupplierOrder, GASSupplierSolidalPact

import logging, copy

log = logging.getLogger(__name__)

#--------------------------------------------------------------------------------

class AddInterGASOrderForm(AddOrderForm):
    """Form to manage InterGAS orders.

    This works only for context resources GAS and Pact
    """

    #WAS: INTERGAS 0
    intergas = forms.BooleanField(label=_('Is this an InterGAS order?'), required=False)
    intergas_grd = forms.ModelMultipleChoiceField(
        label=_('InterGAS order with'), queryset=GAS.objects.none(),
        required=False,
        widget=forms.CheckboxSelectMultiple
    )

    #WAS: INTERGAS 1
    def __init__(self, *args, **kw):

        super(AddInterGASOrderForm, self).__init__(*args, **kw)

        pacts_count = self._pacts.count()
        self._gas = self._pacts[0].gas

        # Check needed because exception will be shown just by the end of the execution
        # of the __init__
        if pacts_count:

            intergas_gas_qs = self._gas.config.intergas_connection_set.all()
            if pacts_count == 1:

                #log.debug("AddOrderForm only one pact %s" % pacts)
                intergas_gas_qs = intergas_gas_qs & self._pacts[0].supplier.gas_list

        self.fields['intergas_grd'].queryset = intergas_gas_qs

    def clean(self):
        """InterGAS clean() checks for selected GAS and set _involved_extra_pacts attributes."""

        #WAS: INTERGAS 2 (rewritten. It can be factorized along with ordinary GASSupplierOrder clean)

        cleaned_data = super(AddInterGASOrderForm, self).clean()
        self._involved_extra_pacts = set()
        self._intergas_requested = cleaned_data.get('intergas')
        _involved_gas_list = cleaned_data.get('intergas_grd',[])
        supplier = cleaned_data['pact'].supplier

        for gas in _involved_gas_list:
            if gas != self._gas:
                log.debug("AddOrderForm intergas finding another PACT for GAS %s..." % gas)

                #retrieve the existing pact for this gas for this supplier. If exist.
                #TODO: Matteo: if not exists -> POST forged -> we should raise specific exception
                extra_pact = None
                try:
                    extra_pact = gas.pacts.get(supplier=supplier)
                    log.debug("Pact %s found." % extra_pact)
                    self._involved_extra_pacts.add(extra_pact)
                except GASSupplierSolidalPact.DoesNotExist as e:
                    #WAS: self._messages['error'].append(ugettext("Please select a gas which has a pact with the same supplier of the pact this order refers to"))
                    log.debug("Not valid InterGAS order: one or more GAS involeved do not have pacts with the same supplier")
                    raise forms.ValidationError("Not valid InterGAS order: one or more GAS involeved do not have pacts with the same supplier")

        if self._intergas_requested and not self._involved_extra_pacts:
            log.debug("Not valid InterGAS order: at least 2 GAS needed")
            raise forms.ValidationError("Not valid InterGAS order: at least 2 GAS needed")

        return cleaned_data

    def create_order_for_another_pact(self, other_pact):
        """This relates to InterGAS."""

        new_obj = self.instance.clone()
        new_obj.pact = other_pact

        obj = self.instance

        # retrieve the first referrer_person
        refs = other_pact.referrers_people
        if len(refs):
            log.debug("refs %s found for pact %s" % (refs, other_pact))
            new_obj.referrer_person = refs[0]
            new_obj.delivery_referrer_person = new_obj.referrer_person
            new_obj.withdrawal_referrer_person = new_obj.referrer_person
        else:
            #FIXME: 'NoneType' object has no attribute 'user'. Cannot be real. But model permitted
            #Cannot create the order.
            log.warning("no referrers for pact %s" % other_pact)

        #Delivery set to default delivery Place if gas is configured accordingly
        if obj.delivery:

            dd_place = other_pact.gas.config.default_delivery_place or \
                other_pact.gas.headquarter
            new_obj.delivery, created = Delivery.objects.get_or_create(
                    date=obj.delivery.date, place=dd_place
            )

        return new_obj

    @transaction.atomic
    def save(self):

        #WAS: INTERGAS 4 (rewritten. Set correctly group_id in base order to not repeat in planned orders)

        if self._intergas_requested:
            self.instance.group_id = GASSupplierOrder.objects.get_new_intergas_group_id()

            # Create complementary InterGAS orders

            for extra_pact in self._involved_extra_pacts:
                other_intergas_order = self.create_order_for_another_pact(extra_pact)
                try:
                    other_intergas_order.save()
                    log.debug("created another intergas order: %s " % other_intergas_order)
                except Exception as e:
                    log.debug("repeat another NOT created: pact %s, start %s , end %s , delivery %s" % (
                        other_intergas_order.pact, other_intergas_order.datetime_start, other_intergas_order.datetime_end,
                        other_intergas_order.delivery.date
                    ))
                    raise

        super(AddInterGASOrderForm, self).save()

    class Meta(AddOrderForm.Meta):

        #WAS: INTERGAS 6
        gf_fieldsets = copy.deepcopy(AddOrderForm.Meta.gf_fieldsets)
        gf_fieldsets[0][1]['fields'].append(('intergas', 'intergas_grd'))

class AddInterGASPlannedOrderForm(AddInterGASOrderForm, AddPlannedOrderForm):
    """Form to manage InterGAS and order planning at the same time."""

    @transaction.atomic
    def save(self):

        AddInterGASOrderForm.save(self)
        AddPlannedOrderForm.save(self)

    class Meta(AddPlannedOrderForm.Meta):

        gf_fieldsets = copy.deepcopy(AddPlannedOrderForm.Meta.gf_fieldsets)
        gf_fieldsets[0][1]['fields'].append(('intergas', 'intergas_grd'))


#DANILO COURA MOREIRA

import time as time
import numpy as np
import matplotlib.pyplot as plt

def normal_equation(points):
	points_x_with_1 = np.append(np.ones((len(points),1)),points[:,0:1],axis=1)
	#w = (H'H)-1 H'y
	return np.dot(np.dot(np.linalg.inv(np.dot(np.transpose(points_x_with_1),points_x_with_1)),np.transpose(points_x_with_1)),points[:,1])

def run():
	tic = time.time()
	points = np.genfromtxt("income.csv", delimiter=",")
	#y = w0 + w1x (slope formula)
	[w0, w1] = normal_equation(points)
	tac = time.time()
	print('Tempo de processamento versão Equação Normal: {0:0.2f} segundos'.format(tac-tic))
	axis_x = range(0,25)
	plt.figure(1)
	plt.xlabel('Escolaridade (anos)')
	plt.ylabel('Salário (mil/ano)')
	plt.title('Regressão Linear')
	plt.plot(points[:,0], points[:,1], 'ro')
	plt.plot(axis_x, w0+w1*axis_x)
	plt.text(5, 60, 'Y = {0:0.3f} + {1:0.3f}x'.format(w0,w1), fontsize=12)
	plt.show()

if __name__ == '__main__':
	run()


#!/usr/bin/python3

import formula_moivre
import grafica_complejos
import sys

#Determina la cantidad correcta de argumentos
if len(sys.argv) != 3:
    sys.exit("\n  ERROR: cantidad de argumentos inválidos\n"
        "\t Uso: raiz_compleja <radicando> <indice>\n")

#Verifica que el segundo argumento sea un complejo valido
try:
    z = complex(sys.argv[1])
except ValueError:
    sys.exit("\n  ERROR: " + str(sys.argv[1]) + " no es un numero complejo válido de la forma a+bj'\n")

#Verifica que el tercer argumento sea un numero natural
try:
    indice = int(sys.argv[2])
    if indice <= 0:
        raise ValueError()
except ValueError:
    sys.exit("\n  ERROR: " + str(sys.argv[2]) + " no es un numero natural'\n")

r = formula_moivre.sacarRaices(z, indice);

for i in r:
    print(i)

grafica_complejos.graficar_complejos(z, indice, r)


from rich.console import Console
from gallow import gallow_frames
from ending import game_over
from the_word import word

c = Console()

def make_gallow(wrong_guesses):
    c.print(gallow_frames[wrong_guesses], style="white")

def enter_word():
    return input("Enter Word: ").upper()

def display_guesses(word, guesses):
    letters = ""
    for letter in word:
        if letter in guesses:
            letters += letter + " "
        elif letter == " ":
            letters += "  "
        else:
            letters += "_ "
    c.print(letters, style="cyan")

def display_wrong_guesses(word, guesses):
    wrong_guesses = ""
    for letter in guesses:
        if letter not in word:
            wrong_guesses += f"{letter} "

    c.print(wrong_guesses, style="magenta")

def get_new_guess(guesses):
    new_guess = input("Make guess: ").upper()
    while new_guess in guesses or new_guess == " ":
        new_guess = input(f"{new_guess} already guessed. Make new guess: ").upper()
    guesses += new_guess[0]
    return guesses

def count_wrong_guesses(word, guesses):
    wrong_guesses = 0
    for letter in guesses:
        if letter not in word:
            wrong_guesses += 1
    return wrong_guesses

def main():
    word_no_dup = "".join(set(word))
    guesses = ""
    wrong_guesses = 0
    playing = True
    while playing:
        make_gallow(wrong_guesses)
        display_guesses(word, guesses)
        display_wrong_guesses(word, guesses)
        guesses = get_new_guess(guesses)
        wrong_guesses = count_wrong_guesses(word,guesses)
        if wrong_guesses >= 6:
            make_gallow(6)
            c.print(game_over, style="red")
            playing = False
        misses = 0
        for letter in word:
            if letter not in guesses and letter != " ":
                misses += 1
        if misses == 0:
            make_gallow(7)
            c.print("Congratulations!\nYou Win!", style="yellow")
            playing = False

if __name__ == '__main__':
    main()


#
# SCORING ANALYSES OF MULTIPLE ALIGNMENTS BY NORMD
#  This script make a NORMD score by slide window using a multiple alignment file in FASTA format
#
#  (!)For to use you need to install some softwares:
#	** NORMD 1.3 ()
#	** EMBOSS toolkit (http://emboss.sourceforge.net/)
#   ** Need copy the SEQRET software for the same folder of this script.

import os
import sys

def getparam(param_name):
    name = False
    for param in sys.argv:
        if (name):
            name = False
            return param
        if (param == param_name):
            name = True
    return False

# Verify if the parameters exists. Case exist show the message.
if (getparam("-h") != False):
    print("This script make a NORMD score by slide window using a multiple alignment file in FASTA format.")
    print(" (!)For to use you need to install some softwares:")
    print("     ** NORMD 1.3 ()")
    print("     ** EMBOSS toolkit (http://emboss.sourceforge.net/)")
    print("     ** Need copy the SEQRET software for the same folder of this script")
    print("")
    print("See the example command:")
    print(" python SMABSW.py -normd -swsize -fasta -finalpos -stepsize")
else:
    #Verify if the mandatory fields is filled.
    validateparam = True
    if (getparam("-normd") == False):
        print("(!)Please select the NORMD folder")
        validateparam = False
    elif (getparam("-swsize") == False):
        print("(!)Please select a slide window number")
        validateparam = False
    elif (getparam("-fasta") == False):
        print("(!)Please select the multiple alignment file in FASTA format")
        validateparam = False
    elif (getparam("-finalpos") == False):
        print("(!)Please select the final position of the alignment")
        validateparam = False
    elif (getparam("-stepsize") == False):
        print("(!)Please select the step size")
        validateparam = False

    # If every parameters is right, continue the pipeline.
    if (validateparam):
        param_normd = getparam("-normd")
        param_swsize = getparam("-swsize")
        param_fasta = getparam("-fasta")
        param_finalpos = getparam("-finalpos")
        param_stepsize = getparam("-stepsize")

        os.system("rm scores.txt")

        # Build the scores by slide window
        inipos = 0
        endpos = int(param_swsize)

        while (endpos <= int(param_finalpos)):

            # Convert the FASTA file in a temporary MSF file with the slide window sequence.
            os.system("./seqret -auto -stdout -sequence " + param_fasta +
                      " -outseq temp.msf --sbegin " + str(inipos) +" --send "+str(endpos)+" "
                      "-sformat1 fasta -osformat2 msf")

            # Run the NORMD for this slide window and save every pontuation in the scores.txt.
            os.system( param_normd + "/normd temp.msf "+param_normd+"/blosum62.bla 11 1 -v >> scores.txt")

            # Show the actual slide window.
            print ("["+ str(inipos) + "..." + str(endpos) + "][N="+str(param_finalpos)+"]")
            inipos = inipos + int(param_stepsize)
            endpos = endpos + int(param_stepsize)

        # Remove the temporary file
        os.system("rm temp.msf")


from iTechnious.helpers import admin_checker
from iTechnious.interactions import response

def run(req, client=None, options=None, mysql=None):
    content = [option["value"] for option in options if option["name"] == "text"][0]
    guild_id = int(req["guild_id"])
    user_id = int(req["member"]["user"]["id"])

    if not admin_checker(guild_id, user_id):
        return response.get_unauthorized()

    with mysql.cursor() as cursor:
        cursor.execute(f"UPDATE competitions SET `description`='{content}' WHERE `guild_id`='{req['guild_id']}'")
    mysql.commit()

    return response.get_ok()


from datetime import date
import sys
import math
from database import session
from attendnum import attendnum
from sqlalchemy import func

args = sys.argv

input1 = int(args[1])
input2 = int(args[2])
input3 = int(args[3])

Y = input1 % 10000
M = Y % 100

dt = date(math.floor(input1 / 10000), math.floor((input1 % 10000) / 100),math.floor(M % 100))

name_count = session.query(attendnum).filter_by(entry_date = dt).count() + 1
print(name_count)

attend = attendnum(
    entry_date = dt,
    seq = name_count,
    adult = input2,
    child = input3
)
session.add(attend)

session.commit()


import json
import os
import subprocess
from datetime import datetime

import requests
from hachoir.metadata import extractMetadata
from hachoir.parser import createParser
from telethon.tl.types import DocumentAttributeVideo

from userbot import LOGS, HELPER
from userbot.events import register

TEMP_DOWNLOAD_DIRECTORY = os.environ.get("TMP_DOWNLOAD_DIRECTORY", "./")

def progress(current, total):
    """ Logs the download progress """
    LOGS.info(
        "Downloaded %s of %s\nCompleted %s",
        current, total, (current / total) * 100
    )

@register(pattern=r".download(?: |$)(.*)", outgoing=True)
async def download(target_file):
    """ For .download command, download files to the userbot's server. """
    if not target_file.text[0].isalpha() and target_file.text[0] not in ("/", "#", "@", "!"):
        if target_file.fwd_from:
            return
        await target_file.edit("Processing ...")
        input_str = target_file.pattern_match.group(1)
        if not os.path.isdir(TEMP_DOWNLOAD_DIRECTORY):
            os.makedirs(TEMP_DOWNLOAD_DIRECTORY)
        if target_file.reply_to_msg_id:
            start = datetime.now()
            downloaded_file_name = await target_file.client.download_media(
                await target_file.get_reply_message(),
                TEMP_DOWNLOAD_DIRECTORY,
                progress_callback=progress,
            )
            end = datetime.now()
            duration = (end - start).seconds
            await target_file.edit(
                "Downloaded to `{}` in {} seconds.".format(downloaded_file_name, duration)
            )
        elif "|" in input_str:
            url, file_name = input_str.split("|")
            url = url.strip()
            # https://stackoverflow.com/a/761825/4723940
            file_name = file_name.strip()
            required_file_name = TEMP_DOWNLOAD_DIRECTORY + "" + file_name
            start = datetime.now()
            resp = requests.get(url, stream=True)
            with open(required_file_name, "wb") as file:
                total_length = resp.headers.get("content-length")
                # https://stackoverflow.com/a/15645088/4723940
                if total_length is None:  # no content length header
                    file.write(resp.content)
                else:
                    downloaded = 0
                    total_length = int(total_length)
                    for chunk in resp.iter_content(chunk_size=128):
                        downloaded += len(chunk)
                        file.write(chunk)
                        done = int(100 * downloaded / total_length)
                        download_progress_string = "Downloading ... [%s%s]" % (
                            "=" * done,
                            " " * (50 - done),
                        )
                        LOGS.info(download_progress_string)
            end = datetime.now()
            duration = (end - start).seconds
            await target_file.edit(
                "Downloaded to `{}` in {} seconds.".format(required_file_name, duration)
            )
        else:
            await target_file.edit("Reply to a message to download to my local server.")

@register(pattern=r".uploadir (.*)", outgoing=True)
async def uploadir(udir_event):
    """ For .uploadir command, allows you to upload everything from a folder in the server"""
    if not udir_event.text[0].isalpha() and udir_event.text[0] not in ("/", "#", "@", "!"):
        if udir_event.fwd_from:
            return
        input_str = udir_event.pattern_match.group(1)
        if os.path.exists(input_str):
            start = datetime.now()
            await udir_event.edit("Processing ...")
            lst_of_files = []
            for r, d, f in os.walk(input_str):
                for file in f:
                    lst_of_files.append(os.path.join(r, file))
                for file in d:
                    lst_of_files.append(os.path.join(r, file))
            LOGS.info(lst_of_files)
            uploaded = 0
            await udir_event.edit(
                "Found {} files. Uploading will start soon. Please wait!".format(
                    len(lst_of_files)
                )
            )
            for single_file in lst_of_files:
                if os.path.exists(single_file):
                    # https://stackoverflow.com/a/678242/4723940
                    caption_rts = os.path.basename(single_file)
                    if not caption_rts.lower().endswith(".mp4"):
                        await udir_event.client.send_file(
                            udir_event.chat_id,
                            single_file,
                            caption=caption_rts,
                            force_document=False,
                            allow_cache=False,
                            reply_to=udir_event.message.id,
                            progress_callback=progress,
                        )
                    else:
                        thumb_image = os.path.join(input_str, "thumb.jpg")
                        metadata = extractMetadata(createParser(single_file))
                        duration = 0
                        width = 0
                        height = 0
                        if metadata.has("duration"):
                            duration = metadata.get("duration").seconds
                        if metadata.has("width"):
                            width = metadata.get("width")
                        if metadata.has("height"):
                            height = metadata.get("height")
                        await udir_event.client.send_file(
                            udir_event.chat_id,
                            single_file,
                            caption=caption_rts,
                            thumb=thumb_image,
                            force_document=False,
                            allow_cache=False,
                            reply_to=udir_event.message.id,
                            attributes=[
                                DocumentAttributeVideo(
                                    duration=duration,
                                    w=width,
                                    h=height,
                                    round_message=False,
                                    supports_streaming=True,
                                )
                            ],
                            progress_callback=progress,
                        )
                    os.remove(single_file)
                    uploaded = uploaded + 1
            end = datetime.now()
            duration = (end - start).seconds
            await udir_event.edit("Uploaded {} files in {} seconds.".format(uploaded, duration))
        else:
            await udir_event.edit("404: Directory Not Found")

@register(pattern=r".upload (.*)", outgoing=True)
async def upload(u_event):
    """ For .upload command, allows you to upload a file from the userbot's server """
    if not u_event.text[0].isalpha() and u_event.text[0] not in ("/", "#", "@", "!"):
        if u_event.fwd_from:
            return
        if u_event.is_channel and not u_event.is_group:
            await u_event.edit("`Uploading isn't permitted on channels`")
            return
        await u_event.edit("Processing ...")
        input_str = u_event.pattern_match.group(1)
        if input_str in ("userbot.session", "config.env"):
            await u_event.edit("`That's a dangerous operation! Not Permitted!`")
            return
        if os.path.exists(input_str):
            start = datetime.now()
            await u_event.client.send_file(
                u_event.chat_id,
                input_str,
                force_document=True,
                allow_cache=False,
                reply_to=u_event.message.id,
                progress_callback=progress,
            )
            end = datetime.now()
            duration = (end - start).seconds
            await u_event.edit("Uploaded in {} seconds.".format(duration))
        else:
            await u_event.edit("404: File Not Found")

def get_video_thumb(file, output=None, width=90):
    """ Get video thhumbnail """
    metadata = extractMetadata(createParser(file))
    popen = subprocess.Popen(
        [
            "ffmpeg",
            "-i",
            file,
            "-ss",
            str(
                int((0, metadata.get("duration").seconds)[metadata.has("duration")] / 2)
            ),
            "-filter:v",
            "scale={}:-1".format(width),
            "-vframes",
            "1",
            output,
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.DEVNULL,
    )
    if not popen.returncode and os.path.lexists(file):
        return output
    return None

def extract_w_h(file):
    """ Get width and height of media """
    command_to_run = [
        "ffprobe",
        "-v",
        "quiet",
        "-print_format",
        "json",
        "-show_format",
        "-show_streams",
        file,
    ]
    # https://stackoverflow.com/a/11236144/4723940
    try:
        t_response = subprocess.check_output(command_to_run, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as exc:
        LOGS.warning(exc)
    else:
        x_reponse = t_response.decode("UTF-8")
        response_json = json.loads(x_reponse)
        width = int(response_json["streams"][0]["width"])
        height = int(response_json["streams"][0]["height"])
        return width, height

@register(pattern=r".uploadas(stream|vn|all) (.*)", outgoing=True)
async def uploadas(uas_event):
    """ For .uploadas command, allows you to specify some arguments for upload. """
    if not uas_event.text[0].isalpha() and uas_event.text[0] not in ("/", "#", "@", "!"):
        if uas_event.fwd_from:
            return
        await uas_event.edit("Processing ...")
        type_of_upload = uas_event.pattern_match.group(1)
        supports_streaming = False
        round_message = False
        spam_big_messages = False
        if type_of_upload == "stream":
            supports_streaming = True
        if type_of_upload == "vn":
            round_message = True
        if type_of_upload == "all":
            spam_big_messages = True
        input_str = uas_event.pattern_match.group(2)
        thumb = None
        file_name = None
        if "|" in input_str:
            file_name, thumb = input_str.split("|")
            file_name = file_name.strip()
            thumb = thumb.strip()
        else:
            file_name = input_str
            thumb_path = "a_random_f_file_name" + ".jpg"
            thumb = get_video_thumb(file_name, output=thumb_path)
        if os.path.exists(file_name):
            start = datetime.now()
            metadata = extractMetadata(createParser(file_name))
            duration = 0
            width = 0
            height = 0
            if metadata.has("duration"):
                duration = metadata.get("duration").seconds
            if metadata.has("width"):
                width = metadata.get("width")
            if metadata.has("height"):
                height = metadata.get("height")
            try:
                if supports_streaming:
                    await uas_event.client.send_file(
                        uas_event.chat_id,
                        file_name,
                        thumb=thumb,
                        caption=input_str,
                        force_document=False,
                        allow_cache=False,
                        reply_to=uas_event.message.id,
                        attributes=[
                            DocumentAttributeVideo(
                                duration=duration,
                                w=width,
                                h=height,
                                round_message=False,
                                supports_streaming=True,
                            )
                        ],
                        progress_callback=progress,
                    )
                elif round_message:
                    await uas_event.client.send_file(
                        uas_event.chat_id,
                        file_name,
                        thumb=thumb,
                        allow_cache=False,
                        reply_to=uas_event.message.id,
                        video_note=True,
                        attributes=[
                            DocumentAttributeVideo(
                                duration=0,
                                w=1,
                                h=1,
                                round_message=True,
                                supports_streaming=True,
                            )
                        ],
                        progress_callback=progress,
                    )
                elif spam_big_messages:
                    await uas_event.edit("TBD: Not (yet) Implemented")
                    return
                end = datetime.now()
                duration = (end - start).seconds
                os.remove(thumb)
                await uas_event.edit("Uploaded in {} seconds.".format(duration))
            except FileNotFoundError as err:
                await uas_event.edit(str(err))
        else:
            await uas_event.edit("404: File Not Found")

HELPER.update({
    "download": ".download <link>\nUsage: Downloads file from link to the server."
})
HELPER.update({
    "upload": ".upload <link>\nUsage: Uploads a locally stored file to telegram."
})


# arrays
import numpy as np
import pandas as pd

# plotting
import matplotlib as mpl
from matplotlib import pyplot as plt
from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import cmocean
# from pandas.plotting import register_matplotlib_converters
# register_matplotlib_converters()

# additional
from datetime import timedelta as td

# maths and stats
import scipy.stats as stats
from scipy.stats import gaussian_kde
from sklearn.metrics import mean_squared_error
from sklearn import linear_model
import statsmodels.api as sm

# custom
from .functions import rmse, bias, si, create_vec_direc, calibration_time

# Calibration-Validation class
class CalVal(object):
    """
        This class CalVal calibrates the wave reanalysis information with
        buoy and satellite data, although we prefer to calibrate it first
        with satellites, so then the data can be compared and validated
        with the buoys. Following this procedure, the calibration is always
        performed and after this, if buoy data is available, then this new
        wave reanalysis calibrated hindcast can be validated
    """

    def __init__(self, hindcast, n_parts,
                 satellite, buoy=(False,None),
                 buoy_corrections=False,
                 hindcast_longitude=-4.5,
                 hindcast_latitude=44.0,
                 buoy_longitude=None,
                 buoy_latitude=None):

        """ Initializes the class with all the necessary attributes that
            will be used in the different methods
            ------------
            Parameters
            hindcast: Hindcast data as a dataframe
            n_parts: Number of partitions in the wave hindcast
            satellite: Satellite data as a netCDF (see extract_satellite.py)
            buoy: Buoy data as a dataframe, and boolean to indicate if it
                is available or not
            buoy_corrections: Boolean to indicate if the buoy corrections
                will be applied or not
            ------------
            Returns
            Attributes initialized and plots for both calibrations, the one
            done with the satellite and the other one performed with buoy
            data, if done. The parameters for the calibrations are also stored
        """

        print('\n Plotting region to be working with!! \n')

        # plot data domains for hindcast, satellite and buoy
        fig, ax = plt.subplots(figsize=(10,10),subplot_kw={
            'projection': ccrs.PlateCarree(central_longitude=hindcast_longitude)
        })
        land_10m = cfeature.NaturalEarthFeature(
            'physical', 'land', '10m', edgecolor='face',
            facecolor=cfeature.COLORS['land']
        ) # add land to image
        ax.scatter(satellite.LONGITUDE,satellite.LATITUDE,
                   s=0.01,c='k',transform=ccrs.PlateCarree())
        ax.scatter(hindcast_longitude,hindcast_latitude,
                   s=50,c='red',zorder=10,transform=ccrs.PlateCarree())
        ax.scatter(buoy_longitude,buoy_latitude,
                   s=50,c='orange',zorder=10,transform=ccrs.PlateCarree()) \
            if buoy[0] else None
        ax.set_extent(
            [hindcast_longitude-4,hindcast_longitude+4,
             hindcast_latitude-4,hindcast_latitude+2]
        )
        ax.stock_img()
        ax.add_feature(land_10m)
        plt.show() # TODO: add better plotting!!
        # TODO: add labels
        # gl = ax.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
        #                   linewidth=2,color='gray',linestyle='--')
        # xlabels = np.arange(plot_region[1][0],plot_region[1][1],plot_labels[1])
        # xlabels = np.where(xlabels<180,xlabels,xlabels-360)
        # ylabels = np.arange(plot_region[1][3],plot_region[1][2],plot_labels[2])
        # gl.xlocator = mticker.FixedLocator(list(xlabels))
        # gl.ylocator = mticker.FixedLocator(list(ylabels))
        # gl.xlabels_top = False
        # gl.ylabels_right = False

        # save all datasets and variables in class
        self.hindcast             =    hindcast.copy()
        self.n_parts              =    n_parts
        self.hindcast_longitude   =    hindcast_longitude
        self.hindcast_latitude    =    hindcast_latitude
        self.possible_to_correct  =    np.where(hindcast['Hs_cal'] > 0.01)[0]
        self.hind_to_corr         =    hindcast.iloc[self.possible_to_correct].copy()
        self.satellite            =    satellite.copy()
        self.hindcast_sat_corr    =    hindcast.copy()
        self.params_sat_corr      =    self.calibration('satellite')
        if buoy[0]:
            self.buoy                 =    buoy[1].copy()
            self.buoy_longitude       =    buoy_longitude
            self.buoy_latitude        =    buoy_latitude
        if buoy_corrections:
            self.hindcast_buoy_corr   =    hindcast.copy()
            self.params_buoy_corr     =    self.calibration('buoy')
        else:
            print('\n No buoy corrections will be done!! \n')

    def calibration(self, calibration_type):
        """ Calibrates hindcast with satellite or buoy data. This calibration
            is performed using a linear regression and selecting only those
            parameters that are significantly representative
            ------------
            Parameters
            calibration_type: (str) Type of calibration to be done
                it can be : (satellite, buoy)
            ------------
            Returns
            Corrected data and calculated params
        """

        print(' -------------------------------------------------------- ')
        print(calibration_type.upper() + ' CALIBRATION will be performed')
        print(' -------------------------------------------------------- \n ')

        # Initializes satellite data to calibrate
        if calibration_type=='satellite':
            print('Satellite box values: ')
            ini_lat = float(input('South latitude: '))
            end_lat = float(input('North latitude: '))
            ini_lon = float(input('West longitude: '))
            end_lon = float(input('East longitude: '))
            print(' \n ')
            hs_calibrate, calibration = self.satellite_values(ini_lat=ini_lat,
                                                              end_lat=end_lat,
                                                              ini_lon=ini_lon,
                                                              end_lon=end_lon)
            title = 'Satellite'
        elif calibration_type=='buoy':
            calibration_tot = pd.concat([self.buoy, self.hind_to_corr],
                                        axis=1)
            notna_values = calibration_tot['Hs_Buoy'].notna().values
            calibration = calibration_tot.iloc[notna_values]
            hs_calibrate = calibration['Hs_Buoy'].values
            title = 'Buoy'
        else:
            return 'Not a valid value for calibration_type'

        print(' \n ')

        # Construct matrices to calibrate
        print('Constructing matrices and calibrating... \n ')
        print('This might take a few minutes... \n')

        print('Sea... \n')
        Hsea = create_vec_direc(calibration['Hsea'],
                                calibration['Dirsea'])
        print('\n')

        print('Swells 1, 2, 3... \n')
        Hs_swells = np.zeros(Hsea.shape)
        for part in np.arange(1, self.n_parts):
            Hs_swells += (create_vec_direc(calibration['Hswell'+str(part)],
                                           calibration['Dirswell'+str(part)])
                         )**2

        # concatenate seas and swells
        Hs_ncorr_mat = np.concatenate([Hsea**2, Hs_swells], axis=1)

        Hs_ncorr = np.sqrt(np.sum(Hs_ncorr_mat, axis=1))
        #---------------------------------------------------------------------#
        print('\n')
        print('Threshold of minimum Hs to calibrate')
        print('Directional families with a mean Hs under this threshold will not be calibrated: ' )
        th_ne = float(input('----- Threshold ----- : '))
        print(' \n ')
        #---------------------------------------------------------------------#
        nedata = np.where(np.mean(Hs_ncorr_mat, axis=0) < th_ne)[0]
        reg = linear_model.LinearRegression()
        hs_calibrate_2 = hs_calibrate**2
        reg.fit(Hs_ncorr_mat, hs_calibrate_2)
        X = sm.add_constant(Hs_ncorr_mat)
        est = sm.OLS(hs_calibrate_2, X)
        est2 = est.fit()
        params = np.array([], dtype = float)
        for p in range(1, len(est2.params)):
            if (est2.pvalues[p] < 0.05 and reg.coef_[p-1] > 0):
                params = np.append(params, reg.coef_[p-1])
            else:
                params = np.append(params, 1.0)
        params[nedata] = 1.0
        paramss = np.array([params])
        Hs_corr_mat = paramss * Hs_ncorr_mat
        Hs_corr = np.sqrt(np.sum(Hs_corr_mat, axis=1))
        params = np.sqrt(params)

        print(' \n ')
        print('Params used for the ' +title.upper()+ ' calibration are: \n ')
        print(params)
        print(' \n ')

        # Plotting corrected results
        print('Plotting just the data used to calibrate... \n ')

        self.calibration_plots(Hs_ncorr, Hs_corr, hs_calibrate,
                               calibration, params, title)

        # Now, we will save all the data corrected
        print('Saving corrected results... \n ')
        print('This might take more than a few minutes... \n')

        for part in np.arange(0, self.n_parts):
            if part==0:
                print('Sea... \n')
                Hsea    = create_vec_direc(self.hind_to_corr['Hsea'],
                                           self.hind_to_corr['Dirsea'])
                Hsea_corr_mat  = paramss[:,0:16] * Hsea**2
                Hsea_corr      = np.sqrt(np.sum(Hsea_corr_mat, axis=1))
                Hs_ncorr_sea   = Hsea**2
                index_hsea     = np.where(self.hindcast.columns.values=='Hsea')[0][0]
                print('\n')
            else:
                print('Swell:' + str(part) + '\n')
                globals()['Hswell%s' % part] = create_vec_direc(
                    self.hind_to_corr['Hswell'+str(part)],self.hind_to_corr['Dirswell'+str(part)])
                globals()['Hswell%s_corr_mat' % part] = paramss[:, 16:32] * globals()['Hswell'+str(part)]**2
                globals()['Hswell%s_corr' % part] = np.sqrt(np.sum(globals()['Hswell%s_corr_mat' % part], axis=1))
                # globals()['index_hswell%s' % part] = np.where(self.hindcast.columns.values==globals()['Hswell%s' % part])[0][0]
                globals()['index_hswell%s' % part] = np.where(self.hindcast.columns.values==['Hswell'+str(part)])[0][0]
                if part==1:
                    Hs_ncorr_swell = globals()['Hswell%s' % part]**2
                else:
                    Hs_ncorr_swell = Hs_ncorr_swell + globals()['Hswell%s' % part]**2
        # print(np.shape(Hs_ncorr_sea))
        # print(np.shape(Hs_ncorr_swell))

        Hs_ncorr_mat = np.concatenate((Hs_ncorr_sea, Hs_ncorr_swell), axis=1)
        Hs_ncorr         = np.sqrt(np.sum(Hs_ncorr_mat, axis=1))
        Hs_corr_mat      = paramss * Hs_ncorr_mat
        Hs_corr          = np.sqrt(np.sum(Hs_corr_mat, axis=1))
        index_hs      = np.where(self.hindcast.columns.values=='Hs')[0][0]
        index_hs_cal  = np.where(self.hindcast.columns.values=='Hs_cal')[0][0]

        if calibration_type=='satellite':
            self.hindcast_sat_corr.iloc[self.possible_to_correct, index_hs] = Hs_corr
            self.hindcast_sat_corr.iloc[self.possible_to_correct, index_hsea] = Hsea_corr
            for part in np.arange(1, self.n_parts):
                self.hindcast_sat_corr.iloc[self.possible_to_correct, globals()['index_hswell%s' % part]] = globals()['Hswell%s_corr' % part]
            self.hindcast_sat_corr.iloc[self.possible_to_correct, index_hs_cal] = Hs_corr

        else:
            self.hindcast_buoy_corr.iloc[self.possible_to_correct, index_hs] = Hs_corr
            self.hindcast_buoy_corr.iloc[self.possible_to_correct, index_hsea] = Hsea_corr
            for part in np.arange(1, self.n_parts):
                self.hindcast_buoy_corr.iloc[self.possible_to_correct, globals()['index_hswell%s' % part]] = globals()['Hswell%s_corr' % part]
            self.hindcast_buoy_corr.iloc[self.possible_to_correct, index_hs_cal] = Hs_corr
        print(' \n  \n ')

        # return
        return (params)

    def satellite_values(self, ini_lat, end_lat, ini_lon, end_lon):
        """ Performs the time calibration step that allows us to perform the
            calibration between the hindcast and the satellite data
            ------------
            Parameters
            Lats and lons to generate the box with the satellite data that
            will be used, previously selected by input
            ------------
            Returns
            Significant wave height for the satellite and a reduced dataframe
            for the hindcast data
        """

        # SATELLITE
        print('Selecting the satellite data choosed... \n ')

        self.satellite = self.satellite.isel(TIME=np.where(
            self.satellite.LATITUDE.values > ini_lat)[0])
        self.satellite = self.satellite.isel(TIME=np.where(
            self.satellite.LATITUDE.values < end_lat)[0])
        self.satellite = self.satellite.isel(TIME=np.where(
            self.satellite.LONGITUDE.values > ini_lon)[0])
        self.satellite = self.satellite.isel(TIME=np.where(
            self.satellite.LONGITUDE.values < end_lon)[0])

        print('Satellite length: ' + str(len(self.satellite.TIME.values)))

        # HINDCAST
        print('Hindcast information able to calibrate: ' + \
              str(len(self.hind_to_corr)) + ' \n ')

        # We perform the calibration
        print('Choose the way to calibrate the data: ')
        type_calib_way = bool(input('True (not recomended): hindcast for each satellite \n' +
                                    'False (empty box): satellite for each hindcast \n' +
                                    '----- Select ----- : '))
        print(' \n ')

        print('Performing the time calibration... \n ')
        times_sat, times_hind = calibration_time(self.satellite.TIME.values,
                                                 self.hind_to_corr.index.values,
                                                 sh = type_calib_way)
        sat_times = self.satellite.sel(TIME=times_sat)

        # All the necessary Satellite data (Quality)
        wave_height_qlt = np.nansum(np.concatenate((sat_times['SWH_KU_quality_control'].\
                                                    values[:, np.newaxis],
                                                    sat_times['SWH_KA_quality_control'].\
                                                    values[:, np.newaxis]),
                                                    axis = 1),
                                    axis = 1)
        good_qlt = np.where(wave_height_qlt < 1.5)
        # All necessary Satellite data (Heights)
        wave_height_cal = np.nansum(np.concatenate((sat_times['SWH_KU_CAL'].\
                                                    values[:, np.newaxis],
                                                    sat_times['SWH_KA_CAL'].\
                                                    values[:, np.newaxis]),
                                                    axis = 1),
                                    axis = 1)
        wave_height_cal = wave_height_cal[good_qlt]

        calibration = self.hind_to_corr.loc[times_hind].iloc[good_qlt]

        print('Length of data to calibrate: ' + str(len(calibration)) + ' \n ')

        return wave_height_cal, calibration

    def density_scatter(self, x, y):
        xy = np.vstack([x, y])
        z = gaussian_kde(xy)(xy)
        idx = z.argsort()
        x1, y1, z = x[idx], y[idx], z[idx]

        return(x1, y1, z)

    def validation_scatter(self, axs, x, y, xlabel, ylabel, title):

        x2, y2, z = self.density_scatter(x, y)

        # plot
        axs.scatter(x2, y2, c=z, s=5, cmap='rainbow')

        # labels
        axs.set_xlabel(xlabel)
        axs.set_ylabel(ylabel)
        axs.set_title(title)

        # axis limits
        maxt = np.ceil(max(max(x)+0.1, max(y)+0.1))
        axs.set_xlim(0, maxt)
        axs.set_ylim(0, maxt)
        axs.plot([0, maxt], [0, maxt], '-r')
        axs.set_xticks(np.linspace(0, maxt, 5))
        axs.set_yticks(np.linspace(0, maxt, 5))
        axs.set_aspect('equal')

        # qq-plot
        xq = stats.probplot(x, dist="norm")
        yq = stats.probplot(y, dist="norm")
        axs.plot(xq[0][1], yq[0][1], "o", markersize=0.5,
                      color='k', label='Q-Q plot')

        # diagnostic errors
        props = dict(boxstyle='round', facecolor='w', edgecolor='grey', linewidth=0.8, alpha=0.5)
        mse = mean_squared_error(x2, y2)
        rmse_e = rmse(x2, y2)
        BIAS = bias(x2, y2)
        SI = si(x2, y2)
        label = '\n'.join((
                r'RMSE = %.2f' % (rmse_e, ),
                r'mse =  %.2f' % (mse,  ),
                r'BIAS = %.2f' % (BIAS,  ),
                R'SI = %.2f' % (SI,  )))
        axs.text(0.05, 0.95, label, transform=axs.transAxes, fontsize=9,
        verticalalignment='top', bbox=props)

    def calibration_plots(self, xx1, xx2, hs, data, coefs, big_title):
        """ Plots differnet graphs for the calibration of hindcast data with
            buoy and satellite information. Plots are explained by their own
            ------------
            Parameters
            xx1: No corrected data
            xx2: Corrected data
            hs: Satellite / Buoy data that has been used to calibrate
            data: Dataframe with more hindcast information
            coefs: Parameters calculated in the calibration
            big_title: Can be 'Buoy' or 'Satellite'
            ------------
            Returns
            Different auto explicative plots
        """

        num='1'

        fig, axs = plt.subplots(2, 3, figsize=(15,8), constrained_layout=True)
        fig.subplots_adjust(hspace=0.4, wspace=0.1)
        fig.suptitle('CSIRO hindcast calibration with ' +
                     big_title + ' data', y=0.99,
                     fontsize=12, fontweight='bold')

        for i in range(2):
            for j in range(3):
                if (i==j==0 or i==1 and j==0):
                    if i==0:
                        x, y = hs, xx1
                        title = 'Not corrected, $H_{s}$ (m)'
                    else:
                        x, y = hs, xx2
                        title = 'Corrected, $H_{s}$ (m)'

                    self.validation_scatter(axs[i,j], x, y, big_title, 'Hindcast', title)

                elif (i==0 and j==1 or i==0 and j==2):
                    if j==1:
                        dataj1 = data[['Dirsea', \
                                       'Hsea']].\
                                       dropna(axis=0, how='any')
                        x, y = dataj1['Dirsea'], \
                               dataj1['Hsea']
                        index = 2
                        title = 'SEA $Wave$ $Climate$'
                    else:
                        dataj2 = data[['Dirswell'+num, \
                                       'Hswell'+num]].\
                                       dropna(axis=0, how='any')
                        x, y = dataj2['Dirswell'+num], \
                               dataj2['Hswell'+num]
                        index = 3
                        title = 'SWELL {0} $Wave$ $Climate$'.format(num)

                    x = (x*np.pi)/180
                    axs[i,j].axis('off')
                    axs[i,j] = fig.add_subplot(2, 3, index, projection='polar')
                    x2, y2, z = self.density_scatter(x, y)
                    axs[i,j].scatter(x2, y2, c=z, s=3, cmap='jet')
                    axs[i,j].set_theta_zero_location('N', offset=0)
                    axs[i,j].set_xticklabels(['N', 'NE', 'E','SE',
                                              'S', 'SW', 'W', 'NW'])
                    axs[i,j].xaxis.grid(True, color='lavender',linestyle='-')
                    axs[i,j].yaxis.grid(True, color='lavender',linestyle='-')
                    #axs[i,j].xaxis.set_tick_params(labelsize=20)
                    axs[i,j].set_theta_direction(-1)
                    axs[i,j].set_xlabel('$\u03B8_{m}$ ($\degree$)')
                    axs[i,j].set_ylabel('$H_{s}$ (m)', labelpad=20)
                    axs[i,j].set_title(title, pad=15, fontweight='bold')

                else:
                    if (j==1):
                        color_vals = coefs[0:16]
                        title = 'SEA $Correction$'
                    else:
                        color_vals = coefs[16:32]
                        title = 'SWELL 1 $Correction$'

                    norm = 0.3
                    fracs = np.repeat(10, 16)
                    my_norm = mpl.colors.Normalize(1-norm, 1+norm)
                    my_cmap = mpl.cm.get_cmap('bwr', len(color_vals))
                    axs[i,j].pie(fracs, labels=None,
                                 colors=my_cmap(my_norm(color_vals)),
                                 startangle=90, counterclock=False, radius=1.2)
                    axs[i,j].set_title(title, fontweight='bold')#fontsize=12, ,

                    if j==2:
                        ax1_divider = make_axes_locatable(axs[i,j])
                        cax1 = ax1_divider.append_axes("right", size="7%", pad="2%")
                        cb = mpl.colorbar.ColorbarBase(cax1, cmap=my_cmap,
                                                       norm=my_norm)
                        cb.set_label('Correction Coefficients')
                        cb.outline.set_color('white')

        # show results
        plt.show()

    def buoy_comparison(self, comparison_type, buoy_name='Buoy NAME'):
        """ Compares data with buoy, even if it's been corrected or not
            ------------
            Parameters
            comparison_type: Type of comparison to be done
                             (raw, sat_corr, buoy_corr)
            ------------
            Returns
            Different auto explicative plots
        """

        # Initialize the data to compare
        if comparison_type=='raw':
            comparison = pd.concat([self.buoy, self.hindcast], axis=1)
        elif comparison_type=='sat_corr':
            comparison = pd.concat([self.buoy, self.hindcast_sat_corr], axis=1)
        elif comparison_type=='buoy_corr':
            comparison = pd.concat([self.buoy, self.hindcast_buoy_corr], axis=1)
        else:
            return 'Not a valid value for comparison_type'

        print('--------------------------------------------------------')
        print(comparison_type.upper() + ' comparison will be performed')
        print('-------------------------------------------------------- \n ')

        comparison = comparison[['Hs_Buoy', 'Tp_Buoy', 'Dir_Buoy',
                                 'Hs', 'Tp', 'DirM']]

        # Perform the comparison
        n = int(input('Number of years: '))
        years = list(map(int, input('Years separated by one space: ')\
                         .strip().split()))[:n]
        # years = [2006, 2007, 2008]

        print(' \n ')
        print('Comparing data... \n ')

        for year in years:
            year_plot = comparison.copy()
            ini = str(year)+'-01-01 00:00:00'
            end = str(year)+'-12-31 23:00:00'
            year_plot = year_plot.loc[ini:end]
            fig, axs = plt.subplots(3, 1, figsize=(20,15), sharex=True)
            fig.subplots_adjust(hspace=0.05, wspace=0.1)
            fig.suptitle('Year: ' + str(year) +
                         ', ' + buoy_name + ' buoy comparison with ' +
                         comparison_type.upper()+ ' CSIRO',
                         fontsize=24, y=0.94, fontweight='bold')
            months = ['                        Jan',
                      '                        Feb',
                      '                        Mar',
                      '                        Apr',
                      '                        May',
                      '                        Jun',
                      '                        Jul',
                      '                        Aug',
                      '                        Sep',
                      '                        Oct',
                      '                        Nov',
                      '                        Dec']
            labels = ['$H_S$ [m]', '$T_P$ [s]', '$\u03B8_{m}$ [$\degree$]']

            i = 0
            while i < 3:
                if i==2:
                    axs[i].plot(year_plot[year_plot.columns.values[i]], '.',
                                markersize=1, color='darkblue')
                    axs[i].plot(year_plot[year_plot.columns.values[i+3]], '.',
                                markersize=1, color='red')
                    axs[i].set_ylabel(labels[i], fontsize=12, fontweight='bold')
                    axs[i].grid()
                    axs[i].set_xlim(ini, end)
                    axs[i].set_xticks(np.arange(pd.to_datetime(ini),
                                                pd.to_datetime(end),
                                                td(days=30.5)))
                    axs[i].tick_params(direction='in')
                    axs[i].set_xticklabels(months, fontsize=12,
                                           fontweight='bold')
                else:
                    axs[i].plot(year_plot[year_plot.columns.values[i]],
                                color='darkblue', linewidth=1)
                    axs[i].plot(year_plot[year_plot.columns.values[i+3]],
                                color='red', linewidth=1)
                    axs[i].set_ylabel(labels[i], fontsize=12,
                                      fontweight='bold')
                    axs[i].grid()
                    axs[i].tick_params(direction='in')
                fig.legend(['Buoy', 'Modelo'], loc=(0.66, 0.04), ncol=3,
                           fontsize=14)
                i += 1

        # show results
        plt.show()

    def buoy_validation(self, validation_type, buoy_name='Buoy NAME'):
        """ Validate data with buoy, even if it's been corrected or not
            ------------
            Parameters
            validation_type: Type of comparison to be done
                             (raw, sat_corr, buoy_corr)
            ------------
            Returns
            Different auto explicative plots
        """

        # Initialize the data to validate
        if validation_type=='raw':
            validation = pd.concat([self.buoy, self.hindcast], axis=1)
            title = 'No previous correction'
        elif validation_type=='sat_corr':
            validation = pd.concat([self.buoy, self.hindcast_sat_corr], axis=1)
            title = 'Previosly corrected with satellite data'
        elif validation_type=='buoy_corr':
            validation = pd.concat([self.buoy, self.hindcast_buoy_corr], axis=1)
            title = 'Previosly corrected with buoy data'
        else:
            return 'Not a valid value for validation_type'

        print('--------------------------------------------------------')
        print(validation_type.upper() + ' VALIDATION will be performed')
        print('-------------------------------------------------------- \n ')

        validation = validation[['Hs_Buoy', 'Tp_Buoy', 'Dir_Buoy',
                                 'Hs', 'Tp', 'DirM']]
        validation = validation.dropna(axis=0, how='any')

        print('Validating and plotting validated data... \n ')
        print('Length of data to validate: ' + str(len(validation)) + ' \n ')

        fig, axs = plt.subplots(2, 3, figsize=(20,20))
        fig.subplots_adjust(hspace=0.2, wspace=0.2)
        fig.suptitle('Hindcast: CSIRO' +
                     ', ' + buoy_name + ' buoy validation \n ' +title,
                     fontsize=24, y=0.98, fontweight='bold')

        for i in range(2):
            for j in range(3):
                if (i==j==0 or i==1 and j==0):
                    if i==0:
                        x, y = validation['Hs_Buoy'], \
                               validation['Hs']
                        title = '$H_S$ [m]'
                    else:
                        x, y = validation['Tp_Buoy'], \
                               validation['Tp']
                        title = '$T_P$ [s]'

                    xy = np.vstack([x, y])
                    z = gaussian_kde(xy)(xy)
                    idx = z.argsort()
                    x2, y2, z = x[idx], y[idx], z[idx]
                    axs[i,j].scatter(x2, y2, c=z, s=1, cmap=cmocean.cm.haline)
                    axs[i,j].set_xlabel('Buoy', fontsize=12,
                                        fontweight='bold')
                    axs[i,j].set_ylabel('Model', fontsize=12,
                                        fontweight='bold')
                    axs[i,j].set_title(title, fontsize=12,
                                       fontweight='bold')
                    maxt = np.ceil(max(max(x)+0.1, max(y)+0.1))
                    axs[i,j].set_xlim(0, maxt)
                    axs[i,j].set_ylim(0, maxt)
                    axs[i,j].plot([0, maxt], [0, maxt], '-k', linewidth=0.6)
                    axs[i,j].set_xticks(np.linspace(0, maxt, 5))
                    axs[i,j].set_yticks(np.linspace(0, maxt, 5))
                    axs[i,j].set_aspect('equal')
                    xq = stats.probplot(x2, dist="norm")
                    yq = stats.probplot(y2, dist="norm")
                    axs[i,j].plot(xq[0][1], yq[0][1], "o", markersize=1,
                                  color='k', label='Q-Q plot')
                    mse = mean_squared_error(x2, y2)
                    rmse_e = rmse(x2, y2)
                    BIAS = bias(x2, y2)
                    SI = si(x2, y2)
                    label = '\n'.join((
                            r'RMSE = %.2f' % (rmse_e, ),
                            r'mse =  %.2f' % (mse,  ),
                            r'BIAS = %.2f' % (BIAS,  ),
                            R'SI = %.2f' % (SI,  )))
                    axs[i,j].text(0.7, 0.05, label,
                                  transform=axs[i,j].transAxes)

                elif (i==0 and j==1 or i==0 and j==2):
                    idx_buoy = validation['Tp_Buoy'].argsort()
                    idx_hind = validation['Tp'].argsort()
                    if j==1:
                        x, y = validation['Dir_Buoy'][idx_buoy], \
                               validation['Hs_Buoy'][idx_buoy]
                        index = 2
                        c = validation['Tp_Buoy'][idx_buoy]
                        title = 'Boya'
                    else:
                        x, y = validation['DirM'][idx_hind], \
                               validation['Hs'][idx_hind]
                        index = 3
                        c = validation['Tp'][idx_hind]
                        title = 'Modelo'
                    x = (x*np.pi)/180
                    axs[i,j].axis('off')
                    axs[i,j] = fig.add_subplot(2, 3, index, projection='polar')
                    c = axs[i,j].scatter(x, y, c=c, s=5, cmap='magma_r',
                                         alpha=0.75)
                    cbar = plt.colorbar(c, pad=0.1)
                    cbar.ax.set_ylabel('$T_P$ [s]', fontsize=12,
                                       fontweight='bold')
                    axs[i,j].set_theta_zero_location('N', offset=0)
                    axs[i,j].set_xticklabels(['N', 'NE', 'E','SE',
                                              'S', 'SW', 'W', 'NW'])
                    axs[i,j].set_theta_direction(-1)
                    axs[i,j].set_xlabel('$\u03B8_{m}$ [$\degree$]', fontsize=12,
                                        fontweight='bold')
                    axs[i,j].set_ylabel('$H_S$ [m]', labelpad=20, fontsize=12,
                                        fontweight='bold')
                    axs[i,j].set_title(title, pad=15, fontsize=12,
                                       fontweight='bold')

                else:
                    if j==1:
                        x, y = validation['Tp_Buoy'], \
                               validation['Hs_Buoy']
                        c = 'darkblue'
                        title = 'Boya'
                    else:
                        x, y = validation['Tp'], \
                               validation['Hs']
                        c = 'red'
                        title = 'Modelo'
                    xy = np.vstack([x, y])
                    z = gaussian_kde(xy)(xy)
                    idx = z.argsort()
                    x2, y2, z = x[idx], y[idx], z[idx]
                    axs[i,j].scatter(x2, y2, c=z, s=3, cmap='Blues_r')
                    axs[i,j].set_xlabel('$T_P$ [s]', fontsize=12,
                                        fontweight='bold')
                    axs[i,j].set_ylabel('$H_S$ [m]', fontsize=12,
                                        fontweight='bold')
                    axs[i,j].set_title(title, fontsize=12,
                                       fontweight='bold')
                    axs[i,j].set_xlim(0, 20)
                    axs[i,j].set_ylim(0, 7.5)

        # show results
        plt.show()


# 取消任务

import schedule

i = 0

def some_task():
    global i
    i += 1
    print(i)
    if i == 10:
        schedule.cancel_job(job)
        print('cancel job')
        exit(0)

job = schedule.every().second.do(some_task)
while True:
    schedule.run_pending()


import torch
from src.VAE import *
from src.filter_bank import *

class ISVAE(nn.Module):
    def __init__(self, x_dim, z_dim, number_f, filter_w, psd, version):
        super(ISVAE, self).__init__()

        self.number_f = number_f
        self.filter_w = filter_w
        self.x_dim = x_dim
        self.z_dim = z_dim
        self.psd = psd
        self.version = version

        self.filter_bank = FB(number_f, x_dim, filter_w)
        self.vae = VAE(x_dim, z_dim, number_f, filter_w, psd, version)

    def forward(self, x):
        H_list, x_filtered_list, x_filtered_sum_list, f_0_list = self.filter_bank(x)

        f_0_torch = torch.cat(tuple(f_0_list),1)
        f_axis = torch.arange(x_filtered_list[0].shape[1])
        f_axis = f_axis.unsqueeze(0).repeat(x_filtered_list[0].shape[0], 1)

        aux = 0

        for f in range(self.number_f):
            if len(list(f_0_list[0].shape)) == 1:
                f_0_list[f] = f_0_list[f].unsqueeze(1)
            aux = aux + x* torch.exp(-0.5*((f_axis-f_0_list[f].repeat((1, x_filtered_list[0].shape[1])))**2/self.filter_w))
        new_x =aux

        if self.version == 2:
            z_mean, z_sigma, z, x_rec, f_0_rec = self.vae(f_0_torch,x)
            return new_x, x_rec, z_mean, z_sigma, z, H_list, x_filtered_list, x_filtered_sum_list, f_0_list, f_0_rec
        else:
            z_mean, z_sigma, z, x_rec = self.vae(f_0_torch, x)
            return new_x, x_rec, z_mean, z_sigma, z, H_list, x_filtered_list, x_filtered_sum_list, f_0_list


from typing import Any

import database
import models
import repos.queries

def one_of(**params) -> models.Question | None:
    """
    Get models.Question object from database by "specifiers" params

    Arguments:
        **params: specifiers, if it needs to perform data filtering
    """
    specifiers = " ".join(params.keys())
    table_fields = [
        field for field in vars(models.Question).get("__annotations__")
        if not field.startswith("_")
    ]
    query = repos.queries.select_query(
        table_name=models.Question._table_name,
        table_fields=table_fields,
        specifiers=specifiers,
    )
    with database.Connection() as db:
        if params.values():
            param_list = [p for p in params.values()]
            question_record = db.connection.execute(query, param_list).fetchone()
        else:
            question_record = db.connection.execute(query).fetchone()
    if not question_record:
        return None
    return models.Question.from_dict(question_record)

def all_of(**params) -> list[models.Question]:
    """
    Get models.Question objects from database by "specifiers" params

    Arguments:
        **params: specifiers, if it needs to perform data filtering
    """
    specifiers = " ".join(params.keys())
    table_fields = [
        field for field in vars(models.Question).get("__annotations__")
        if not field.startswith("_")
    ]
    query = repos.queries.select_query(
        table_name=models.Question._table_name,
        table_fields=table_fields,
        specifiers=specifiers,
    )
    with database.Connection() as db:
        if params.values():
            param_list = [p for p in params.values()]
            question_records = db.connection.execute(query, param_list).fetchall()
        else:
            question_records = db.connection.execute(query).fetchall()
    return [models.Question.from_dict(record) for record in question_records]

def new(
    question: str,
    asking_user: models.User | None = None,
    asking_user_id: int | None = None,
    expert: models.User | None = None,
    expert_id: int | None = None,
    answer: str | None = None,
) -> models.Question:
    """
    Creates and returns new question

    Arguments:
        question: text of question
        asking_user: user asking. Excludes asking_user_id
        asking_user_id: user's asking. Excludes asking_user
        expert: answering user. Excludes expert_id
        expert_id: answering user. Excludes expert
        answer: text of answer
    """
    if not (asking_user or asking_user_id):
        raise ValueError("Neither 'asking_user' was provided, nor 'asking_user_id'")
    if not (expert or expert_id):
        raise ValueError("Neither 'expert' was provided, nor 'expert_id'")

    table_fields = [
        field for field in vars(models.Question).get("__annotations__")
        if not field.startswith("_") and not field == "id"
    ]
    query = repos.queries.insert_query(
        table_name=models.Question._table_name,
        table_fields=table_fields,
    )
    asking_user_id = asking_user_id or asking_user.id
    expert_id = expert_id or expert.id
    with database.Connection() as db:
        db.cursor.execute(query, [question, asking_user_id, expert_id, answer])
        db.connection.commit()
        new_question_id = db.cursor.lastrowid
    return models.Question(
        id=new_question_id,
        question=question,
        asking_user_id=asking_user_id,
        expert_id=expert_id,
        answer=answer,
    )

def change(
    updating_data: dict[str, Any],
    question: models.Question | None = None,
    **where_params,
) -> None:
    """
    Updates users of provided users of by where_params

    Arguments
        updating_data: dictionary with field and val to update
        question: if you have Question object, and you need to
                change it, you can pass this obj with this arg
        **where_params: WHERE conditions
    """
    table_fields = [
        field for field in vars(models.Question).get("__annotations__")
        if not field.startswith("_")
    ]
    specifiers = None
    params = None
    if question:
        specifiers = "id"
        params = [question.id]
    elif where_params:
        specifiers = " ".join(where_params.keys())
        params = [val for val in where_params.values()]
    query = repos.queries.update_query(
        table_name=models.Question._table_name,
        table_fields=table_fields,
        updating_data=updating_data,
        specifiers=specifiers
    )
    with database.Connection() as db:
        if specifiers:
            db.cursor.execute(query, params)
        else:
            db.cursor.execute(query)
        db.connection.commit()

def all_unanswered_questions(expert_id: int) -> list[models.Question]:
    query = "SELECT * FROM questions WHERE expert_id = ? AND answer IS NULL;"
    with database.Connection() as db:
        questions = db.cursor.execute(query, [expert_id]).fetchall()
    return [models.Question.from_dict(question) for question in questions]

def all_answered_questions() -> list[models.Question]:
    query = "SELECT * FROM questions WHERE answer IS NOT NULL;"
    with database.Connection() as db:
        questions = db.cursor.execute(query).fetchall()
    return [models.Question.from_dict(question) for question in questions]


import argparse
import os
import copy
import logging

import torch
from torch.distributed.distributed_c10d import _get_default_group
from torch.distributed.utils import _sync_module_states

from torchvision.models import resnet18

from pippy.IR import Pipe
from pippy import split_into_equal_size

from easydist import easydist_setup, mdconfig
from easydist.torch.api import easydist_compile
from easydist.torch import set_device_mesh
from easydist.utils.testing import TorchMockDeviceMesh

def broadcast_module(model):
    _sync_module_states(model,
                        _get_default_group(),
                        broadcast_bucket_size=int(250 * 1024 * 1024),
                        src=0,
                        params_and_buffers_to_ignore=set())
    return model

def train_submodule(train_step, name, module, *prev_mod_input):
    with torch.device('cuda'):
        opt = torch.optim.Adam(module.parameters(),
                               lr=0.001, foreach=True, capturable=True)
        module_2 = copy.deepcopy(module)
        opt_2 = torch.optim.Adam(
            module_2.parameters(), lr=0.001, foreach=True, capturable=True)

        torch_step_1_result = train_step.original_func(
            module, opt, *prev_mod_input)
        torch_step_2_result = train_step.original_func(
            module, opt, *prev_mod_input)

    md_step_1_result = train_step(module_2, opt_2, *prev_mod_input)
    md_step_2_result = train_step(module_2, opt_2, *prev_mod_input)

    warp_fn = lambda item: [item] if isinstance(item, torch.Tensor) else item
    local_rank = int(os.environ["LOCAL_RANK"])
    for i, (torch_res, md_res) in enumerate(zip(warp_fn(torch_step_1_result), warp_fn(md_step_1_result))):
        # assert torch.allclose(torch_res, md_res), f"{name} training test step 1 failed."
        if not torch.allclose(torch_res, md_res):
            print(
                '\033[31m'
                f'rank {local_rank} {name} step 1 {i}-th output failed.'
                f'\n\tabs sum: {torch.sum(torch.abs(torch_res - md_res))}'
                '\033[0m'
                )

    for i, (torch_res, md_res) in enumerate(zip(warp_fn(torch_step_2_result), warp_fn(md_step_2_result))):
        # assert torch.allclose(torch_res, md_res), f"{name} training test step 2 failed."
        if not torch.allclose(torch_res, md_res):
            print(
                '\033[31m'
                f'rank {local_rank} {name} step 2 {i}-th output failed.'
                f'\n\tabs sum: {torch.sum(torch.abs(torch_res - md_res))}'
                '\033[0m'
                )

    return torch_step_2_result

@easydist_compile(tracing_mode="fake", cuda_graph=False)
def train_step_submod0(model, opt, *input):
    out = model(*input)
    _out = out[0].mean() + out[1].mean()
    _out.backward()
    opt.step()
    opt.zero_grad(True)
    return out

@easydist_compile(tracing_mode="fake", cuda_graph=False)
def train_step_submod1(model, opt, *input):
    out = model(*input)
    _out = out.mean()
    _out.backward()
    opt.step()
    opt.zero_grad(True)
    return out

def train_example():
    world_size = int(os.environ["WORLD_SIZE"])
    local_rank = int(os.environ["LOCAL_RANK"])
    model = resnet18().cuda()
    model.train()
    # broadcast the parameter and input
    model = broadcast_module(model)

    split_policy = split_into_equal_size(world_size)
    pipe = Pipe.from_tracing(model, split_policy=split_policy).cuda()

    input = [torch.randn(16, 3, 224, 224).cuda()]
    torch.distributed.broadcast(input[0], src=0)
    input = train_submodule(train_step_submod0, "submod_0", pipe.split_gm.submod_0, *input)

    input = [t.detach() for t in input]
    train_submodule(train_step_submod1, "submod_1", pipe.split_gm.submod_1, *input)

    print(f"rank {local_rank} training test finished.")

def inference_example():
    raise NotImplementedError()

def main():
    parser = argparse.ArgumentParser(
        description="Simple example of parallelize model.")
    parser.add_argument("--mode",
                        type=str,
                        default=None,
                        choices=["train", "inference"],
                        required=True)
    args = parser.parse_args()

    mdconfig.log_level = logging.ERROR
    easydist_setup(backend="torch", device="cuda", allow_tf32=False)
    world_size = int(os.environ["WORLD_SIZE"])
    assert world_size == 2, "This example only support 2 GPUs."
    mock_mesh = TorchMockDeviceMesh(1, 2, debug_only=True)
    set_device_mesh(mock_mesh)

    torch.distributed.init_process_group(backend="nccl")
    local_rank = int(os.environ["LOCAL_RANK"])
    torch.cuda.set_device(local_rank)

    if args.mode == "train":
        train_example()
    else:
        inference_example()

if __name__ == "__main__":
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    main()


from slithy.library import *

fontpath.append( '.' )
fontpath.append( '/Users/cog/Documents/Homework/PHYS576' )

add_extra_characters( u'\u201c\u201d' )

create_slithy_fonts( ('times.ttf', 50, 'times.slf'),
                     ('ehrhardt.pfb', 50, 'ehrhardt.slf'),
                     ('mob.pfb', 50, 'minion.slf'),
                     ('mobi.pfb', 50, 'minion_i.slf'),
                     )

fonts = { 'times' : search_font( 'times.slf' ),
          'ehrhardt' : search_font( 'ehrhardt.slf' ),
          'body' : search_font( 'minion.slf' ),
          'bodyi' : search_font( 'minion_i.slf' ),
          }

imagepath.append( '.' )


import re

batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
mo = batRegex.search('Batmobile lost a wheel')
mo.group()
# 'Batmobile'
mo = batRegex.search('Batmotorcycle lost a wheel')
# mo = None

#Groups are created in regular expressions with parentheses
#The first group is group 1, the second group is group 2, and so on.
#The | character is called a pipe. You can use it anywhere you want to match one of many expressions.
#The (Batman|Tina Fey) part of the regular expression is called a group.
#When a regular expression has groups, the findall() method returns a list of tuples.
#Each tuple represents a found match, and its items are the matched strings for each group in the regex.