import inspect
import logging
from datetime import datetime
from typing import Optional, List

import strawberry

from felicity.apps.analysis import schemas
from felicity.apps.analysis.conf import states
from felicity.apps.analysis.models import results as result_models
from felicity.apps.patient.models import logger
from felicity.gql import auth_from_info, verify_user_auth
from felicity.gql.analysis.types import analysis as a_types
from felicity.gql.analysis.types import results as r_types
from felicity.utils import get_passed_args

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@strawberry.input
class ARSampleInputType:
    sample_type: int
    profiles: List[int]
    analyses: List[int]

@strawberry.input
class ARResultInputType:
    uid: int
    result: str
    reportable: Optional[bool] = True

@strawberry.input
class QCSetInputType:
    qcTemplateUid: Optional[int]
    qcLevels: List[int]
    analysisProfiles: List[int]
    analysisServices: List[int]

@strawberry.type
class CreateQCSetData:
    samples: List[a_types.SampleType]
    qc_sets: List[a_types.QCSetType]

@strawberry.input
class SampleRejectInputType:
    uid: int
    reasons: List[int]
    other: Optional[str] = None

@strawberry.mutation
async def submit_analysis_results(self, info, analysis_results: List[ARResultInputType]) -> List[r_types.AnalysisResultType]:
    inspector = inspect.getargvalues(inspect.currentframe())
    passed_args = get_passed_args(inspector)

    is_authenticated, felicity_user = await auth_from_info(info)
    verify_user_auth(is_authenticated, felicity_user, "Only Authenticated user can submit analysis results")

    return_results = []

    if len(analysis_results) == 0:
        raise Exception(f"No Results to update are provided!")

    for _ar in analysis_results:
        uid = _ar.uid
        a_result: result_models.AnalysisResult = await result_models.AnalysisResult.get(uid=uid)
        if not a_result:
            raise Exception(f"AnalysisResult with uid {uid} not found")

        # only submit results in pending state
        if a_result.status not in [states.result.PENDING]:
            return_results.append(a_result)
            continue

        analysis_result = a_result.to_dict(nested=False)
        for field in analysis_result:
            if field in _ar.__dict__.keys():
                try:
                    setattr(a_result, field, getattr(_ar, field, None))
                except AttributeError as e:
                    logger.warning(e)

        # No Empty Results
        result = getattr(a_result, 'result', None)
        if not result or result.strip() == '' or len(result.strip()) == 0:
            setattr(a_result, 'result', None)
        else:
            setattr(a_result, 'status', states.result.RESULTED)

            # set submitter ad date_submitted
            setattr(a_result, 'submitted_by_uid', felicity_user.uid)
            setattr(a_result, 'date_submitted', datetime.now())

            # set updated_by
            try:
                setattr(a_result, 'updated_by_uid', felicity_user.uid)
            except AttributeError as e:
                pass

        a_result_in = schemas.AnalysisResultUpdate(**a_result.to_dict())
        a_result = await a_result.update(a_result_in)

        # try to submit sample
        if a_result.sample:
            await a_result.sample.submit(submitted_by=felicity_user)

        # try to submit associated worksheet
        if a_result.worksheet_uid:
            await a_result.worksheet.submit(submitter=felicity_user)

        return_results.append(a_result)
    return return_results

@strawberry.mutation
async def verify_analysis_results(self, info, analyses: List[int]) -> List[r_types.AnalysisResultType]:
    inspector = inspect.getargvalues(inspect.currentframe())
    passed_args = get_passed_args(inspector)

    is_authenticated, felicity_user = await auth_from_info(info)
    verify_user_auth(is_authenticated, felicity_user, "Only Authenticated user can verify analysis results")

    return_results = []

    if len(analyses) == 0:
        raise Exception(f"No analyses to verify are provided!")

    for _ar_uid in analyses:
        a_result: result_models.AnalysisResult = await result_models.AnalysisResult.get(uid=_ar_uid)
        if not a_result:
            raise Exception(f"AnalysisResult with uid {_ar_uid} not found")

        # No Empty Results
        status = getattr(a_result, 'status', None)
        if status == states.result.RESULTED:
            a_result = await a_result.verify(verifier=felicity_user)
            return_results.append(a_result)
        else:
            continue

        # TODO: optimisation -> reduce db-calls
        #  Avoid calling verify sample & verify worksheet len(analyses) times
        #  However create "set" holder variables and hold sample, worksheet ids
        #  after the for loop has completed, then try verify linkages

        # try to verify associated sample
        if a_result.sample:
            await a_result.sample.verify(verified_by=felicity_user)

        # try to submit associated worksheet
        if a_result.worksheet_uid:
            await a_result.worksheet.verify(verified_by=felicity_user)

    return return_results

@strawberry.mutation
async def retract_analysis_results(self, info, analyses: List[int]) -> List[r_types.AnalysisResultType]:
    inspector = inspect.getargvalues(inspect.currentframe())
    passed_args = get_passed_args(inspector)

    is_authenticated, felicity_user = await auth_from_info(info)
    verify_user_auth(is_authenticated, felicity_user, "Only Authenticated user can retract analysis results")

    return_results = []

    if len(analyses) == 0:
        raise Exception(f"No analyses to retract are provided!")

    for _ar_uid in analyses:
        a_result: result_models.AnalysisResult = await result_models.AnalysisResult.get(uid=_ar_uid)
        if not a_result:
            raise Exception(f"AnalysisResult with uid {_ar_uid} not found")

        retest, a_result = await a_result.retest_result(retested_by=felicity_user, next_action="retract")

        # if in worksheet then keep add retest to ws
        if a_result.worksheet_uid:
            retest.worksheet_uid = a_result.worksheet_uid
            retest.worksheet_position = a_result.worksheet_position
            retest.assigned = True
            retest = await retest.save()

        # add retest
        if retest:
            return_results.append(retest)

        # add original
        return_results.append(a_result)
    return return_results

@strawberry.mutation
async def retest_analysis_results(self, info, analyses: List[int]) -> List[r_types.AnalysisResultType]:
    inspector = inspect.getargvalues(inspect.currentframe())
    passed_args = get_passed_args(inspector)

    is_authenticated, felicity_user = await auth_from_info(info)
    verify_user_auth(is_authenticated, felicity_user, "Only Authenticated user can retest analysis results")

    return_results = []

    if len(analyses) == 0:
        raise Exception(f"No analyses to Retest are provided!")

    for _ar_uid in analyses:
        a_result: result_models.AnalysisResult = await result_models.AnalysisResult.get(uid=_ar_uid)
        if not a_result:
            raise Exception(f"AnalysisResult with uid {_ar_uid} not found")

        retest, a_result = await a_result.retest_result(retested_by=felicity_user, next_action="verify")
        if retest:
            return_results.append(retest)
        return_results.append(a_result)

    return return_results

@strawberry.mutation
async def cancel_analysis_results(self, info, analyses: List[int]) -> List[r_types.AnalysisResultType]:
    inspector = inspect.getargvalues(inspect.currentframe())
    passed_args = get_passed_args(inspector)

    is_authenticated, felicity_user = await auth_from_info(info)
    verify_user_auth(is_authenticated, felicity_user, "Only Authenticated user can cancel analysis results")

    return_results = []

    if len(analyses) == 0:
        raise Exception(f"No analyses to Retest are provided!")

    for _ar_uid in analyses:
        a_result: result_models.AnalysisResult = await result_models.AnalysisResult.get(uid=_ar_uid)
        if not a_result:
            raise Exception(f"AnalysisResult with uid {_ar_uid} not found")

        a_result = await a_result.cancel(cancelled_by=felicity_user)
        if a_result:
            return_results.append(a_result)

    return return_results

@strawberry.mutation
async def re_instate_analysis_results(self, info, analyses: List[int]) -> List[r_types.AnalysisResultType]:
    inspector = inspect.getargvalues(inspect.currentframe())
    passed_args = get_passed_args(inspector)

    is_authenticated, felicity_user = await auth_from_info(info)
    verify_user_auth(is_authenticated, felicity_user, "Only Authenticated user can re instate cancelled analysis "
                                                      "results")

    return_results = []

    if len(analyses) == 0:
        raise Exception(f"No analyses to Reinstate are provided!")

    for _ar_uid in analyses:
        a_result: result_models.AnalysisResult = await result_models.AnalysisResult.get(uid=_ar_uid)
        if not a_result:
            raise Exception(f"AnalysisResult with uid {_ar_uid} not found")

        a_result = await a_result.re_instate(re_instated_by=felicity_user)
        if a_result:
            return_results.append(a_result)

    return return_results


from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import *
from decodeur import *
import platform
from PIL import ImageTk
from PIL import Image

