# -*- coding: utf-8 -*-
"""
IAMSI - TME4
Programmation SAT - Générateur de championnat
2022-2023

@author: @dataymeric
"""

def encodage(ne, nj, j, x, y):
    """Code une variable m_{j, x, y} par k.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.
    j : int
        Jour.
    x : int
        Equipe jouant à domicile.
    y : int
        Equipe jouant à l'extérieur.

    Returns
    -------
    k : int
        Variable encodée.

    Examples
    --------
    >>> encodage(3, 4, 1, 0, 1)
    11
    """
    return j * ne**2 + x * ne + y + 1

def decodage(k, ne):
    """Retrouve j, x et y à partir de k, ne.

    Parameters
    ----------
    k : int
        Variable encodée.
    ne : int
        Nombre d'équipes.

    Returns
    -------
    j : int
        Jour.
    x : int
        Equipe jouant à domicile.
    y : int
        Equipe jouant à l'extérieur.

    Examples
    --------
    >>> decodage(11, 3)
    (1, 0, 1)
    """
    y = (k - 1) % ne
    x = ((k - 1 - y) // ne) % ne
    j = (k - 1 - y - x * ne) // (ne * ne)
    return j, x, y

def au_moins_un(variables):
    """Renvoie une clause (au format DIMACS) correspondant à la contrainte
    "au moins une de ces variables est vraie".

    Parameters
    ----------
    variables : liste d'int
        Variables à encoder sous la contrainte de cardinalité "au moins 1".

    Returns
    -------
    clause : liste de str de taille (1,)
        Clause encodée sous la contrainte de cardinalité "au moins 1".

    Examples
    --------
    >>> variables = [1, 2, 3]
    >>> au_moins_un(variables)
    ['1 2 3 0']
    """
    clause = [str(v) for v in variables] + ["0"]
    return [" ".join(clause)]

def au_plus_un(variables):
    """Renvoie une clause (au format DIMACS) correspondant à la contrainte
    "au plus une de ces variables est vraie".

    Parameters
    ----------
    variables : liste d'int
        Variables à encoder sous la contrainte de cardinalité "au plus 1".

    Returns
    -------
    clauses : liste de str
        Clauses encodées sous la contrainte de cardinalité "au plus 1".

    Examples
    --------
    >>> variables = [1, 2, 3]
    >>> au_plus_un(variables)
    ['-1 -2 0', '-1 -3 0', '-2 -3 0']
    """
    clauses = []
    n = len(variables)
    for i in range(n):
        for j in range(i + 1, n):
            clauses.append(f"{-variables[i]} {-variables[j]} 0")
    return clauses

def au_plus_k(variables, k):
    """Renvoie une clause (au format DIMACS) correspondant à la contrainte
    "au plus k de ces variables sont vraies".

    Parameters
    ----------
    variables : liste d'int
        Variables à encoder.
    k : int
        Limite.

    Returns
    -------
    clauses : liste de str
        Clauses encodées.

    Examples
    --------
    >>> variables = [1, 2, 3]
    >>> au_plus_k(variables, 2)
    ['-1 -2 -3 0']

    On peut vérifier que cette contrainte est satisfaite lorsque 1 ou 2 (mais
    pas 3) variables sont vraies (au plus 2).
    """
    from itertools import combinations

    clauses = []
    n = len(variables)
    for i in range(k + 1, n + 1):
        for c in combinations(variables, i):
            clause = [str(-x) for x in c] + ["0"]
            clauses.append(" ".join(clause))
    return clauses

def au_moins_k(variables, k):
    """Renvoie une clause (au format DIMACS) correspondant à la contrainte
    "au moins k de ces variables sont vraies".

    Parameters
    ----------
    variables : liste d'int
        Variables à encoder.
    k : int
        Limite.

    Returns
    -------
    liste de str
        Clauses encodées.

    Examples
    --------
    >>> variables = [1, 2, 3]
    >>> au_moins_k(variables, 2)
    ['1 2 0', '1 3 0', '2 3 0', '1 2 3 0']

    On peut vérifier que ces contraintes de cardinalités ne sont satisfaites
    que si 2 ou 3 (mais pas 1) variables sont vraies (au moins 2).
    """
    n = len(variables)
    neg_variables = [-x for x in variables]
    return au_plus_k(neg_variables, n - k)

def encoderC1(ne, nj):
    """Renvoie des contraintes (au format DIMACS) correspondant à la contrainte
    C1 : "chaque équipe ne peut jouer plus d'un match par jour".

    Indication : pour 3 équipes et 4 jours, cela génère 72 contraintes.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.

    Returns
    -------
    clauses : liste de str
        Contraintes générées.
    """
    clauses = []
    for j in range(nj):
        for x in range(ne):
            # Contrainte "au plus 1" pour chaque équipe x et chaque jour j
            domicile = [encodage(ne, nj, j, x, y) for y in range(ne) if y != x]
            exterieur = [encodage(ne, nj, j, y, x) for y in range(ne) if y != x]
            clauses.extend(au_plus_un(domicile + exterieur))
    return clauses

def encoderC2(ne, nj):
    """Renvoie des contraintes (au format DIMACS) correspondant à la contrainte
    C2 : "sur la durée d'un championnat, chaque équipe doit rencontrer l'ensemble
    des autres équipes une fois à domicile et une fois à l'extérieur, soit
    exactement 2 matchs par équipe adverse".

    Indication : pour 3 équipes et 4 jours, cela génère 42 contraintes.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.

    Returns
    -------
    clauses : liste de str
        Contraintes générées.
    """
    clauses = []
    for x in range(ne):
        for y in range(ne):
            if x != y:
                list_match = [encodage(ne, nj, j, x, y) for j in range(nj)]
                clauses.extend(au_moins_un(list_match))
                clauses.extend(au_plus_un(list_match))
    return clauses

def encoderC3(ne, nj, pext=50, pdom=40):
    """Renvoie des contraintes (au format DIMACS) correspondant aux contraintes
    des matchs le dimanche.
    On considère que le dimanche est le deuxième jour de la semaine (chiffres impairs).

    Indication : pour 3 équipes et 4 jours, cela génère 24 contraintes.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.
    pext : int, default=50
        Pourcentage de matchs à l'extérieur.
    pdom : int, default=40
        Pourcentage de matchs à domicile.

    Returns
    -------
    clauses : liste de str
        Contraintes générées.
    """
    kext = int((ne - 1) * 2 * pext / 100)
    kdom = int((ne - 1) * 2 * pdom / 100)
    clauses = []
    for x in range(ne):
        for y in range(ne):
            if x != y:
                # tous les matchs à domicile joués le dimanche
                domicile = [encodage(ne, nj, j, x, y) for j in range(1, nj, 2)]
                clauses.extend(au_moins_k(domicile, kdom))
                # tous les matchs à l'extérieur joués le dimanche
                exterieur = [encodage(ne, nj, j, y, x) for j in range(1, nj, 2)]
                clauses.extend(au_moins_k(exterieur, kext))
    return clauses

def encoderC4(ne, nj):
    """Renvoie des contraintes (au format DIMACS) correspondant aux contraintes
    des matchs consécutifs.

    Note : cette implémentation est fausse, n'ayant pas bien compris comment récupérer
    la notion de matchs consécutifs.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.

    Returns
    -------
    clauses : liste de str
        Contraintes générées.
    """
    clauses = []
    for j in range(nj):
        for x in range(ne):
            domicile = [encodage(ne, nj, j, x, y) for y in range(ne) if y != x]
            clauses.extend(au_plus_k(domicile, 2))
            exterieur = [encodage(ne, nj, j, y, x) for y in range(ne) if y != x]
            clauses.extend(au_plus_k(exterieur, 2))
    return clauses

def encoder(ne, nj, extension=False):
    """Encode toutes les contraintes C1 et C2 dans un fichier 'championnat.cnf'.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.
    extension : bool, optional
        Rajoute les contraintes afin d'étendre le problème avec l'équilibrage
        des déplacements et des week-ends.

    Returns
    -------
    contraintes : liste de str
        Contraintes C1 et C2 (avec C3 et C4 si extension).
    """
    contraintes = encoderC1(ne, nj) + encoderC2(ne, nj)
    if extension:
        contraintes.extend(encoderC3(ne, nj) + encoderC4(ne, nj))
    with open("championnat.cnf", "w") as f:
        # Ecrire l'en-tête du fichier DIMACS
        f.write(f"p cnf {ne**2 * nj - 1} {len(contraintes)}\n")
        # Ecrire les contraintes
        for contrainte in contraintes:
            f.write(contrainte + "\n")
    return contraintes

def decoder(output_file, ne, nj, team_names_file=None):
    """Traduit le modèle en un planning. Si le modèle est insatisfiable, renvoie
    None. Sinon, renvoie un dictionnaire.

    Parameters
    ----------
    output_file : str
        Nom du fichier généré par glucose.
    ne : int
        Nombre d'équipes.
    nj : int
        Nombre de jours.
    team_names_file : str, optional
        Nom du fichier contenant le nom des équipes.

    Returns
    -------
    planning : dict
        Planning du championnat.
        Les clés correspondent aux jours (0, nj - 1).
        Les items correspondent aux équipes devant jouer ce jour-là, sous la forme
        d'un dictionnaire et de listes (car plusieurs matchs peuvent avoir lieu
        le même jour !) {"Domicile": [x_1, x_2, ...], "Extérieur": [y_1, y_2, ...]}.
    """
    # Ouvrir le fichier contenant les noms d'équipe
    if team_names_file is not None:
        with open(team_names_file, "r") as f:
            team_names = [line.strip() for line in f]
        assert len(team_names) == ne, "Le nombre d'équipes ne correspondent pas."

    # Ouvrir le fichier de sortie de glucose
    with open(output_file, "r") as f:
        output_lines = f.readlines()

    # Extraire le modèle s'il existe
    model = output_lines[0].split()

    # Si aucun modèle n'a été trouvé, il n'y a pas de solution
    if "UNSAT" in model:
        return None

    # Cas SAT : initialisation du planning sous forme de dictionnaire
    planning = {j: {"Domicile": [], "Extérieur": []} for j in range(nj)}

    for literal in model:
        literal = int(literal)
        if literal > 0:
            j, x, y = decodage(literal, ne)
            if team_names_file is not None:
                x = team_names[x]
                y = team_names[y]
            planning[j]["Domicile"].append(x)
            planning[j]["Extérieur"].append(y)

    return planning

def affichage(planning):
    """Affiche un planning de matchs sous la forme d'un tableau ASCII dans la console.

    Parameters
    ----------
    planning : dict
        Planning des matchs.

    Returns
    -------
    None (stdout)
        Affichage console.
    """
    if planning is None:
        print("Le problème posé n'a pas de solutions. :(")
    else:
        # Détermine la largeur maximale de chaque colonne
        column_lengths = {"Jour": len("Jour")}
        for row in planning.values():
            for column, values in row.items():
                if values:  # cas liste vide
                    column_lengths[column] = max(
                        column_lengths.get(column, 0),
                        len(column),
                        max(len(str(value)) for value in values),
                    )
                else:
                    column_lengths[column] = max(
                        column_lengths.get(column, 0), len(column)
                    )

        # Calcule la largeur totale de la table
        total_width = sum(column_lengths.values()) + len(column_lengths) * 3 + 1

        # Affiche le titre
        title = "Planning des matchs"
        print(f"\n{title:^{total_width}}")

        # Affiche la bordure supérieure du tableau
        columns = sorted(planning[0].keys())
        headers = ["Jour"] + columns
        print(
            "+"
            + "+".join("-" * (column_lengths[column] + 2) for column in headers)
            + "+"
        )

        # Affiche le header
        print(
            "| "
            + " | ".join(f"{header:^{column_lengths[header]}}" for header in headers)
            + " |"
        )

        # Affiche le séparateur du header
        print(
            "+"
            + "+".join("-" * (column_lengths[column] + 2) for column in headers)
            + "+"
        )

        # Affiche chaque ligne
        for row_name, row in planning.items():
            row_length = max(len(value) for value in row.values())
            for i in range(row_length):
                row_values = [str(row_name)]
                for column in columns:
                    if i < len(row[column]):
                        value = row[column][i]
                        row_values.append(str(value))
                    else:
                        row_values.append("")
                print(
                    "| "
                    + " | ".join(
                        f"{value:^{column_lengths[column]}}"
                        for column, value in zip(headers, row_values)
                    )
                    + " |"
                )

        # Affiche la bordure inférieure du tableau
        print(
            "+"
            + "+".join("-" * (column_lengths[column] + 2) for column in headers)
            + "+"
        )

def glucose():
    """Appel le solveur SAT glucose. Considére qu'il fait parti de l'environnement
    (e.g. /usr/local/bin/, ne marchera pas sous Windows). Travaille dans le répertoire
    courant, à partir des fichiers générés à l'aide de la fonction `encoder`.
    Enregistre les résultats dans un fichier `planning.cnf`.
    """
    import subprocess

    cmd = "glucose championnat.cnf planning.cnf"
    subprocess.run(cmd, shell=True, stdout=subprocess.DEVNULL)

def optimisation(ne, nj_min, nj_max, timeout=10):
    """Trouve le nombre de jours minimal pour pouvoir planifier tous les matchs
    de championnat pour un nombre d'équipes donné. Utilise des appels SAT (glucose) de
    façon itérative. Si le solveur met plus de 10 secondes à traiter le problème,
    on passe à une itération suivante. Si la fonction ne renvoie rien, c'est que
    le problème est trop lourd pour être trouvé en 10 secondes (une solution existe
    forcément dans notre problème). Le programme dure au maximum (nj_max - nj_min) * 10
    secondes.

    Parameters
    ----------
    ne : int
        Nombre d'équipes.
    nj_min : int
        Borne minimale de la recherche.
    nj_max : int
        Borne maximale de la recherche.
    timeout : int, default=10
        Valeur du timeout (en secondes).

    Returns
    -------
    j : int
        Nombre de jours optimal.

    Examples
    --------
    >>> optimisation(3, 3, 10)
    6

    >>> optimisation(10, 10, 20)
    18

    >>> optimisation(20, 20, 40)
    None

    Le timeout est trop bas pour permettre à glucose de résoudre le problème avec ne=20.
    """
    import multiprocessing

    for j in range(nj_min, nj_max + 1):
        encoder(ne, j)
        p = multiprocessing.Process(target=glucose)
        p.start()
        p.join(timeout)  # on attend 10 secondes
        if p.is_alive():  # si le processus est toujours vivant après 10 secondes
            print("timeout atteint...")
            p.terminate()  # on le termine
            continue  # on passe à l'itération suivante
        # sinon, c'est qu'il a fini : on regarde si le modèle est satisfiable, et si
        # c'est le cas, on renvoie j
        if decoder("planning.cnf", ne, j) is not None:
            return j

if __name__ == "__main__":
    """Programme principal. Permet à l'utilisateur de saisir le nombre d'équipes,
    le nombre de jours, préciser s'il y a un fichier texte contenant le nom des équipes,
    avec la possibilité de nettoyer les fichiers générés par glucose. Affiche le
    planning s'il y a une solution au problème.
    """
    import os

    # Saisie
    ne = int(input("Saisir le nombre d'équipes : "))
    nj = int(input("Saisir le nombre de jours : "))
    teams = input(
        "Nom du fichier donnant le nom des équipes "
        + "(appuyer sur la touche 'enter' pour passer ou s'il n'y en a pas) : "
    )
    janitor = input(
        "Voulez vous nettoyer les fichiers de travail à la fin du programme ?"
        + "(o/oui, appuyer sur la touche 'enter' pour passer) "
    )

    # Checks
    if teams == "":
        teams = None
    elif not os.path.isfile(teams):
        raise ValueError(f"Le fichier '{teams}' n'existe pas.")

    # Programme
    encoder(ne, nj)  # Encodage du problème
    glucose()  # Résolution grâce à glucose
    planning = decoder("planning.cnf", ne, nj, teams)  # Décodage le résultat
    affichage(planning)  # Affichage du résultat sous la forme d'un tableau

    # Nettoyage des fichiers de travail (si l'utilisateur l'a spécifié)
    if janitor.lower() in ("o", "oui"):
        os.remove("planning.cnf")
        os.remove("championnat.cnf")

"""---- Résultats ----
Pour ne=3, nj=4, le problème n'est pas satisfiable. Par optimisation, il faut au minimum
6 jours pour organiser un championnat avec 3 équipes.

Pour ne=3, nj=6, et le nom des équipes étant stockées dans 'equipes.txt' on
obtient le résultat suivant à l'aide de glucose et du programme python :

                Planning des matchs
+------+---------------------+---------------------+
| Jour |      Domicile       |      Extérieur      |
+------+---------------------+---------------------+
|  0   |    Saint-Etienne    | Paris Saint-Germain |
|  1   | Paris Saint-Germain |    Saint-Etienne    |
|  2   | Paris Saint-Germain |       Monaco        |
|  3   |    Saint-Etienne    |       Monaco        |
|  4   |       Monaco        | Paris Saint-Germain |
|  5   |       Monaco        |    Saint-Etienne    |
+------+---------------------+---------------------+

Que les meilleurs gagnent !

Pour ne=8, nj=14 (valeur trouvée par optimisation), on a 4 matchs par jour (soit 56
matchs en tout) :

                   Planning des matchs
+------+------------------------+------------------------+
| Jour |        Domicile        |       Extérieur        |
+------+------------------------+------------------------+
|  0   |         Monaco         |        RC Lens         |
|  0   | Olympique de Marseille |     Saint-Etienne      |
|  0   |   Olympique Lyonnais   |       FC Nantes        |
|  0   |       LOSC Lille       |  Paris Saint-Germain   |
|  1   |  Paris Saint-Germain   |        RC Lens         |
|  1   |     Saint-Etienne      |       FC Nantes        |
|  1   |         Monaco         | Olympique de Marseille |
|  1   |   Olympique Lyonnais   |       LOSC Lille       |
|  2   |  Paris Saint-Germain   | Olympique de Marseille |
|  2   |     Saint-Etienne      |        RC Lens         |
|  2   |   Olympique Lyonnais   |         Monaco         |
|  2   |       LOSC Lille       |       FC Nantes        |
|  3   |         Monaco         |   Olympique Lyonnais   |
|  3   |       FC Nantes        |     Saint-Etienne      |
|  3   |        RC Lens         |  Paris Saint-Germain   |
|  3   |       LOSC Lille       | Olympique de Marseille |
|  4   |     Saint-Etienne      |  Paris Saint-Germain   |
|  4   |   Olympique Lyonnais   | Olympique de Marseille |
|  4   |       FC Nantes        |         Monaco         |
|  4   |        RC Lens         |       LOSC Lille       |
|  5   |  Paris Saint-Germain   |         Monaco         |
|  5   | Olympique de Marseille |   Olympique Lyonnais   |
|  5   |       FC Nantes        |       LOSC Lille       |
|  5   |        RC Lens         |     Saint-Etienne      |
|  6   |     Saint-Etienne      | Olympique de Marseille |
|  6   |         Monaco         |       LOSC Lille       |
|  6   |   Olympique Lyonnais   |        RC Lens         |
|  6   |       FC Nantes        |  Paris Saint-Germain   |
|  7   | Olympique de Marseille |  Paris Saint-Germain   |
|  7   |   Olympique Lyonnais   |     Saint-Etienne      |
|  7   |       FC Nantes        |        RC Lens         |
|  7   |       LOSC Lille       |         Monaco         |
|  8   |     Saint-Etienne      |   Olympique Lyonnais   |
|  8   |         Monaco         |  Paris Saint-Germain   |
|  8   | Olympique de Marseille |       LOSC Lille       |
|  8   |        RC Lens         |       FC Nantes        |
|  9   |  Paris Saint-Germain   |       LOSC Lille       |
|  9   |         Monaco         |     Saint-Etienne      |
|  9   | Olympique de Marseille |        RC Lens         |
|  9   |       FC Nantes        |   Olympique Lyonnais   |
|  10  |  Paris Saint-Germain   |   Olympique Lyonnais   |
|  10  |         Monaco         |       FC Nantes        |
|  10  |        RC Lens         | Olympique de Marseille |
|  10  |       LOSC Lille       |     Saint-Etienne      |
|  11  |  Paris Saint-Germain   |       FC Nantes        |
|  11  |     Saint-Etienne      |       LOSC Lille       |
|  11  | Olympique de Marseille |         Monaco         |
|  11  |        RC Lens         |   Olympique Lyonnais   |
|  12  |     Saint-Etienne      |         Monaco         |
|  12  |   Olympique Lyonnais   |  Paris Saint-Germain   |
|  12  |       FC Nantes        | Olympique de Marseille |
|  12  |       LOSC Lille       |        RC Lens         |
|  13  |  Paris Saint-Germain   |     Saint-Etienne      |
|  13  | Olympique de Marseille |       FC Nantes        |
|  13  |        RC Lens         |         Monaco         |
|  13  |       LOSC Lille       |   Olympique Lyonnais   |
+------+------------------------+------------------------+
"""


"""
A file for parsing a bunch of text files that were produced from Northwestern University CTECs
written poorly by Matt Nicholson
"""

import json
import re
import traceback

def count_occurrences(word, sentence):
    """
    a helper for counting the number of time a word appears in a sentence
    """
    return sentence.lower().split().count(word)

def read_demographics(course_dict, lines, index):
    """
    a function for parsing the specific part that asks about demographics

    @params:
    course_dict - a dictionary with all of the information about a course in it
    lines - a list containing each line of a text file
    index - an integer the line number you are looking at

    @returns course_dict,  index

    """
    demo_done = 0

    sb = {}
    your_class = {}
    reasons = {}
    interests = {}

    consecutive_newlines = 0

    i = index

    while consecutive_newlines < 3 and i < len(lines):
        if "Graphs illustrating the information" in lines[i]:
            consecutive_newlines = 0
            if demo_done == 0:
                i += 2
                while "Your Class\n" not in lines[i]:
                    words = re.split(r'\s{2,}', lines[i])
                    sb[words[0]] = int(words[1].strip())
                    i += 1
                demo_done += 1

            elif demo_done == 1:
                i += 2
                while "What is your reason" not in lines[i]:
                    words = re.split(r'\s{2,}', lines[i])
                    your_class[words[0]] = int(words[1].strip())
                    i += 1
                demo_done += 1

            elif demo_done == 2:
                i += 2
                while "Respond" not in lines[i]:
                    words = re.split(r'\s{2,}', lines[i])
                    #print(words)
                    reasons[words[0]] = int(words[1].strip())
                    i += 1
                demo_done += 1
            elif demo_done == 3:
                i += 2
                while lines[i] != "\n":
                    words = re.split(r'\s{2,}', lines[i])
                    # print(words)
                    interests[words[0]] = int(words[1].strip())
                    i += 1
                demo_done += 1
        else:
            if lines[i] == "\n":
                consecutive_newlines += 1

        i += 1

    course_dict["school_breakdown"] = sb
    course_dict["reason_for_taking_course"] = reasons
    course_dict["student_years"] = your_class
    course_dict["interest_before"] = interests

    return course_dict, i

def read_number_ratings(course_dict, lines, index):
    """
    a function for parsing the specific part that asks about course ratings and stuff

    """
    done = 0
    instruction_rating = ""
    course_rating = ""
    learned = ""
    how_hard = ""
    instructor_interest = ""
    time = {}

    consecutive_newlines = 0

    i = index

    while done < 5:
        if "Graphs illustrating the information" in lines[i]:
            if done == 0:
                i += 3
                words = re.split(r'\s{2,}', lines[i])
                instruction_rating = float(words[1].strip())
                # print(instruction_rating)
                done += 1
            elif done == 1:
                i += 3
                words = re.split(r'\s{2,}', lines[i])
                course_rating = float(words[1].strip())
                # print(course_rating)
                done += 1
            elif done == 2:
                i += 3
                words = re.split(r'\s{2,}', lines[i])
                learned = float(words[1].strip())
                # print(learned)
                done += 1
            elif done == 3:
                i += 3
                words = re.split(r'\s{2,}', lines[i])
                how_hard = float(words[1].strip())
                # print(how_hard)
                done += 1

            elif done == 4:
                i += 3
                words = re.split(r'\s{2,}', lines[i])
                instructor_interest = float(words[1].strip())
                # print(instructor_interest)
                done += 1
            elif done == 5:
                i += 2
                while lines[i] != "ESSAY QUESTIONS\n":
                    words = re.split(r'\s{2,}', lines[i])
                    time[words[0]] = int(words[1].strip())
                    i += 1
                done += 1
        i += 1

    course_dict["rating_of_instruction"] = instruction_rating
    course_dict["rating_of_course"] = course_rating
    course_dict["how_much_learned"] = learned
    course_dict["how_hard"] = how_hard
    course_dict["instructor_interest"] = instructor_interest
    course_dict["time_spent"] = time

    # print(course_dict.keys())

    return course_dict, i

def read_in_course_info(lines):
    """
    a function for reading in all of the information for a course
    """
    course_info = {}

    num_lines = len(lines)
    at_comments = False
    at_number_questions = False
    at_demographics = False

    # sorry about hitting everyone with the gender binary, Brent told me to
    she_her_hers_count = 0
    he_him_his_count = 0

    comments = []

    ii = 0

    while ii < num_lines:
        if "DEMOGRAPHICS" in lines[ii]:
            at_comments = False
            course_info, ii = read_demographics(course_info, lines, ii)

        elif at_comments:
            comments.append(lines[ii].strip())

            she_her_hers_count += count_occurrences("she", lines[ii])
            she_her_hers_count += count_occurrences("her", lines[ii])
            she_her_hers_count += count_occurrences("hers", lines[ii])

            he_him_his_count += count_occurrences("he", lines[ii])
            he_him_his_count += count_occurrences("him", lines[ii])
            he_him_his_count += count_occurrences("his", lines[ii])

        elif "Student Report for" in lines[ii]:
            # they are all funky, so I standardized some
            course_info["course_name"] = lines[ii].split("Student Report for")[1].split("(")[0].strip()
            course_info["instructor"] = lines[ii].split("(")[1].split(")")[0].strip()

        elif "Project Audience" in lines[ii]:
            course_info["students_enrolled"] = int(lines[ii].split("Project Audience ")[1].strip())

        elif "Responses Received" in lines[ii]:
            course_info["responses_recieved"] = int(lines[ii].split("Responses Received ")[1].strip())

        elif "Comments\n" == lines[ii]:
            at_comments = True
            at_number_questions = False

        elif "COURSE QUESTIONS" in lines[ii]:
            at_number_questions = True
            course_info, ii = read_number_ratings(course_info, lines, ii)
            # print(course_info.keys())

        ii += 1

    course_info["comments"] = comments

    if she_her_hers_count > he_him_his_count:
        course_info["instructor_gender"] = "F"
    elif she_her_hers_count == he_him_his_count:
        course_info["instructor_gender"] = "unknown"
    else:
        course_info["instructor_gender"] = "M"

    return course_info

def do_the_whole_thing(which):
    """
    this function is the main driver for parsing one CTEC text file

    @params: which - a string saying which file you want to parse

    @returns: None

    @modifies: writes a file to disk
    """
    with open("CTECs/{}.txt".format(which), "r", encoding="utf8") as f:
        all_lines = f.readlines()

    total_num_lines = len(all_lines)

    jj = 0

    with open('data.json', 'r') as fp:
        all_courses = json.load(fp)

    start_points = []

    # this is dumb, but it's gonna work and really it only needs to work one time

    while jj < total_num_lines:

        if 'Northwestern\n' in all_lines[jj]:
            start_points.append(jj)
            # print("found start point at {}".format(jj))
        jj += 1

    num_start_points = len(start_points)
    kk = 0
    all_courses[which] = []

    while kk+1 < num_start_points:
        all_courses[which].append(read_in_course_info(all_lines[start_points[kk]:start_points[kk+1]]))
        print("done with course {}".format(kk))
        kk += 1

    with open('data.json', 'w') as fp:
        json.dump(all_courses, fp, indent=4)

def main():
    with open('data.json', 'w') as fp:
        json.dump({}, fp, indent=4)

    depts = ["BME", "EECS", "English", "Gender Studies", "Linguistics", "LOC", "Music", "Spanish"]

    for dept in depts:
        try:
            do_the_whole_thing(dept)
        except Exception as e:
            print("+"*20)
            print(dept)
            print("Something messed up here: {}".format(e))
            traceback.print_exc()
            print("+"*20)

if __name__ == "__main__":
    main()


import os
import sys
import subprocess
sys.path.append(snakemake.config['args']['mcc_path'])
import scripts.mccutils as mccutils
import config.relocate.relocate_post as config

class Insertion:
    def __init__(self):
        self.chromosome = "None"
        self.start = -1
        self.end = -1
        self.name = "None"
        self.type = "None"
        self.left_support = -1
        self.right_support = -1
        self.strand = "."

def main():
    relocate_gff = snakemake.input.relocate_gff
    te_gff = snakemake.input.te_gff

    out_dir = snakemake.params.out_dir
    log = snakemake.params.log
    sample_name = snakemake.params.sample_name
    chromosomes = snakemake.params.chromosomes.split(",")

    mccutils.log("relocate","processing RelocaTE results")

    insertions = get_insertions(relocate_gff, sample_name, chromosomes, ref_l_threshold=config.REF_LEFT_THRESHOLD, ref_r_threshold=config.REF_RIGHT_THRESHOLD, nonref_l_threshold=config.NONREF_LEFT_THRESHOLD, nonref_r_threshold=config.NONREF_RIGHT_THRESHOLD)

    insertions = set_ref_orientations(insertions, te_gff)

    if len(insertions) >= 1:
        insertions = make_redundant_bed(insertions, sample_name, out_dir)
        make_nonredundant_bed(insertions, sample_name, out_dir)
    else:
        mccutils.run_command(["touch",out_dir+"/"+sample_name+"_relocate_redundant.bed"])
        mccutils.run_command(["touch",out_dir+"/"+sample_name+"_relocate_nonredundant.bed"])

    mccutils.log("relocate","RelocaTE postprocessing complete")

def get_insertions(gff, sample_name, chromosomes, ref_l_threshold=0, ref_r_threshold=0, nonref_l_threshold=0, nonref_r_threshold=0):
    insertions = []
    with open(gff, "r") as ingff:
        for line in ingff:
            if "#" not in line:
                split_line = line.split("\t")
                feats = split_line[8].split(";")
                insert = Insertion()
                insert.chromosome = split_line[0]
                insert.start = int(split_line[3])
                insert.end = int(split_line[4])
                insert.strand = split_line[6]

                feat_id = ""
                feat_te_name = ""
                for feat in feats:
                    if "ID=" in feat:
                        feat_id = feat.split("=")[1]
                    elif "TE_Name=" in feat:
                        feat_te_name = feat.split("=")[1]
                    elif "Note=" in feat:
                        if "Shared" in feat:
                            insert.type = "ref"
                        elif "Non-reference" in feat:
                            insert.type = "nonref"
                        else:
                            insert.type = "missing"

                    elif "left_flanking_read_count=" in feat:
                        insert.left_support = int(feat.split("=")[1])

                    elif "right_flanking_read_count=" in feat:
                        insert.right_support = int(feat.split("=")[1])

                if insert.type == "ref":
                    insert.name = feat_te_name+"_reference_"+sample_name+"_relocate_sr_"
                elif insert.type == "nonref":
                    feat_te_name = feat_id.split(".")[0]
                    insert.name = feat_te_name+"_non-reference_"+sample_name+"_relocate_sr_"

            if insert.type == "ref" and insert.left_support >= ref_l_threshold and insert.right_support >= ref_r_threshold and insert.chromosome in chromosomes:
                insertions.append(insert)
            elif insert.type == "nonref" and insert.left_support >= nonref_l_threshold and insert.right_support >= nonref_r_threshold and insert.chromosome in chromosomes:
                insertions.append(insert)

    return insertions

def set_ref_orientations(insertions, te_gff):
    ref_strands = {}
    out_inserts = []
    with open(te_gff, "r") as gff:
        for line in gff:
            if "#" not in line:
                split_line = line.split("\t")
                chrom = split_line[0]
                start = split_line[3]
                end = split_line[4]
                strand = split_line[6]
                ref_strands["_".join([chrom, start, end])] = strand

    for insert in insertions:
        if insert.type == "ref":
            insert.strand = ref_strands["_".join([insert.chromosome, str(insert.start), str(insert.end)])]

        out_inserts.append(insert)

    return out_inserts

def make_redundant_bed(insertions, sample_name, out_dir):
    tmp_bed = out_dir+"/tmp.bed"

    insertion_dict = {}
    out_inserts = []
    for insert in insertions:
        insertion_dict[ "_".join([insert.chromosome, str(insert.start-1), str(insert.end), insert.name, "0", insert.strand])] = insert

    with open(tmp_bed, "w") as out:
        for insert in insertions:
            out_line = "\t".join([insert.chromosome, str(insert.start-1), str(insert.end), insert.name, "0", insert.strand])
            out.write(out_line+"\n")

    sorted_bed = out_dir+"/sorted.bed"
    command = ["bedtools", "sort", "-i", tmp_bed]
    mccutils.run_command_stdout(command, sorted_bed)

    redundant_bed = out_dir+"/"+sample_name+"_relocate_redundant.bed"
    with open(redundant_bed, "w") as outbed:
        header = 'track name="'+sample_name+'_RelocaTE" description="'+sample_name+'_RelocaTE"\n'
        outbed.write(header)
        with open(sorted_bed, "r") as inbed:
            for x, line in enumerate(inbed):

                # outputs inserts in sorted order with unique number added to name
                key = line.replace("\t","_")
                key = key.replace("\n","")
                insert = insertion_dict[key]
                insert.name += str(x+1)
                out_inserts.append(insert)

                # write to bed with unique number added to name
                split_line = line.split("\t")
                split_line[3] += str(x+1)
                line = "\t".join(split_line)
                outbed.write(line)

    mccutils.remove(tmp_bed)
    mccutils.remove(sorted_bed)

    return out_inserts

def make_nonredundant_bed(insertions, sample_name, out_dir):
    uniq_inserts = {}

    for insert in insertions:
        key = "_".join([insert.chromosome, str(insert.end)])
        if key not in uniq_inserts.keys():
            uniq_inserts[key] = insert
        else:
            if (uniq_inserts[key].left_support + uniq_inserts[key].right_support) < (insert.left_support + insert.right_support):
                uniq_inserts[key] = insert

    tmp_bed = out_dir+"/tmp.bed"
    with open(tmp_bed, "w") as outbed:
        for key in uniq_inserts.keys():
            insert = uniq_inserts[key]
            out_line = "\t".join([insert.chromosome, str(insert.start-1), str(insert.end), insert.name, "0", insert.strand])
            outbed.write(out_line+"\n")

    sorted_bed = out_dir+"/sorted.bed"
    command = ["bedtools", "sort", "-i", tmp_bed]
    mccutils.run_command_stdout(command, sorted_bed)

    nonredundant_bed = out_dir+"/"+sample_name+"_relocate_nonredundant.bed"
    with open(sorted_bed, "r") as inbed:
        with open(nonredundant_bed, "w") as outbed:
            header = 'track name="'+sample_name+'_RelocaTE" description="'+sample_name+'_RelocaTE"\n'
            outbed.write(header)
            for line in inbed:
                outbed.write(line)

    mccutils.remove(tmp_bed)
    mccutils.remove(sorted_bed)

if __name__ == "__main__":
    main()


import time

import torch
import numpy as np
import transforms
from models import SSD300, Backbone
from PIL import Image
from torch2trt import torch2trt

def load_model(device, num_classes=20 + 1, checkpoint="../SSD/save_weights/ssd300-14.pth"):
    """
    加载SSD目标检测模型
    :return:
        SSD model
    """
    # create model
    # 目标检测数 + 背景
    model = create_model(num_classes=num_classes)

    # load train weights
    train_weights_dict = torch.load(checkpoint, map_location=device)['model']

    model.load_state_dict(train_weights_dict)
    model.to(device)
    model.eval()
    x = torch.ones((1, 3, 300, 300)).cuda()
    model_trt = torch2trt(model, [x])
    # with torch.no_grad():
    #     # initial model
    #     init_img = torch.zeros((1, 3, 300, 300), device=device)
    #     model(init_img)
    #
    return model_trt

def inference(model, tf, images_batches, category_index, threshold=0.5, device='cpu'):
    height, width = images_batches[0].shape[:2]
    imgs = []
    for img in images_batches:
        imgPIL = Image.fromarray(img)
        _img, _ = tf(imgPIL)
        imgs.append(_img)
    images = torch.stack(imgs, dim=0)

    with torch.no_grad():
        predictions = model(images.to(device))[0]  # bboxes_out, labels_out, scores_out
        predict_boxes = predictions[0].to("cpu").numpy()
        predict_boxes[:, [0, 2]] = predict_boxes[:, [0, 2]] * width
        predict_boxes[:, [1, 3]] = predict_boxes[:, [1, 3]] * height
        predict_classes = predictions[1].to("cpu").numpy()
        predict_scores = predictions[2].to("cpu").numpy()
        if len(predict_boxes) == 0:
            print("没有检测到任何目标!")
        filter_boxes = predict_boxes[predict_scores > threshold].astype(int)
        classes_str = [category_index[i] for i in predict_classes[predict_scores > threshold]]
    return filter_boxes, classes_str

def create_model(num_classes):
    backbone = Backbone()
    model = SSD300(backbone=backbone, num_classes=num_classes)

    return model

def time_synchronized():
    torch.cuda.synchronize() if torch.cuda.is_available() else None
    return time.time()

def get_data_transform():
    return transforms.Compose([transforms.Resize(),
                               transforms.ToTensor(),
                               transforms.Normalization()])


import cv2

video = cv2.VideoCapture(0)  # aqui eu inicio minha webcam, e coloco o 0 pois é minha camera padrão

while True:
    conectado, frame = video.read()

    #mostrar a imagem que ta na camera
    cv2.imshow('Video', frame )

    # para imagem ficar travada, para nao abrir e fechar logo e espero 1 para fechar
    #coloquei a letra 'q' pois ela na tabela asc é == 1
    if cv2.waitKey(1) == ord('q'):
        break
video.release() #pra liberar a captura
cv2.destroyWindow() #pra nao ficar salvo na memoria


#! /usr/bin/env python
import rospy
import csv
import matlab.engine
from std_msgs.msg import String
import numpy as np
import ast
import json
import math
from sklearn.metrics import mean_squared_error
import pandas as pd

def callback(data):
    if len(data.data) != 0 and data.data != "Waiting for enough data":
        traj, expData, expSigma = data.data.split("splitTag")
        traj, expData, expSigma = matlab.double(json.loads(str(traj))), matlab.double(json.loads(str(expData))[:100]), matlab.double(json.loads(str(expSigma))[:100])
        predictedMeans, variances = [],[]

        #i = 0
#        print(len(expData))
        for row in expData:
            #for col in row:
            #if i % 10 == 0:
            predictedMeans.append(row)
            #i += 1
        #i = 0
 #       print("NUM")

        #rint(np.array(traj).shape)
        for timestep in range(len(expSigma)):
            data = []
            #if i % 10 == 0:
            for row in range(len(expSigma[timestep])):
                for col in expSigma[timestep][row]:
                    data.append(col)
            variances.append(data)
            #i+=1

        #print("Mean length = " + str(len(predictedMeans)) + " Variance length = " + str(len(variances)))
        df1 = pd.DataFrame(predictedMeans)
        df1.to_csv('predSampledtraj_1001_trimmed.csv',index=False, header=False)
        df2 = pd.DataFrame(variances)
        df2.to_csv('varPredSampledtraj_1001_trimmed.csv',index=False, header=False)
        df3 = pd.DataFrame(traj)
        df3.to_csv('traj_1001_trimmed.csv',index=False,header=False)
        df3.append(df1, ignore_index=True).to_csv('traj_1001.csv', index=False,header=False)

        #print(predictedMeans)
        # print(str(len(expSigma)) + " " + str(len(expSigma[0])) + " " + str(len(expSigma[0][0])))

def listener():
    rospy.init_node('parse', anonymous=False)
    rospy.Subscriber("human_traj_pred", String, callback)
    rospy.spin()

if __name__ == '__main__':
    print("Calling Listener")
    listener()


import time
from typing import Union, Callable
from soc import UdpSocketWithOp, UDP_OPCODES

class SignalingClient(UdpSocketWithOp):
    def __init__(self, my_id: str, other_id: str, my_address: tuple[str, int], server_address: tuple[str, int]) -> None:
        super().__init__(my_address)
        self.my_id = my_id
        self.other_id = other_id
        self.callbacks = []
        self.send(f"{my_id}|{other_id}".encode('utf-8'),
                  server_address, UDP_OPCODES.CLIENT_SIGNALING)
        self.other_address: Union[tuple[str, int], None] = None

    def add_on_packet(self, callback: Callable[[int, bytes, tuple[str, int]], None]):
        self.callbacks.append(callback)

    def on_packet(self, packet: bytes, address: tuple[str, int], op: int):
        if op == UDP_OPCODES.SERVER_SIGNALING:
            ip, port = packet.decode('utf-8').split("|")
            port = int(port)
            self.other_address = (ip, port)
            print("Connected to", self.other_id)
        elif op == UDP_OPCODES.CLIENT_DEBUG:
            print(f"Debug {packet.decode('utf-8')}")

        [callback(packet, address, op) for callback in self.callbacks]


import numpy as np
from corr_functions import make_surrogates
from brainsmash.mapgen.eval import base_fit
import matplotlib.pyplot as plt

# Settings
plt.ioff()
n_jobs = 10
n_surrogates = 5000
PROJ_DIR = '/home/cnorman/Documents/CUBRIC/ALSPAC/CardiffFC/'
sc_isv_fil = PROJ_DIR + 'data/structural/isv_sc_z_noarea.csv'
out_fil_surr = PROJ_DIR+'data/structural/isv_sc_z_noarea_'+str(n_surrogates)+'_surrogates.csv'
out_fil_lh_vario = PROJ_DIR+'gradients/figures/sc_isv_lh_'+str(n_surrogates)+'_surrogates_variogram.png'
out_fil_rh_vario = PROJ_DIR+'gradients/figures/sc_isv_rh_'+str(n_surrogates)+'_surrogates_variogram.png'

# Load SC ISV data
sc_isv_raw = np.loadtxt(open(sc_isv_fil,"r"),delimiter=' ')
nreg = np.shape(sc_isv_raw)[0]
sc_isv = np.row_stack((sc_isv_raw[:int(len(sc_isv_raw)/2)],sc_isv_raw[int(len(sc_isv_raw)/2):]))

# Load geodesic distances
dist_mats = np.zeros((2,int(nreg/2),int(nreg/2)))
dist_mats[0,:,:] = np.loadtxt(PROJ_DIR + 'parcellations/HCP-MMP1/lh.fsaverage-32k_glasser-360_geodesic_distmat.txt')
dist_mats[1,:,:] = np.loadtxt(PROJ_DIR + 'parcellations/HCP-MMP1/rh.fsaverage-32k_glasser-360_geodesic_distmat.txt')

# Make & save surrogates
lh_surrogates = make_surrogates(sc_isv[0], dist_mats[0], n=n_surrogates, n_jobs=n_jobs)
rh_surrogates = make_surrogates(sc_isv[1], dist_mats[1], n=n_surrogates, n_jobs=n_jobs)
surrogates = np.concatenate((lh_surrogates,rh_surrogates),axis=0)
np.savetxt(out_fil_surr,surrogates,delimiter=',')

# Make & save variogram figures
# Left
base_fit(sc_isv[0], dist_mats[0],nsurr=n_surrogates)
plt.savefig(out_fil_lh_vario)
# Right
base_fit(sc_isv[1], dist_mats[1],nsurr=n_surrogates)
plt.savefig(out_fil_rh_vario)


import numpy as np
import pandas as pd
import math
import time
import itertools
import matplotlib.pyplot as plt
start_time = time.time()

df = pd.read_csv('s_data.csv')

#number of features
m=2

#returns mode of array 'x'
def mode1(x):
    values, counts = np.unique(x, return_counts=True)
    m = counts.argmax()
    return values[m]

#gets number of folds and returns 'i'th fold as test-set and remaining data as train-fold

def train_test_data(data,n,feature1,feature2):
    train_data = data[[feature1,feature2,'inauthentic']].iloc[:n,:]
    test_data = data[[feature1,feature2,'inauthentic']].iloc[n:,:]
    return train_data,test_data

def euclidean_distance(x,y):
    return np.linalg.norm(x - y)

#sorts data of matrix 'data' based on their distance from point 'x', distance is calculated with 'distance_method'
def get_neighbors_sorted(data,x,distance_method):
    global m
    z = np.zeros((len(data),1), dtype='int64')
    data = np.append(data, z, axis=1)
    for row in range(len(data)):
        data[row,m+1] = distance_method(x,data[row,:m])
    return data[data[:,-1].argsort()]

#gets train and test set;number of nearest neighbors as 'k' and 'distance method'
#predicts a label for each data of test-set and add it to a new colomn of test-set
#then returns test-set
def knn(train,test,distance_method,k,h):
    global m
    #convert data_frame to numpy matrix to speed-up calculations
    train = train.copy().values
    #add new column for predicted data to test-set
    z = np.zeros((h,1), dtype='int64')
    ##test = np.append(test, z, axis=1)
    #predict label for each point in test-set and return it
    pred = []
    for i in range(h):
        for j in range(h):
            x = [test[0,i,0],test[0,j,1]]
            nearest_neighbors = get_neighbors_sorted(train,x,distance_method)[:k]
            pred.append(mode1(nearest_neighbors[:,m]))
    colors=[]
    for i in pred:
        if int(i) == 1:
            colors.append(0)
        else:
            colors.append(255)
    return np.asarray(colors).reshape(h,h)

#returns accuracy
def get_accuracy(actual, predicted):
    return (actual == predicted).sum() / float(len(actual))

#main function
#gets data,number of folds for k-fold cross validation, distance method and number of nearest neighbors
#return sum of confusion matrixes and mean of accuracy

def diagram(data,distance_method,k,n,featuures,h):
    train,test = train_test_data(df,n,featuures[0],featuures[1])
    test_x = np.linspace(start=min(data[featuures[0]]), stop=max(data[featuures[0]]), num=h)
    test_y = np.linspace(start=min(data[featuures[1]]), stop=max(data[featuures[1]]), num=h)
    test = np.dstack((test_x,test_y))
    colors = knn(train,test,distance_method,k,h)
    fig, ax = plt.subplots()
    ax.pcolormesh(test_x,test_y, colors,cmap='gray')
    p_class = data.loc[data['inauthentic'].isin([1])][[featuures[0],featuures[1]]].values
    n_class = data.loc[data['inauthentic'].isin([0])][[featuures[0],featuures[1]]].values
    plt.legend()
    plt.xlabel(featuures[0])
    plt.ylabel(featuures[1])
    plt.title(f'k={k}')
    plt.show()

#call main function
#cross_validation(data,num_fold,distance_method,k)
print(diagram(df,euclidean_distance,3,500,['Variance','Skewness'],300))


""" This file defines utilities for trajectory optimization. """
import abc
import logging

import numpy as np
import scipy as sp

LOGGER = logging.getLogger(__name__)

# Constants used in TrajOptLQR.
DGD_MAX_ITER = 50
DGD_MAX_LS_ITER = 20
DGD_MAX_GD_ITER = 200

ALPHA, BETA1, BETA2, EPS = 0.005, 0.9, 0.999, 1e-8  # Adam parameters

def traj_distr_kl(new_mu, new_sigma, new_traj_distr, prev_traj_distr, tot=True):
    """
    Compute KL divergence between new and previous trajectory
    distributions.
    Args:
        new_mu: T x dX, mean of new trajectory distribution.
        new_sigma: T x dX x dX, variance of new trajectory distribution.
        new_traj_distr: A linear Gaussian policy object, new
            distribution.
        prev_traj_distr: A linear Gaussian policy object, previous
            distribution.
        tot: Whether or not to sum KL across all time steps.
    Returns:
        kl_div: The KL divergence between the new and previous
            trajectories.
    """
    # Constants.
    T = new_mu.shape[0]
    dU = new_traj_distr.dU

    # Initialize vector of divergences for each time step.
    kl_div = np.zeros(T)

    # Step through trajectory.
    for t in range(T):
        # Fetch matrices and vectors from trajectory distributions.
        mu_t = new_mu[t, :]
        sigma_t = new_sigma[t, :, :]
        K_prev = prev_traj_distr.K[t, :, :]
        K_new = new_traj_distr.K[t, :, :]
        k_prev = prev_traj_distr.k[t, :]
        k_new = new_traj_distr.k[t, :]
        chol_prev = prev_traj_distr.chol_pol_covar[t, :, :]
        chol_new = new_traj_distr.chol_pol_covar[t, :, :]

        # Compute log determinants and precision matrices.
        logdet_prev = 2 * sum(np.log(np.diag(chol_prev)))
        logdet_new = 2 * sum(np.log(np.diag(chol_new)))
        prc_prev = sp.linalg.solve_triangular(
            chol_prev, sp.linalg.solve_triangular(chol_prev.T, np.eye(dU),
                                                  lower=True)
        )
        prc_new = sp.linalg.solve_triangular(
            chol_new, sp.linalg.solve_triangular(chol_new.T, np.eye(dU),
                                                 lower=True)
        )

        # Construct matrix, vector, and constants.
        M_prev = np.r_[
            np.c_[K_prev.T.dot(prc_prev).dot(K_prev), -K_prev.T.dot(prc_prev)],
            np.c_[-prc_prev.dot(K_prev), prc_prev]
        ]
        M_new = np.r_[
            np.c_[K_new.T.dot(prc_new).dot(K_new), -K_new.T.dot(prc_new)],
            np.c_[-prc_new.dot(K_new), prc_new]
        ]
        v_prev = np.r_[K_prev.T.dot(prc_prev).dot(k_prev),
                       -prc_prev.dot(k_prev)]
        v_new = np.r_[K_new.T.dot(prc_new).dot(k_new), -prc_new.dot(k_new)]
        c_prev = 0.5 * k_prev.T.dot(prc_prev).dot(k_prev)
        c_new = 0.5 * k_new.T.dot(prc_new).dot(k_new)

        # Compute KL divergence at timestep t.
        kl_div[t] = max(
            0,
            -0.5 * mu_t.T.dot(M_new - M_prev).dot(mu_t) -
            mu_t.T.dot(v_new - v_prev) - c_new + c_prev -
            0.5 * np.sum(sigma_t * (M_new-M_prev)) - 0.5 * logdet_new +
            0.5 * logdet_prev
        )

    # Add up divergences across time to get total divergence.
    return np.sum(kl_div) if tot else kl_div

def traj_distr_kl_alt(new_mu, new_sigma, new_traj_distr, prev_traj_distr, tot=True):
    """
    This function computes the same quantity as the function above.
    However, it is easier to modify and understand this function, i.e.,
    passing in a different mu and sigma to this function will behave properly.
    """
    T, dX, dU = new_mu.shape[0], new_traj_distr.dX, new_traj_distr.dU
    kl_div = np.zeros(T)

    for t in range(T):
        K_prev = prev_traj_distr.K[t, :, :]
        K_new = new_traj_distr.K[t, :, :]

        k_prev = prev_traj_distr.k[t, :]
        k_new = new_traj_distr.k[t, :]

        sig_prev = prev_traj_distr.pol_covar[t, :, :]
        sig_new = new_traj_distr.pol_covar[t, :, :]

        chol_prev = prev_traj_distr.chol_pol_covar[t, :, :]
        chol_new = new_traj_distr.chol_pol_covar[t, :, :]

        inv_prev = prev_traj_distr.inv_pol_covar[t, :, :]
        inv_new = new_traj_distr.inv_pol_covar[t, :, :]

        logdet_prev = 2 * sum(np.log(np.diag(chol_prev)))
        logdet_new = 2 * sum(np.log(np.diag(chol_new)))

        K_diff, k_diff = K_prev - K_new, k_prev - k_new
        mu, sigma = new_mu[t, :dX], new_sigma[t, :dX, :dX]

        kl_div[t] = max(
                0,
                0.5 * (logdet_prev - logdet_new - new_traj_distr.dU +
                       np.sum(np.diag(inv_prev.dot(sig_new))) +
                       k_diff.T.dot(inv_prev).dot(k_diff) +
                       mu.T.dot(K_diff.T).dot(inv_prev).dot(K_diff).dot(mu) +
                       np.sum(np.diag(K_diff.T.dot(inv_prev).dot(K_diff).dot(sigma))) +
                       2 * k_diff.T.dot(inv_prev).dot(K_diff).dot(mu))
        )

    return np.sum(kl_div) if tot else kl_div

def approximated_cost(sample_list, traj_distr, traj_info):
    """
    This function gives the LQR estimate of the cost function given the noise
    experienced along each sample in sample_list.
    Args:
        sample_list: List of samples to extract noise from.
        traj_distr: LQR controller to roll forward.
        traj_info: Used to obtain dynamics estimate to simulate trajectories.
    Returns:
        mu_all: Trajectory means corresponding to each sample in sample_list.
        predicted_cost: LQR estimates of cost of each sample in sample_list.
    """
    T = traj_distr.T
    N = len(sample_list)
    dU = traj_distr.dU
    dX = traj_distr.dX
    noise = sample_list.get_noise()

    # Constants.
    idx_x = slice(dX)
    mu_all = np.zeros((N, T, dX+dU))

    # Pull out dynamics.
    Fm = traj_info.dynamics.Fm
    fv = traj_info.dynamics.fv
    dyn_covar = traj_info.dynamics.dyn_covar

    for i in range(N):
        mu = np.zeros((T, dX+dU))
        mu[0, idx_x] = traj_info.x0mu
        for t in range(T):
            mu[t, :] = np.hstack([
                mu[t, idx_x],
                (traj_distr.K[t, :, :].dot(mu[t, idx_x]) + traj_distr.k[t, :]
                 + traj_distr.chol_pol_covar[t].T.dot(noise[i, t]))
            ])
            if t < T - 1:
                mu[t+1, idx_x] = Fm[t, :, :].dot(mu[t, :]) + fv[t, :]
        mu_all[i, :, :] = mu

    # Compute cost.
    predicted_cost = np.zeros((N, T))

    for i in range(N):
        for t in range(T):
            predicted_cost[i, t] = traj_info.cc[t] + \
                    0.5 * mu_all[i,t,:].T.dot(traj_info.Cm[t, :, :]).dot(mu_all[i,t,:]) + \
                    mu_all[i,t,:].T.dot(traj_info.cv[t, :])

    return mu_all, predicted_cost


from flask import Flask, request, jsonify
from datetime import datetime
from collections import OrderedDict

app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False  # Disable sorting of JSON keys

@app.route('/api')
def index():
    # Get the query parameters
    slack_name = request.args.get('slack_name')
    track = request.args.get('track')

    # Get the current day of the week
    current_day = datetime.utcnow().strftime('%A')

    # Get the current UTC time
    utc_time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')

    # Create the response data as an OrderedDict
    data = OrderedDict([
        ('slack_name', slack_name),
        ('current_day', current_day),
        ('utc_time', utc_time),
        ('track', track),
        ('github_file_url', 'https://github.com/BUSOLA12/my_HNGx_project_1/blob/main/app.py'),
        ('github_repo_url', 'https://github.com/BUSOLA12/my_HNGx_project_1.git'),
        ('status_code', 200)
    ])

    # Return the JSON response
    return jsonify(data)

if __name__ == '__main__':
    app.run()


import folium
import pandas
m=folium.Map(location=[25.041807, 77.899597],zoom_start=5,tiles='Mapbox Bright')
np= pandas.read_csv("national park.txt")
vol=pandas.read_excel("volcanoes.xlsx",sheetname=0)
lat=list(np["Lat"])
lon=list(np["Lon"])
msg=list(np["Name"])
fg=folium.FeatureGroup(name="National Parks")
fgv=folium.FeatureGroup(name="Volcanoes")
pop=folium.FeatureGroup(name="Population")
for lt,ln,mg in zip(lat,lon,msg):
    fg.add_child(folium.CircleMarker(location=[lt,ln],popup=mg,radius="5",fill_color='green'))
lat=list(vol["LAT"])
lon=list(vol["LON"])
msg=list(vol["NAME"])
for lt,ln,mg in zip(lat,lon,msg):
    fgv.add_child(folium.CircleMarker(location=[lt,ln],popup=mg,radius="5",fill_color='red'))
pop.add_child(folium.GeoJson(data=open("world.json","r",encoding="utf-8-sig"),
style_function=lambda x:{"fillColor":"blue" if x['properties']['POP2005']<=1000000
else 'yellow' if x['properties']['POP2005']<=10000000
else 'green' if x['properties']['POP2005']<=100000000
else 'orange' if x['properties']['POP2005']<80000000
else 'red'}))
m.add_child(pop)
m.add_child(fg)
m.add_child(fgv)
m.add_child(folium.LayerControl())
m.save("final.html")


import optparse
import sys
import textwrap

from kedja.utils import get_role
from pyramid.paster import bootstrap
from pyramid.security import ALL_PERMISSIONS

from kedja.interfaces import INamedACL

def print_acl():
    description = """\
    Print the specified acl or list available.
    """
    usage = "usage: %prog config_uri"
    parser = optparse.OptionParser(
        usage=usage,
        description=textwrap.dedent(description)
        )

    options, args = parser.parse_args(sys.argv[1:])
    if not len(args) >= 1:
        print('You must provide at least one argument')
        return 2
    config_uri = args[0]
    with bootstrap(config_uri) as env:
        registry = env['registry']
        for acl in registry.getAllUtilitiesRegisteredFor(INamedACL):
            print("="*80)
            print('%-20s     %-20s' % ("id/name:", acl.name))
            print('%-20s     %-20s' % ("title:", acl.title))
            print("description:\n%s" % acl.description)
            print("-"*80)
            for ace in acl:
                role = get_role(ace[1])
                role_title = "%s (%s)" % (role.title, role)
                permissions = ace[2]
                if permissions == ALL_PERMISSIONS:
                    permissions = "ALL PERMISSIONS"
                print('%-10s    %-20s   %-20s' % (ace[0], role_title, permissions))


import boto3
import json
import sys
import requests
dynamo = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamo.Table('Test-TokenTable')
file = '/home/ec2-user/Projects/src/processBlocks/transferCounter.txt'
def processJson(results):
    with table.batch_writer(overwrite_by_pkeys=['Address', 'Script_TxID']) as batch:
        for jsn in results:
            if 'amount' not in jsn:
                continue
            val = str(jsn['amount'])
            fromAddr = "empty"
            if 'addr_from' in jsn:
                fromAddr=jsn['addr_from']
            toAddr = jsn['addr_to']
            scriptHash = jsn['contract']

            txid = jsn['tx']
#            print(txid)
            blockindex = jsn['block']
            if fromAddr == "AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM" or (fromAddr == "" and 'addr_from' in jsn):
                batch.put_item(
                    Item={
                        'Address': toAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': val,
                        'BlockNumber': blockindex,
                        'Type': "deploy",
                    }

                )
            elif jsn['notify_type'] == "refund":
                batch.put_item(
                    Item={
                        'Address': toAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': val,
                        'BlockNumber': blockindex,
                        'Type': "mint",
                    }
                )

            elif jsn['notify_type'] == "transfer":
                batch.put_item(
                    Item={
                        'Address': toAddr,
                        'From': fromAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': val,
                        'BlockNumber': blockindex,
                        'Type': "received",
                    }
                )
                batch.put_item(
                    Item={
                        'Address': fromAddr,
                        'To': toAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': '-'+val,
                        'BlockNumber': blockindex,
                        'Type': "sent",
                    }
                )

            elif jsn['notify_type'] == "approve":
                batch.put_item(
                    Item={
                        'Address': toAddr,
                        'From': fromAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': val,
                        'BlockNumber': blockindex,
                        'Type': "approve",
                    }
                )
                batch.put_item(
                    Item={
                        'Address': fromAddr,
                        'To': toAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': '-'+val,
                        'BlockNumber': blockindex,
                        'Type': "approve",
                    }
                )

            elif jsn['notify_type'] == "mint":
                batch.put_item(
                    Item={
                        'Address': toAddr,
                        'From': fromAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': val,
                        'BlockNumber': blockindex,
                        'Type': "mint",
                    }
                )
                batch.put_item(
                    Item={
                        'Address': fromAddr,
                        'From': toAddr,
                        'Script_TxID':scriptHash+"_"+txid,
                        'Value': '-'+val,
                        'BlockNumber': blockindex,
                        'Type': "mint",
                    }
                )
def getResp(blockNumber, pageNumber):
    url = 'http://testnotifications.neeeo.org/v1/notifications/block/'+ str(blockNumber) #+text
    params = dict(
        page=pageNumber,
    )
    resp = requests.get(url=url, params=params)
    # print("Response", resp.json())
    data = resp.json()
    #Check the next page to see if there are results
    params = dict(
        page=pageNumber+1,
    )

    resp = requests.get(url=url, params=params)

    moreRes = resp.json()['results']

    if len(moreRes) > 1:
        return (True,data)
    else:
        return (False, data)

if __name__ == "__main__":
    f = open(file, 'r+')
    text = f.read()
    num = int(text)
    results = []
    pageNumber = 1

    for i in range(num,num+200): #[a,b)
        pageNumber = 1
        moreResults = True
        while moreResults:
            moreResults, result = getResp(i,pageNumber)
            pageNumber=pageNumber+1
            results.append(result)
       # print(i)
        hasResults = False
        for element in results:
            hasResults = True
                # print(element['results'])
            processJson(element['results'])
        newNum = i
        if i > results[0]['current_height']:
            newNum = results[0]['current_height']
        f = open(file, 'w')
        f.write(str(newNum))


from environments.quicksort_list_env import ListEnvEncoder, QuickSortListEnv
from core.curriculum import CurriculumScheduler
from core.policy import Policy
import core.config as conf
from core.trainer import Trainer
from core.prioritized_replay_buffer import PrioritizedReplayBuffer
import argparse
import numpy as np
import torch
from tensorboardX import SummaryWriter
import time

if __name__ == "__main__":

    # Get command line params
    parser = argparse.ArgumentParser()
    parser.add_argument("--seed", help='random seed', default=1, type=int)
    parser.add_argument('--tensorboard', help='display on tensorboard', action='store_true')
    parser.add_argument('--verbose', help='print training monitoring in console', action='store_true')
    parser.add_argument('--save-model', help='save neural network model', action='store_true')
    parser.add_argument('--save-results', help='save training progress in .txt file', action='store_true')
    parser.add_argument('--num-cpus', help='number of cpus to use', default=8, type=int)
    parser.add_argument('--load-model', help='Load a pretrained model and train from there', default="", type=str)
    parser.add_argument('--min-length', help='Minimum size of the list we want to order', default=2, type=int)
    parser.add_argument('--max-length', help='Max size of the list we want to order', default=7, type=int)
    parser.add_argument('--validation-length', help='Size of the validation lists we want to order', default=7, type=int)
    parser.add_argument('--start-level', help='Specify up to which level we are trying to learn', default=1, type=int)
    parser.add_argument('--tb-base-dir', help='Specify base tensorboard dir', default="runs", type=str)
    parser.add_argument('--structural-constraint', help="Use the structural constraint to train", action='store_true')
    parser.add_argument('--gamma', help="Specify gamma discount factor", default=0.97, type=float)
    parser.add_argument('--penalize-level-0', help="Penalize level 0 operations when computing the Q-value", default=True, action='store_false')
    parser.add_argument('--level-0-penalty', help="Custom penalty value for the level 0 actions", default=1.0, type=float)
    parser.add_argument('--expose-stack', help="When observing the environment, simply expose the firs two element of the stack", default=False, action='store_true')
    parser.add_argument('--sample-error-prob', help="Probability of sampling error envs when doing training", default=0.3, type=float)
    parser.add_argument('--without-partition-update', help="Train everything without the partition update program", default=False, action="store_true")
    parser.add_argument('--reduced-operation-set', help="Train everything with a reduced set of operations", default=False, action="store_true")
    parser.add_argument('--keep-training', help="Keep training even if we reach 'perfection' on all the task", default=False, action="store_true")
    parser.add_argument('--recursive-quicksort', help="The QUICKSORT function is made recursive.", default=False, action="store_true")
    parser.add_argument('--max-rec-depth', help="Maximum recursion depth", default=100, type=int)
    parser.add_argument('--max-quicksort-depth', help="Maximum recursion depth", default=15, type=int)
    parser.add_argument('--do-not-expose-pointers-values', help="Do not expose pointers values in the observations", action="store_false", default=True)
    args = parser.parse_args()

    # Get arguments
    seed = args.seed
    tensorboard = args.tensorboard
    base_tb_dir = args.tb_base_dir
    verbose = args.verbose
    save_model = args.save_model
    save_results = args.save_results
    num_cpus = args.num_cpus
    sample_error_prob = args.sample_error_prob
    conf.gamma = args.gamma
    conf.penalize_level_0 = args.penalize_level_0
    conf.level_0_penalty = args.level_0_penalty
    expose_pointers_values = args.do_not_expose_pointers_values

    # Verbose output
    if verbose:
        print(args)

    load_model = False
    if args.load_model != "":
        load_model = True

    custom_start_level = False
    if args.start_level != 0:
        custom_start_level = True

    # Set if we are using the structural constraint
    if args.structural_constraint:
        conf.structural_constraint = True

    # Set number of cpus used
    torch.set_num_threads(num_cpus)

    # get date and time
    ts = time.localtime(time.time())
    date_time = '{}_{}_{}-{}_{}_{}'.format(ts[0], ts[1], ts[2], ts[3], ts[4], ts[5])
    # Path to save policy
    model_save_path = '../models/list_npi_{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}.pth'.format(date_time, seed, args.structural_constraint,
                                                               args.penalize_level_0, args.level_0_penalty, args.expose_stack,
                                                                           sample_error_prob, args.without_partition_update,
                                                                                args.reduced_operation_set,
                                                                                args.keep_training,
                                                                                args.recursive_quicksort,
                                                                                expose_pointers_values)
    # Path to save results
    results_save_path = '../results/list_npi_{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}.txt'.format(date_time, seed, args.structural_constraint,
                                                               args.penalize_level_0, args.level_0_penalty, args.expose_stack,
                                                                              sample_error_prob, args.without_partition_update,
                                                                                args.reduced_operation_set,
                                                                                args.keep_training,
                                                                                args.recursive_quicksort,
                                                                                expose_pointers_values)
    # Path to tensorboard
    tensorboard_path = '{}/list_npi_{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}'.format(base_tb_dir, date_time, seed, args.structural_constraint,
                                                               args.penalize_level_0, args.level_0_penalty, args.expose_stack,
                                                                 sample_error_prob, args.without_partition_update,
                                                                          args.reduced_operation_set,
                                                                          args.keep_training,
                                                                          args.recursive_quicksort,
                                                                          expose_pointers_values)

    # Instantiate tensorboard writer
    if tensorboard:
        writer = SummaryWriter(tensorboard_path)

    # Instantiate file writer
    if save_results:
        results_file = open(results_save_path, 'w')

    # Set random seed
    np.random.seed(seed)
    torch.manual_seed(seed)

    # Load environment constants
    env_tmp = QuickSortListEnv(length=5, encoding_dim=conf.encoding_dim, expose_stack=args.expose_stack,
                               sample_from_errors_prob=sample_error_prob,
                               without_partition_update=args.without_partition_update,
                               reduced_set=args.reduced_operation_set,
                               recursive_version=args.recursive_quicksort,
                               expose_pointers_value=expose_pointers_values)
    num_programs = env_tmp.get_num_programs()
    num_non_primary_programs = env_tmp.get_num_non_primary_programs()
    observation_dim = env_tmp.get_observation_dim()
    programs_library = env_tmp.programs_library

    # Load alphanpi policy
    encoder = ListEnvEncoder(env_tmp.get_observation_dim(), conf.encoding_dim)
    indices_non_primary_programs = [p['index'] for _, p in programs_library.items() if p['level'] > 0]
    policy = Policy(encoder, conf.hidden_size, num_programs, num_non_primary_programs, conf.program_embedding_dim,
                    conf.encoding_dim, indices_non_primary_programs, conf.learning_rate)

    # Load a pre-trained policy (to speed up testing)
    if load_model:
        policy.load_state_dict(torch.load(args.load_model))

    # Load replay buffer
    idx_tasks = [prog['index'] for key, prog in env_tmp.programs_library.items() if prog['level'] > 0]
    buffer = PrioritizedReplayBuffer(conf.buffer_max_length, idx_tasks, p1=conf.proba_replay_buffer)

    # Load curriculum sequencer
    curriculum_scheduler = CurriculumScheduler(conf.reward_threshold, num_non_primary_programs, programs_library,
                                               moving_average=0.99)
    curriculum_scheduler.maximum_level = args.start_level

    # Prepare mcts params
    length = 5

    if args.without_partition_update:
        max_depth_dict = {1: 3 * (length - 1) + 2, 2: 4, 3: 4, 4: length + 2}
    elif args.reduced_operation_set:
        max_depth_dict = {1: 3 * (length - 1) + 2, 2: 6, 3: length + 2}
    elif args.recursive_quicksort:
        max_depth_dict = {1: 3 * (length - 1) + 2, 2: 7, 3: 3}
    else:
        max_depth_dict = {1: 3, 2: 2 * (length - 1) + 2, 3: 4, 4: 4, 5: length + 2}

    mcts_train_params = {'number_of_simulations': conf.number_of_simulations, 'max_depth_dict': max_depth_dict,
                         'temperature': conf.temperature, 'c_puct': conf.c_puct, 'exploit': False,
                         'level_closeness_coeff': conf.level_closeness_coeff, 'gamma': conf.gamma,
                         'use_dirichlet_noise': True, 'use_structural_constraint': conf.structural_constraint,
                         'penalize_level_0': conf.penalize_level_0, 'level_0_penalty': conf.level_0_custom_penalty,
                         'max_recursion_depth': args.max_rec_depth, 'max_recursion_program_call': args.max_quicksort_depth}

    mcts_test_params = {'number_of_simulations': conf.number_of_simulations_for_validation,
                        'max_depth_dict': max_depth_dict, 'temperature': conf.temperature,
                        'c_puct': conf.c_puct, 'exploit': True, 'level_closeness_coeff': conf.level_closeness_coeff,
                        'gamma': conf.gamma, 'use_structural_constraint': conf.structural_constraint,
                        'penalize_level_0': conf.penalize_level_0, 'level_0_penalty': conf.level_0_custom_penalty,
                        'max_recursion_depth': args.max_rec_depth, 'max_recursion_program_call': args.max_quicksort_depth}

    # Specify a custom start level
    if custom_start_level:
        curriculum_scheduler.maximum_level = args.start_level

    # Instanciate trainer
    trainer = Trainer(env_tmp, policy, buffer, curriculum_scheduler, mcts_train_params,
                      mcts_test_params, conf.num_validation_episodes, conf.num_episodes_per_task, conf.batch_size,
                      conf.num_updates_per_episode, verbose)

    min_length = args.min_length
    max_length = args.max_length
    validation_length = args.validation_length
    failed_executions_envs = None

    # Start training
    for iteration in range(conf.num_iterations):
        # play one iteration
        task_index = curriculum_scheduler.get_next_task_index()
        task_level = env_tmp.get_program_level_from_index(task_index)
        length = np.random.randint(min_length, max_length+1)
        env = QuickSortListEnv(length=length, encoding_dim=conf.encoding_dim, expose_stack=args.expose_stack,
                               sample_from_errors_prob=sample_error_prob,
                               without_partition_update=args.without_partition_update,
                               reduced_set=args.reduced_operation_set,
                               recursive_version=args.recursive_quicksort,
                               expose_pointers_value=expose_pointers_values)

        if args.without_partition_update:
            max_depth_dict = {1: 3 * (length - 1) + 2, 2: 4, 3: 4, 4: length + 2}
        elif args.reduced_operation_set:
            max_depth_dict = {1: 3 * (length - 1) + 2, 2: 6, 3: length + 2}
        elif args.recursive_quicksort:
            max_depth_dict = {1: 3 * (length - 1) + 2, 2: 7, 3: 3}
        else:
            max_depth_dict = {1: 3, 2: 2 * (length - 1) + 2, 3: 4, 4: 4, 5: length + 2}

        # Restore the previous failed executions
        if failed_executions_envs != None:
            env.failed_executions_env = failed_executions_envs

        trainer.env = env
        trainer.mcts_train_params['max_depth_dict'] = max_depth_dict
        trainer.mcts_test_params['max_depth_dict'] = max_depth_dict
        trainer.play_iteration(task_index)

        # Save the failed execution env
        failed_executions_envs = env.failed_executions_env

        # perform validation
        if verbose:
            print("Start validation .....")
        for idx in curriculum_scheduler.get_tasks_of_maximum_level():
            task_level = env_tmp.get_program_level_from_index(idx)
            length = validation_length
            env = QuickSortListEnv(length=length, encoding_dim=conf.encoding_dim, expose_stack=args.expose_stack,
                                   validation_mode=True,
                                   without_partition_update=args.without_partition_update,
                                   reduced_set=args.reduced_operation_set,
                                   recursive_version=args.recursive_quicksort,
                                   expose_pointers_value=expose_pointers_values)

            if args.without_partition_update:
                max_depth_dict = {1: 3 * (length - 1) + 2, 2: 4, 3: 4, 4: length + 2}
            elif args.reduced_operation_set:
                max_depth_dict = {1: 3 * (length - 1) + 2, 2: 6, 3: length + 2}
            elif args.recursive_quicksort:
                max_depth_dict = {1: 3 * (length - 1) + 2, 2: 7, 3: 3}
            else:
                max_depth_dict = {1: 3, 2: 2 * (length - 1) + 2, 3: 4, 4: 4, 5: length + 2}

            trainer.env = env
            trainer.mcts_train_params['max_depth_dict'] = max_depth_dict
            trainer.mcts_test_params['max_depth_dict'] = max_depth_dict
            # Evaluate performance on task idx
            v_rewards, v_lengths, programs_failed_indices = trainer.perform_validation_step(idx)
            # Update curriculum statistics
            curriculum_scheduler.update_statistics(idx, v_rewards)

        # display training progress in tensorboard
        if tensorboard:
            for idx in curriculum_scheduler.get_tasks_of_maximum_level():
                v_task_name = env.get_program_from_index(idx)
                # record on tensorboard
                writer.add_scalar('validation/' + v_task_name, curriculum_scheduler.get_statistic(idx), iteration)

        # write training progress in txt file
        if save_results:
            str = 'Iteration: {}'.format(iteration)
            for idx in curriculum_scheduler.indices_non_primary_programs:
                task_name = env.get_program_from_index(idx)
                str += ', %s:%.3f' % (task_name, curriculum_scheduler.get_statistic(idx))
            str += '\n'
            results_file.write(str)

        # print new training statistics
        if verbose:
            curriculum_scheduler.print_statistics()
            print('')
            print('')

        # If succeed on al tasks, go directly to next list length
        if curriculum_scheduler.maximum_level > env.get_maximum_level():
            if not args.keep_training:
                break
            else:
                # keep on training
                curriculum_scheduler.maximum_level = env.get_maximum_level()

        # Save policy
        if save_model:
            torch.save(policy.state_dict(), model_save_path)

    # Close tensorboard writer
    if verbose:
        print('End of training !')
    if tensorboard:
        writer.close()
    if save_results:
        results_file.close()


#!/usr/bin/env python
from selenium import webdriver
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import title_is, staleness_of
import os
import logging
from telegram import Update
from telegram.constants import MESSAGEENTITY_URL, CHATACTION_UPLOAD_VIDEO
from telegram.ext import Updater, MessageHandler, Filters, CallbackContext

logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)

