import pymysql  as sql
import common as c

def sql_conn():
	db = sql.connect("localhost","root","","stocki")
	return db

def sql_array(qry,key):
    ret_arr = []
    db_obj  = sql_conn()
    cursor  = db_obj.cursor(sql.cursors.DictCursor)
    try:
        cursor.execute(qry)
        results = cursor.fetchall()
        for row in results:
            if key in row:
                ret_arr.append(row[key])
    except (sql.Error, sql.Warning) as e:
        print("-E- Query Failed")
        print(e)
        db_obj.rollback()
    cursor.close()
    return ret_arr

def sql_insert(table,keys,data,limit):
    c.pr("I","Initiating Insert Operation On Table -> "+table+" Query Limit -> "+str(limit)+" Columns -> "+str(len(data)),0)
    ctr = 0
    dap = ""
    for clm in data:
        if ctr == limit:
            dap = dap[1:]
            qry = "INSERT INTO `"+table+"` ("+keys+") VALUES "+dap
            execQuery(qry)
            dap = ""
            ctr = 0
        ctr = ctr + 1
        dap = dap+","+clm
    if ctr > 1:
        dap = dap[1:]
        qry = "INSERT INTO `"+table+"` ("+keys+") VALUES "+dap
        execQuery(qry)
    return

def sql_hash(table,key,cols,whr):
    query = ""
    ret   = {}
    vals  = cols.split(":")
    col   = key+","+",".join(vals)
    query = "SELECT "+col+" FROM `"+table+"` "+whr
    #c.pr("S",query,1)
    db_obj  = sql_conn()
    cursor  = db_obj.cursor()
    try:
        cursor.execute(query)
        results = cursor.fetchall()
        for row in results:
            k       = row[0]
            ct      = 1
            ret[k]  = {}
            for cl in vals:
                ret[k][cl] = row[ct]
                ct = ct + 1
    except (sql.Error, sql.Warning) as e:
        print("-E- Query Failed -> "+query)
        print(e)
        db_obj.rollback()
    cursor.close()
    del cursor
    db_obj.close()
    return ret

def rcnt(qry):
    db_obj  = sql_conn()
    cursor  = db_obj.cursor()
    rows    = 0
    try:
        cursor.execute(qry)
        rows = cursor.rowcount
    except (sql.Error, sql.Warning) as e:
        print("-E- Query Failed")
        print(e)
        db_obj.rollback()
    cursor.close()
    del cursor
    db_obj.close()
    return rows

def execQuery(qry):
    #c.pr("S","Executing Query "+qry,1)
    db_obj  = sql_conn()
    cursor  = db_obj.cursor()
    try:
        cursor.execute(qry)
        db_obj.commit()
    except (sql.Error, sql.Warning) as e:
        print("-E- Query Failed")
        print(e)
        db_obj.rollback()
    cursor.close()
    del cursor
    db_obj.close()
    return

def sql_single(qry):
    ret_str = ""
    db_obj  = sql_conn()
    cursor  = db_obj.cursor()
    try:
        cursor.execute(qry)
        results = cursor.fetchall()
        for row in results:
            ret_str = row[0]
    except (sql.Error, sql.Warning) as e:
        print("-E- Query Failed")
        print(e)
        db_obj.rollback()
    cursor.close()
    del cursor
    db_obj.close()
    return ret_str

def create_table(name,schema):
    c.pr("I","Creating Table "+name,1)
    var_map = {"FL" : "FLOAT" , "IN" : "INT(11)" , "DT": "DATETIME" ,"TS" : "TIMESTAMP" ,"VC" : "VARCHAR","TX":"TEXT"}
    query   = "CREATE TABLE `"+name+"` ("
    scharr  = schema.split(",")
    for sch in scharr:
        tmp = sch.split(":")
        col = tmp[0]
        dt  = tmp[1]
        if dt == "VC":
            size  = tmp[2]
            query = query+"`"+col+"` "+var_map[dt] + "("+size+") NOT NULL,"
        else:
            query = query+"`"+col+"` "+var_map[dt] + " NOT NULL,\n"
    query = query[0:-2]+")"

    qry = "SELECT * FROM information_schema.tables WHERE table_schema = 'stocki'  AND table_name = '"+name+"' LIMIT 1;"
    execQuery(query)
    if rcnt(qry):
        c.pr("I",str(name+" Table Created"),1)
        execQuery("UPDATE scrips SET status='YES' WHERE scrip='"+name+"'")
    else:
        c.pr("W",str(name+" Table Not Created"),1)
    cursor.close()
    del cursor
    db_obj.close()
    return


from ..common.basetrackservice import BaseTrackService, track_registry
import requests
from ..models.model import StatusChoice
import parsel

# from dateutil.parser import parse

def get_elem_text(el):
    sentence = ""
    if el:
        for word in el:
            s_word = word.strip()
            if s_word[0].isalpha():
                sentence = sentence + s_word + " "
        return sentence.strip()

@track_registry.register("rl-carriers")
class RLCarriers(BaseTrackService):
    def status_mapper(self, status):
        """
        docstring
        """
        if status.startswith("Picked Up"):
            return StatusChoice.InTransit.value
        elif status.startswith("Departed"):
            return StatusChoice.InTransit.value
        elif status.startswith("Accepted"):
            return StatusChoice.InTransit.value
        elif status.startswith("Arrived"):
            return StatusChoice.InTransit.value
        elif status.startswith("Out for Delivery"):
            return StatusChoice.OutForDelivery.value
        elif status.startswith("Delivered"):
            return StatusChoice.Delivered.value
        elif "Delivered" in status:
            return StatusChoice.Delivered.value
        else:
            return "Exception"

    def __init__(self, waybill, *args, **kwargs):
        super().__init__(waybill, "rl-carriers", *args, **kwargs)

    """
    This method will populate self.raw_data
    """

    def _fetch(self):
        self.raw_data = requests.post(
            " https://www.rlcarriers.com/freight/shipping/shipment-tracing?source=web",
            data={
                " https://www.rlcarriers.com/freight/shipping/shipment-tracing?source=web": self.waybill
            },
        ).text
        # print(self.raw_data, "####")

    """
    This method will convert self.raw_data to self.data
    """

    def _transform(self):
        selector = parsel.Selector(text=self.raw_data)
        sub_status = selector.xpath(
            '//*[@id="result-container"]/h4/span[3]/text()'
        ).get()
        print(sub_status)
        # sub_status = sub_status.strip() if sub_status else ''

        # soup= BeautifulSoup(self.raw_data, 'html.parser')
        # soup_data= soup.find('table').find_all('tr')

        # checkpoints = []
        # checkpoints_data= []
        # checkpoint_table = soup_data
        # for row in checkpoint_table:
        #     if row == []:
        #         continue
        #     cols= row.find_all('td')
        #     cols = [ele.text.strip() for ele in cols]
        #     cols = [ele for ele in cols if ele]
        #     if len(cols) != 3:
        #         continue
        #     checkpoints.append(self._transform_checkpoint(cols))
        #     checkpoints_data.append(cols)
        # delivered_date = None
        # delivered_time = None
        # if sub_status == 'Delivered':
        #     delivered_date= checkpoints_data[0][0].split(' at ')[0]
        #     delivered_time= checkpoints_data[0][0].split(' at ')[1]
        # data = {
        #     'waybill': self.waybill,
        #     'provider': self.provider,
        #     'status': self.status_mapper(sub_status),
        #     'substatus': sub_status,
        #     'estimated_date': '',
        #     'delivered_date' : delivered_date,
        #     'delivered_time' : delivered_time,
        #     'reference_no' : '',
        #     'destination' : '',
        #     'receiver_name': ''
        # }

        # data['checkpoints'] = checkpoints

        # self.data = data

    def _transform_checkpoint(self, scan):

        checkpoint = {
            "slug": self.provider,
            "location": scan[2],
            "country_name": "Unites States",
            "message": "",
            "submessage": "",
            "country_iso3": "US",
            "status": self.status_mapper(scan[1]),
            "substatus": scan[1],
            "checkpoint_time": scan[0],
            "state": None,
            "zip": None,
        }

        return checkpoint


import os
import pandas
import re
from urllib.request import urlopen
from urllib.parse import urlparse
from bs4 import BeautifulSoup
from nltk.stem.wordnet import WordNetLemmatizer

def parse_page(filename,page):

    soup = BeautifulSoup(urlopen(filename), 'html.parser')
    lmtzr = WordNetLemmatizer()

    keyword = soup.find('input',{'id':'lst-ib'}).get('value').lower()
    keyword_token = list(set([lmtzr.lemmatize(token) for token in keyword.split(' ')]))

    combined_result = []

    search_results = soup.find_all('div', {'class': 'g'})
    position = 0
    for search_result in search_results:

        ## Position of the search result in this page
        position += 1

        ## Title flag and keyword density in title
        title = search_result.find('div',{'class':'rc'}).find('h3',{'class':'r'}).get_text()
        title_token = re.sub('[^a-zA-Z0-9\'\.\n]+', ' ', title.lower()).split()
        title_token = [lmtzr.lemmatize(token) for token in title_token]

        title_flag_count = list(filter(lambda token:token in title_token, keyword_token))
        title_flag = 1 if len(title_flag_count) == len(keyword_token) else 0
        title_density_count = sum([keyword_token.count(token) for token in title_token])
        title_density = round(title_density_count / len(title_token),4)

        ## URL flag and keyword density in URL
        url = search_result.find('div',{'class':'rc'}).find('h3',{'class':'r'}).find('a').get('href')

        url_path_token = re.sub('[^a-zA-Z0-9\']+', ' ', urlparse(url).path).lower().split()
        url_path_token = [lmtzr.lemmatize(token) for token in url_path_token]
        url_netloc_token = re.sub('[^a-zA-Z0-9\']+', ' ', urlparse(url).netloc).lower().split()
        url_netloc_token = [lmtzr.lemmatize(token) for token in url_netloc_token]
        url_query_token = re.sub('[^a-zA-Z0-9\']+', ' ', urlparse(url).query).lower().split()
        url_query_token = [lmtzr.lemmatize(token) for token in url_query_token]
        url_flag_count = list(filter(lambda token:token in url_path_token+url_netloc_token+url_query_token,keyword_token))
        url_flag = 1 if len(url_flag_count) == len(keyword_token) else 0

        url_density_count = sum([keyword_token.count(token) for token in url_path_token+url_netloc_token+url_query_token])
        url_density = round(url_density_count / (len(url_path_token)+len(url_netloc_token)+len(url_query_token)) ,4)

        ## Meta description and keyword density in meta description
        meta = search_result.find('div',{'class':'rc'}).find('div',{'class':'s'}).find('span',{'class':'st'})
        meta_description = re.sub('[^a-zA-Z0-9\n\.\']+', ' ',meta.get_text().strip().lower())
        meta_token = [lmtzr.lemmatize(token) for token in meta_description.split()]
        meta_em =  ' '.join([x.get_text() for x in meta.find_all('em')]).split()
        meta_em_token = [lmtzr.lemmatize(token) for token in meta_em]

        meta_flag_count = list(filter(lambda token:token in meta_token,keyword_token))
        meta_flag = 1 if len(meta_flag_count) == len(keyword_token) else 0
        meta_density = round(len(meta_em_token) / len(meta_token), 4)

        ## Append the result to list
        combined_result.append([position,page,title,url,meta_description,title_flag,title_density,url_flag,url_density,meta_flag,meta_density])

    return combined_result