def Guide(self):

	# MENU PRINCIPAL
	def Accueil():
		# Suppression FenConf de la rubrique (si ouverte)
		cadre.grid_remove()
		boutonFermerRub.grid_remove()

		# Affichage menu
		label.grid(row=0, column=0, padx=5, pady=5)
		bouton1.grid(row=1, column=0, padx=5, pady=5, sticky='EW')
		bouton2.grid(row=2, column=0, padx=5, pady=5, sticky='EW')
		bouton3.grid(row=3, column=0, padx=5, pady=5, sticky='EW')
		bouton4.grid(row=4, column=0, padx=5, pady=5, sticky='EW')
		bouton5.grid(row=5, column=0, padx=5, pady=5, sticky='EW')
		boutonFermer.grid(row=6, column=0, padx=5, pady=5)

	# MODÈLE DE RUBRIQUE
	def Afficher(type):
		# Suppression FenConf du menu
		label.grid_remove()
		bouton1.grid_remove()
		bouton2.grid_remove()
		bouton3.grid_remove()
		bouton4.grid_remove()
		bouton5.grid_remove()
		boutonFermer.grid_remove()

		# Ouverture fichier texte de la rubrique
		fichier = open("Guide/"+type+".nonote", 'r', encoding='utf-8')
		varFichier = fichier.read()
		fichier.close()

		# Configuration du widget de texte
		cadre.delete("0.0", END)

		### Décodage

		balises = ['GRAS', 'JAUNE', 'T1', 'AVERTISSEMENT', 'CODE']
		cadre.insert(END, FichSupprBalises(balises, varFichier))

		for i in balises:
			p1 = FichChPositions(balises, varFichier, i)
			p2 = FichChPositions(balises, varFichier, "/"+i)
			ii = 0
			while ii < len(p2):
				cadre.tag_add(i, p1[ii], p2[ii])
				ii += 1

		### Insertion des images

		self.imagesGuide = []
		listeUrlImage = FichChercherImages(varFichier)

		if len(listeUrlImage) > 0:
			for i in listeUrlImage:
				try:
					self.imagesGuide.append(ImageTk.PhotoImage\
					(Image.open("Guide/Images/"+i), name=i))
				except:
					pass

			listePositionsImage = FichChPositionsImages(varFichier)

			i = 0
			while i < len(self.imagesGuide):
				cadre.image_create(listePositionsImage[i],
				image=self.imagesGuide[i])
				i += 1

		police = font.Font(family='Times', size=10)
		cadre.config(highlightthickness=0, wrap='word', width=35, height=15,
		font=police)

		# Affichage de la rubrique
		cadre.grid(row=0, column=0)
		boutonFermerRub.grid(row=1, column=0)

	# TYPES DE RUBRIQUES
	def Presentation():
		Afficher("presentation")

	def Tuto():
		Afficher("tuto")

	def Classer():
		Afficher("classer")

	def Avance():
		Afficher("avance")

	def Technique():
		Afficher("technique")

	# FENÊTRE
	Fenetre = Toplevel()

	# Propriétés de la fenêtre
	if platform.system() == "Windows":
		Fenetre.iconbitmap('Icones\logo.ico')

	Fenetre.title("Guide")
	Fenetre.resizable(False,False)

	# Widgets du menu
	label = Label(Fenetre, text="\
Bienvenue dans le guide, vous pouvez\n\
garder cette fenêtre ouverte tout en\n\
utilisant Nonote.")

	bouton1 = ttk.Button(Fenetre, text="Présentation du logiciel",
	command=Presentation)
	bouton2 = ttk.Button(Fenetre, text="Ma première note",
	command=Tuto)
	bouton3 = ttk.Button(Fenetre, text="Gérer et Classer ses notes",
	command=Classer)
	bouton4 = ttk.Button(Fenetre, text="Fonctions avancées",
	command=Avance)
	bouton5 = ttk.Button(Fenetre, text="Informations Techniques",
	command=Technique)
	boutonFermer = ttk.Button(Fenetre, text="Fermer",
	command=Fenetre.destroy)

	# Widgets pour les rubriques
	cadre = ScrolledText(Fenetre)

	PoliceGras = font.Font(family='Times', weight='bold', size=10)
	PoliceT1 = font.Font(family='Times', size=16, weight='bold')
	PoliceCode = font.Font(family="Liberation Mono", size=10)

	cadre.tag_configure("GRAS", font=PoliceGras)
	cadre.tag_configure("CODE", font=PoliceCode)
	cadre.tag_configure("JAUNE", background="#FFFF00")
	cadre.tag_configure("T1", font=PoliceT1)

	boutonFermerRub = ttk.Button(Fenetre, text="Fermer", command=Accueil)

	# Envoi du menu
	Accueil()

	Fenetre.mainloop()


import csv
import os

filename = "model_table_Q3"
f = open(os.path.dirname(__file__)+"/"+filename+".csv",'r')
csvreader = csv.reader(f)
header = next(csvreader)
nocols = len(header)

table_type = '|c'*nocols+'|'
cmd = "\\begin{tabular}{"+table_type+"} \n \\hline \n"

def rowtoline(row, roundoff = False):
    n = 0
    line = ''
    for col in row:
        if n == 0:
            line += col
            n += 1
        else:
            if roundoff == True:
                col_float = float(col)
                col_rounded = round(col_float,2)
                col = str(col_rounded)
            line += ' & ' + col
    line += '\\\\ \n'
    return line

head_line = rowtoline(header)
cmd += head_line + '\\hline \n'

for row in csvreader:

    line = rowtoline(row,roundoff = False)
    cmd += line + '\\hline \n'

cmd += "\\end{tabular}"

print(cmd)


# 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 http://mozilla.org/MPL/2.0/.
import pytest
import requests
import requests_mock

from landoui.landoapi import (
    LandoAPI,
    LandoAPIError,
    LandoAPICommunicationException,
)

@pytest.mark.parametrize(
    "exc",
    [
        requests.ConnectionError,
        requests.Timeout,
        requests.ConnectTimeout,
        requests.TooManyRedirects,
    ],
)
def test_raise_communication_exception_on_request_exceptions(api_url, exc):
    api = LandoAPI(api_url)
    with requests_mock.mock() as m:
        m.get(api_url + "/stacks/D1", exc=exc)

        with pytest.raises(LandoAPICommunicationException):
            api.request("GET", "stacks/D1")

        assert m.called

def test_raise_communication_exception_on_invalid_json(api_url):
    api = LandoAPI(api_url)
    with requests_mock.mock() as m:
        m.get(api_url + "/stacks/D1", text="invalid } json {[[")

        with pytest.raises(LandoAPICommunicationException):
            api.request("GET", "stacks/D1")

        assert m.called

@pytest.mark.parametrize(
    "status, body",
    [
        (404, "[]"),
        (500, "{}"),
        (500, '{"detail": "detail", "instance": "instance"}'),
        (400, "{}"),
        (401, "{}"),
    ],
)
def test_raise_error_exception_on_error_response(api_url, status, body):
    api = LandoAPI(api_url)
    with requests_mock.mock() as m:
        m.get(api_url + "/stacks/D1", status_code=status, text=body)

        with pytest.raises(LandoAPIError):
            api.request("GET", "stacks/D1")

        assert m.called

def test_raise_error_with_details_on_error_response(api_url):
    api = LandoAPI(api_url)
    error = {
        "detail": "Couldn't find it",
        "status": 404,
        "title": "Not Found",
        "type": "about:blank",
    }
    with requests_mock.mock() as m:
        m.get(api_url + "/stacks/D1", status_code=error["status"], json=error)

        with pytest.raises(LandoAPIError) as exc_info:
            api.request("GET", "stacks/D1")

        assert m.called
        assert exc_info.value.detail == error["detail"]
        assert exc_info.value.title == error["title"]
        assert exc_info.value.type == error["type"]
        assert exc_info.value.status_code == error["status"]
        assert exc_info.value.response == error
        assert exc_info.value.instance is None

def test_phabricator_api_token_in_request_header(api_url):
    api = LandoAPI(api_url, phabricator_api_token="api_token")
    with requests_mock.mock() as m:
        m.get(
            api_url + "/stacks/D1",
            request_headers={"X-Phabricator-API-Key": "api_token"},
            status_code=404,
            text="{}",
        )

        # NoMockAddress would be raised for the wrong header
        with pytest.raises(LandoAPIError):
            api.request("GET", "stacks/D1")

        assert m.called


from textblob import TextBlob
import tweepy
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import nltk
import re
import string
import warnings

from wordcloud import WordCloud
from PIL import Image
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from sklearn.feature_extraction.text import CountVectorizer
from IPython.display import display

# Twitter API authentication codes
access_token = "***"
access_token_secret = "***"
consumer_key = "***"
consumer_key_secret = "***"
bearer_token = "***"
client_id = "***"
client_secret = "***"

auth = tweepy.OAuthHandler(consumer_key, consumer_key_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth, wait_on_rate_limit=True)

warnings.filterwarnings("ignore", category=DeprecationWarning) # depricationwarning on piechart

# to be used in PieChart
def percentage(part, whole):
    return 100 * float(part)/float(whole)

keyword = input("please enter keyword or hashtag to search: ")
noOfTweet = int(input("please enter how many tweets to analyze: "))

tweets = tweepy.Cursor(api.search_tweets, lang='en', q=keyword).items(noOfTweet)
positive = 0
negative = 0
neutral = 0
polarity = 0
tweet_list = []
neutral_list = []
negative_list = []
positive_list = []

for tweet in tweets:
    tweet_list.append(tweet.text)
    analysis = TextBlob(tweet.text)
    score = SentimentIntensityAnalyzer().polarity_scores(tweet.text)
    neg = score['neg']
    neu = score['neu']
    pos = score['pos']
    comp = score['compound']
    polarity += analysis.sentiment.polarity

    if neg > pos:
        negative_list.append(tweet.text)
        negative += 1

    elif pos > neg:
        positive_list.append(tweet.text)
        positive += 1

    elif pos == neg:
        neutral_list.append(tweet.text)
        neutral += 1

positive = percentage(positive, noOfTweet)
negative = percentage(negative, noOfTweet)
neutral = percentage(neutral, noOfTweet)
polarity = percentage(polarity, noOfTweet)
positive = format(positive, '.1f')
negative = format(negative, '.1f')
neutral = format(neutral, '.1f')

tweet_list = pd.DataFrame(tweet_list)
neutral_list = pd.DataFrame(neutral_list)
negative_list = pd.DataFrame(negative_list)
positive_list = pd.DataFrame(positive_list)
# print('total number: ', len(tweet_list))
# print('posive number: ', len(positive_list))
# print('negative number: ', len(negative_list))
# print('neutral number: ', len(neutral_list))

# create pie chart
labels = ['Positive [' + str(positive)+ '%',
          'Neutral [' + str(neutral) + '%',
          'Negative [' + str(negative) + '%']
sizes = [positive, neutral, negative]
colors = ['yellowgreen', 'blue', 'red']
patches, texts = plt.pie(sizes, colors=colors, startangle=90)
plt.style.use('default')
plt.legend(labels)
plt.title("Sentiment analysis for: "+keyword)
plt.axis('equal')
# plt.show()

tweet_list.drop_duplicates(inplace=True)

# clean text

tw_list = pd.DataFrame(tweet_list)
tw_list["text"] = tw_list[0]

# remove punct and other
remove_rt = lambda x: re.sub('RT @\w+: ', " ", x)
rt = lambda x: re.sub("(@[A-Za-z0-9]+)|([^A-Za-z0-9 \t])|(\w+:\/\/\S+)", " ", x)
tw_list['text'] = tw_list.text.map(remove_rt).map(rt)
tw_list['text'] = tw_list.text.str.lower()
# print(tw_list.head(10))

tw_list[['polarity', 'subjectivity']] = tw_list['text'].apply(lambda Text: pd.Series(TextBlob(Text).sentiment))
for index, row in tw_list['text'].iteritems():
    score = SentimentIntensityAnalyzer().polarity_scores(row)
    neg = score['neg']
    neu = score['neu']
    pos = score['pos']
    comp = score['compound']
    if neg > pos:
        tw_list.loc[index, 'sentiment'] = 'negative'
    elif pos > neg:
        tw_list.loc[index, 'sentiment'] = 'positive'
    else:
        tw_list.loc[index, 'sentiment'] = 'neutral'
    tw_list.loc[index, 'neg'] = neg
    tw_list.loc[index, 'neu'] = neu
    tw_list.loc[index, 'pos'] = pos
    tw_list.loc[index, 'compound'] = comp

# print(tw_list.head(10))

tw_list_negative = tw_list[tw_list['sentiment'] == 'negative']
tw_list_positive = tw_list[tw_list['sentiment'] == 'positive']
tw_list_neutral = tw_list[tw_list['sentiment'] == 'neutral']

# count values in single columns

def count_values_in_column(data, feature):
    total = data.loc[:, feature].value_counts(dropna=False)
    percentage = round(data.loc[:, feature].value_counts(dropna=False, normalize=True)*100, 2)
    return pd.concat([total, percentage], axis=1, keys=['Total', 'Percentage'])