cwd = os.getcwd()

def download_tiktok_video(url: str) -> str:
    '''
    Download a TikTok video

    Parameters:
            url (str): any url that leads to a tik tok

    Returns:
            path (str): Absolute path to the downloaded file
    '''
    options = Options()
    options.add_argument('--headless')
    options.page_load_strategy = 'eager'

    profile = FirefoxProfile()
    profile.set_preference('browser.download.folderList', 2)
    profile.set_preference('browser.download.dir', cwd)
    profile.set_preference('browser.helperApps.neverAsk.saveToDisk',
                           'video/mp4, application/octet-stream, mp4')
    profile.set_preference('browser.download.manager.showWhenStarting', False)
    profile.set_preference('browser.download.useDownloadDir', True)
    profile.set_preference(
        'browser.download.viewableInternally.enabledTypes', '')
    profile.set_preference('media.play-stand-alone', False)
    profile.set_preference('webdriver.load.strategy', 'fast')
    profile.set_preference('browser.tabs.remote.autostart.2', False)

    driver = webdriver.Firefox(profile, options=options)

    driver.get(url)
    elem = driver.find_element(By.TAG_NAME, 'video')
    src = elem.get_attribute('src')
    script = f'''
        var link = document.createElement('a');
        link.setAttribute('download', 'download');
        link.setAttribute('href', '{src}');
        link.click();
        document.title = "dl start";
        '''
    driver.execute_script(script)
    WebDriverWait(driver, 60).until(title_is('dl start'))
    while(os.path.getsize('mp4') == 0):
        pass
    new_name = 'v.mp4'
    os.rename('mp4', new_name)
    driver.quit()
    return os.path.abspath(new_name)