## The filepath where you store your downloaded HTML pages,please change accordingly
filepath = '/Users/apple/Google Drive/Study/NUS/SEM 7/BT4212/Assignment/Assignment 3/SEOtask_final_v2/Example'
all_files = os.listdir(filepath)
output = []
for index, page in enumerate(all_files):
    ## to skip the temp file generated on Mac
    if (page == '.DS_Store') or (".html" not in page):
        continue
    filename = 'file://127.0.0.1' + filepath + '/' + page
    result = parse_page(filename,page)
    output.extend(result)

df = pandas.DataFrame(output, columns =['Position','Filename','Title','URL','Meta','TitleFlag','TitleDensity','URLFlag','URLDensity','MetaFlag','MetaDensity'])
df.to_csv('output.csv',header = True, index = False,encoding = 'utf-8')

print('Output successfully generated!')


import process_data
import select_feature
import numpy as np
import pandas as pd
import pickle
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import  LogisticRegression
from sklearn.linear_model import SGDClassifier
from sklearn import svm
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold
from sklearn.metrics import confusion_matrix, f1_score, classification_report
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score

#string to test
doc_new = ['Trump is running for president in 2016']

#building classifier using naive bayes
nb_pipeline = Pipeline([
        ('NBCV',select_feature.countV),
        ('nb_clf',MultinomialNB())])

nb_pipeline.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_nb = nb_pipeline.predict(process_data.test_news['Statement'])
np.mean(predicted_nb == process_data.test_news['Label'])

#building classifier using logistic regression
logR_pipeline = Pipeline([
        ('LogRCV',select_feature.countV),
        ('LogR_clf',LogisticRegression(max_iter=10000))
        ])

logR_pipeline.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_LogR = logR_pipeline.predict(process_data.test_news['Statement'])
np.mean(predicted_LogR == process_data.test_news['Label'])

#building Linear SVM classfier
svm_pipeline = Pipeline([
        ('svmCV',select_feature.countV),
        ('svm_clf',svm.LinearSVC())
        ])

svm_pipeline.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_svm = svm_pipeline.predict(process_data.test_news['Statement'])
np.mean(predicted_svm == process_data.test_news['Label'])

#using SVM Stochastic Gradient Descent on hinge loss
sgd_pipeline = Pipeline([
        ('svm2CV',select_feature.countV),
        # ('svm2_clf',SGDClassifier(loss='hinge', penalty='l2', alpha=1e-3, n_iter=10))
        ('svm2_clf',SGDClassifier(loss='hinge', penalty='l2', alpha=1e-3))
        ])

sgd_pipeline.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_sgd = sgd_pipeline.predict(process_data.test_news['Statement'])
np.mean(predicted_sgd == process_data.test_news['Label'])

#random forest
random_forest = Pipeline([
        ('rfCV',select_feature.countV),
        ('rf_clf',RandomForestClassifier(n_estimators=200, n_jobs=3))
        ])

random_forest.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_rf = random_forest.predict(process_data.test_news['Statement'])
np.mean(predicted_rf == process_data.test_news['Label'])

#User defined functon for K-Fold cross validatoin
def create_confusion_matrix(classifier):

    k_fold = KFold(n_splits=5)
    scores = []
    confusion = np.array([[0,0],[0,0]])
    for train_ind, test_ind in k_fold.split(process_data.train_news):
        train_text = process_data.train_news.iloc[train_ind]['Statement']
        train_y = process_data.train_news.iloc[train_ind]['Label']

        test_text = process_data.train_news.iloc[test_ind]['Statement']
        test_y = process_data.train_news.iloc[test_ind]['Label']

        classifier.fit(train_text,train_y)
        predictions = classifier.predict(test_text)

        confusion += confusion_matrix(test_y,predictions)
        score = f1_score(test_y,predictions)
        scores.append(score)

    return (print('Total statements classified:', len(process_data.train_news)),
    print('Score:', sum(scores)/len(scores)),
    print('score length', len(scores)),
    print('Confusion matrix:'),
    print(confusion))

print('---------------------Bag of Words---------------------')
create_confusion_matrix(nb_pipeline)
create_confusion_matrix(logR_pipeline)
create_confusion_matrix(svm_pipeline)
create_confusion_matrix(sgd_pipeline)
create_confusion_matrix(random_forest)

#using n-grams
#naive-bayes classifier
nb_pipeline_ngram = Pipeline([
        ('nb_tfidf',select_feature.tfidf_ngram),
        ('nb_clf',MultinomialNB())])

nb_pipeline_ngram.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_nb_ngram = nb_pipeline_ngram.predict(process_data.test_news['Statement'])
np.mean(predicted_nb_ngram == process_data.test_news['Label'])

#logistic regression classifier
logR_pipeline_ngram = Pipeline([
        ('LogR_tfidf',select_feature.tfidf_ngram),
        ('LogR_clf',LogisticRegression(penalty="l2",C=1))
        ])

logR_pipeline_ngram.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_LogR_ngram = logR_pipeline_ngram.predict(process_data.test_news['Statement'])
np.mean(predicted_LogR_ngram == process_data.test_news['Label'])

#linear SVM classifier
svm_pipeline_ngram = Pipeline([
        ('svm_tfidf',select_feature.tfidf_ngram),
        ('svm_clf',svm.LinearSVC())
        ])

svm_pipeline_ngram.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_svm_ngram = svm_pipeline_ngram.predict(process_data.test_news['Statement'])
np.mean(predicted_svm_ngram == process_data.test_news['Label'])

#sgd classifier
sgd_pipeline_ngram = Pipeline([
         ('sgd_tfidf',select_feature.tfidf_ngram),
         ('sgd_clf',SGDClassifier(loss='hinge', penalty='l2', alpha=1e-3))
         ])

sgd_pipeline_ngram.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_sgd_ngram = sgd_pipeline_ngram.predict(process_data.test_news['Statement'])
np.mean(predicted_sgd_ngram == process_data.test_news['Label'])

#random forest classifier
random_forest_ngram = Pipeline([
        ('rf_tfidf',select_feature.tfidf_ngram),
        ('rf_clf',RandomForestClassifier(n_estimators=300,n_jobs=3))
        ])

random_forest_ngram.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_rf_ngram = random_forest_ngram.predict(process_data.test_news['Statement'])
np.mean(predicted_rf_ngram == process_data.test_news['Label'])

print('---------------------TFIDF and N-Grams---------------------')

create_confusion_matrix(nb_pipeline_ngram)
create_confusion_matrix(logR_pipeline_ngram)
create_confusion_matrix(svm_pipeline_ngram)
create_confusion_matrix(sgd_pipeline_ngram)
create_confusion_matrix(random_forest_ngram)

print(classification_report(process_data.test_news['Label'], predicted_nb_ngram))
print(classification_report(process_data.test_news['Label'], predicted_LogR_ngram))
print(classification_report(process_data.test_news['Label'], predicted_svm_ngram))
print(classification_report(process_data.test_news['Label'], predicted_sgd_ngram))
print(classification_report(process_data.test_news['Label'], predicted_rf_ngram))

process_data.test_news['Label'].shape