print(count_values_in_column(tw_list, 'sentiment'))

def create_wordcloud(text):
    mask = np.array(Image.open("cloud.png"))
    stopwords = nltk.corpus.stopwords.words('english')
    stopwords.append('spotify')
    wc = WordCloud(background_color='white',
                   mask=mask,
                   max_words=3000,
                   stopwords=stopwords,
                   repeat=True,)
    wc.generate_from_text(str(text))
    wc.to_file("wc_clean_base.png")
    print('wordcloud saved successfully')
    path = 'wc_clean_base.png'
    display(Image.open(path))

def remove_punctuation(text):
    text = "".join([char for char in text if char not in string.punctuation])
    text = re.sub('[0-9]+', '', text)
    return text

tw_list['punct'] = tw_list['text'].apply(lambda x: remove_punctuation(x))

# apply tokenization and lower because this is the first time we access individual words
def tokenization(text):
    text = re.split('\W+', text)
    return text

tw_list['tokenized'] = tw_list['punct'].apply(lambda x: tokenization(x.lower()))

# remove stopwords
stopword = nltk.corpus.stopwords.words('english')
stopword.append(['spotify', 'th'])

def remove_stopword(text):
    text = [word for word in text if word not in stopword]
    return text

tw_list['nostop'] = tw_list['tokenized'].apply(lambda x: remove_stopword(x))

ps = nltk.PorterStemmer()  # apply porter

def stemming(text):
    text = [ps.stem(word) for word in text]
    return text

tw_list['stemmed'] = tw_list['nostop'].apply(lambda x: stemming(x))

def clean_text(text):
    text_lc = "".join([word.lower() for word in text if word not in string.punctuation])
    text_rc = re.sub('[0-9]+', '', text_lc)
    text = re.sub('(\\b[A_Za-z] \\b|\\b [A_Za-z]\\b)', ' ', text)
    tokens = re.split('\W+', text_rc)  # tokenization
    text = [ps.stem(word) for word in tokens if word not in stopword]  # removes stopwords and stemming
    return text

countVectorizer = CountVectorizer(analyzer=clean_text)
countVector = countVectorizer.fit_transform(tw_list['text'])
print('{} Number of tweets has {} words'.format(countVector.shape[0], countVector.shape[1]))

count_vect_df = pd.DataFrame(countVector.toarray(), columns=countVectorizer.get_feature_names_out())
count = pd.DataFrame(count_vect_df.sum())
countdf = count.sort_values(0, ascending=False).head(20)
print(countdf[1:11])

create_wordcloud(tw_list['text'])


import os
import threading
import time
import requests
from dokuWikiDumper.dump.content.revisions import getRevisions, save_page_changes
from dokuWikiDumper.dump.content.titles import getTitles

from dokuWikiDumper.utils.util import loadTitles, smkdirs, uopen
from dokuWikiDumper.utils.util import print_with_lock as print
from dokuWikiDumper.utils.config import running_config

HTML_DIR = 'html/'
HTML_PAGR_DIR = HTML_DIR + 'pages/'
HTML_OLDPAGE_DIR = HTML_DIR + 'attic/'

sub_thread_error = None

def dump_HTML(doku_url, dumpDir,
                  session: requests.Session, skipTo: int = 0, threads: int = 1,
                  ignore_errors: bool = False, current_only: bool = False):
    smkdirs(dumpDir, HTML_PAGR_DIR)

    titles = loadTitles(titlesFilePath=dumpDir + '/dumpMeta/titles.txt')
    if titles is None:
        titles = getTitles(url=doku_url, session=session)
        with uopen(dumpDir + '/dumpMeta/titles.txt', 'w') as f:
            f.write('\n'.join(titles))
            f.write('\n--END--\n')

    if not len(titles):
        print('Empty wiki')
        return False

    index_of_title = -1  # 0-based
    if skipTo > 0:
        index_of_title = skipTo - 2
        titles = titles[skipTo-1:]

    def try_dump_html_page(*args, **kwargs):
        try:
            dump_html_page(*args, **kwargs)
        except Exception as e:
            if not ignore_errors:
                global sub_thread_error
                sub_thread_error = e
                raise e
            print('[',args[1]+1,']Error in sub thread: (', e, ') ignored')
    for title in titles:
        while threading.active_count() > threads:
            time.sleep(0.1)
        if sub_thread_error:
            raise sub_thread_error

        index_of_title += 1
        t = threading.Thread(target=try_dump_html_page, args=(dumpDir,
                                                    index_of_title,
                                                    title,
                                                    doku_url,
                                                    session,
                                                    current_only))
        print('HTML: (%d/%d): [[%s]] ...' % (index_of_title+1, len(titles), title))
        t.daemon = True
        t.start()

    while threading.active_count() > 1:
        time.sleep(2)
        print('Waiting for %d threads to finish' %
            (threading.active_count() - 1), end='\r')

def dump_html_page(dumpDir, index_of_title, title, doku_url, session: requests.Session, current_only: bool = False):
    r = session.get(doku_url, params={'do': running_config.export_xhtml_action, 'id': title})
    # export_html is a alias of export_xhtml, but not exist in older versions of dokuwiki
    r.raise_for_status()
    if r.text is None or r.text == '':
        raise Exception(f'Empty response (r.text)')

    msg_header = '['+str(index_of_title + 1)+']: '

    title2path = title.replace(':', '/')
    child_path = os.path.dirname(title2path)
    html_path = dumpDir + '/' + HTML_PAGR_DIR + title2path + '.html'
    smkdirs(dumpDir, HTML_PAGR_DIR, child_path)
    with uopen(html_path, 'w') as f:
        f.write(r.text)
        print(msg_header, '[[%s]]' % title, 'saved')

    if current_only:
        return True

    revs = getRevisions(doku_url=doku_url, session=session, title=title, msg_header=msg_header)

    for rev in revs[1:]:
        if 'id' in rev and rev['id']:
            try:
                r = session.get(doku_url, params={'do': running_config.export_xhtml_action, 'id': title, 'rev': rev['id']})
                r.raise_for_status()
                if r.text is None or r.text == '':
                    raise Exception(f'Empty response (r.text)')
                smkdirs(dumpDir, HTML_OLDPAGE_DIR, child_path)
                old_html_path = dumpDir + '/' + HTML_OLDPAGE_DIR + title2path + '.' + rev['id'] + '.html'

                with uopen(old_html_path, 'w') as f:
                    f.write(r.text)
                print(msg_header, '    Revision %s of [[%s]] saved.' % (rev['id'], title))
            except requests.HTTPError as e:
                print(msg_header, '    Revision %s of [[%s]] failed: %s' % (rev['id'], title, e))

    save_page_changes(dumpDir=dumpDir, child_path=child_path, title=title,
                       revs=revs, msg_header=msg_header)


def ParseFile(_File):
    ReturnValue = []
    with open(_File) as InputFile:
        for InputLine in InputFile:
            ReturnValue.append(InputLine.strip())
    return ReturnValue

def ProcessInstructions(_Input):
    X = 1
    Output = [X]

    for Instruction in _Input:
        Output.append(X)
        if Instruction[:4] == "addx":
            Value = int(Instruction.split(" ")[1])
            Output.append(X + Value)
            X += Value
    return Output

def GetSignalStrengths(_CPUList, _Required):
    TotalSignal = 0
    for Value in _Required:
        TotalSignal += _CPUList[Value-1] * Value
    return TotalSignal

def GetPicture(_CPUList, _Fancy = True):
    OutputData = []
    Lit = "ðŸŸ¨"
    Dim = "â¬›"
    if not _Fancy:
        Lit = "#"
        Dim = "."
    for Index in range(240):
        HorizontalPosition = Index % 40
        if HorizontalPosition == 0:
            OutputData.append("\n")

        if _CPUList[Index] in range(HorizontalPosition-1, HorizontalPosition+2):
            OutputData.append(Lit)
        else:
            OutputData.append(Dim)
    return "".join(OutputData)

Instructions = ParseFile("Day10\Input.txt")
CPUOutput = ProcessInstructions(Instructions)

print(f'Puzzle 1: {GetSignalStrengths(CPUOutput, [20, 60, 100, 140, 180, 220])}')
print(f'Puzzle 2: {GetPicture(CPUOutput)}')


'''
Created on 20 Apr 2018

@author: Bryan
'''
import sys
from lark import Lark, Transformer

bif_grammar = r"""
    model: (network | variable | root_prob | nonroot_prob)+

    name : STRING
    variable_name : STRING
    type : CONTINUOUS | DISCRETE
    num_states : NUMBER
    state : STRING
    child : variable_name
    parent : variable_name
    table : "table" (NUMBER)+
    state_prob : "(" state ")" (NUMBER)+ ";"

    network : "network" name "{" "}"
    variable : "variable" variable_name "{" "type" type ["[" num_states "]"] ["{" (state)+ "}"] ";" "}"
    root_prob : "probability" "(" child ")" "{" (table ";")+"}"
    nonroot_prob : "probability" "(" child "|" parent")" "{" (state_prob)+"}"

    CONTINUOUS : "continuous"
    DISCRETE : "discrete"

    %import common.ESCAPED_STRING -> STRING
    %import common.SIGNED_NUMBER -> NUMBER
    %import common.WS
    %ignore WS
    """

bif_parser = Lark(bif_grammar, start='model', lexer='standard')
tree = bif_parser.parse(open("continuoustoy.bif").read())

# print(tree.pretty())
print(tree)

def read_row(t):
    row = []
    for ins in t:
        row.append(float(ins))
    return row

def read_tree(t):
    if t.data == "network":
        name = t.children[0].children[0].value
        print("network : ", name)
    if t.data == "variable":
        name = t.children[0].children[0].value
        type = t.children[1].children[0].value

        print("variable : %s, type: %s" % (name, type))
        if type == "discrete":
            num_states = t.children[2].children[0].value
            states = []
            for ins in t.children[3:]:
                states.append(ins.children[0].value)
            print("%d states: %s" % (int(num_states), " ".join(states)))
    if t.data == "root_prob":
        varname = t.children[0].children[0].children[0].value
        table = t.children[1].children
        prob = read_row(table)
        print("probability: ", varname)
        print("%s" % (" ".join([str(x) for x in prob])))
    if t.data == "nonroot_prob":
        child = t.children[0].children[0].children[0].value
        parent = t.children[1].children[0].children[0].value
        print("probability (%s | %s)" % (child, parent))
        prob = []
        for ins in t.children[2:]:
            state_prob = read_row(ins.children[1:])
            prob.append(state_prob)
        print("%s" % (" ".join([str(x) for x in prob])))

for inst in tree.children:
    read_tree(inst)


import unittest
from bst import BinarySearchTree