def reply_video(update: Update, context: CallbackContext) -> None:
    try:
        for ent in update.message.entities:
            if ent.type == 'url':
                url = update.message.parse_entity(ent)
                update.message.chat.send_action(CHATACTION_UPLOAD_VIDEO)
                file = download_tiktok_video(url)
                update.message.chat.send_video(video=open(file, 'rb'))
    except Exception as exception:
        update.message.chat.send_message(text=str(exception))

def main():
    token = os.getenv('TELEGRAM_TOKEN')
    updater = Updater(token)
    dispatcher = updater.dispatcher

    dispatcher.add_handler(MessageHandler(Filters.text & Filters.entity(
        MESSAGEENTITY_URL) & Filters.regex(r'tiktok\.com\/[-A-Za-z0-9+/=]+'), reply_video))

    updater.start_polling()
    updater.idle()

if __name__ == '__main__':
    main()


import bpy
from . import preferences
from .onion import update_onion, force_update_onion, update_opacity, update_peel_color

from bpy.props import BoolProperty, EnumProperty, \
    IntProperty, FloatVectorProperty, CollectionProperty, \
    PointerProperty, StringProperty, FloatProperty

class GPOP_PGT_frame_settings(bpy.types.PropertyGroup):
    opacity : IntProperty(default=100, min=1, max=100, subtype='PERCENTAGE', options={'HIDDEN'}, update=update_opacity)
    visibility : BoolProperty(default=True, options={'HIDDEN'}, update=update_opacity)