#grid-search parameter optimization
#random forest classifier parameters
parameters = {'rf_tfidf__ngram_range': [(1, 1), (1, 2),(1,3),(1,4),(1,5)],
               'rf_tfidf__use_idf': (True, False),
               'rf_clf__max_depth': (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
}

gs_clf = GridSearchCV(random_forest_ngram, parameters, n_jobs=-1)
gs_clf = gs_clf.fit(process_data.train_news['Statement'][:10000],process_data.train_news['Label'][:10000])

gs_clf.best_score_
gs_clf.best_params_
gs_clf.cv_results_

#logistic regression parameters
parameters = {'LogR_tfidf__ngram_range': [(1, 1), (1, 2),(1,3),(1,4),(1,5)],
               'LogR_tfidf__use_idf': (True, False),
               'LogR_tfidf__smooth_idf': (True, False)
}

gs_clf = GridSearchCV(logR_pipeline_ngram, parameters, n_jobs=-1)
gs_clf = gs_clf.fit(process_data.train_news['Statement'][:10000],process_data.train_news['Label'][:10000])

gs_clf.best_score_
gs_clf.best_params_
gs_clf.cv_results_

#Linear SVM
parameters = {'svm_tfidf__ngram_range': [(1, 1), (1, 2),(1,3),(1,4),(1,5)],
               'svm_tfidf__use_idf': (True, False),
               'svm_tfidf__smooth_idf': (True, False),
               'svm_clf__penalty': ('l1','l2'),
}

gs_clf = GridSearchCV(svm_pipeline_ngram, parameters, n_jobs=-1)
gs_clf = gs_clf.fit(process_data.train_news['Statement'][:10000],process_data.train_news['Label'][:10000])

#finding the model with best performing parameters
gs_clf.best_score_
gs_clf.best_params_
gs_clf.cv_results_

#running both random forest and logistic regression models again with best parameter found with GridSearch method
random_forest_final = Pipeline([
        ('rf_tfidf',TfidfVectorizer(stop_words='english',ngram_range=(1,3),use_idf=True,smooth_idf=True)),
        ('rf_clf',RandomForestClassifier(n_estimators=300,n_jobs=3,max_depth=10))
        ])

random_forest_final.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_rf_final = random_forest_final.predict(process_data.test_news['Statement'])
np.mean(predicted_rf_final == process_data.test_news['Label'])
print(classification_report(process_data.test_news['Label'], predicted_rf_final))

logR_pipeline_final = Pipeline([
        ('LogR_tfidf',TfidfVectorizer(stop_words='english',ngram_range=(1,5),use_idf=True,smooth_idf=False)),
        ('LogR_clf',LogisticRegression(penalty="l2",C=1))
        ])

logR_pipeline_final.fit(process_data.train_news['Statement'],process_data.train_news['Label'])
predicted_LogR_final = logR_pipeline_final.predict(process_data.test_news['Statement'])
np.mean(predicted_LogR_final == process_data.test_news['Label'])
print(classification_report(process_data.test_news['Label'], predicted_LogR_final))

#saving best model to the disk
model_file = 'final_model.sav'
pickle.dump(logR_pipeline_ngram,open(model_file,'wb'))

def find_most_informative_features(model, vect, clf, text=None, n=50):
    # Extract the vectorizer and the classifier from the pipeline
    vectorizer = model.named_steps[vect]
    classifier = model.named_steps[clf]

     # Check to make sure that we can perform this computation
    if not hasattr(classifier, 'coef_'):
        raise TypeError(
            "Cannot compute most informative features on {}.".format(
                classifier.__class__.__name__
            )
        )

    if text is not None:
        # Compute the coefficients for the text
        tvec = model.transform([text]).toarray()
    else:
        # Otherwise simply use the coefficients
        tvec = classifier.coef_

    # Zip the feature names with the coefs and sort
    coefs = sorted(
        zip(tvec[0], vectorizer.get_feature_names()),
        reverse=True
    )

    # Get the top n and bottom n coef, name pairs
    topn  = zip(coefs[:n], coefs[:-(n+1):-1])

    # Create the output string to return
    output = []

    # If text, add the predicted value to the output.
    if text is not None:
        output.append("\"{}\"".format(text))
        output.append(
            "Classified as: {}".format(model.predict([text]))
        )
        output.append("")

    # Create two columns with most negative and most positive features.
    for (cp, fnp), (cn, fnn) in topn:
        output.append(
            "{:0.4f}{: >15}    {:0.4f}{: >15}".format(
                cp, fnp, cn, fnn
            )
        )
    print(output)

find_most_informative_features(logR_pipeline_ngram,vect='LogR_tfidf',clf='LogR_clf')
find_most_informative_features(nb_pipeline_ngram,vect='nb_tfidf',clf='nb_clf')
find_most_informative_features(svm_pipeline_ngram,vect='svm_tfidf',clf='svm_clf')
find_most_informative_features(sgd_pipeline_ngram,vect='sgd_tfidf',clf='sgd_clf')


# c'è bisogno di importare un file nella cartella "code",
# quindi devo aggiungerla al path di python
# (l'operazione è locale per questo programma soltanto)
import sys, os
sys.path.append(os.path.abspath('../code'))

import q_function as q_fn_module
import numpy as np
import gym

# Cominciamo creando una piccola q
# Prima devo definire dei semplici spazi
# fatti senza particolare attenzione
obs_lo = np.full(3, -float('inf'), dtype=np.float32)
obs_hi = np.full(3, float('inf'), dtype=np.float32)
observation_space = gym.spaces.Box(obs_lo, obs_hi)
act_lo = np.full(2, -0.4, dtype=np.float32)
act_hi = np.full(2, 0.4, dtype=np.float32)
action_space = gym.spaces.Box(act_lo, act_hi)

# E ora la policy
q = q_fn_module.Q_Function(observation_space, action_space)

print(q.q_model.summary())

# Se superiamo questo punto, vuol dire che __init__ è almeno "compilabile".
print()
print("---------- EVVIVA ----------")
print()

# Ora vediamo come si comportano i due/tre metodi che mi preme esporre
# Cominciamo con quello facile
# print(polisi.trainable_weights)
# In realtà è un po' grandicello, mostrami soltanto un elemento
print(q.trainable_weights[-1])

# Per il prossimo devo inventarmi qualche osservazione e azione
oss0 = np.array([0.0,0.1,0.2])
oss1 = np.array([1.0,1.1,1.2])
oss2 = np.array([2.0,2.1,2.2])
oss3 = np.array([3.0,3.1,3.2])
oss_batch = np.array([oss0,oss1,oss2,oss3])
azn0 = np.array([0.0,0.1])*0.01
azn1 = np.array([1.0,1.1])*0.01
azn2 = np.array([2.0,2.1])*0.01
azn3 = np.array([3.0,3.1])*0.01
azn_batch = np.array([azn0,azn1,azn2,azn3])
# E poi cerchiamo di farci dare i valori q
values = q.compute_q_values(oss_batch, azn_batch)
print("--- [*] ---")
print(values)

# Ovviamente adesso i valori numerici puri non c'azzeccano niente,
# ma voglio solo controllare che i metodi si eseguano senza problemi
print()
print("---------- FINE ----------")


import cherrypy
import re, json

class RatingController(object):
	def __init__(self, mdb=None):
		self.mdb = mdb

	def GET(self, movie_id):
		output = {'result': 'success'}
		movie_id = int(movie_id)
		try:
			output['rating'] = self.mdb.get_rating(movie_id)
			output['movie_id'] = movie_id
		except Exception as ex:
			output['result'] = 'error'
			output['message'] = 'could not retrieve the average rating for a movie'
		return json.dumps(output)


"""
Utilities for processing waveforms
"""
import numpy as np
from scipy import signal

from obspy import Stream
from obspy.geodetics import gps2dist_azimuth
from pysep import logger
from pysep.utils.fmt import get_codes

def format_streams_for_rotation(st):
    """
    ObsPy requires specific channel naming to get stream rotation working.
    Comb through the stream and check that this is correct before passing
    stream to rotation

    :type st: obspy.core.stream.Stream
    :param st: Stream to format for rotation
    :rtype st: obspy.core.stream.Stream
    :return st: Stream that has been formatted for rotation
    """
    st_original = st.copy()
    logger.info(f"formatting stream of length {len(st)} for component rotation")
    codes = get_codes(st, choice="channel", suffix="?", up_to=True)

    st_out = Stream()
    for code in codes:
        net, sta, loc, cha = code.split(".")
        st = st_original.select(network=net, station=sta, location=loc,
                                channel=cha).copy()
        missing_vertical, missing_horizontal = _check_component_availability(st)

        if missing_vertical and missing_horizontal:
            logger.debug(f"{code} is missing vertical and at least 1 "
                         f"horizontal, skipping over")
            continue
        elif missing_vertical and not missing_horizontal:
            logger.debug(f"{code} is missing vertical, replacing vertical "
                         f"component with zeros")
            st = _append_null_trace(st, component="Z", cmpaz=0, cmpinc=-90.)
        elif not missing_vertical and missing_horizontal:
            logger.debug(f"{code} is missing at least 1 horizontal component, "
                         f"removing existing horizontal data and writing zeros "
                         f"to North and East components")
            for comp in ["E", "N", "1", "2"]:
                for tr in st.select(component=comp)[:]:
                    st.remove(tr)
                    logger.debug(f"{code} replacing existing component "
                                 f"'{comp}' with zeros")

            st = _append_null_trace(st, component="E", cmpaz=90., cmpinc=0.)
            st = _append_null_trace(st, component="N", cmpaz=0., cmpinc=0.)

        st_out += st

    logger.info(f"stream formatting returned {len(st_out)} traces")

    return st_out

def append_back_azimuth_to_stats(st, inv, event):
    """
    ObsPy rotation requires back azimuth information which is accessed through
    trace.stats.back_azimuth. This function appends back azimuth values to the
    stream by cacluating using metadata from the inventory and event objects.

    .. note::
        This was written and then I realized that `_append_sac_headers_trace`
        already does this, so it is unused, but left incase it's useful later.

    :type st: obspy.core.stream.Stream
    :param st: Stream with missing components
    :type inv: obspy.core.inventory.Inventory
    :param inv: optional user-provided inventory object which will force a
        skip over StationXML/inventory searching
    :type event: obspy.core.event.Event
    :param event: optional user-provided event object which will force a
        skip over QuakeML/event searching
    :rtype: obspy.core.stream.Stream
    :return: stream with back azimuth values appended
    """
    st_out = st.copy()
    ev_lat = event.preferred_origin().latitude
    ev_lon = event.preferred_origin().longitude
    for net in inv:
        for sta in net:
            _, _, baz = gps2dist_azimuth(lat1=ev_lat, lon1=ev_lon,
                                         lat2=sta.latitude, lon2=sta.longitude
                                         )
            # Apply back azimuth changes to stream in place
            for tr in st_out.select(network=net.code, station=sta.code):
                tr.stats.back_azimuth = baz
    return st_out

def _append_null_trace(st, component, cmpaz=None, cmpinc=None):
    """
    Create a copy of a trace with zeroed out data, used for rotation

    :type st: obspy.core.stream.Stream
    :param st: Stream with missing components
    :type component: str
    :param component: component of data to turn into a null trace
    :type cmpaz: float
    :param cmpaz: component azimuth for SAC header
    :type cmpinc: float
    :param cmpinc: component inclination for SAC header
    :rtype st: obspy.core.stream.Stream
    :return st: Stream that has had null traces appended
    """
    st_out = st.copy()
    trace_null = st_out[0].copy()
    trace_null.data = np.zeros(len(trace_null.data))
    trace_null.stats.component = component
    if cmpaz is not None:
        trace_null.stats.sac["cmpaz"] = cmpaz
    if cmpinc is not None:
        trace_null.stats.sac["cmpinc"] = cmpinc
    st_out.append(trace_null)

    return st_out

def _check_component_availability(st):
    """
    Quick logic check to see if stream is missing horizontals or vertical

    :type st: obspy.core.stream.Stream
    :param st: Steam to check
    :rtype: tuple of bool
    :return: (is the vertical component missing?,
              is one or both horizontal components missing?)
    """
    comps = sorted([tr.stats.component.upper() for tr in st])
    missing_vertical, missing_horizontal = False, False

    if comps:
        if "Z" not in comps:
            missing_vertical = True

        # Any one of these criteria will trigger a 'missing_horizontal' flag
        for pairs in [("N", "E"), ("R", "T"), ("1", "2")]:
            first, second = pairs
            if first in comps and second not in comps:
                missing_horizontal = True
            elif second in comps and first not in comps:
                missing_horizontal = True
    # Deal with the case where we have an empty Stream
    else:
        missing_vertical, missing_horizontal = True, True

    return missing_vertical, missing_horizontal

def rotate_to_uvw(st):
    """
    UVW orthogonal frame rotation

    In Symmetric Triaxial Seismometers, the sensing elements are also arranged
    to be mutually orthogonal, but instead of one axis being vertical, all
    three are inclined upwards from the horizontal at precisely the same angle,
    as if they were aligned with the edges of a cube balanced on a corner.

    TODO test this, not sure how it's supposed to work

    See reference:
    http://link.springer.com/referenceworkentry/10.1007/978-3-642-36197-5_194-1

    Rotation matrix reference:
    http://link.springer.com/referenceworkentry/10.1007/
                                                  978-3-642-36197-5_194-1#page-1

    :type st: obspy.core.stream.Stream
    :param st: three-component stream to rotate the UVW
    :rtype: obspy.core.stream.Stream
    :return: Stream that has been rotated to UVW
    """
    st_out = st.copy()
    assert(len(st) == 3), f"UVW rotation requires 3 component stream input"

    xyz = np.array([[st_out[0].data],
                    [st_out[1].data],
                    [st_out[2].data]])
    xyz = np.asmatrix(xyz)

    rotation_matrix = np.matrix([[2, 0, np.sqrt(2)],
                                 [-1, np.sqrt(3), np.sqrt(2)],
                                 [-1, -np.sqrt(3), np.sqrt(2)]])
    rotation_matrix *= 1 / np.sqrt(6)

    # Theta is the angle between the axis and the horizontal plane
    theta = (np.arcsin(1 / np.sqrt(3))) * (180.0 / np.pi)

    uvw = rotation_matrix * xyz
    for i, comp in enumerate(["U", "V", "W"]):
        st_out[i].data = np.reshape(np.asarray(uvw[i]), uvw.shape[1])
        st_out[i].stats.component = comp
        st_out[i].stats.sac["kcmpnm"] = st_out[i].stats.channel
        st_out[i].stats.sac["cmpaz"] *= (120 * i)  # azimuth
        st_out[i].stats.sac["cmpinc"] -= theta  # inclination
        if comp == "W":
            st_out[i].stats.sac["cmpinc"] += 90.

    return st_out

def trim_start_end_times(st, starttime=None, endtime=None, fill_value=None):
    """
    Trim all traces in a Stream to a uniform start and end times. If no
    `starttime` or `endtime` are provided, they are selected as the outer
    bounds of the Streams time bounds.

    :type st: obspy.core.stream.Stream
    :param st: stream to merge and trim start and end times for
    :type starttime: obspy.core.UTCDateTime
    :param starttime: user-defined starttime to trim stream. If None, will get
        the maximum starttime in entire stream
    :type endtime: obspy.core.UTCDateTime
    :param endtime: user-defined endtime to trim stream. If None, will get
        the minimum endtime in entire stream
    :type fill_value: str or int or float
    :param fill_value: How to deal with data gaps (missing sections of
        waveform before trace start or trace end w.r.t requested start and end
        times). NoneType by default, which means data with gaps are removed
        completely.

        Options include:

        - 'mean': fill with the mean of all data values in the gappy data
        - <int or float>: fill with a constant, user-defined value, e.g.,
        0 or 1.23 or 9.999
        - None: do not fill data gaps
    """
    st_edit = st.copy()

    if starttime is None:
        starttime = min([tr.stats.starttime for tr in st_edit])
    if endtime is None:
        endtime = max([tr.stats.endtime for tr in st_edit])

    # Trace.trim() can only take float or int as fill values
    if fill_value in ["interpolate", "latest"]:
        logger.warning("ObsPy cannot use `fill_value` 'interpolate' or "
                       "'latest' for missing boundary times. Setting to 'mean'")
        fill_value = "mean"

    # Go through all stations and look for those with late starts or early ends.
    # Then either remove short traces or fill them with acceptable values
    for tr in st_edit:
        if tr.stats.starttime > starttime or tr.stats.endtime < endtime:
            if fill_value is not False:
                if fill_value == "mean":
                    _fillval = np.nanmean(tr.data).astype(tr.data.dtype)
                else:
                    _fillval = fill_value

                logger.info(f"{tr.get_id()} filling start/endtime data gap w/: "
                            f"{_fillval}")

                tr.trim(starttime=starttime, endtime=endtime, pad=True,
                        nearest_sample=False, fill_value=_fillval)
            else:
                # Directly remove stations with late starttime or early endtime
                logger.warning(f"{tr.get_id()} start or endtime does not match "
                               f"requested bounds, remove")
                st_edit.remove(tr)
        else:
            tr.trim(starttime=starttime, endtime=endtime, nearest_sample=False)

    return st_edit

def merge_gapped_data(st, fill_value=None, gap_fraction=1.):
    """
    Merges traces with the same ID, filling gappy data with values if requested,
    otherwise removes traces that have gapped data.

    .. note::
        Be careful about `fill_value` data types, as there are no checks that
        the fill value matches the internal data types. This may cause
        unexpected errors.

    :type st: obspy.core.stream.Stream
    :param st: stream to merge and trim start and end times for
    :type fill_value: str or int or float
    :param fill_value: How to deal with data gaps (missing sections of
        waveform over a continuous time span). NoneType by default, which
        means data with gaps are removed completely. Users who want access
        to data with gaps must choose how gaps are filled. See API for
        ObsPy.core.stream.Stream.merge() for how merge is handled:

        Options include:

        - 'mean': fill with the mean of all data values in the gappy data
        - <int or float>: fill with a constant, user-defined value, e.g.,
        0 or 1.23 or 9.999
        - 'interpolate': linearly interpolate from the last value pre-gap
        to the first value post-gap
        - 'latest': fill with the last value of pre-gap data
        - False: do not fill data gaps, which will lead to stations w/
        data gaps being removed.
    :type gap_fraction: float
    :param gap_fraction: if `fill_data_gaps` is not None, determines the
        maximum allowable fraction (percentage) of data that gaps can
        comprise. For example, a value of 0.3 means that 30% of the data
        (in samples) can be gaps that will be filled by `fill_data_gaps`.
        Traces with gap fractions that exceed this value will be removed.
        Defaults to 1. (100%) of data can be gaps.
    :rtype: obspy.core.stream.Stream
    :return: Stream that has been trimmed
    """
    st_edit = st.copy()

    logger.info("trimming start and end times on a per-station basis")
    st_out = Stream()
    # e.g., NN.SSS.LL.CC?  i.e., only getting per-component codes
    codes = get_codes(st=st_edit, choice="component")

    for code in codes:
        # Subset the stream at each component
        net, sta, loc, cha = code.split(".")
        st_edit_select = st_edit.select(network=net, station=sta,
                                        location=loc, channel=cha)

        # Try-except catches any general ObsPy merge errors to keep code going
        try:
            data_gaps = st_edit_select.get_gaps()
            fillval = fill_value  # dummy value to allow in-place changes

            # Check if there are data gaps that we need to address
            if data_gaps and fill_value is not False:
                # Determine the percentage of data that comprises gaps
                gap_duration_samp = data_gaps[0][-1]  # assuming only one set
                starttime = min([tr.stats.starttime for tr in st_edit_select])
                endtime = max([tr.stats.endtime for tr in st_edit_select])
                total_samps = \
                    (endtime - starttime) / st_edit_select[0].stats.delta

                gap_percentage = gap_duration_samp / total_samps

                # If we exceed the allowable amount of data gap, do not fill
                if gap_percentage > gap_fraction:
                    logger.info(f"{code} has gap fraction "
                                f"({gap_percentage:.2f}) > allowable "
                                f"{gap_fraction}, will not fill gaps")
                    fillval = None
                else:
                    # Decide how we're going to fill the gaps
                    if fill_value == "mean":
                        # Collect mean value over all data surrounding the gap
                        # Convert to data type expected by array
                        fillval = np.nanmean(
                            [np.nanmean(tr.data) for tr in st_edit_select]
                        ).astype(st_edit_select[0].data.dtype)
                    else:
                        fillval = fill_value

                    logger.info(f"{code} has data gaps, filling with: "
                                f"{fillval}")
            else:
                fillval = None

            st_edit_select.merge(fill_value=fillval)  # combine like trace ID
        except Exception as e:  # NOQA
            logger.warning(f"{code} merge error: {e}")
            continue

        st_out += st_edit_select

    return st_out

def resample_data(st, resample_freq, method="interpolate"):
    """
    Apply a lowpass filter and taper data before resampling it using
    one of a choice of resampling strategies

    TODO did not refactor `resample_cut` which doesn't seem to do anything but
        is included in old code

    :type st: obspy.core.stream.Stream
    :param st: Stream to resample data for
    :type resample_freq: float
    :param resample_freq: frequency to resample for
    :type method: str
    :param method: choice of ObsPy resampling strategy:
        - interpolate: interpolate data, requires anti-aliasing lowpass filter
            before interpolating
        - resample: reample data with fourier methods
    :rtype: obspy.core.stream.Stream
    :return: Stream that has been resampled and maybe filtered
    """
    if method not in ["interpolate", "resample"]:
        logger.warning(f"unexpected resample method {method}, defaulting to "
                       f"'interpolate'")
        method = "interpolate"

    logger.info(f"resampling data to sampling rate: {resample_freq}Hz with "
                f"method '{method}'")
    st_out = st.copy()
    for i, tr in enumerate(st_out[:]):
        target_nyquist = 0.5 * resample_freq
        current_nyquist = 0.5 * tr.stats.sampling_rate
        if target_nyquist < current_nyquist:
            try:
                logger.debug(f"{tr.get_id()} applying lowpass filter to prep "
                             f"for new nyquist freq: "
                             f"{current_nyquist} -> {target_nyquist}")
                # This function affects the trace in-place
                zerophase_chebychev_lowpass_filter(
                    tr=tr, freqmax=target_nyquist
                )
            except Exception as e:
                logger.warning(f"exception in lowpass filtering "
                               f"{tr.get_id()}, remove: {e}")
                logger.debug(e)
                st_out.remove(tr)
        else:
            tr.detrend("linear")
        tr.taper(max_percentage=0.01, type="hann")
        # Enforce that this data array is 'c'ontiguous
        tr.data = np.require(tr.data, requirements=["C"])
        if method == "interpolate":
            tr.interpolate(sampling_rate=resample_freq, method="lanczos", a=8)
        elif method == "resample":
            tr.resample(sampling_rate=resample_freq, strict_length=True)

    return st_out

def zerophase_chebychev_lowpass_filter(tr, freqmax):
    """
    Custom Chebychev type two zerophase lowpass filter useful for decimation
    filtering. This filter is stable up to a reduction in frequency with a
    factor of 10. If more reduction is desired, simply decimate in steps.
    Partly based on a filter in ObsPy.

    Filter parameters:
        rp: maximum ripple of passband
        rs: attenuation of stopband
        ws: stop band frequency
        wp: pass band frequency

    .. note::
        Should be replaced once ObsPy has a proper decimation filter.

    .. note::
        This function affects the trace in place!

    :type tr: obspy.core.trace.Trace
    :param tr: The trace to be filtered.
    :type freqmax: float
    :param freqmax: The desired lowpass frequency.
    """
    rp, rs, order = 1, 96, 1e99
    ws = freqmax / (tr.stats.sampling_rate * 0.5)
    wp = ws
    wn = None

    while True:
        if order <= 12:
            break
        wp *= 0.99
        order, wn = signal.cheb2ord(wp=wp, ws=ws, gpass=rp, gstop=rs,
                                    analog=False)
    b, a = signal.cheby2(N=order, rs=rs, Wn=wn, btype="low", analog=0,  # NOQA
                         output="ba")                                   # NOQA
    # Apply twice to get rid of the phase distortion.
    tr.data = signal.filtfilt(b, a, tr.data)

def estimate_prefilter_corners(tr):
    """
    Estimates corners for pre-deconvolution (instrument response removal)
    Essentially band limits the data based on the minimum and maximum allowable
    periods based on the sampling rate and overall waveform length.

    See also: https://ds.iris.edu/files/sac-manual/commands/transfer.html

    Replaces the old `get_pre_filt` function

    :type tr: obspy.core.trace.Trace
    :param tr: trace from which stats are taken
    :rtype: tuple of float
    :return: frequency corners (f0, f1, f2, f3)
    """
    # filtering constants
    fcut1_par = 4.0
    fcut2_par = 0.5

    f1 = fcut1_par / (tr.stats.endtime - tr.stats.starttime)
    nyquist_freq = tr.stats.sampling_rate / 2
    f2 = nyquist_freq * fcut2_par
    f0 = 0.5 * f1
    f3 = 2.0 * f2

    return f0, f1, f2, f3


import asyncio
import logging
import os.path
import platform
import signal
import time
from asyncio.subprocess import Process
from datetime import datetime
from logging import Logger
from typing import Optional, Callable, List, Union

import psutil
from tinyioc import get_service

from . import constants
from .handler.base import BaseTaskHandler
from .logger import logger
from .scanner import AsyncScanner
from .types.options import TaskOptions
from .types.task import Task
from .configuration import AppConfiguration

class TaskRunner:
    _handlers: List[BaseTaskHandler]
    _handler: BaseTaskHandler

    _task: Task
    _process: Optional[Process]
    _completion_callback: Optional[Callable]
    _scanner: AsyncScanner
    _log_handler: logging.Handler

    _logger: Logger
    _err_logger: Logger

    def __init__(self, task: Task, file_output_dir: Optional[str], log_level: Union[int, str],
                 log_handler: logging.Handler):
        configuration: AppConfiguration = get_service(AppConfiguration)

        self._task = task
        self._handlers = configuration.handlers
        self._process = None
        self._running = True
        self._completion_callback = None
        self._log_handler = log_handler

        self._handler = next(h for h in self._handlers if h.task_type == task['type'])

        if not self._handler:
            raise RuntimeError(f"Task type '{task['type']}' unrecognized")

        self._logger = logging.Logger(task["name"])
        self._logger.setLevel(log_level)
        self._err_logger = logging.Logger(task["name"])
        self._err_logger.setLevel(log_level)

        self._logger.addHandler(log_handler)
        self._err_logger.addHandler(log_handler)

        if file_output_dir and os.path.isdir(file_output_dir):
            now_time = datetime.now().strftime("%d-%m-%Y_%H-%M-%S")
            output_file = os.path.join(file_output_dir, f"{task['name']}_{now_time}.log")
            file_handler = logging.FileHandler(output_file)
            file_handler.terminator = ''

            self._logger.addHandler(file_handler)
            self._err_logger.addHandler(file_handler)

    @property
    def name(self):
        return self._task["name"]

    def _on_stop(self):
        # noinspection PyTypedDict
        self._handler.on_exit(self._task[self._handler.task_type], self._process)

    def stop(self, timeout=1):
        if self._process and self._process.returncode is None:
            logger.debug(f"Process {self.name} is alive. Killing it")

            self._on_stop()
            pid = self._process.pid

            if platform.system() == "Windows":
                os.kill(pid, signal.CTRL_C_EVENT)
            else:
                os.kill(pid, signal.SIGTERM)

            init_time = time.time()
            while psutil.pid_exists(pid) and time.time() < init_time + timeout:
                time.sleep(constants.PROCESS_KILL_POLLING_INTERVAL)

            if psutil.pid_exists(pid):
                logger.debug(f"Process {self.name} still alive after {timeout}s timeout. Sending SIGKILL")
                if platform.system() == "Windows":
                    os.kill(pid, signal.CTRL_BREAK_EVENT)
                else:
                    os.kill(pid, signal.SIGKILL)

    async def start(self, completion_callback: Optional[Callable]):
        try:
            self._completion_callback = completion_callback
            t = self._task

            stderr_redirect = t.get('pattern_in_stderr', False)

            # noinspection PyTypedDict
            task_options: Optional[TaskOptions] = t.get(self._handler.task_type)

            self._process = await self._handler.execute(task_options, self._completion_callback,
                                                        stderr_redirect)
            if not self._process:
                self._running = False
                return

            run_mode = t.get("run_mode") or "await_completion"
            completion_pattern = t.get("completion_pattern")
            self._scanner = AsyncScanner(self._logger, self._err_logger, self._process, self._completion_callback,
                                         not stderr_redirect)

            if run_mode == "await_completion" and completion_pattern:
                await self._scanner.print_and_scan(completion_pattern, self._task['name'])
            else:
                await self._scanner.print(self._task['name'])
        except asyncio.CancelledError:
            pass


import os
from pathlib import Path, PureWindowsPath
from google.cloud.bigquery import dbapi
import utils.bq as ubq
from utils.string_formatter import FormatSQLString
from config.conf import gcp, logger

def path_formatter(path_str):
    """
    This function helps format file paths to meet operating system
    requirements. So issues can be avoided in a linux environment.
    :param path_str:
    :return:
    """
    if os.name == 'nt':
        return PureWindowsPath(path_str)
    else:
        return Path(path_str)

def execute_query_task(sql_file,
                       destination_table,
                       dataset_id=gcp['dataset'],
                       run_disposition='WRITE_TRUNCATE',
                       use_legacy=False):
    """
    This function is used to open and execute files containing SQL scripts.
    The query results are stored in given destination table id.
    :param sql_file:
    :param destination_table:
    :param dataset_id:
    :param run_disposition:
    :param use_legacy:
    :return:
    """
    path = path_formatter(sql_file)
    sql_string = FormatSQLString.format_dataset_id(open(path).read(), dataset_id)

    try:
        ubq.bq_query_to_table(destination_table,
                              sql_string,
                              dataset_id=dataset_id,
                              write_disposition=run_disposition,
                              use_legacy=use_legacy)
        success = True
    except dbapi.Error as err:
        logger.exception("The following exception occured: \n" + err)
        logger.info("Something went wrong during query run."
                    "An unknown error was detected in the script.")
        success = False
    return success

def archive_tables(sql_file, source_table, destination_table, run_disposition='WRITE_APPEND'):
    """
    This function is used for archiving tables before overwriting for historical record.
    :param sql_file:
    :param source_table:
    :param destination_table:
    :param run_disposition:
    :return:
    """
    path = path_formatter(sql_file)
    sql_string = open(path).read()
    sql_string.format(source_table)

    try:
        ubq.bq_query_to_table(destination_table, sql_string, write_disposition=run_disposition)
        success = True
    except dbapi.Error as err:
        logger.exception("The following exception occured: \n" + err)
        logger.info("Something went wrong during query run."
                    "An unknown error was detected in the script.")
        success = False
    return success

def move_and_rename_tables(sql_file, source, destination, run_disposition='WRITE_TRUNCATE'):
    path = path_formatter(sql_file)
    sql_string = open(path).read().format(table_id=source)

    try:
        ubq.bq_query_to_table(destination, sql_string, write_disposition=run_disposition)
        success = True
    except dbapi.Error as err:
        logger.exception("The following exception occured: \n" + err)
        logger.info("Something went wrong during query run."
                    "An unknown error was detected in the script.")
        success = False
    return success

def test_summary(sql_file, destination, test_tables, dataset_id=gcp['dataset']):
    """
    :param sql_file:
    :param destination:
    :param test_tables:
    :param dataset_id=gcp['dataset']:
    """
    path = path_formatter(sql_file)
    temp_sql_string = open(path).read()

    lst_sql_str = [
        temp_sql_string.format(table_id=table_id, dataset_id=dataset_id)
        for table_id in test_tables
    ]

    sql_str = '\nunion all\n'.join(lst_sql_str)

    logger.info(f'sql script to execute: {sql_str}')

    try:
        ubq.bq_query_to_table(destination, sql_str)
        run_success = True
    except dbapi.Error as err:
        logger.exception("The following exception occured: \n" + err)
        logger.info("Something went wrong during query run."
                    "An unknown error was detected in the script.")

    return run_success


from torch import nn
import torch.nn.functional as F

class ResidualConvBlock(nn.Module):

    def __init__(self, c_in, c_out, k_size=3, stride=1, pad=1, bn=False, conv_layers=4, lrelu=True, conv_residual=False):
        nn.Module.__init__(self)
        self.c_in = c_in
        self.c_out = c_out
        self.k_size = k_size
        self.stride = stride
        self.pad = pad
        self.bn = bn
        self.conv_layers = conv_layers

        if bn:
            self.bns = nn.ModuleList([nn.BatchNorm2d(c_out) for i in range(conv_layers)])

        self.convs = nn.ModuleList([nn.Conv2d(c_in, c_out, k_size, stride=stride, padding=pad)])
        for i in range(conv_layers - 1):
            self.convs.append(nn.Conv2d(c_out, c_out, k_size, stride=stride, padding=pad))

        self.residual_conv = nn.Conv2d(c_in, c_out, 1)

    def forward(self, x):
        conv_out = x
        # conv_out = self.convs(conv_out)
        for layer_index in range(self.conv_layers):
            if self.bn:
                conv_out = self.bns[layer_index](conv_out)
            conv_out = self.convs[layer_index](F.relu(conv_out))

        return F.interpolate(self.residual_conv(x), scale_factor=1, mode='bilinear') + conv_out


# -*- coding: utf-8 -*-

import logging
import ask_sdk_core.utils as ask_utils

from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model.interfaces.videoapp import LaunchDirective, VideoItem, Metadata
from ask_sdk_model.interfaces.audioplayer import (
    PlayDirective, PlayBehavior, AudioItem, Stream, AudioItemMetadata,
    StopDirective)
from ask_sdk_model.interfaces import display
from ask_sdk_model import Response

from pytube import YouTube
import urllib.request, json
from urllib.error import  URLError, HTTPError

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

class LaunchRequestHandler(AbstractRequestHandler):
    """Handler for Skill Launch."""
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool

        return ask_utils.is_request_type("LaunchRequest")(handler_input)

    def handle(self, handler_input):
        # type: (handler_input) -> Response

        logger.info(">>>>> In LaunchRequestHandler")
        interfaces = (ask_utils.request_util
            .get_supported_interfaces(handler_input)
            .to_dict())

        with open("parameters.json") as conf_data:
            conf = json.load(conf_data)
        locale = ask_utils.get_locale(handler_input)
        logger.debug(f"Locale is {locale}")
        # localized strings stored in language_strings.json
        with open("language_strings.json") as language_prompts:
            language_data = json.load(language_prompts)
        try:
            loc_data = language_data[locale[:2]]
            skill_name = loc_data['SKILL_NAME']
        except KeyError:
            loc_data = language_data['en']
            skill_name = loc_data['SKILL_NAME']
        speak_output = loc_data['NO_VIDEO']
        channel_id = loc_data['CHANNEL']
        youtube_url = (
            "https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=" +
            channel_id +
            "&maxResults=1&order=date&type=video&key=" +
            conf['youtube_key']
        )
        success = True
        try:
            url = urllib.request.urlopen(youtube_url)
        except URLError as e:
            speak_output = loc_data['URL_ERROR']
            logger.info("URLError %s", e)
            success = False
        except HTTPError as e:
            logger.info("HTTPError %s, %e", e, e.code)
            if e.code == 429:
                speak_output = loc_data['TOO_MANY_REQUESTS']
            success = False
        if success:
            try:
                data = json.loads(url.read().decode())
                videoId = data['items'][0]['id']['videoId']
                yt = YouTube('https://www.youtube.com/watch?v=' + videoId)
            except Exception as e:
                speak_output = loc_data['YOUTUBE_ERROR']
                success = False
        if success:
            logger.info("List of the available interfaces: %s", interfaces)
            if interfaces['video_app'] is not None: # device has video support
                for stream in yt.streams.order_by('resolution').desc():
                    if stream.includes_audio_track:
                        break
                speak_output = loc_data['VIDEO_MESSAGE'] + ": " + stream.title + ". " + yt.description
                logger.info("Video {}. "
                            "Locale='{}'. "
                            "channel_id='{}'. "
                            "speak_output='{}'. "
                            "youtube_key='{}'".format(
                    stream,
                    locale[:2],
                    channel_id,
                    speak_output,
                    conf['youtube_key'])
                )
                directive = LaunchDirective(video_item=VideoItem(
                    source=stream.url,
                    metadata=Metadata(title=stream.title, subtitle=yt.description)))
                return (
                    handler_input.response_builder
                        .speak(speak_output)
                        .add_directive(directive)
                        .response
                )
            elif interfaces['audio_player'] is not None: # device has only audio support (no video)
                stream = (yt.streams
                            .filter(only_audio=True, subtype='mp4')
                            .order_by('fps')
                            .desc()
                            .first()
                )
                speak_output = loc_data['AUDIO_MESSAGE'] + ": " + stream.title + ". " + yt.description
                logger.info("Audio {}. "
                            "Locale='{}'. "
                            "channel_id='{}'. "
                            "speak_output='{}'. "
                            "youtube_key='{}'".format(
                    stream,
                    locale[:2],
                    channel_id,
                    speak_output,
                    conf['youtube_key'])
                )
                directive = PlayDirective(
                    play_behavior=PlayBehavior.REPLACE_ALL,
                    audio_item=AudioItem(
                        stream=Stream(
                            expected_previous_token=None,
                            token=stream.url,
                            url=stream.url,
                            offset_in_milliseconds=0
                        ),
                        metadata=AudioItemMetadata(
                            title=stream.title,
                            subtitle=yt.description,
                            art=display.Image(
                                content_description=stream.title,
                                sources=[
                                    display.ImageInstance(
                                        url=yt.thumbnail_url
                                    )
                                ]
                            ),
                            background_image=display.Image(
                                content_description=stream.title,
                                sources=[
                                    display.ImageInstance(
                                        url=yt.thumbnail_url
                                    )
                                ]
                            )
                        )
                    )
                )
                return (
                    handler_input.response_builder
                        .speak(speak_output)
                        .add_directive(directive)
                        .set_should_end_session(True)
                        .response
                )
            else:
                speak_output = loc_data['NO_INTERFACE'] + ": " + stream.title + ". " + yt.description
        return (
            handler_input.response_builder
                .speak(speak_output)
                .response
        )

class MainIntentHandler(AbstractRequestHandler):
    """Handler for Main Intent."""
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool
        return (ask_utils.is_intent_name("mainIntent")(handler_input) or
                ask_utils.is_intent_name("AMAZON.ResumeIntent")(handler_input) or
                ask_utils.is_intent_name("AMAZON.NavigateHomeIntent")(handler_input))

    def handle(self, handler_input):
        # type: (handler_input) -> Response
        logger.info(">>>>> In MainIntentHandler: %s", handler_input.request_envelope.request)
        speak_output = "No main intent implemented"

        return (
            handler_input.response_builder
                .speak(speak_output)
                .ask(speak_output)
                .response
        )

class HelpIntentHandler(AbstractRequestHandler):
    """Handler for Help Intent."""
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool
        return ask_utils.is_intent_name("AMAZON.HelpIntent")(handler_input)

    def handle(self, handler_input):
        # type: (handler_input) -> Response
        logger.info(">>>>> In HelpIntentHandler")
        speak_output = "No help intent implemented"

        return (
            handler_input.response_builder
                .speak(speak_output)
                .ask(speak_output)
                .response
        )

class AudioPlaybackHandler(AbstractRequestHandler):
    """Handler for audio playback events."""
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool
        return (ask_utils.is_request_type("AudioPlayer.PlaybackStarted")(handler_input) or
                ask_utils.is_request_type("AudioPlayer.PlaybackFinished")(handler_input) or
                ask_utils.is_request_type("AudioPlayer.PlaybackStopped")(handler_input) or
                ask_utils.is_request_type("AudioPlayer.PlaybackNearlyFinished")(handler_input) or
                ask_utils.is_request_type("AudioPlayer.PlaybackFailed")(handler_input))

    def handle(self, handler_input):
        # type: (handler_input) -> Response
        logger.debug(">>>>> In AudioPlaybackHandler")
        return handler_input.response_builder.response

class CancelOrStopIntentHandler(AbstractRequestHandler):
    """Single handler for Cancel and Stop Intent."""
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool
        return (ask_utils.is_intent_name("AMAZON.CancelIntent")(handler_input) or
                ask_utils.is_intent_name("AMAZON.PauseIntent")(handler_input) or
                ask_utils.is_intent_name("AMAZON.StopIntent")(handler_input))

    def handle(self, handler_input):
        # type: (handler_input) -> Response

        logger.info(">>>>> In CancelOrStopIntentHandler")
        locale = ask_utils.get_locale(handler_input)
        with open("language_strings.json") as language_prompts:
            language_data = json.load(language_prompts)
        try:
            loc_data = language_data[locale[:2]]
            skill_name = loc_data['SKILL_NAME']
        except KeyError:
            loc_data = language_data['en']
            skill_name = loc_data['SKILL_NAME']
        speak_output = loc_data['GOODBYE']
        directive = StopDirective()

        return (
            handler_input.response_builder
                .speak(speak_output)
                .add_directive(directive)
                .set_should_end_session(True)
                .response
        )

class SessionEndedRequestHandler(AbstractRequestHandler):
    """Handler for Session End."""
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool
        return ask_utils.is_request_type("SessionEndedRequest")(handler_input)

    def handle(self, handler_input):
        # type: (handler_input) -> Response

        logger.info(">>>>> In SessionEndedRequestHandler")
        logger.debug("Session ended with reason: {}".format(
            handler_input.request_envelope.request.reason)
        )
        # Any cleanup logic goes here.

        return handler_input.response_builder.response

class IntentReflectorHandler(AbstractRequestHandler):
    """The intent reflector is used for interaction model testing and debugging.
    It will simply repeat the intent the user said. You can create custom handlers
    for your intents by defining them above, then also adding them to the request
    handler chain below.
    """
    def can_handle(self, handler_input):
        # type: (handler_input) -> bool
        return ask_utils.is_request_type("IntentRequest")(handler_input)

    def handle(self, handler_input):
        # type: (handler_input) -> Response

        logger.info(">>>>> In IntentReflectorHandler")
        intent_name = ask_utils.get_intent_name(handler_input)
        logger.info("Triggered intent: %s", intent_name)
        speak_output = "You just triggered " + intent_name + "."

        return (
            handler_input.response_builder
                .speak(speak_output)
                # .ask("add a reprompt if you want to keep the session open for the user to respond")
                .response
        )

class CatchAllExceptionHandler(AbstractExceptionHandler):
    """Generic error handling to capture any syntax or routing errors. If you receive an error
    stating the request handler chain is not found, you have not implemented a handler for
    the intent being invoked or included it in the skill builder below.
    """
    def can_handle(self, handler_input, exception):
        # type: (handler_input, exception) -> bool
        return True

    def handle(self, handler_input, exception):
        # type: (handler_input, exception) -> Response

        logger.info(">>>>> In CatchAllExceptionHandler: check handler '%s'",
            ask_utils.get_request_type(handler_input)
        )
        logger.debug("Dump of request_envelope: %s",
            str(handler_input.request_envelope)
        )
        logger.error(exception, exc_info=True)

        return handler_input.response_builder.response

# The SkillBuilder object acts as the entry point for your skill, routing all request and response
# payloads to the handlers above. Make sure any new handlers or interceptors you've
# defined are included below. The order matters - they're processed top to bottom.

sb = SkillBuilder()

sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(MainIntentHandler())
sb.add_request_handler(AudioPlaybackHandler())
sb.add_request_handler(CancelOrStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_request_handler(IntentReflectorHandler()) # make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers

sb.add_exception_handler(CatchAllExceptionHandler())

lambda_handler = sb.lambda_handler()


import pytest
from task1.task1 import ValueCannotBeConvertedError

class TestConverter:
    @pytest.mark.xfail(raises=ValueCannotBeConvertedError)
    @pytest.mark.parametrize('test_in', [
        ("30", 30),
        ("30s", 30),
        ("S", 1),
        ("60.5m", 3630),
        ("10seconds", None),
        ("1m30s", None),
        ("1y", None),
        ("", None)]
    )
    def test_converter_work(self, test_in, converter):
        res = converter.to_seconds(test_in[0])
        print(res)
        assert res == test_in[1]


from django.db import models

# Create your models here.

class Comment(models.Model):
    text = models.TextField(max_length=240)
    quote = models.ForeignKey(
      'quotes.quotes',
      related_name='comments',
      on_delete=models.CASCADE
  )


# test for tm1637.py

import time
import datetime
import RPi.GPIO as GPIO
import tm1637

def show_time():
   while(True):
       now = datetime.datetime.now()
       hour = now.hour
       minute = now.minute
       second = now.second
       currenttime = [ repr(int(hour / 10)), repr(hour % 10),
                       repr(int(minute / 10)), repr(minute % 10) ]

       Display.Show(currenttime)
       Display.ShowDoublepoint(second % 2) # 0, 1

       time.sleep(1)

Display = tm1637.TM1637(23,24,tm1637.BRIGHT_TYPICAL)

Display.Clear() #
Display.SetBrightnes(2)

Display.Show(['0', '1', '2', '3'])
Display.ShowDoublepoint(0)
time.sleep(3)

Display.Show(['C', 'O', 'O', 'L'])
Display.ShowDoublepoint(1)
time.sleep(3)

Display.Show([' ', '-', '*', 'Unknown'])
Display.ShowDoublepoint(1)
time.sleep(3)

Display.Clear()
show_time()


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

import pickle
from datetime import datetime
from io import StringIO
from pathlib import Path

from ruamel.yaml import YAML, RoundTripRepresenter

from sl_maptools import CoordType, RegionsDBRecord3

DB_PATH = Path(r"C:\Cache\SL-Carto\RegionsDB3.pkl")
CUTOFF = 3

_NAO = datetime.now().astimezone()

DATABASE: dict[CoordType, RegionsDBRecord3] = {}

def main():
    global DATABASE

    with DB_PATH.open("rb") as fin:
        DATABASE.update(pickle.load(fin))

    yaml = YAML()
    yaml.Representer = RoundTripRepresenter

    region_locations: dict[str, set[CoordType]] = {}
    for co, data in DATABASE.items():
        if not data["current_name"]:
            continue
        if data["current_name"] == "Beorn City":
            with StringIO() as fout:
                yaml.dump({str(co): data}, fout)
                fout.seek(0)
                print(fout.read())
        region_locations.setdefault(data["current_name"], set()).add(co)
        for hname in data["name_history3"]:
            if not hname:
                continue
            region_locations.setdefault(hname, set()).add(co)

    for name, locs in sorted(region_locations.items()):
        if len(locs) < 2:
            continue
        print(f"{name}: {locs}")

if __name__ == '__main__':
    main()


import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome.const import CONF_ADDRESS, CONF_ID
from .. import (
    ExtraflameComponent,
    extraflame_ns,
    EXTRAFLAME_COMPONENT_SCHEMA,
    get_memory_address,
)
from ..const import CONF_EXTRAFLAME_ID, CONF_MEMORY

DEPENDENCIES = ["extraflame"]
CODEOWNERS = ["@edenhaus"]

ExtraflameSensor = extraflame_ns.class_(
    "ExtraflameSensor", ExtraflameComponent, sensor.Sensor
)

CONFIG_SCHEMA = EXTRAFLAME_COMPONENT_SCHEMA.extend(
    sensor.SENSOR_SCHEMA.extend(
        {
            cv.GenerateID(): cv.declare_id(ExtraflameSensor),
        }
    )
)

async def to_code(config):
    var = cg.new_Pvariable(
        config[CONF_ID], get_memory_address(config[CONF_MEMORY]), config[CONF_ADDRESS]
    )
    await cg.register_component(var, config)
    await sensor.register_sensor(var, config)
    await cg.register_parented(var, config[CONF_EXTRAFLAME_ID])


from typing import Any, Dict, Tuple

from gymnasium.core import ActionWrapper

class UsefulActionsWrapper(ActionWrapper):
    """
    A wrapper returning negative reward in observation doesn't change.

    >>> import gymnasium as gym
    >>> env = gym.make("Vampair-v0", max_clauses=10)
    >>> wrapped_env = UsefulActionsWrapper(env)

    although it's an action wrapper, the ``action`` method does nothing

    >>> wrapped_env.action(0)
    0
    >>> _ = wrapped_env.reset()
    >>> _, reward, _, _, _ = wrapped_env.step((0, 2))
    >>> reward
    0.0

    repeating an action is useless and results in a negative reward

    >>> _, reward, _, _, _ = wrapped_env.step((0, 2))
    >>> reward
    -1.0
    """

    def step(
        self, action: Any
    ) -> Tuple[Any, float, bool, bool, Dict[str, Any]]:
        """
        Run the ``step`` and modify ``action``.

        :param action: action selected by an agent
        :return: standard Gymnasium ``step`` results
        """
        old_state_size = len(self.env.unwrapped.state.clauses)  # type: ignore
        observation, reward, terminated, truncated, info = self.env.step(
            action
        )
        return (
            observation,
            -1.0
            if len(self.env.unwrapped.state.clauses)  # type: ignore
            == old_state_size
            else reward,
            terminated,
            truncated,
            info,
        )

    def action(self, action: Any) -> Any:
        """Return the non-modified action. Left for compatibility.

        :param action: the original  actions
        :returns: the non-modified actions
        """
        return action


from flask import Flask, request, make_response, Response, jsonify;
from flask_jwt_extended import jwt_required, get_jwt, JWTManager
from redis import Redis;
import io
import csv
import json
from configuration import Configuration;
from models import database;

app = Flask(__name__);
app.config.from_object(Configuration);

jwt = JWTManager(app);

@app.route("/", methods=["GET", "POST"])
def index():
    return "Officials page working";

@app.route("/vote", methods=["POST"])
@jwt_required()
def vote():
    if not request.files or "file" not in request.files or not request.files["file"]:
        return make_response(jsonify(message="Field file is missing."), 400);
    content = request.files["file"].stream.read().decode("utf-8");
    stream = io.StringIO(content);
    reader = csv.reader(stream);
    voteList = [];
    officialJMBG = get_jwt()["jmbg"];
    with Redis(host=Configuration.REDIS_HOST, port=6379) as redis:
        i = 0;
        for row in reader:
            if len(row) != 2:
                return make_response(jsonify(message=("Incorrect number of values on line {}.".format(i))), 400);
            try:
                voteData = {
                    "guid": row[0],
                    "pollNumber": int(row[1]),
                    "officialJMBG": officialJMBG
                }
                if voteData["pollNumber"] <= 0:
                    raise ValueError;
            except ValueError:
                return make_response(jsonify(message=("Incorrect poll number on line {}.".format(i))), 400);
            voteList.append(voteData);
            i = i + 1;

        voteList.reverse();
        print(voteList);

        for voteData in voteList:
            redis.lpush(Configuration.REDIS_VOTES_LIST, json.dumps(voteData));

    return Response(status=200);

if __name__ == "__main__":
    database.init_app(app);
    app.run(debug=True, host="0.0.0.0", port=5003);


from collections import defaultdict

dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]

def bfs(v, y, x, edges):
    n = len(v)
    m = len(v[0])

    q = [(y, x)]
    vis = set()
    vis.add((y, x))

    while len(q) > 0:
        (y, x) = q.pop(0)

        for i in range(4):
            ny = y + dy[i]
            nx = x + dx[i]

            if ny < 0 or nx < 0 or ny == n or nx == m: continue
            if v[y][x] != v[ny][nx]:
                edges[v[y][x]].add(v[ny][nx])
            if (ny, nx) not in vis:
                vis.add((ny, nx))
                q.append((ny, nx))

def check(edges, color):
    for x, v in edges.items():
        for y in v:
            if color[x] == color[y]: return False
    return True

def dfs(x, c, edges, color):
    if x == len(edges):
        return check(edges, color)
    for i in range(c):
        color[list(edges.keys())[x]] = i
        if dfs(x + 1, c, edges, color): return True
    return False

def can_color(c, edges):
    return dfs(0, c, edges, {})

def color(testmap):
    edges = defaultdict(set)
    bfs(testmap.strip().split('\n'), 0, 0, edges)

    if len(edges) <= 1: return 1
    if can_color(2, edges): return 2
    if can_color(3, edges): return 3
    return 4

codewars/4kyu/4_Four Color Theorem (Easy Version).py


import pygame
from settings import *
from mainSolver import *

class Visualizer:
    def __init__(self, words: dict[str, int]) -> None:
        pygame.init()
        self.screen = pygame.display.set_mode((width, height))
        pygame.display.set_caption(title)
        self.clock = pygame.time.Clock()
        self.running = True
        self.font_name = pygame.font.match_font(font_name)
        self.word_bank = words
        self.text = ""
        self.all_words = None
        self.solver = None
        self.all_word_comb = {}

    def show_start_screen(self) -> None:
        self.screen.fill(black)
        self.draw_text(title, 48, white, width / 2, height / 4)
        self.draw_text("Enter 16 letters for a 4x4 board", 22, white, width / 2, height / 2)
        self.input()

    def input(self) -> None:
        waiting = True
        while waiting:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    waiting = False
                    self.running = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_BACKSPACE:
                        self.text = self.text[:-1]
                    elif event.key == pygame.K_RETURN:
                        if len(self.text) < 16:
                            self.draw_text("Not enough letters", 22, white, width / 2, height * 4/5)
                        else:
                            waiting = False
                    else:
                        self.text += event.unicode
            input_rect = pygame.Rect(185, 400, 230, 32)
            pygame.draw.rect(self.screen, white, input_rect)
            base_font = pygame.font.Font(None, 32)
            text_surface = base_font.render(self.text, True, black)
            self.screen.blit(text_surface, (input_rect.x + 5, input_rect.y + 5))
            pygame.display.flip()
            self.clock.tick(fps)

    def new(self) -> None:
        if self.running:
            self.solver = WordHuntSolverDict(self.text, self.word_bank)
            self.solver.all_comb()
            for i in sorted(self.solver.comb, key=len, reverse=True):
                self.all_word_comb[i] = self.solver.comb[i]
            self.all_words = list(self.all_word_comb.keys())
            word_num = 0
            while word_num < len(self.all_words) and self.running:
                self.screen.fill(black)
                self.draw_map()
                pygame.display.flip()
                self.draw_words(word_num)
                word_num += 1
                self.clock.tick(fps)

    def end(self) -> None:
        while self.running:
            mouse = pygame.mouse.get_pos()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if width/3 <= mouse[0] <= width/3+200 and height * 2/3 <= mouse[1] <= height * 2/3 + 60:
                        self.running = False
                    if width/3 <= mouse[0] <= width/3+200 and height / 3 <= mouse[1] <= height / 3 + 60:
                        self.text = ""
                        self.all_words = None
                        self.solver = None
                        self.all_word_comb = {}
                        self.run()
            self.screen.fill(black)
            if width/3 <= mouse[0] <= width/3+200 and height / 3 <= mouse[1] <= height / 3 + 60:
                pygame.draw.rect(self.screen, green, [width/3, height / 3, 200, 60])
            else:
                pygame.draw.rect(self.screen, color_dark, [width/3, height / 3, 200, 60])
            if width/3 <= mouse[0] <= width/3+200 and height * 2/3 <= mouse[1] <= height * 2/3 + 60:
                pygame.draw.rect(self.screen, green, [width/3, height * 2/3, 200, 60])
            else:
                pygame.draw.rect(self.screen, color_dark, [width/3, height * 2/3, 200, 60])
            self.draw_text("Restart", 48, white, width / 2, height / 3)
            self.draw_text("Quit", 48, white, width / 2, height * 2/3)
            pygame.display.flip()

    def run(self) -> None:
        self.show_start_screen()
        self.new()
        self.end()

    def draw_map(self) -> None:
        self.draw_text(self.text[0], 48, white, 125, 75)
        self.draw_text(self.text[1], 48, white, 250, 75)
        self.draw_text(self.text[2], 48, white, 375, 75)
        self.draw_text(self.text[3], 48, white, 500, 75)
        self.draw_text(self.text[4], 48, white, 125, 200)
        self.draw_text(self.text[5], 48, white, 250, 200)
        self.draw_text(self.text[6], 48, white, 375, 200)
        self.draw_text(self.text[7], 48, white, 500, 200)
        self.draw_text(self.text[8], 48, white, 125, 325)
        self.draw_text(self.text[9], 48, white, 250, 325)
        self.draw_text(self.text[10], 48, white, 375, 325)
        self.draw_text(self.text[11], 48, white, 500, 325)
        self.draw_text(self.text[12], 48, white, 125, 450)
        self.draw_text(self.text[13], 48, white, 250, 450)
        self.draw_text(self.text[14], 48, white, 375, 450)
        self.draw_text(self.text[15], 48, white, 500, 450)

    def draw_words(self, word_num: int) -> None:
        curr_word = self.all_words[word_num]
        for i in range(len(self.all_word_comb[curr_word][1])):
            location = self.all_word_comb[curr_word][0][i]
            num_x, num_y = 125 * location[0], 125 * location[1]
            if self.all_word_comb[curr_word][1][i] == 'right':
                arrow = ((150 + num_x, 100 + num_y), (150 + num_x, 110 + num_y), (190 + num_x, 110 + num_y), (190 + num_x, 120 + num_y), (225 + num_x, 105 + num_y), (190 + num_x, 90 + num_y), (190 + num_x, 100 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'left':
                arrow = ((100 + num_x, 100 + num_y), (100 + num_x, 110 + num_y), (60 + num_x, 110 + num_y), (60 + num_x, 120 + num_y), (25 + num_x, 105 + num_y), (60 + num_x, 90 + num_y), (60 + num_x, 100 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'up':
                arrow = ((120 + num_x, 80 + num_y), (130 + num_x, 80 + num_y), (130 + num_x, 50 + num_y), (140 + num_x, 50 + num_y), (125 + num_x, 25 + num_y), (110 + num_x, 50 + num_y), (120 + num_x, 50 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'down':
                arrow = ((120 + num_x, 145 + num_y), (130 + num_x, 145 + num_y), (130 + num_x, 175 + num_y), (140 + num_x, 175 + num_y), (125 + num_x, 200 + num_y), (110 + num_x, 175 + num_y), (120 + num_x, 175 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'left_up':
                arrow = ((95 + num_x, 85 + num_y), (105 + num_x, 75 + num_y), (40 + num_x, 10 + num_y), (50 + num_x, num_y), (20 + num_x, num_y), (20 + num_x, 30 + num_y), (30 + num_x, 20 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'left_down':
                arrow = ((105 + num_x, 135 + num_y), (95 + num_x, 125 + num_y), (30 + num_x, 190 + num_y), (20 + num_x, 180 + num_y), (20 + num_x, 210 + num_y), (50 + num_x, 210 + num_y), (40 + num_x, 200 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'right_up':
                arrow = ((145 + num_x, 75 + num_y), (155 + num_x, 85 + num_y), (220 + num_x, 20 + num_y), (230 + num_x, 30 + num_y), (230 + num_x, num_y), (200 + num_x, num_y), (210 + num_x, 10 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            elif self.all_word_comb[curr_word][1][i] == 'right_down':
                arrow = ((155 + num_x, 125 + num_y), (145 + num_x, 135 + num_y), (210 + num_x, 200 + num_y), (200 + num_x, 210 + num_y), (230 + num_x, 210 + num_y), (230 + num_x, 180 + num_y), (220 + num_x, 190 + num_y))
                pygame.draw.polygon(self.screen, white, arrow)
            self.draw_text('The word is: %s' % curr_word, 48, white, 250, 525)
        pygame.display.flip()
        self.events()

    def events(self) -> None:
        waiting = True
        while waiting:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        waiting = False
                if event.type == pygame.QUIT:
                    waiting = False
                    self.running = False

    def draw_text(self, text, size, color, x, y) -> None:
        font = pygame.font.Font(self.font_name, size)
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect()
        text_rect.midtop = (x, y)
        self.screen.blit(text_surface, text_rect)

g = Visualizer(all_words)
g.run()


import argparse
import json
import logging
import os
from pathlib import Path
from traceback import format_exc
from typing import List, IO, Dict, Any

class Config(object):
    DIR_KEY: str = "_dir"
    FILE_KEY: str = "_file"

    # Command line arguments take precedence over config file values
    def __init__(self, name: str, args: Dict):
        self.name = name
        self.base_dir = f"{Path.home()}/.{name}"
        self._defaults = {}
        self.conf = {}

        try:
            # the slash does work either way on windows, but including a standard one for compatibility
            conf_file_locations: List[str] = [args.get('config_file', ''),
                                              f"{self.base_dir}/config.json",
                                              f"{os.getcwd()}/config.json",
                                              f"{os.getcwd()}\\config.json"]

            f = self._open_config(conf_file_locations)
            conf: Dict = json.load(f)
            # We want to remove all the keys with value None so that the merge works as expected. At this point
            # writing our own merge method that does all of this in one pass is prob more efficient but not worth the
            # effort.args is of type Namespace, we want a dict, hence vars()

            # In this merge, command line arguments take precedence over config file values, which take precedence over
            # hardcoded default values
            self.conf: Dict = {**self.defaults(), **conf, **args}
        except Exception as ex:
            logging.error(f"Failed to initialize {self.name}: {repr(ex)}")
            logging.debug(format_exc())

    def defaults(self):
        return self._defaults

    @classmethod
    def from_args(cls, name: str, args: argparse.Namespace):
        args_dict: Dict = {k: v for k, v in vars(args).items() if v is not None}
        return cls(name, args_dict)

    def _open_config(self, paths: List[str]) -> IO:
        for p in paths:
            try:
                f = open(p, 'r')
                logging.info(f"Using config file at {p}")
                return f
            except OSError as err:
                logging.debug(f"Could not find/open config file {p}: {repr(err)}")

        logging.error("Failed to find any configuration file. Exiting")

    def __getitem__(self, key: str) -> Any:
        attr = ''  # type checker error if not defined

        try:
            attr = self.conf[key]
        except KeyError:
            logging.warning(f"Property {key} not found in configuration")
            return None

        # Some smarts to try and provide absolute paths when the attribute requested is a dir or a file
        if key.endswith(self.DIR_KEY) or key.endswith(self.FILE_KEY):
            logging.debug(f"Converted {attr} to a path because it ({key}) ends with {self.DIR_KEY} or {self.FILE_KEY}")
            try:
                attr = Path(attr).resolve()
            except TypeError:
                logging.error(f"Tried to convert {attr} to a Path but failed.")
                logging.debug(format_exc())
        return attr

    def __setitem__(self, key: str, value: Any) -> None:
        # We really probably don't want to be overwriting any of our config stuff, but don't prevent it
        if key in self.conf:
            logging.warning(f"Overwriting {key} with value {value} (previously {self.conf[value]}")
        else:
            logging.debug(f"Setting {key} to {value}")

        self.conf[key] = value


import sqlite3

connection = sqlite3.connect('banco.db')
cursor = connection.cursor()

create_table = "CREATE TABLE IF NOT EXISTS hoteis(hotel_id text PRIMARY KEY, \
  nome text, estrelas real, diaria real, cidade text)"

insert_hotel = "INSERT INTO hoteis VALUES('1','hOTEL PIrata',4.5,180.50,'Fortaleza')"

cursor.execute(create_table)

cursor.execute(insert_hotel)

connection.commit()

connection.close()


#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets

style = '''
    QDialog{
        border:4px solid green;
    }

    QPushButton
    {
        color: rgb(255, 255, 255);
        background-color: rgb(167, 205, 255);
        background: green;
        border:none;
        font-family: "Verdana";
        font-size: 15px;
        text-align: center;
        width: 60px;
    }
    QPushButton:hover, QPushButton:pressed , QPushButton:checked
    {
        background-color: rgb(85, 170, 255);
        text-align: center;
        font-family: "Verdana";
    }
    QPushButton:hover
    {
        background-repeat:no-repeat;
        background-position: center left;
    }
    QPushButton:pressed, QPushButton:checked
    {
        background-repeat:no-repeat;
        background-position: center left;
    }

    QPushButton:disabled{
        color: gray;
        background-color: rgb(167, 205, 255);
    }

    QLineEdit {
        padding: 1px;
        border-style: solid;
        border: 2px solid lightgray;
        border-radius: 8px;
        width:40px;
        height: 30px;
    }
'''

class BaseDialog(QtWidgets.QDialog):

    def __init__(self, styleoptions, parent=None):
        super(BaseDialog, self).__init__(parent)
        title = styleoptions['title']
        windowicon = styleoptions['windowicon']
        minsize = styleoptions['minsize']
        size = styleoptions['size']
        logo_title = styleoptions['logo_title']
        logo_img_url = styleoptions['logo_img_url']

        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(windowicon))  # 设置程序图标
        self.setMinimumSize(minsize[0], minsize[1])
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowMinimizeButtonHint)  # 无边框， 带系统菜单， 可以最小化

        self.logowidget = DynamicTextWidget(logo_title, logo_img_url)

        # 主布局
        mainlayout = QtWidgets.QVBoxLayout()
        mainlayout.addWidget(self.logowidget)
        self.setLayout(mainlayout)

        self.setStyleSheet(style) # 设置主窗口样式
        self.resize(size[0], size[1])

    def mousePressEvent(self, event):
        # 鼠标点击事件
        if event.button() == QtCore.Qt.LeftButton:
            self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()
            event.accept()

    def mouseReleaseEvent(self, event):
        # 鼠标释放事件
        if hasattr(self, "dragPosition"):
            del self.dragPosition

    def mouseMoveEvent(self, event):
        # 鼠标移动事件
        if hasattr(self, "dragPosition"):
            if event.buttons() == QtCore.Qt.LeftButton:
                self.move(event.globalPos() - self.dragPosition)
                event.accept()

class DynamicTextWidget(QtWidgets.QWidget):
    def __init__(self, text, bg, parent=None):
        super(DynamicTextWidget, self).__init__(parent)
        self.setFixedSize(443, 132)
        self.bg = bg
        self.text = text

        newFont = self.font()
        newFont.setPointSize(newFont.pointSize() + 10)
        self.setFont(newFont)

        self.painter = QtGui.QPainter()

        self.timer = QtCore.QBasicTimer()

        self.step = 0
        self.timer.start(60, self)

    def paintEvent(self, event):
        self.painter.begin(self)
        self.drawBackground(self.painter)
        self.drawDynamicText(self.painter)
        self.painter.end()

    def set_painterpencolor(self, painter):
        color = QtGui.QColor()
        import random
        i = random.randint(1, 15)
        color.setHsv((15 - i) * 16, 255, 191)
        painter.setPen(color)

    def drawBackground(self, painter):
        painter.drawPixmap(0, 0, self.width(), self.height(), QtGui.QPixmap(self.bg))

    def drawDynamicText(self, painter):
        sineTable = (0, 38, 71, 92, 100, 92, 71, 38, 0, -38, -71, -92, -100, -92, -71, -38)
        metrics = QtGui.QFontMetrics(self.font())
        x = (self.width() - metrics.width(self.text)) / 2
        y = (self.height() + metrics.ascent() - metrics.descent()) / 2
        color = QtGui.QColor()

        for i, ch in enumerate(self.text):
            index = (self.step + i) % 16
            color.setHsv((15 - index) * 16, 255, 191)
            painter.setPen(color)
            painter.drawText(x, y - ((sineTable[index] * metrics.height()) / 400), ch)
            x += metrics.width(ch)

    def setText(self, newText):
        self.text = newText

    def setspreed(self, spreed):
        self.spreed = spreed
        self.timer.stop()
        self.timer.start(self.spreed, self)

    def timerEvent(self, event):
        if self.text:
            if event.timerId() == self.timer.timerId():
                self.step += 1
                self.update()
            else:
                super(DynamicTextWidget, self).timerEvent(event)
        else:
            self.timer.stop()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    styleoptions = {
        'title': u'退出设置',
        'windowicon': "../skin/images/ov-orange-green.png",
        'minsize': (400, 300),
        'size': (400, 300),
        'logo_title': u'dssssssss',
        'logo_img_url': "../skin/images/ov-orange-green.png"
    }
    dialog = BaseDialog(styleoptions)
    dialog.show()
    sys.exit(app.exec_())