class BstInOrderIterator(unittest.TestCase):

  def setUp(self):
    self.dataset = [5, 3, 7, 2, 4, 6, 8, 9, 10]
    self.bst = BinarySearchTree(comparator=lambda x, y: x - y)
    self.bst.insert(self.dataset)

  def runTest(self):
    array = [n.data for n in self.bst.in_order_iterator()]
    self.assertEqual(array, [2, 3, 4, 5, 6, 7, 8, 9, 10])
    self.assertEqual(array, sorted(self.dataset))


# bug 2 OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'

import torch, torchvision
import torch.nn as nn
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np

# rusume是否使用预训练模型继续训练,问号处输入模型的编号
resume = True  # 是继续训练，否重新训练
datasets = 'mnist'  # 选择cifar10, cifar100, mnist, fashion_mnist,STL10,Anime

if datasets == 'cifar10' or datasets == 'cifar100' or datasets == 'STL10' or datasets == 'Anime':
    nc = 3  # 图片的通道数
elif datasets == 'mnist' or datasets == 'fashion_mnist':
    nc = 1
else:
    print('数据集选择错误')

batch_size = 128
nz = 100  # 噪声向量的维度
ndf = 64
ngf = 64
real_label = 1
fake_label = 0
start_epoch = 0

# 定义模型

# 生成器                             #(N,nz, 1,1)
netG = nn.Sequential(nn.ConvTranspose2d(nz, ngf * 8, 4, 1, 0, bias=False), nn.BatchNorm2d(ngf * 8),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 4),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.ConvTranspose2d(ngf * 4, ngf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 4),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 2),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.ConvTranspose2d(ngf * 2, ngf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 2),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.ConvTranspose2d(ngf * 2, nc, 4, 2, 1, bias=False),
                     nn.Tanh()  # (N,nz, 128,128)

                     )

# 判别器             #(N,nc, 128,128)
netD = nn.Sequential(nn.Conv2d(nc, ndf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 2),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Conv2d(ndf * 2, ndf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 2),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 4),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Conv2d(ndf * 4, ndf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 4),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 8),
                     nn.LeakyReLU(0.2, inplace=True),
                     nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False),  # (N,1,1,1)
                     nn.Flatten(),  # (N,1)
                     nn.Sigmoid()
                     )

# custom weights initialization called on netG and netD
def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        torch.nn.init.normal_(m.weight, 0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        torch.nn.init.normal_(m.weight, 1.0, 0.02)
        torch.nn.init.zeros_(m.bias)

netD.apply(weights_init)
netG.apply(weights_init)

# 加载数据集
apply_transform1 = transforms.Compose([
    transforms.Resize(128),
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])

apply_transform2 = transforms.Compose([
    transforms.Resize(128),
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,)),
])

if datasets == 'cifar100':
    train_dataset = torchvision.datasets.CIFAR100(root='../data/cifar100', train=False, download=True,
                                                  transform=apply_transform1)
elif datasets == 'cifar10':
    train_dataset = torchvision.datasets.CIFAR10(root='../data/cifar10', train=False, download=True,
                                                 transform=apply_transform1)
elif datasets == 'STL10':
    train_dataset = torchvision.datasets.STL10(root='../data/STL10', split='train', download=True,
                                               transform=apply_transform1)
elif datasets == 'mnist':
    train_dataset = torchvision.datasets.MNIST(root='../data/mnist', train=False, download=True,
                                               transform=apply_transform2)
elif datasets == 'fashion_mnist':
    train_dataset = torchvision.datasets.FashionMNIST(root='../data/fashion_mnist', train=False, download=True,
                                                      transform=apply_transform2)
elif datasets == 'Anime':
    train_dataset = torchvision.datasets.ImageFolder(root='../data/Anime', transform=apply_transform1)

else:
    print('数据集不存在')
# bug 1 DataLoader worker (pid(s) 11268, 1384, 10744, 11168) exited unexpectedly
# dataloader=tud.DataLoader(data,batch_size=BATCH_SIZE,shuffle=True,num_workers=4)
# DataLoader worker (pid(s) 11404, 1168, 15692, 13308) exited unexpectedly
# dataloader=tud.DataLoader(data,batch_size=BATCH_SIZE,shuffle=True,num_workers=0)
# 因为windows中不能使用多进程
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=0)

# 定义损失函数
criterion = torch.nn.BCELoss()
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# setup optimizer
optimizerD = torch.optim.Adam(netD.parameters(), lr=0.0002, betas=(0.5, 0.999))
optimizerG = torch.optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999))

# 显示16张图片

if datasets == 'Anime':
    image, label = next(iter(train_loader))
    image = (image * 0.5 + 0.5)[:16]
elif datasets == 'mnist' or datasets == 'fashion_mnist':
    image = next(iter(train_loader))[0]
    image = image[:16] * 0.5 + 0.5

elif datasets == 'STL10':
    image = torch.Tensor(train_dataset.data[:16] / 255)
else:
    image = torch.Tensor(train_dataset.data[:16] / 255).permute(0, 3, 1, 2)
plt.imshow(torchvision.utils.make_grid(image, nrow=4).permute(1, 2, 0))

# 训练和保存模型
# 如果继续训练，就加载预训练模型
if resume:
    print('==> Resuming from checkpoint..')
    checkpoint = torch.load('./checkpoint/GAN_%s_best.pth' % datasets)
    netG.load_state_dict(checkpoint['net_G'])
    netD.load_state_dict(checkpoint['net_D'])
    start_epoch = checkpoint['start_epoch']
print('netG:', '\n', netG)
print('netD:', '\n', netD)

print('training on:   ', device, '   start_epoch', start_epoch)

netD, netG = netD.to(device), netG.to(device)
# 固定生成器，训练判别器
for epoch in range(start_epoch, 300):
    for batch, (data, target) in enumerate(train_loader):
        batch_size = data.size(0)
        label = torch.full((batch_size, 1), real_label).to(device)

        # （1）训练判别器
        # training real data
        netD.zero_grad()
        data = data.to(device)
        output = netD(data)
        loss_D1 = criterion(output, label)
        loss_D1.backward()

        # training fake data
        noise_z = torch.randn(batch_size, nz, 1, 1, device=device)
        fake_data = netG(noise_z)
        label = torch.full((batch_size, 1), fake_label).to(device)
        output = netD(fake_data.detach())
        loss_D2 = criterion(output, label)
        loss_D2.backward()

        # 更新判别器
        optimizerD.step()

        # （2）训练生成器
        netG.zero_grad()
        label = torch.full((batch_size, 1), real_label).to(device)
        output = netD(fake_data)
        lossG = criterion(output, label)
        lossG.backward()

        # 更新生成器
        optimizerG.step()

        if batch % 100 == 0:
            print('epoch: %4d, batch: %4d, discriminator loss: %.4f, generator loss: %.4f'
                  % (epoch, batch, loss_D1.item() + loss_D2.item(), lossG.item()))

    # 每2个epoch保存图片
    if epoch % 2 == 0:

        # 如果是单通道图片，那么就转成三通道进行保存
        if nc == 1:
            fake_data = torch.cat((fake_data, fake_data, fake_data), dim=1)  # fake_data（N,1,H,W）->(N,3,H,W)
        # 保存图片
        data = fake_data.detach().cpu().permute(0, 2, 3, 1)
        data = np.array(data)

        # 保存单张图片，将图片归一化到(0,1)
        data = (data * 0.5 + 0.5)

        plt.imsave('./generated_fake/%s/epoch_%d.png' % (datasets, epoch), data[0])
        torchvision.utils.save_image(fake_data[:16],
                                     filename='./generated_fake/%s/epoch%d_grid.png' % (datasets, epoch), nrow=4,
                                     normalize=True)

    # 保存模型
    state = {
        'net_G': netG.state_dict(),
        'net_D': netD.state_dict(),
        'start_epoch': epoch + 1
    }
    torch.save(state, './checkpoint/GAN_%s_best.pth' % (datasets))
    torch.save(state, './checkpoint/GAN_Anime_best_copy.pth' % (datasets))


Import(['getCPPFiles', 'env', 'project', 'build_type', 'arch'])

# precompiled header
env['GchSh'] = env.GchSh(target = '../game_shared_common.h.gch/'+build_type+'-'+arch, source = 'game_shared_common.h')[0]

# libs to link against
if build_type == 'debug':
    env.Append(LIBS=['k2_debug-'+arch])
else:
    env.Append(LIBS=['k2-'+arch])

# cpp defines
env.Append(CPPDEFINES = ['K2_DLL', 'GAME_SHARED_DLL', 'GAME_SHARED_EXPORTS'])

# library search path
env.Append(LIBPATH = ['#k2/'+build_type+'-'+arch])

# runtime lib path
env.Append(LINKFLAGS = '-z origin -Wl,--enable-new-dtags')
env.Append(RPATH = [ Literal('\\$$ORIGIN/../libs-'+arch), Literal('\\$$ORIGIN/..') ])

# source files
src = getCPPFiles('../game_shared.vcproj')

# create the library, dependencies, install to game dir, target
if build_type == 'debug':
    libname = 'game_shared_debug-'+arch+'.so'
    env.SharedLibrary(target = libname, source = src)
    env.Depends('lib'+libname, Alias('k2-' + build_type + '-' + arch))
    env.Install('#../Heroes of Newerth/game', 'lib'+libname)
    Alias(project + '-' + build_type + '-' + arch, 'lib'+libname)
    Alias('install-' + project + '-' + build_type + '-' + arch, '#../Heroes of Newerth/game/lib'+libname)
else:
    libname = 'game_shared-'+arch+'.so'
    env.SplitSharedLibrary(target = [libname, libname+'.dbg'], source = src)
    env.Depends(['lib'+libname, 'lib'+libname+'.dbg'], Alias('k2-' + build_type + '-' + arch))
    env.Install('#../Heroes of Newerth/game', ['lib'+libname, 'lib'+libname+'.dbg'])
    Alias(project + '-' + build_type + '-' + arch, ['lib'+libname, 'lib'+libname+'.dbg'])
    Alias('install-' + project + '-' + build_type + '-' + arch, ['#../Heroes of Newerth/game/lib'+libname, '#../Heroes of Newerth/game/lib'+libname+'.dbg'])


from flask import Flask, jsonify
from flask import request
from flask import send_file
import openpyxl
from werkzeug.utils import secure_filename
app = Flask(__name__)

folder_dir="files"
import os
if not os.path.exists(folder_dir):
    os.makedirs(folder_dir)