class GPOP_PGT_settings(bpy.types.PropertyGroup):

    activated : BoolProperty(name='Activate', default=False,
        description='Activate the onion skinning with auto-refresh on frame change',
        update=force_update_onion
        )

    ## Wip target choice
    # only_active : BoolProperty(name='Only Active', default=True,
    # description='Refresh only active object peels, and hide other, else refresh all (can slow down)')

    world_space : BoolProperty(name='World Space', default=False,
        description='Consider the object animation to place onion peels in world space (Else local space)\nIf your GP object does not move, disable for better performance')

    offset_mode : EnumProperty(
        name="Mode", description="Ghost offset mode", default='KEYS', options={'HIDDEN'}, update=None, get=None, set=None,
        items=(
            ('KEYS', 'Keys', 'Ghost number are keys', 0),
            ('FRAMES', 'Frames', 'Ghost number are frames', 1),
            ))

    # xray : BoolProperty(name='X-ray', default=False,
    #     description='Set "In Front" mode for both object and the onion peels',
    #     update=update_peel_xray)

    keyframe_type : EnumProperty(
        name="Keyframe Filter", description="Only peel the onion for keyframe of chosen type",
        default='ALL', options={'HIDDEN'}, update=force_update_onion,
        items=(
            ('ALL', 'All', '', 0), # 'KEYFRAME'
            ('KEYFRAME', 'Keyframe', '', 'KEYTYPE_KEYFRAME_VEC', 1),
            ('BREAKDOWN', 'Breakdown', '', 'KEYTYPE_BREAKDOWN_VEC', 2),
            ('MOVING_HOLD', 'Moving Hold', '', 'KEYTYPE_MOVING_HOLD_VEC', 3),
            ('EXTREME', 'Extreme', '', 'KEYTYPE_EXTREME_VEC', 4),
            ('JITTER', 'Jitter', '', 'KEYTYPE_JITTER_VEC', 5),
            ))

    before_color : FloatVectorProperty(
        name="Before Color",
        subtype='COLOR',
        default=(0.019, 0.15, 0.017), # (0.157, 0.496, 0.151)
        min=0.0, max=1.0,
        description="Color for previous onion peels",
        update=update_peel_color
        )

    after_color : FloatVectorProperty(
        name="After Color",
        subtype='COLOR',
        default=(0.014, 0.01, 0.25), #  (0.579, 0.158, 0.604)
        min=0.0, max=1.0,
        description="Color for next onion peels",
        update=update_peel_color
        )

    before_num : IntProperty(
        name="Before", description="Number of previous ghost displayed",
        default=2, min=1, max=32, soft_min=1, soft_max=16, step=1, options={'HIDDEN'}, update=force_update_onion)

    after_num : IntProperty(
        name="After", description="Number of next ghost displayed",
        default=2, min=1, max=32, soft_min=1, soft_max=16, step=1, options={'HIDDEN'}, update=force_update_onion)

    pos_frames : CollectionProperty(type=GPOP_PGT_frame_settings)
    neg_frames : CollectionProperty(type=GPOP_PGT_frame_settings)

    o_general: IntProperty(default=50, min=1, max=100, subtype='PERCENTAGE', options={'HIDDEN'}, update=update_opacity)

    frame_prev : IntProperty(
        name="frame prev", description="previous frame holder",
        default= -9999)