def process(file_name):
    wb = openpyxl.load_workbook(file_name)
    sheet=wb.get_sheet_by_name('Table 1')
    wb.active
    wb.create_sheet('Extracted1')
    sheet1=wb.get_sheet_by_name('Extracted1')

    max_row=sheet.max_row
    TS1=sheet.cell(row=(max_row-5),column=1).value
    print(TS1)

    college=sheet.cell(row=1,column=1).value
    exam=sheet.cell(row=4,column=1).value
    s1=sheet.cell(row=6,column=4).value
    s2=sheet.cell(row=6,column=7).value
    s3=sheet.cell(row=6,column=10).value
    s4=sheet.cell(row=6,column=13).value
    s5=sheet.cell(row=6,column=16).value
    s6=sheet.cell(row=6,column=19).value
    s7=sheet.cell(row=6,column=22).value
    s8=sheet.cell(row=6,column=25).value
    s9=sheet.cell(row=6,column=28).value

    sheet1["A1"]="Name"
    sheet1.merge_cells('B1:D1')
    sheet1["B1"]=s1
    sheet1.merge_cells('E1:G1')
    sheet1["E1"]=s2
    sheet1.merge_cells('H1:J1')
    sheet1["H1"]=s3
    sheet1.merge_cells('K1:M1')
    sheet1["K1"]=s4
    sheet1.merge_cells('N1:P1')
    sheet1["N1"]=s5
    sheet1.merge_cells('Q1:S1')
    sheet1["Q1"]=s6
    sheet1.merge_cells('T1:V1')
    sheet1["T1"]=s7
    sheet1.merge_cells('W1:Y1')
    sheet1["W1"]=s8
    sheet1.merge_cells('Z1:AB1')
    sheet1["Z1"]=s9
    sheet1['AC1']="Result"
    sheet1['AD1']="GPA"

    def copyRange(startCol, startRow, endCol, endRow, sheet):
        rangeSelected = []
        #Loops through selected Rows
        for i in range(startRow,endRow + 1,1):
            #Appends the row to a RowSelected list
            rowSelected = []
            for j in range(startCol,endCol+1,1):
                rowSelected.append(sheet.cell(row = i, column = j).value)
            #Adds the RowSelected List and nests inside the rangeSelected
            rangeSelected.append(rowSelected)

        return rangeSelected

    #Paste range
    #Paste data from copyRange into template sheet
    def pasteRange(startCol, startRow, endCol, endRow, sheetReceiving,copiedData):
        countRow = 0
        for i in range(startRow,endRow+1,1):
            countCol = 0
            for j in range(startCol,endCol+1,1):

                sheetReceiving.cell(row = i, column = j).value = copiedData[countRow][countCol]
                countCol += 1
            countRow += 1

    def createData():
        print("Processing...")
        selectedRange = copyRange(4,8,30,457,sheet) #Change the 4 number values
        pastingRange = pasteRange(2,2,28,451,sheet1,selectedRange) #Change the 4 number values

    createData()

    print("Processing...")
    selectedRange = copyRange(2,8,2,457,sheet) #Change the 4 number values
    pastingRange = pasteRange(1,2,1,451,sheet1,selectedRange) #Change the 4 number values
    print("Range copied and pasted!")

    j=4
    for i in range(1,(TS1+1)):
        sheet1.delete_rows(j)
        sheet1.delete_rows(j)
        sheet1.delete_rows(j)
        j=j+1
        j=j+1

    import re
    j=2
    for i in range(1,(TS1+1)):

       test_str = sheet1.cell(row=j,column=1)

       res= ''.join(filter(lambda k: k.isdigit(),test_str.value))
       s=j+1
       (sheet1.cell(row=s,column=1).value)=res
       j=j+2

    j=8
    k=2
    for i in range(1,(TS1+1)):

        s = sheet.cell(row=j,column=31)
        a=re.split('\s+', s.value)
        (sheet1.cell(row=k,column=29).value)=a[1]
        (sheet1.cell(row=k,column=30).value)=a[4]
        j=j+5
        k=k+2

    # COUNTING KT STUDENTS
    flag=0
    value=0
    for i in range(2,(2*(TS1+1))):
        if (flag==0):
            for j in range(2,29):
                if(flag==0):
                    temp1=sheet1.cell(row=i,column=j).value
                    temp=str(temp1)
                    for char in temp:
                        if char is '+':
                            value=i
                            flag=1
                            break
                        else:
                            continue

                    j=j+1
                else:
                    break
            i=i+1
        else:
            break
    print(value)
    kt=TS1-(value/2)+1

    kt=int(kt)

    print(kt)
    TS=TS1-kt

    j=156
    for i in range(1,(2*kt)+1):
        sheet1.delete_rows(j)

    wb.save("result_output.xlsx")

    pcount=0
    fcount=0
    k=2
    for i in range(1,(TS+1)):
        if((sheet1.cell(row=k,column=29).value)=="P"):
            pcount=pcount+1
        if((sheet1.cell(row=k,column=29).value)=="F"):
            fcount=fcount+1
        k=k+2
    print(pcount)
    print(fcount)

    import array as arr
    a=arr.array('i',[0,0,0,0,0,0,0,0,0,0])
    count=0
    y=1
    k=3
    l=4
    while(l<29):
        for i in range(1,(TS+1)):

            if((sheet1.cell(row=k,column=l).value)=="--"):
                count=count+1
            k=k+2

        a[y]=count
        y=y+1
        count=0
        k=3
        l=l+3
    for i in range(1,10):
        print(a[i])
    a1=a[1]
    a2=a[2]
    a3=a[3]
    a4=a[4]
    a5=a[5]
    a6=a[6]
    a7=a[7]
    a8=a[8]
    a9=a[9]

    wb.save("result_output.xlsx")

    import pandas as pd

    xl = pd.ExcelFile("result_output.xlsx")
    df = xl.parse("Extracted1")
    df = df.sort_values(["GPA"],ascending=False)

    writer = pd.ExcelWriter("cal.xlsx")
    df.to_excel(writer,sheet_name='sheet1',columns=["Name","Result","GPA"],index=False)
    writer.save()

    wb2 = openpyxl.load_workbook('cal.xlsx')
    sheet5=wb2.get_sheet_by_name('sheet1')
    wb2.active

    distinction=0
    first=0
    second=0
    f=0
    k=2

    for i in range(1,(TS+1)):

        a=sheet5.cell(row=k,column=3).value

        if(a=='--'):
            f=f+1
            break
        else:
            a=float(sheet5.cell(row=k,column=3).value)
            if(a>=7.75):
                distinction=distinction+1
                k=k+1
            elif(a>=6.75 ):
                first=first+1
                k=k+1
            elif(a<6.75 ):
                second=second+1
                k=k+1
            else:
                f=f+1

    print(distinction)
    print(first)
    print(second)

    wb.create_sheet('Result Analysis')
    sheet3=wb.get_sheet_by_name('Result Analysis')
    wb.active

    sheet3.merge_cells('B1:H1')
    sheet3.merge_cells('A2:K2')
    sheet3.merge_cells('B3:D3')
    sheet3.merge_cells('B4:D4')
    sheet3['B1']=college
    sheet3['A2']=exam
    sheet3['B4']="Result Analysis "

    sheet3['B6']="Class"
    sheet3['B7']="No. of Student Appeared"
    sheet3['B8']="No. of Student passed"
    sheet3['B9']="No. of Student failed"
    sheet3['B10']="No. of Student having SGPA 7.75 and above (Distinction)"
    sheet3['B11']="No. of Student having SGPA 6.75 and above (First)"
    sheet3['B12']="No. of Student having SGPA below 6.75 (Second )"
    sheet3["B13"]="% of passing"
    sheet3['C6']="S.E.I.T"
    sheet3['C7']=TS
    sheet3['C8']=pcount
    sheet3['C9']=fcount
    sheet3['C10']=distinction
    sheet3['C11']=first
    sheet3['C12']=second
    sheet3["C13"]=(pcount/TS)*100

    sheet3['B15']="Subject Wise Analysis"
    sheet3['A17']="SR No"
    sheet3['B17']="Subject"
    sheet3['C17']="No. of candidates appeared"
    sheet3['D17']="No. of candidates passed"
    sheet3['E17']="% of passing in the subject"
    sheet3['A18']="1"
    sheet3['A19']="2"
    sheet3['A20']="3"
    sheet3['A21']="4"
    sheet3['A22']="5"
    sheet3['A23']="6"
    sheet3['A24']="7"
    sheet3['A25']="8"
    sheet3['A26']="9"
    sheet3['B18']=s1
    sheet3['B19']=s2
    sheet3['B20']=s3
    sheet3['B21']=s4
    sheet3['B22']=s5
    sheet3['B23']=s6
    sheet3['B24']= s7
    sheet3['B25']=s8
    sheet3['B26']=s9

    sheet3["C18"]=TS
    sheet3['C19']=TS
    sheet3["C20"]=TS
    sheet3["C21"]=TS
    sheet3["C22"]=TS
    sheet3["C23"]=TS
    sheet3["C24"]=TS
    sheet3["C25"]=TS
    sheet3["C26"]=TS
    sheet3["D18"]=(TS)-a1
    sheet3['D19']=TS-a2
    sheet3["D20"]=TS-a3
    sheet3["D21"]=TS-a4
    sheet3["D22"]=TS-a5
    sheet3["D23"]=TS-a6
    sheet3["D24"]=TS-a7
    sheet3["D25"]=TS-a8
    sheet3["D26"]=TS-a9
    sheet3["E18"]=((TS-a1)/TS1)*100
    sheet3['E19']=((TS-a2)/TS1)*100
    sheet3["E20"]=((TS-a3)/TS1)*100
    sheet3["E21"]=((TS-a4)/TS1)*100
    sheet3["E22"]=((TS-a5)/TS1)*100
    sheet3["E23"]=((TS-a6)/TS1)*100
    sheet3["E24"]=((TS-a7)/TS1)*100
    sheet3["E25"]=((TS-a8)/TS1)*100
    sheet3["E26"]=((TS-a9)/TS1)*100

    wb.save("result_output.xlsx")

    wb.create_sheet('Topper')
    sheet2=wb.get_sheet_by_name('Topper')

    sheet2["A6"]="Student Name  Seat No"
    sheet2.merge_cells('A1:H1')
    sheet2.merge_cells('A2:K2')
    sheet2.merge_cells('B3:E3')
    sheet2.merge_cells('A4:F4')
    sheet2["A1"]=college
    sheet2["A2"]=exam
    sheet2["A4"]="Heartiest Congratulations To All The Toppers"

    sheet2["B6"]="College Rank"
    sheet2["C6"]="SGPA"

    p=sheet5.cell(row=2,column=3).value

    r=1
    sheet2.cell(row=7,column=1).value=sheet5.cell(row=2,column=1).value
    sheet2.cell(row=7,column=2).value=1
    sheet2.cell(row=7,column=3).value=sheet5.cell(row=2,column=3).value
    k=3

    for i in range(1,(TS1+1)):
        while(r<5):
            sp=sheet5.cell(row=k,column=3).value
            if(sp==p):
                sheet2.cell(row=k+5,column=1).value=sheet5.cell(row=k,column=1).value
                sheet2.cell(row=k+5,column=2).value=r
                sheet2.cell(row=k+5,column=3).value=sheet5.cell(row=k,column=3).value
            else:
                r=r+1
                sheet2.cell(row=k+5,column=1).value=sheet5.cell(row=k,column=1).value
                sheet2.cell(row=k+5,column=2).value=r
                sheet2.cell(row=k+5,column=3).value=sheet5.cell(row=k,column=3).value
                p=sp
            k=k+1

    wb.save("result_output.xlsx")

    wb.remove_sheet(sheet1)

    wb.save("result_output.xlsx")
    return send_file('result_output.xlsx', attachment_filename='result_output.xlsx')

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        #image=request.args.get('image')
        file=request.files['myFile']
        filename = secure_filename(file.filename)
        upload_file=folder_dir+"/"+filename
        file.save(upload_file)
        #with open(filename, "rb") as image_file:
         #   encoded_string = base64.b64encode(image_file.read())
        print("excel recieved")
        print(upload_file)
        return process(upload_file)

    return '''

<meta name="viewport" content="width=device-width, initial-scale=1">

K.J. SOMAIYA INSTITUTE OF ENGINEERING AND INFORMATION TECHNOLOGY

RESULT ANALYSIS

 <form method=post enctype=multipart/form-data>
   Select a file: <input type="file" name="myFile">

   <input type=submit value=Upload>
</form>

    '''

if __name__ == '__main__':
    #app.run(host='localhost', port=5000) #run in local
    app.run()


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

"""
DataMatrix样例演示

Project: alphahunter
Author: HJQuant
Description: Asynchronous driven quantitative trading framework
"""

import sys
import asyncio

from quant import const
from quant.state import State
from quant.utils import tools, logger
from quant.config import config
from quant.market import Market, Kline, Orderbook, Trade, Ticker
from quant.tasks import LoopRunTask
from quant.trader import Trader
from quant.strategy import Strategy
from quant.utils.decorator import async_method_locker
from quant.order import Order, Fill, ORDER_ACTION_BUY, ORDER_ACTION_SELL, ORDER_STATUS_FILLED, ORDER_TYPE_MARKET
from quant.position import Position
from quant.asset import Asset
from quant.startup import default_main
from quant.interface.datamatrix_api import DataMatrixAPI

class DataMatrixDemo(Strategy):

    def __init__(self):
        """ 初始化
        """
        super(DataMatrixDemo, self).__init__()

        self.platform = config.platforms[0]["platform"] #交易所
        self.symbols = config.platforms[0]["symbols"]
        # 交易模块参数
        params = {
            "strategy": config.strategy,
            "platform": self.platform,
            "symbols": self.symbols,

            "enable_kline_update": True,
            "enable_orderbook_update": True,
            "enable_trade_update": True,
            "enable_ticker_update": True,
            "enable_order_update": False,
            "enable_fill_update": False,
            "enable_position_update": False,
            "enable_asset_update": False,

            "direct_kline_update": True,
            "direct_orderbook_update": True,
            "direct_trade_update": True,
            "direct_ticker_update": True
        }
        self.gw = self.create_gateway(**params)

    async def on_state_update_callback(self, state: State, **kwargs):
        """ 状态变化(底层交易所接口,框架等)通知回调函数
        """
        logger.info("on_state_update_callback:", state, caller=self)

    async def on_kline_update_callback(self, kline: Kline):
        """ 市场K线更新
        """
        logger.info("kline:", kline, caller=self)
        #ts = DataMatrixAPI.current_milli_timestamp()
        #r = await DataMatrixAPI.get_klines_between(self.platform, self.symbols[0], ts, ts+10*60*1000)
        #print(r)
        # add some logic and calculations here.
        # await add_row(Row)

    async def on_orderbook_update_callback(self, orderbook: Orderbook):
        """ 订单薄更新
        """
        logger.info("orderbook:", orderbook, caller=self)
        # add some logic and calculations here.
        # await add_row(Row)

    async def on_trade_update_callback(self, trade: Trade):
        """ 市场最新成交更新
        """
        logger.info("trade:", trade, caller=self)
        # add some logic and calculations here.
        # await add_row(Row)

    async def on_ticker_update_callback(self, ticker: Ticker):
        """ 市场行情tick更新
        """
        logger.info("ticker:", ticker, caller=self)
        # add some logic and calculations here.
        # await add_row(Row)

    async def add_row(self, Row):
        # add this Row to an existing csv file
        pass

    async def on_order_update_callback(self, order: Order): ...
    async def on_fill_update_callback(self, fill: Fill): ...
    async def on_position_update_callback(self, position: Position): ...
    async def on_asset_update_callback(self, asset: Asset): ...

if __name__ == '__main__':
    default_main(DataMatrixDemo)


print("HI")

def prefill(n, v, memo=[]):
    if type(n) is str:
        try:
            arr = []
            int(n)
            arr.append(v)
            return arr
        except Exception as e:
            print(e)
            print(f"{n} is invalid")
    else:
        if n == 0:
            arr = memo.copy()
            memo = []
            return arr
        else:
            memo.append(v)
            return prefill(n - 1, v, memo=memo.copy())

print("hlo")

print(prefill(3, 1))
print(prefill(2, "abc"))
print(prefill(3, prefill(2, "2d")))


import sys

input = sys.stdin.readline
sys.setrecursionlimit(10 ** 6)

num = int(input())
tree = [[] for _ in range(num + 1)]
table = {}
check = [False] * (num + 1)

def dfs(v):
    check[v] = True
    for i in tree[v]:
        if not check[i]:
            # print(i)
            table[i] = v
            dfs(i)

for _ in range(num - 1):
    a, b = map(int, input().split())
    tree[a].append(b)
    tree[b].append(a)
# print(tree)

dfs(1)
# print(table)

# 출력
for i in range(2, num + 1):
    if i in table:
        print(table[i])
    # else:
    #     break


from __future__ import unicode_literals

import argparse
import os
try:
    from urllib.parse import urlparse
except ImportError:
     from urlparse import urlparse
# import kronos
import urllib
import subprocess
import sys
import shutil
import stat
from contextlib import closing
from django.core.management.base import BaseCommand
from django.core.management import settings
from django.db.models import Q
from odm2admin.models import Dataloggerfiles
from odm2admin.models import ProcessDataloggerfile

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "templatesAndSettings.settings")

__author__ = 'leonmi'

parser = argparse.ArgumentParser(description='update datalogger file from ftp - ' +
                                             'ftp file URL should be the file description.')\

# @kronos.register('55 14 * * *', args={'-dataloggerfilelink': [],
#                                       '-dataloggerfileid': [],
#                                       '-databeginson': [],
#                                       '-columnheaderson': [],
#                                       '-ftpfrequencyhours': [],
#                                       '-ftpfile': [],
#                                       '-check_dates': [],
#                                       '-cmdline': [],
#                                       '-reversed': []})
class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument('dataloggerfilelink', nargs=1, type=str)
        parser.add_argument('dataloggerfileid', nargs=1, type=str)
        parser.add_argument('databeginson', nargs=1, type=str)
        parser.add_argument('columnheaderson', nargs=1, type=str)
        parser.add_argument('ftpfrequencyhours', nargs=1, type=str)
        # parser.add_argument('ftpfile', nargs=1, type=bool)
        parser.add_argument('check_dates', nargs=1, type=bool)
        parser.add_argument('cmdline', nargs=1, type=bool)
        # parser.add_argument('reversed', nargs=1, type=bool, default=False)

    def handle(self, *args, **options):  # (f,fileid, databeginson,columnheaderson, cmd):
        cmdline = bool(options['cmdline'][0])
        filename = str(options['dataloggerfilelink'][0])
        fileid = int(options['dataloggerfileid'][0])
        databeginson = int(options['databeginson'][0])  # int(databeginson[0])
        columnheaderson = int(options['columnheaderson'][0])  # int(columnheaderson[0])
        check_dates = bool(options['check_dates'][0])
        ftpfrequencyhours = int(options['ftpfrequencyhours'][0])
        # reversed = bool(options['reversed'][0])
        print(ftpfrequencyhours)
        intfileid = fileid
        fileid = Dataloggerfiles.objects.filter(dataloggerfileid=fileid).get()
        ftpfile = fileid.dataloggerfiledescription
        ftpparse = urlparse(ftpfile)
        pythonpath = settings.PYTHON_EXEC
        apppath = settings.BASE_DIR
        # print(ftpparse.netloc)
        if len(ftpparse.netloc) > 0:
            out_file = str(settings.MEDIA_ROOT)+ filename
            # print(settings.MEDIA_ROOT)
            # print(out_file)
            # print(ftpfile)
            # urllib.urlretrieve(ftpfile, out_file)
            # with closing(urllib.request.urlopen(ftpfile)) as r:
            #     with open(out_file, 'wb+') as f:
            #        shutil.copyfileobj(r, f)
            # write script file
            pdlf = ProcessDataloggerfile.objects.filter(dataloggerfileid=fileid). \
                filter(Q(processingCode__icontains='ftp setup complete') | Q(processingCode__icontains='done'))
            # filter(processingCode__icontains='done')
            ftpestablished = pdlf.count()
            localbasedir = settings.TEMPLATE_DIR
            if ftpestablished == 0:
                pdlf = ProcessDataloggerfile.objects.get(dataloggerfileid=fileid)
                pdlf.processingCode = 'ftp setup complete'
                pdlf.save()
                print('create ftp file')
                #     # ProcessDataloggerfile(dataloggerfileid=fileid,
                #     #                      processingCode=str(ftpfrequencyhours)+" hours between download",
                #     #                      databeginson=databeginson,columnheaderson=columnheaderson)
                #     # ProcessDataloggerfile.save()
                #     intftpfrequencyhours = int(ftpfrequencyhours)
                #     kronos.register('0 */'+ str(intftpfrequencyhours) + ' * * * wget -q ' +out_file)
                #     # need a setting
                #     kronos.register('5 */' + str(intftpfrequencyhours) + ' * * *  ' + pythonpath +
                #                     " " +  apppath + "/manage.py updata_preprocess_process_datalogger_file dataloggerfiles/"+
                #                     filename + " " + str(fileid.dataloggerfileid) + " " +
                #                     str(databeginson) + " " + str(columnheaderson) + " True ")
                # file = str(settings.MEDIA_ROOT) + filename  # args[0].name
                sysout = sys.stdout

                sys.stdout = open(localbasedir + '/templatesAndSettings/scripts/ftp_file_download.sh', 'w')
                # / home / miguelcleon / webapps / odm2admin2 / manageexport.py
                # create_sqlite_export
                # sys.stdout = sysout
                commandstring = '#!/usr/bin/env bash \n '
                # print(commandstring)
                commandstring += 'sudo crontab -l >'+ localbasedir + '/templatesAndSettings/scripts/mycron \n '
                # print(commandstring)
                commandstring += 'echo "49 */' + str(ftpfrequencyhours) + ' * * * wget -q ' +ftpfile + ' -O ' + \
                                out_file + '" >> '+ localbasedir + '/templatesAndSettings/scripts/mycron \n'
                # commandstring += ' %>> ' + settings.BASE_DIR + '/logging/ftp_download.log'
                # print(commandstring)

                commandstring += 'echo "50 */' + str(ftpfrequencyhours) + ' * * * '
                commandstring += pythonpath + ' '
                commandstring += settings.TEMPLATE_DIR  + '/managecli.py'
                commandstring += ' update_preprocess_process_datalogger_file ' + filename + ' ' \
                            +  str(intfileid) + ' ' + str(databeginson)+ ' ' + str(columnheaderson) + ' ' + str(ftpfrequencyhours) + ' ' \
                            + ' True'
                commandstring += " &>> " + localbasedir + '/templatesAndSettings/logging/downloadftp.log " >> ' +\
                                 localbasedir + '/templatesAndSettings/scripts/mycron \n'
                # print(commandstring)
                commandstring += 'sudo crontab '+ localbasedir + '/templatesAndSettings/scripts/mycron \n '
                print(commandstring)
                # command = settings.BASE_DIR + '/scripts/ftp_file_download.sh'  # + dbfile2 + ' %>> ' + settings.BASE_DIR +'/logging/sqlite_export.log'
                # st = os.stat(command)
                # try:
                #     os.chmod(command, st.st_mode | stat.S_IEXEC)
                # except OSError as e:
                #     pass
                # # print(command)
                sys.stdout = sysout
                # print(commandstring)
                # response = subprocess.check_call(command, shell=True)  #