### --- REGISTER ---

classes=(
GPOP_PGT_frame_settings,
GPOP_PGT_settings,
)

def register():
    for cls in classes:
        bpy.utils.register_class(cls)

    bpy.types.Scene.gp_ons_setting = PointerProperty(type = GPOP_PGT_settings)

def unregister():
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)
    del bpy.types.Scene.gp_ons_setting


from pyparsing import (
    Word,
    nums,
    alphas,
    Combine,
    one_of,
    OpAssoc,
    infix_notation,
    Literal,
    ParserElement,
)

ParserElement.enablePackrat()

class EvalConstant:
    "Class to evaluate a parsed constant or variable"
    vars_ = {}

    def __init__(self, tokens):
        self.value = tokens[0]

    def eval(self):
        if self.value in EvalConstant.vars_:
            return EvalConstant.vars_[self.value]
        else:
            return float(self.value)

class EvalSignOp:
    "Class to evaluate expressions with a leading + or - sign"

    def __init__(self, tokens):
        self.sign, self.value = tokens[0]

    def eval(self):
        mult = {"+": 1, "-": -1}[self.sign]
        return mult * self.value.eval()

def operatorOperands(tokenlist):
    "generator to extract operators and operands in pairs"
    it = iter(tokenlist)
    while 1:
        try:
            yield (next(it), next(it))
        except StopIteration:
            break