###########################################################################
### Chapter 7 - Evaluating Fielders                                     ###
# Mathletics: How Gamblers, Managers, and Sports Enthusiasts              #
# Use Mathematics in Baseball, Basketball, and Football                   #
###########################################################################

import pandas as pd
import numpy as np
from scipy.optimize import differential_evolution

df = pd.read_csv("shift.csv")

df['changeDistance'] = [(df['Base'].iloc[i] - 1)*90 + df['distance'].iloc[i] for i in range(len(df))]

## return the negative of the objective function since we want to maximize but the built-in optimization functions are minimizers
def obj(x):
	ffielded = np.array([1 if min([abs(x[k]-df['changeDistance'].iloc[i]) for k in range(4)])<=5 else 0 for i in range(len(df))]).mean()
	return -ffielded

## since our objective function is not smooth we are using differential_evolution
res = differential_evolution(obj, bounds = [(0,8),(0,180),(0,180),(0,180)])

print("The optimal positions are: \n \t",round(res.x[0],2),"\n \t",round(res.x[1],2),"\n \t",round(res.x[2],2),"\n \t",round(res.x[3],2),"\n and the fraction fielded is expected to be: ",round(abs(obj(res.x)),2))


import mpv
from enum import Enum
from typing import Callable
import yt_dlp

ID = "LoK17z6xDwI"

def mpvLog(loglevel, component, message):
    print('[{}] {}: {}'.format(loglevel, component, message))

class AudioQuality(int, Enum):
    LOW = 0
    MEDIUM = 1
    HIGH = 2

class RepeatMode(int, Enum):
    OFF = 0
    ONE = 1
    ALL = 2

class PlayerState(int, Enum):
    IDLE = 0
    BUFFERING = 1
    READY = 2
    ENDED = 3

class Event:
    current_client_id: bytes | None = None

    def __init__(self, properties: list[str]):
        assert("id" not in properties and "type" not in properties)
        self.properties = properties

        self.id = -1
        self.client_id = Event.current_client_id

    def init(self, id: int, client_amount: int):
        self.id = id
        self.client_amount = client_amount

    def unassociateClient(self):
        self.client_id = None

    def toDict(self) -> dict:
        ret = {"type": type(self).__name__[:-5], "id": self.id}
        for key in self.properties:
            ret[key] = self.__getattribute__(key)
        return ret

class SongTransitionEvent(Event):
    def __init__(self, index: int):
        super().__init__(["index"])
        self.index = index

class PropertyChangedEvent(Event):
    def __init__(self, key: str, value):
        super().__init__(["key", "value"])
        self.key = key
        self.value = value

class SeekedEvent(Event):
    def __init__(self, position_ms: int):
        super().__init__(["position_ms"])
        self.position_ms = position_ms

class SongAddedEvent(Event):
    def __init__(self, song_id: str, index: int):
        super().__init__(["song_id", "index"])
        self.song_id = song_id
        self.index = index

class SongRemovedEvent(Event):
    def __init__(self, index: int):
        super().__init__(["index"])
        self.index = index

class SongMovedEvent(Event):
    def __init__(self, from_index: int, to_index: int):
        super().__init__(["from_index", "to_index"])
        self.from_index = from_index
        self.to_index = to_index

class Player:

    def __init__(
        self,
        id2filename: Callable = lambda f: f,
        filename2id: Callable = lambda id: id,
        eventListener: Callable | None = None
    ):
        self.id2filename = id2filename
        self.filename2id = filename2id
        self.eventListener = eventListener

        self.player = mpv.MPV(log_handler=mpvLog, ytdl=True, vid="no", start_event_thread=True)

        @self.player.property_observer("playlist-pos")
        def onFileStarted(key: str, index: int):
            event = SongTransitionEvent(index)
            event.unassociateClient()
            self._onEvent(event)

        @self.player.property_observer("file-loaded")
        def onFileLoaded(key: str, _):
            event = PropertyChangedEvent("duration_ms", self.duration_ms)
            event.unassociateClient()
            self._onEvent(event)

    def _onEvent(self, event: Event):
        if self.eventListener is not None:
            self.eventListener(event)

    @property
    def state(self) -> PlayerState:
        # raise NotImplementedError()
        return PlayerState.IDLE

    @property
    def is_playing(self) -> bool:
        return not self.player.core_idle
        #return self.state == PlayerState.READY and not self.player.pause

    @property
    def song_count(self) -> int:
        return self.player.playlist_count # type: ignore

    @property
    def current_song_index(self) -> int:
        return self.player.playlist_playing_pos # type: ignore

    @property
    def current_position_ms(self) -> int:
        return int((self.player.playback_time or 0) * 1000) # type: ignore

    @property
    def duration_ms(self) -> int:
        return int((self.player.duration or 0) * 1000) # type: ignore

    @property
    def shuffle_enabled(self) -> bool:
        return False # TODO

    @property
    def repeat_mode(self) -> RepeatMode:
        return RepeatMode.OFF # TODO

    @property
    def volume(self) -> float:
        return self.player.volume # type: ignore

    @property
    def playlist(self) -> list:
        return [self.filename2id(filename) for filename in self.player.playlist_filenames]

    STATE_PROPERTIES = (state, is_playing, current_song_index, current_position_ms, duration_ms, shuffle_enabled, repeat_mode, volume, playlist)

    def getCurrentState(self) -> dict:
        return {prop.fget.__name__: prop.__get__(self) for prop in self.STATE_PROPERTIES}

    def play(self):
        if self.player.pause:
            self.player.pause = False
            self._onEvent(PropertyChangedEvent("is_playing", self.is_playing))

    def pause(self):
        if not self.player.pause:
            self.player.pause = True
            self._onEvent(PropertyChangedEvent("is_playing", self.is_playing))

    def playPause(self):
        self.player.pause = not self.player.pause
        self._onEvent(PropertyChangedEvent("is_playing", self.is_playing))

    def seekTo(self, position_ms: int):
        seconds, position_ms = divmod(position_ms, 1000)
        minutes, seconds = divmod(seconds, 60)
        hours, minutes = divmod(minutes, 60)

        seek_time =  f"{hours:02d}:{minutes:02d}:{seconds:02d}.{position_ms//100}"
        self.player.seek(seek_time, "absolute", "exact")

        self._onEvent(SeekedEvent(position_ms))

    def seekToSong(self, index: int):
        if index == self.current_song_index or index < 0 or index >= self.song_count:
            return

        self.player.playlist_play_index(index)
        self._onEvent(SongTransitionEvent(index))

    def seekToNext(self):
        index = self.current_song_index
        self.player.playlist_next()

        new_index = self.current_song_index
        if index != new_index:
            self._onEvent(SongTransitionEvent(index))

    def seekToPrevious(self):
        index = self.current_song_index
        self.player.playlist_prev()

        new_index = self.current_song_index
        if index != new_index:
            self._onEvent(SongTransitionEvent(index))

    def getSong(self, index: int = -1) -> str | None:
        if not self.hasSong(index):
            return None

        if index < 0:
            index = self.current_song_index

        return self.filename2id(self.player.playlist_filenames[index])

    def addSong(self, id: str, index: int = -1):
        url = self.id2filename(id)

        if self.song_count == 0:
            self.player.loadfile(url)
        else:
            self.player.playlist_append(url)

        if index >= self.song_count or index < 0:
            index = self.song_count - 1
        elif index + 1 < self.song_count:
            self.moveSong(self.song_count - 1, index, False)

        self._onEvent(SongAddedEvent(id, index))

    def moveSong(self, from_index: int, to_index: int, add_event: bool = True):
        if from_index == to_index or not self.hasSong(from_index) or not self.hasSong(to_index):
            return

        self.player.playlist_move(from_index, to_index)

        if add_event:
            self._onEvent(SongMovedEvent(from_index, to_index))

    def removeSong(self, index: int):
        if not self.hasSong(index):
            return

        self.player.playlist_remove(str(index))

        self._onEvent(SongRemovedEvent(index))

    def setRepeatMode(self, value: RepeatMode):
        if value == self.repeat_mode:
            return
        # TODO
        self._onEvent(PropertyChangedEvent("repeat_mode", self.repeat_mode))

    def setVolume(self, value: float):
        if value == self.volume:
            return
        self.player.volume = value
        self._onEvent(PropertyChangedEvent("volume", self.volume))

    ACTIONS = (play, pause, playPause, seekTo, seekToSong, seekToNext, seekToPrevious, getSong, addSong, moveSong, removeSong, setRepeatMode, setVolume)

    def hasSong(self, index: int) -> bool:
        return index >= 0 and index + 1 < self.song_count

    def getStreamUrl(self, video_id: str) -> str:
        ytd = yt_dlp.YoutubeDL({"skip_download": True, "quiet": True})

        info = ytd.extract_info(video_id, download=False)
        if info == None:
            raise RuntimeError("No formats returned by yt-dlp")

        audio_formats = []
        for format in info["formats"]:
            if format["video_ext"] != "none":
                continue
            if format["audio_ext"] == "none":
                continue
            audio_formats.append(format)

        return getFormatByQuality(audio_formats, AudioQuality.MEDIUM)["url"]