class EvalPowerOp:
    "Class to evaluate multiplication and division expressions"

    def __init__(self, tokens):
        self.value = tokens[0]

    def eval(self):
        res = self.value[-1].eval()
        for val in self.value[-3::-2]:
            res = val.eval() ** res
        return res

class EvalMultOp:
    "Class to evaluate multiplication and division expressions"

    def __init__(self, tokens):
        self.value = tokens[0]

    def eval(self):
        prod = self.value[0].eval()
        for op, val in operatorOperands(self.value[1:]):
            if op == "*":
                prod *= val.eval()
            if op == "/":
                prod /= val.eval()
        return prod

class EvalAddOp:
    "Class to evaluate addition and subtraction expressions"

    def __init__(self, tokens):
        self.value = tokens[0]

    def eval(self):
        sum = self.value[0].eval()
        for op, val in operatorOperands(self.value[1:]):
            if op == "+":
                sum += val.eval()
            if op == "-":
                sum -= val.eval()
        return sum

class EvalComparisonOp:
    "Class to evaluate comparison expressions"
    opMap = {
        "<": lambda a, b: a < b,
        "<=": lambda a, b: a <= b,
        ">": lambda a, b: a > b,
        ">=": lambda a, b: a >= b,
        "!=": lambda a, b: a != b,
        "=": lambda a, b: a == b,
        "LT": lambda a, b: a < b,
        "LE": lambda a, b: a <= b,
        "GT": lambda a, b: a > b,
        "GE": lambda a, b: a >= b,
        "NE": lambda a, b: a != b,
        "EQ": lambda a, b: a == b,
        "<>": lambda a, b: a != b,
    }

    def __init__(self, tokens):
        self.value = tokens[0]

    def eval(self):
        val1 = self.value[0].eval()
        for op, val in operatorOperands(self.value[1:]):
            fn = EvalComparisonOp.opMap[op]
            val2 = val.eval()
            if not fn(val1, val2):
                break
            val1 = val2
        else:
            return True
        return False

# define the parser
integer = Word(nums)
real = Combine(Word(nums) + "." + Word(nums))
variable = Word(alphas, exact=1)
operand = real | integer | variable

signop = one_of("+ -")
multop = one_of("* /")
plusop = one_of("+ -")
expop = Literal("**")

# use parse actions to attach EvalXXX constructors to sub-expressions
operand.setParseAction(EvalConstant)
arith_expr = infix_notation(
    operand,
    [
        (signop, 1, OpAssoc.RIGHT, EvalSignOp),
        (expop, 2, OpAssoc.LEFT, EvalPowerOp),
        (multop, 2, OpAssoc.LEFT, EvalMultOp),
        (plusop, 2, OpAssoc.LEFT, EvalAddOp),
    ],
)

comparisonop = one_of("< <= > >= != = <> LT GT LE GE EQ NE")
comp_expr = infix_notation(
    arith_expr,
    [
        (comparisonop, 2, OpAssoc.LEFT, EvalComparisonOp),
    ],
)

# sample expressions posted on comp.lang.python, asking for advice
# in safely evaluating them
rules = [
    "( A - B ) = 0",
    "( B - C + B ) = 0",
    "(A + B + C + D + E + F + G + H + I) = J",
    "(A + B + C + D + E + F + G + H) = I",
    "(A + B + C + D + E + F) = G",
    "(A + B + C + D + E) = (F + G + H + I + J)",
    "(A + B + C + D + E) = (F + G + H + I)",
    "(A + B + C + D + E) = F",
    "(A + B + C + D) = (E + F + G + H)",
    "(A + B + C) = D",
    "(A + B + C) = (D + E + F)",
    "(A + B) = (C + D + E + F)",
    "(A + B) = (C + D)",
    "(A + B) = (C - D + E - F - G + H + I + J)",
    "(A + B) = C",
    "(A + B) = 0",
    "(A+B+C+D+E) = (F+G+H+I+J)",
    "(A+B+C+D) = (E+F+G+H)",
    "(A+B+C+D)=(E+F+G+H)",
    "(A+B+C)=(D+E+F)",
    "(A+B)=(C+D)",
    "(A+B)=C",
    "(A-B)=C",
    "(A/(B+C))",
    "(B/(C+D))",
    "(G + H) = I",
    "-0.99 LE ((A+B+C)-(D+E+F+G)) LE 0.99",
    "-0.99 LE (A-(B+C)) LE 0.99",
    "-1000.00 LE A LE 0.00",
    "-5000.00 LE A LE 0.00",
    "A < B",
    "A < 7000",
    "A = -(B)",
    "A = C",
    "A = 0",
    "A GT 0",
    "A GT 0.00",
    "A GT 7.00",
    "A LE B",
    "A LT -1000.00",
    "A LT -5000",
    "A LT 0",
    "G=(B+C+D)",
    "A=B",
    "I = (G + H)",
    "0.00 LE A LE 4.00",
    "4.00 LT A LE 7.00",
    "0.00 LE A LE 4.00 LE E > D",
    "2**2**(A+3)",
]
vars_ = {
    "A": 0,
    "B": 1.1,
    "C": 2.2,
    "D": 3.3,
    "E": 4.4,
    "F": 5.5,
    "G": 6.6,
    "H": 7.7,
    "I": 8.8,
    "J": 9.9,
}