def getFormatByQuality(formats: list[dict], quality: AudioQuality) -> dict:
    formats.sort(key = lambda f: f["quality"], reverse = True)

    if quality == AudioQuality.HIGH:
        return formats[0]
    elif quality == AudioQuality.MEDIUM:
        return formats[len(formats)//2]
    elif quality == AudioQuality.LOW:
        return formats[-1]
    else:
        raise NotImplementedError(str(quality))


#Cria a  grafo, tudo certo exceto a parte da matriz de adjacencia

def imprime_matriz(lista_de_1,n):
    print(lista_de_1)
    limite=len(n)
    for i in range(0,limite):
        #print("[",end=" ")
        for j in range(0,limite):
            sinal =0
            for k in lista_de_1:
                v1=Busca(i,k)
                v2=Busca(j,k)
            if(v1 != -1 and v2 != -1):
                    sinal = 1
                    print(1,end=" ")
            if(sinal ==1 ):
                print(1,end=" ")
            else:
                print(0,end=" ")

#
#            for k in lista_de_1:
#                aux = k.split(" ")
#                sinal = 0
#                v1 = aux[0]
#                v2 = aux[1]
#                print(f"\naux:{aux} i:{i} j:{j}\n")
#                if(i == v1 and j == v2):
#                    print("eh igual\n")
#                    sinal = 1
#                    break
#                print(f"sin:{sinal}")
#        if (sinal == 1):
#            print(1, end=" ")
#        else:
#            print(0,end=" ")
        #print("]")
#
#    for k in lista_de_1:
#        aux = k.split(" ")
#        for i in range(0,len(vertices)):
#            for j in range(0,len(vertices)):
#                Busca(i,aux[0])
#                print(f"a[0]:{aux[0]} a[1]:{aux[1]}")
#                print(f"i:{i} j:{j}")
#                if(i == aux[0] and j == aux[1]):
#                    print(1)
#                    break
#                else:
#                    print(0)
#                    break
#        print()
#    print()

def Busca(elemento_procurado,fonte):
    #print(f"vou buscar {elemento_procurado}\nem\n{fonte}")
    try:
        val = fonte.index(elemento_procurado)
        #print(f"achei {val}\n")
    except:
        val = -1
        #print("não achei\n")
    return val

vertices=[]
arestas=[]
matriz_ad=[]

#Pega os vertices
while True:
    print("Digite o vertice do grafo :")
    temp = input()
    vertices.append(temp)
    if(temp == ""):
        vertices.pop(-1)
        break
#Pega as arestas
while True:
    print("Digite os dois vertices que compoem essa aresta do grafo no seguinte formado:\nv1 v2")
    temp = input()
    arestas.append(temp)
    if(temp == ""):
        arestas.pop(-1)
        break
print("Qual o nome desse Grafo ?")
nome_grafo = input()
print(f"{nome_grafo} = ({vertices}, {arestas})\n")

#impressao matriz de adjacencia vazia
linha = [0]*(len(vertices))
matriz_ad = [linha]*(len(vertices))
print(f"matriz de adjacencia a ser preenchida:\n{matriz_ad} \n\n")

contador=0
compoem_matriz_ad = []
for i in vertices:

    for j in arestas:
        aux = j.split(" ")
        if(i == aux[0]):
            indice = Busca(aux[1],vertices)
            if(indice != -1):
                x = f"{contador} {indice}"
                print("x:")
                print(x)
                compoem_matriz_ad.append(x)
        elif(i == aux[1]):
            indice = Busca(aux[0],vertices)
            if(indice != -1):
                x = f"{contador} {indice}"
                print("x:")
                print(x)
                compoem_matriz_ad.append(x)
    contador+=1
compoem_matriz_ad.sort()
imprime_matriz(compoem_matriz_ad,vertices)
#separador=[]
#for i in arestas:
#    separador = i.split(" ")
#    v1 = Busca(separador[0],vertices)
#    v2 = Busca(separador[1],vertices)
#    for i in matriz_ad:
#        for j in i:
            #if(i == v1 and j == v2):
#            i[j] = 1

#    if(v1 != -1 and v2 != -1):
#        print(f"essa aresta existe, então vou marcar os índices {v1}x{v2} e {v2}x{v1} da matriz.\n")
#        print(f"v1v2:{matriz_ad[v1][v2]}")
#        print(f"v2v1:{matriz_ad[v2][v1]}")
#        print(f"{matriz_ad} \n\n")

#        matriz_ad[v1][v2] = 1
#        matriz_ad[v2][v1] = 1

#        print(f"v1v2:{matriz_ad[v1][v2]}")
#        print(f"v2v1:{matriz_ad[v2][v1]}")
#        print(f"{matriz_ad} \n\n")

#print(f"{matriz_ad} \n\n")


import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import quad
from scipy.interpolate import interp1d

class Spectrum(object):

    def __init__(self, edges, values, error=False, S=1, dfde=False, label=None):
        assert len(edges) - 1 == len(values), '{} edges and {} values given.'.format(len(edges), len(values))
        self.label = label
        self.scaling_factor = S
        self.values = values
        self.num_bins, self.num_edges = self.count_bins()
        self.edges = edges
        self.region = self.edges[0], self.edges[-1]
        self.values = self.scale_values()
        if isinstance(error, bool):
            self.error = self.estimate_error()
        else:
            self.error = error * self.scaling_factor
        self.rel_error = self.error / self.values
        self.widths = self.edges[1:] - self.edges[:-1]
        self.midpoints = (self.edges[1:] + self.edges[:-1]) / 2
        if dfde:
            self.normalized_values = self.values
            self.values = self.values * self.widths
        else:
            self.normalized_values = self.values / self.widths
        self.step_x, self.step_y = self.make_step()
        self.step = self.step_x, self.step_y
        self.stepu_x, self.stepu_y = self.make_step_unnormalized()
        self.stepu = self.stepu_x, self.stepu_y
        self.total_flux = np.sum(self.values)

    def count_bins(self):
        '''Counts the number of bins and bin edges in the data'''
        l = len(self.values)
        return l, l + 1

    def scale_values(self):
        '''Normalizes values to given scaling factor'''
        return self.values * self.scaling_factor

    def estimate_error(self):
        '''If error is not given, '''
        return np.full(len(self.values), 0.5) * self.scaling_factor

    def make_step(self):
        '''Make the binned flux data able to be plotted with plt.plot'''
        assert len(self.edges) - 1 == len(self.normalized_values), 'x - 1 != y'
        Y = np.array([[yy, yy] for yy in np.array(self.normalized_values)]).flatten()
        X = np.array([[xx, xx] for xx in np.array(self.edges)]).flatten()[1:-1]
        return X, Y

    def make_step_unnormalized(self):
        '''Make the binned flux data able to be plotted with plt.plot'''
        assert len(self.edges) - 1 == len(self.values), 'x - 1 != y'
        Y = np.array([[yy, yy] for yy in np.array(self.values)]).flatten()
        X = np.array([[xx, xx] for xx in np.array(self.edges)]).flatten()[1:-1]
        return X, Y

    def functional_form(self, E):
        '''Produce a function from the step data (for use in integration)'''
        if type(E) == np.ndarray:
            val = np.empty(len(E))
            for j, e in enumerate(E):
                for i, v in enumerate(self.normalized_values):
                    if e >= self.edges[i] and e < self.edges[i+1]:
                        val[j] = v
        else:
            val = 0
            for i, v in enumerate(self.normalized_values):
                if E >= self.edges[i] and E < self.edges[i+1]:
                    val = v
        return val

    def change_bins(self, bins):
        '''Makes discrete energy groups from continuous function above, given a desired bin structure.
        TODO: Change method of integration.'''
        bin_values = []
        for i in range(len(bins) - 1):
            area, err = quad(self.functional_form, bins[i], bins[i+1])
            height = area / (bins[i+1] - bins[i])
            bin_values.append(height)
        Spectrum.__init__(self, bins, bin_values, dfde=True, label=self.label)
        return bin_values

    def findroot(self, percentile, func):
        l, r = self.region
        c = np.geomspace(l, r, 3)[1]
        while abs(func(c) - percentile) > 1e-12:
            c = np.geomspace(l, r, 3)[1]
            if percentile < func(c):
                r = c
            else:
                l = c
        return c

    def e_avg(self):
        '''Calculates the average x value of the spectrum.'''
        cumsum = 0
        values = self.values / self.total_flux
        for i, val in enumerate(values):
            if cumsum + val < 0.5:
                cumsum += val
            else:
                x1, x2 = self.edges[i], self.edges[i+1]
                next_val = values[i]
                break
        percent = (0.5 - cumsum) / (next_val)
        x_avg = (x2 - x1) * percent
        return x_avg

    def calc_r_tot_ratio(self, cutoff):
        '''Given a cutoff value, calculates the ratio of the integrated value
        above that cutoff to the total integrated value of the spectrum.'''
        top = quad(self.functional_form, cutoff, self.region[1])[0]
        return top / self.total_flux

    def plot(self, perMev=True):
        '''Plot flux data'''
        plt.figure(99)
        if perMev:
            plt.plot(self.step_x, self.step_y)
        else:
            plt.plot(self.stepu_x, self.stepu_y)
        plt.xlabel('Energy MeV')
        plt.ylabel('Flux $MeV^{-1}cm^{-2}s^{-1}$')
        plt.xlim(1E-8, 20)
        plt.xscale('log')
        plt.yscale('log')
        plt.legend()

    def info(self):
        s = '********************************************\n'
        s += 'Information on spectrum: {}\n'.format(self.label)
        s += '*******************************************\n'
        s += 'Number of Bins: {}\n'.format(self.num_bins)
        s += 'Number of Bin Edges: {}\n'.format(self.num_edges)
        s += 'Scaling Factor: {}\n'.format(self.scaling_factor)
        s += 'Total Flux: {:8.5e}\n'.format(self.total_flux)
        s += '*******************************************\n'
        s += ' |  Bin Edges  | Values     |\n'
        for i in range(len(self.edges)):
            s += ' |  {:8.5e}             |\n'.format(self.edges[i])
            if i != len(self.values - 1):
                s += ' |              {:8.5e} |\n'.format(self.values[i])
        print(s)

if __name__ == '__main__':
    bins = np.array([1E-11, 1E-5, 0.5, 1, 20])
    vals = np.array([0.1, 1, 10, 2])
    err = vals * 0.05
    s = Spectrum(bins, vals, err, 2, label='Test Spectrum')
    s.plot()
    s.change_bins(np.array([1E-8, 1E-4, 1E-2, 0.6, 1, 15, 20]))
    s.plot()
    s.info()


import logging

import aiopg
from app.core.config import settings
from fastapi import FastAPI

async def connect_to_db(app: FastAPI) -> None:
    """
    Handler which connects to DB and adding connection
    pool to global state.
    :app: application
    """
    logger = logging.getLogger("uvicorn.asgi")
    logger.info(f"Connecting to {settings.DATABASE_DSN}")

    app.state.pool = await aiopg.create_pool(settings.DATABASE_DSN)

    logger.info("Connection established")

async def close_db_connection(app: FastAPI) -> None:
    """
    Handler which closes DB connections pool
    :app: application
    """
    logger = logging.getLogger("uvicorn.asgi")
    logger.info("Closing connection to database")

    await app.state.pool.close()

    logger.info("Connection closed")