# define tests from given rules
tests = []
for t in rules:
    t_orig = t
    t = t.replace("=", "==")
    t = t.replace("EQ", "==")
    t = t.replace("LE", "<=")
    t = t.replace("GT", ">")
    t = t.replace("LT", "<")
    t = t.replace("GE", ">=")
    t = t.replace("LE", "<=")
    t = t.replace("NE", "!=")
    t = t.replace("<>", "!=")
    tests.append((t_orig, eval(t, vars_)))

# copy vars_ to EvalConstant lookup dict
EvalConstant.vars_ = vars_
failed = 0
for test, expected in tests:
    ret = comp_expr.parseString(test)[0]
    parsedvalue = ret.eval()
    print(test, expected, parsedvalue)
    if abs(parsedvalue - expected) > 1e-6:
        print("<<< FAIL")
        failed += 1
    else:
        print("")

print("")
if failed:
    raise Exception("could not parse")


from keras.utils import plot_model
from keras.models import Sequential, Model, model_from_json

def load_model(path_model, path_weights):
    # load json and create model
    json_file = open(path_model, 'r')
    loaded_model_json = json_file.read()
    json_file.close()
    loaded_model = model_from_json(loaded_model_json)
    # load weights into new model
    loaded_model.load_weights(path_weights)
    print("Loaded model from disk")
    return loaded_model

if __name__ == "__main__":
    model = load_model("/var/lib/arhuaco/data/models/model.json",
                       "/var/lib/arhuaco/data/models/weights_file_network")
    plot_model(model, to_file='/var/lib/arhuaco/data/models/model_network.png')


import shelve
from SQLighter import SQLighter
from config import shelve_name, database_name
from random import shuffle
from telebot import types

def count_rows():
    # метод считает общее число строк в БД и сохраняет в хранилище.
    # Далее из него выбирается музыка
    db = SQLighter(database_name)
    rowsnum = db.count_rows()
    with shelve.open(shelve_name) as storage:
        storage['rows_counts'] = rowsnum

def get_rows_count():
    # Получаем из хранилища число строк в БД (:return: (int))
    with shelve.open(shelve_name) as storage:
        rowsnum = storage['rows_count']
    return rowsnum

def set_user_game(chat_id, estimated_answers):
    # записываем пользователя в игроки и запоминаем ответ
    with shelve.open(shelve_name) as storage:
        storage[str(chat_id)] = estimated_answers

def finish_user_game(chat_id):
    # заканчиваем игру
    with shelve.open(shelve_name) as storage:
        del storage[str(chat_id)]

def get_answer_for_user(chat_id):
    # получаем правильный ответ от пользователя
    with shelve.open(shelve_name) as storage:
        try:
            answer = storage[str(chat_id)]
            return answer

        except KeyError:
            return None

def generate_markup(right_answer, wrong_answers):
    markup = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
    all_answers = '{},{}'.format(right_answer, wrong_answers)
    list_items = []
    for item in all_answers.split(','):
        list_items.append(item)
    shuffle(list_items)
    for item in list_items:
        markup.add(item)
    return markup