##############################################################
# Groupe BI TD2                                              #
# Guillaume EMERDJIAN                                        #
# Victor DE BAETS                                            #
# Léa OSTER                                                  #
# Maxime BOUAMRA                                             #
# https://github.com/uvsq22107719/projet-2-proies-predateurs #
##############################################################

### Import des librairies

import tkinter as tk
import random as rd

### Définitions des constantes

N = 30 # Taille de la matrice
HAUTEUR = 700 # Hauteur du canevas
LARGEUR = 600 # Largeur du canevas
LARGEUR_CASE = 20 # Largeur des cases
HAUTEUR_CASE = LARGEUR_CASE # Hauteur des cases

CHRONO = 500 # Temps en millisecondes entre chaque tour

MIAM = 5 # Niveau d'énergie gagné lorsqu'un prédateur mange une proie
FLAIR_PRE = 5 # Nombre maximal de cases pour qu'un prédateur puisse sentir une proie et la pourchasser
FLAIR_PRO = 2 # Nombre maximal de cases pour qu'une proie puisse sentir un prédateur et fuir

### Définitions des variables globales

tour = 0 # Numéro du tour
arret = True # Variable pour arrêter le passage des tours
var_chrono = 0 # Variable pour le compte à rebours entre chaque tour

Npro = 50 # Nombre initial de proies (Npro proies apparaissent au début)
Apro = 10 # Espérance de vie des proies en nombre de tours
Epro = 2 # Énergie des proies (augmente de 1 par tour avec Epro en plafond. Une énergie maximale (égale à Epro) est nécessaire pour qu'une proie puisse se reproduire. Epro revient à 0 à chaque reproduction.)

Npre = 3 # Nombre initial de prédateurs (Npre prédateurs apparaissent au début)
Apre = 15 # Espérance de vie des prédateurs en nombre de tours
Epre = 10 # Énergie des prédateurs (baisse de 1 par tour, s'il elle atteint zéro, le prédateur meurt de faim)
Erepro = 15 # Niveau d'énergie nécessaire pour qu'un prédateur puisse se reproduire

sauv_validee = False # Variable pour afficher si la matrice actuelle est sauvegardée

### Définitions des fonctions

# Création de la grille
def init_grille():
    """Retourne une grille carrée vide de dimension N+2, les éléments de la configuration vont de 1 à N. Les indices 0 et N+1 sont les bords."""
    global grille, config

    grille = [[0 for x in range(N + 2)] for y in range(N + 2)] # Création de la matrice de taille N + 2 pour les bords
    grille[0] = ["#" for x in range(N + 2)] # Ajout de "#" sur le bord gauche (invisible)
    grille[-1] = ["#" for x in range(N + 2)] # Ajout de "#" sur le bord droit (invisible)
    for x in range(1, N + 1): # Ajout de "#" en haut et en bas de chaque colonne
        grille[x][0] = "#"
        grille[x][-1] = "#"
    config = [[0 for x in range(N + 2)] for y in range(N + 2)] # Création de la matrice de taille N + 2 pour les bords
    config[0] = ["#" for x in range(N + 2)] # Ajout de "#" sur le bord gauche (invisible)
    config[-1] = ["#" for x in range(N + 2)] # Ajout de "#" sur le bord droit (invisible)
    for x in range(1, N + 1): # Ajout de "#" en haut et en bas de chaque colonne
        config[x][0] = "#"
        config[x][-1] = "#"

    for x in range(1, N + 1):
        i = (x - 1) * LARGEUR_CASE
        for y in range(1, N + 1):
            j = (y - 1) * HAUTEUR_CASE
            col = "green" # Couleur du fond
            carre = canvas.create_rectangle(i, j, i + LARGEUR_CASE, j + HAUTEUR_CASE, fill = col, outline = "green") # outline = couleur du contour des carrés
            grille[x][y] = carre

# Initialise les proies
def init_proies():
    """Ajoute Npro proies à des coordonnées aléatoires."""
    global config
    cpt = Npro
    while cpt > 0:
        x, y = rd.randint(1, N + 1), rd.randint(1, N + 1) # Génération des coordonnées aléatoires
        if config[x][y] == 0: # Si c'est une case vide
            config[x][y] = ["Proie", Apro, Epro] # Création d'une liste avec toutes les infos sur l'animal (ici c'est une proie avec Apro le nombre de tours d'espérance de vie puis Epro l'énergie de la proie)
            cpt -= 1
    affiche_grille(config)

# Initialise les prédateurs
def init_prédateurs():
    """Ajoute Npre prédateurs à des coordonnées aléatoires."""
    global config
    cpt = Npre
    while cpt > 0:
        x, y = rd.randint(1, N + 1), rd.randint(1, N + 1) # Génération des coordonnées aléatoires
        if config[x][y] == 0: # Si c'est une case vide
            config[x][y] = ["Predateur", Apre, Epre] # Création d'une liste avec toutes les infos sur l'animal (ici c'est un prédateur avec Apre le nombre de tours d'espérance de vie puis Epre l'énergie du prédateur)
            cpt -= 1
    affiche_grille(config)

# Affichage de la grille
def affiche_grille(config):
    """Affiche la configuration donnée."""
    for x in range(1, N + 1): # Pour chaque abscisse
        for y in range(1, N + 1): # Pour chaque ordonnée
            col = choix_couleur(config[x][y]) # Choix de la couleur en fonction de l'élément
            canvas.itemconfigure(grille[x][y], fill = col) # Changement de la couleur de la case en fonction de la couleur retournée

# Choix des couleurs
def choix_couleur(n):
    """Retourne une couleur à partir de l'entier n."""
    if n == 0: # S'il n'y a rien
        return "green" # Couleur du fond
    else:
        if n[0] == "Proie": # Si c'est une proie
            return "yellow" # Couleur des proies
        elif n[0] == "Predateur": # Si c'est un prédateur
            return "red" # Couleur des prédateurs
        else: # Si c'est autre chose
            return "grey"

# Compter le nombre d'animaux
def compter_animaux():
    """Compte le nombre total d'animaux, le nombre de proies et le nombre de prédateurs."""
    global nbre_animaux, nbre_proies, nbre_predateurs
    nbre_animaux = nbre_proies = nbre_predateurs = 0
    for x in range(1, N + 1):
        for y in range(1, N + 1):
            if type(config[x][y]) == list: # Si c'est une liste (donc un animal)
                nbre_animaux += 1 # On ajoute 1 au compteur d'animaux
                if config[x][y][0] == "Proie": # Si c'est une proie
                    nbre_proies += 1 # On ajoute 1 au compteur de proies
                if config[x][y][0] == "Predateur": # Si c'est un prédateur
                    nbre_predateurs += 1 # On ajoute 1 au compteur de prédateurs
    label_animaux.configure(text = ("Nombre d'animaux : " + str(nbre_animaux))) # Actualise le texte du nombre d'animaux
    label_proies.configure(text = ("Nombre de proies : " + str(nbre_proies))) # Actualise le texte du nombre de proies
    label_predateurs.configure(text = ("Nombre de prédateurs : " + str(nbre_predateurs))) # Actualise le texte du nombre de prédateurs

# Commencer/arrêter le passage des tours
def commencer():
    """Démarre ou arrête le passage des tours."""
    global arret
    compter_animaux() # Compter le nombre d'animaux
    if arret == True and nbre_animaux > 0: # Si la simulation est en pause et qu'il y a des animaux
        arret = False
        bouton_start.configure(text = "Arrêter") # Changer le texte du bouton en "Arrêter"
        passage_tours() # Faire passer les tours
    elif not arret: # Si arret == False (simulation en cours)
        arret = True
        bouton_start.configure(text = "Reprendre") # Changer le texte du bouton start en "Reprendre"
        canvas.after_cancel(var_chrono) # Arrêter le passage des tours

# Passage des tours
def passage_tours():
    """Lance la fonction de passage des tours toutes les [CHRONO] millisecondes."""
    global var_chrono
    var_chrono = canvas.after(CHRONO, tour_suivant) # La fonction tour_suivant est lancée toutes les [CHRONO] ms

# Tour suivant
def tour_suivant():
    """Fait passer les tours (modification de l'âge, de l'énergie et déplacement et reproduction)."""
    global tour, sauv_validee, arret

    vie_energie() # Modification de l'espérance de vie et de l'énergie des animaux
    reproduction_proies() # Reproduction des proies
    reproduction_predateurs() # Reproduction des prédateurs
    chasse() # Déplacement et chasse des prédateurs
    deplacement_proies() # Déplacement des proies

    # Boucle pour supprimer les termes "Reproduit" et "Déplacé" à la fin de chaque liste une fois que tous les déplacements/reproductions de ce tour ont été effectués
    for x in range(1, N + 1):
        for y in range(1, N + 1):
            if type(config[x][y]) == list and config[x][y].count("Reproduit") > 0: # Seulement si c'est une liste (donc un animal) et qu'elle contient le terme "Reproduit"
                config[x][y].remove("Reproduit") # Supprimer le terme "Reproduit" de la liste
            if type(config[x][y]) == list and config[x][y].count("Déplacé") > 0: # Seulement si c'est une liste (donc un animal) et qu'elle contient le terme "Déplacé"
                config[x][y].remove("Déplacé") # Supprimer le terme "Déplacé" de la liste

    affiche_grille(config) # Actualise la grille
    tour += 1 # Ajout d'un tour au compteur
    label_tours.configure(text = ("Tour", tour)) # Actualise le texte du numéro de tour
    compter_animaux() # Compter le nombre d'animaux
    if nbre_animaux == 0: # S'il n'y a plus d'animaux
        arret = True # Arrêter la simulation
        bouton_start.configure(text = "Reprendre") # Changer le texte du bouton start en "Reprendre"
    if not arret: # Si la simulation n'est pas arrêtée
        passage_tours() # Continuer à passer les tours
    if sauv_validee: # Si le message de validation de la sauvegarde est affiché
        sauv_validee = False # Le supprimer (car la matrice affichée n'est plus celle qui a été sauvegardée dans le fichier)
        label_sauv_validee.configure(text = "") # Supprimer le texte "Sauvegarde effectuée"

# Modification de l'espérance de vie et de l'énergie des animaux
def vie_energie():
    """Retire 1 tour d'espérance de vie à tous les animaux, retire 1 d'énergie à tous les prédateurs et ajoute 1 d'énergie à toutes les proies."""
    global config
    for x in range(1, N + 1): # Pour chaque abscisse (ex : [0, 0, ["Proie", 5, 3], ["Proie", 2, 3], 0, ["Predateur", 15, 12], 0])
        for y in range(1, N + 1): # Pour chaque ordonnée (ex : ["Proie", 5, 3])
            # Espérance de vie des animaux
            if type(config[x][y]) == list: # Seulement si c'est une liste (donc un animal)
                config[x][y][1] -= 1 # Retirer 1 à l'espérance de vie (ex : ["Proie", 5, 3] devient ["Proie", 4, 3])
                if config[x][y][1] <= 0: # Si c'est par exemple ["Proie", 0, 3]
                    config[x][y] = 0 # Remplacer par 0 (mort de l'animal)

            # Énergie des proies
            if type(config[x][y]) == list and config[x][y][0] == "Proie" and config[x][y][2] < Epro: # Si c'est une proie et que celle-ci a une énergie inférieure à Epro
                config[x][y][2] += 1 # Ajouter 1 d'énergie

            # Énergie des prédateurs
            if type(config[x][y]) == list and config[x][y][0] == "Predateur": # Seulement si c'est un prédateur
                config[x][y][2] -= 1 # Retirer 1 à l'énergie (ex : ["Predateur", 14, 12] devient ["Predateur", 14, 11])
                if config[x][y][2] <= 0: # Si c'est par exemple ["Predateur", 14, 0]
                    config[x][y] = 0 # Remplacer par 0 (mort de l'animal)

# Reproduction des proies
def reproduction_proies():
    """Reproduit toutes les proies qui sont côte à côte si elles ont une énergie égale à Epro."""
    global config
    for x in range(1, N + 1):
        for y in range(1, N + 1):
            if type(config[x][y]) == list and config[x][y][0] == "Proie" and config[x][y][2] >= Epro: # Seulement si c'est une proie et que son niveau d'énergie est maximal (égal à Epro)
                case = direction(x, y, "Proie", "Reproduction") # Obtenir une case aléatoire ou se trouve une proie pour une reproduction
                if case == 0: # Si aucune case disponible
                    break # Annuler la boucle
                else:
                    coordonnees_case(x, y, case) # Récupérer les coordonnées i et j de la case selon son numéro
                    config[x][y][2] = 0 # Réinitialisation de l'énergie
                    config[i][j][2] = 0 # Réinitialisation de l'énergie
                    case = direction(x, y, 0, "Déplacement")
                    if case == 0: # Si aucune case disponible
                        break # Annuler la boucle
                    else: # Si la case 2 est disponible
                        coordonnees_case(x, y, case) # Récupérer les coordonnées i et j de la case selon son numéro
                        config[i][j] = ["Proie", Apro, (Epro - 1)]

# Reproduction des prédateurs
def reproduction_predateurs():
    """Pour chaque prédateur, s'il possède une énergie supérieure ou égale à Erepro, un nouveau prédateur apparaît à un endroit aléatoire sur la grille."""
    global config
    for x in range(1, N + 1):
        for y in range(1, N + 1):
            if type(config[x][y]) == list and config[x][y][0] == "Predateur" and config[x][y][2] >= Erepro and config[x][y].count("Reproduit") == 0: # Seulement si c'est un prédateur, qu'il ne s'est pas déjà reproduit pendant ce tour et que son niveau d'énergie est supérieur ou égal au niveau d'énergie Erepro nécessaire pour pouvoir se reproduire
                config[x][y].append("Reproduit") # Ajouter le terme "Reproduit" à la fin de la liste pour éviter qu'il se reproduise deux fois dans le même tour
                r = True # Variable pour arrêter la boucle
                while r: # Tant que r == True
                    x, y = rd.randint(1, N + 1), rd.randint(1, N + 1) # Génération de coordonnées aléatoires
                    if config[x][y] == 0: # Si la case à ces coordonnées est vide
                        config[x][y] = ["Predateur", Apre, Epre] # Ajouter un prédateur (Apre le nombre de tours d'espérance de vie et Epre l'énergie du prédateur)
                        r = False # Variable pour arrêter la boucle

# Déplacement et chasse des prédateurs
def chasse():
    """Déplace les prédateurs sur une case adjacente, en priorité une case où se trouve une proie."""
    global config
    for x in range(1, N + 1):
        for y in range(1, N + 1):
            if type(config[x][y]) == list and config[x][y][0] == "Predateur" and config[x][y].count("Déplacé") == 0: # Seulement si c'est un prédateur et qu'il n'a pas déjà effectué de déplacement pendant ce tour
                case = direction(x, y, "Proie", "Déplacement") # Retourner une case adjacente aléatoire où se situe une proie
                if case == 0: # S'il n'y a pas de proie à côté
                    case = direction(x, y, 0, "Déplacement") # Cherche une case vide adjacente aléatoire
                    if case == 0: # S'il n'y a pas de case vide non plus
                        break # Annuler la boucle
                    else:
                        coordonnees_case(x, y, case) # Récupérer les coordonnées i et j de la case selon son numéro
                        config[i][j] = config[x][y][:] # Copie de la liste sur la nouvelle position
                        config[x][y] = 0 # Suppression de la liste sur l'ancienne position
                        config[i][j].append("Déplacé") # Ajout du terme "Déplacé" à la fin de la liste pour éviter de déplacer le même animal 2 fois dans le même tour
                else: # Si la case 1 a une proie
                    coordonnees_case(x, y, case) # Récupérer les coordonnées i et j de la case selon son numéro
                    config[i][j] = config[x][y][:] # Copie de la liste sur la nouvelle position
                    config[x][y] = 0 # Suppression de la liste sur l'ancienne position
                    config[i][j].append("Déplacé") # Ajout du terme "Déplacé" à la fin de la liste pour éviter de déplacer le même animal 2 fois de suite
                    if not pas_de_proie: # Si le prédateur se déplace sur la case d'une proie
                        config[i][j][2] += MIAM # Ajout de MIAM énergie à l'énergie du prédateur

# Déplacement des proies
def deplacement_proies():
    """Déplace toutes les proies aléatoirement si une case adjacente est vide."""
    global config
    for x in range(1, N + 1):
        for y in range(1, N + 1):
            if type(config[x][y]) == list and config[x][y][0] == "Proie" and config[x][y].count("Déplacé") == 0: # Seulement si c'est une proie et qu'elle n'a pas déjà effectué un déplacement pendant ce tour
                case = direction(x, y, 0, "Déplacement") # Obtenir une case aléatoire pour un déplacement
                if case == 0: # Si aucune case disponible
                    break # Annuler la boucle
                else:
                    coordonnees_case(x, y, case) # Récupérer les coordonnées i et j de la case selon son numéro
                    config[i][j] = config[x][y][:] # Copie de la liste sur la nouvelle position
                    config[x][y] = 0 # Suppression de la liste sur l'ancienne position
                    config[i][j].append("Déplacé") # Ajout du terme "Déplacé" à la fin de la liste pour éviter de déplacer la même proie plusieurs fois dans le même tour

# Récupérer les coordonnées de la case
def coordonnees_case(x, y, case):
    """Récupère les nouvelles coordonnées i et j de la case à partir du numéro de cette case et des coordonnées x et y de la case de départ."""
    global i, j
    if case == 1: # En haut à gauche
        i, j = x - 1, y - 1
    elif case == 2: # À gauche
        i, j = x - 1, y
    elif case == 3: # En bas à gauche
        i, j = x - 1, y + 1
    elif case == 4: # En haut
        i, j = x, y - 1
    elif case == 5: # En bas
        i, j = x, y + 1
    elif case == 6: # En haut à droite
        i, j = x + 1, y - 1
    elif case == 7: # À droite
        i, j = x + 1, y
    elif case == 8: # En bas à droite
        i, j = x + 1, y + 1

# Retourne une case adjacente aléatoire selon la condition demandée
def direction(x, y, recherche, action):
    """Retourne une case adjacente aléatoire. recherche = 0 ou "Proie" ou "Predateur" et action = "Déplacement" (= chasse pour les prédateurs) ou "Reproduction"."""
    global pas_de_proie
    case_1 = case_2 = case_3 = case_4 = case_5 = case_6 = case_7 = case_8 = False # Création des variables pour chaque case (False = case indisponible, True = case disponible)
    pas_de_proie = False # Réinitialisation de la variable pour la chasse des prédateurs

    # Pour le déplacement (ou chasse)
    if action == "Déplacement":
        # Si on cherche une case vide
        if recherche == 0:
            # Vérifier pour chaque case (8 directions) si elle est vide
            if not type(config[x-1][y-1]) == list and config[x-1][y-1] == 0:
                case_1 = True # Case 1 : en haut à gauche
            if not type(config[x-1][y-1]) == list and config[x-1][y] == 0:
                case_2 = True # Case 2 : à gauche
            if not type(config[x-1][y+1]) == list and config[x-1][y+1] == 0:
                case_3 = True # Case 3 : en bas à gauche
            if not type(config[x][y-1]) == list and config[x][y-1] == 0:
                case_4 = True # Case 4 : en haut
            if not type(config[x][y+1]) == list and config[x][y+1] == 0:
                case_5 = True # Case 5 : en bas
            if not type(config[x+1][y-1]) == list and config[x+1][y-1] == 0:
                case_6 = True # Case 6 : en haut à droite
            if not type(config[x+1][y]) == list and config[x+1][y] == 0:
                case_7 = True # Case 7 : à droite
            if not type(config[x+1][y+1]) == list and config[x+1][y+1] == 0:
                case_8 = True # Case 8 : en bas à droite
            # Flair des proies
            if config[x][y][0] == "Proie":
                for i in range(1, (FLAIR_PRO + 1)):
                    for j in range(1, (FLAIR_PRO + 1)):
                        if x - i > 0 and y - j > 0: # Pour éviter que ça cherche des listes qui n'existent pas (et donc que ça fasse une erreur)
                            if type(config[x-i][y-j]) == list and config[x-i][y-j][0] == "Predateur": # S'il y a un prédateur pas loin
                                case_1 = case_2 = case_4 = False # Les cases 1, 2 et 4 sont indisponibles car un prédateur est dans cette direction
                        if x - i > 0:
                            if type(config[x-i][y]) == list and config[x-i][y][0] == "Predateur":
                                case_1 = case_2 = case_3 = False
                        if x - i > 0 and y + j < N:
                            if type(config[x-i][y+j]) == list and config[x-i][y+j][0] == "Predateur":
                                case_2 = case_3 = case_5 = False
                        if y - j > 0:
                            if type(config[x][y-j]) == list and config[x][y-j][0] == "Predateur":
                                case_1 = case_4 = case_6 = False
                        if y + j < N:
                            if type(config[x][y+j]) == list and config[x][y+j][0] == "Predateur":
                                case_3 = case_5 = case_7 = False
                        if x + i < N and y - j > 0:
                            if type(config[x+i][y-j]) == list and config[x+i][y-j][0] == "Predateur":
                                case_4 = case_6 = case_7 = False
                        if x + i < N:
                            if type(config[x+i][y]) == list and config[x+i][y][0] == "Predateur":
                                case_6 = case_7 = case_8 = False
                        if x + i < N and y + j < N:
                            if type(config[x+i][y+j]) == list and config[x+i][y+j][0] == "Predateur":
                                case_5 = case_7 = case_8 = False

        # Chasse des prédateurs
        elif recherche == "Proie": # Si on cherche une proie
            if type(config[x-1][y-1]) == list and config[x-1][y-1][0] == "Proie": # Vérifier dans chaque direction s'il y a une proie
                case_1 = True # La case 1 est disponible
            if type(config[x-1][y]) == list and config[x-1][y][0] == "Proie":
                case_2 = True
            if type(config[x-1][y+1]) == list and config[x-1][y+1][0] == "Proie":
                case_3 = True
            if type(config[x][y-1]) == list and config[x][y-1][0] == "Proie":
                case_4 = True
            if type(config[x][y+1]) == list and config[x][y+1][0] == "Proie":
                case_5 = True
            if type(config[x+1][y-1]) == list and config[x+1][y-1][0] == "Proie":
                case_6 = True
            if type(config[x+1][y]) == list and config[x+1][y][0] == "Proie":
                case_7 = True
            if type(config[x+1][y+1]) == list and config[x+1][y+1][0] == "Proie":
                case_8 = True
            # S'il n'y a aucune proie à côté du prédateur
            # Flair des prédateurs
            if case_1 == case_2 == case_3 == case_4 == case_5 == case_6 == case_7 == case_8 == False:
                pas_de_proie = True # Variable pour indiquer que l'on ne va pas se déplacer sur la case d'une proie
                for i in range(1, (FLAIR_PRE + 1)):
                    for j in range(1, (FLAIR_PRE + 1)):
                        if x - i > 0 and y - j > 0: # Pour éviter que ça cherche des listes qui n'existent pas (et donc que ça fasse une erreur)
                            if type(config[x-i][y-j]) == list and config[x-i][y-j][0] == "Proie": # S'il y a une proie pas loin
                                if not type(config[x-1][y-1]) == list and config[x-1][y-1] == 0: # Et qu'il y a une case de libre dans cette direction
                                    case_1 = True # La case est disponible
                        if x - i > 0:
                            if type(config[x-i][y]) == list and config[x-i][y][0] == "Proie":
                                if not type(config[x-1][y]) == list and config[x-1][y] == 0:
                                    case_2 = True
                        if x - i > 0 and y + j < N:
                            if type(config[x-i][y+j]) == list and config[x-i][y+j][0] == "Proie":
                                if not type(config[x-1][y+1]) == list and config[x-1][y+1] == 0:
                                    case_3 = True
                        if y - j > 0:
                            if type(config[x][y-j]) == list and config[x][y-j][0] == "Proie":
                                if not type(config[x][y-1]) == list and config[x][y-1] == 0:
                                    case_4 = True
                        if y + j < N:
                            if type(config[x][y+j]) == list and config[x][y+j][0] == "Proie":
                                if not type(config[x][y+1]) == list and config[x][y+1] == 0:
                                    case_5 = True
                        if x + i < N and y - j > 0:
                            if type(config[x+i][y-j]) == list and config[x+i][y-j][0] == "Proie":
                                if not type(config[x+1][y-1]) == list and config[x+1][y-1] == 0:
                                    case_6 = True
                        if x + i < N:
                            if type(config[x+i][y]) == list and config[x+i][y][0] == "Proie":
                                if not type(config[x+1][y]) == list and config[x+1][y] == 0:
                                    case_7 = True
                        if x + i < N and y + j < N:
                            if type(config[x+i][y+j]) == list and config[x+i][y+j][0] == "Proie":
                                if not type(config[x+1][y+1]) == list and config[x+1][y+1] == 0:
                                    case_8 = True

    # Pour la reproduction des proies
    if action == "Reproduction":
        # Vérifier pour chaque case (8 directions) que c'est une proie, que celle-ci a une énergie supérieure où égale à l'énergie maximale et qu'elle ne s'est pas déjà reproduite pendant ce tour
        if type(config[x-1][y-1]) == list and config[x-1][y-1][0] == "Proie" and config[x-1][y-1][2] >= Epro and config[x-1][y-1].count("Reproduit") == 0:
            case_1 = True
        if type(config[x-1][y]) == list and config[x-1][y][0] == "Proie" and config[x-1][y][2] >= Epro and config[x-1][y].count("Reproduit") == 0:
            case_2 = True
        if type(config[x-1][y+1]) == list and config[x-1][y+1][0] == "Proie" and config[x-1][y+1][2] >= Epro and config[x-1][y+1].count("Reproduit") == 0:
            case_3 = True
        if type(config[x][y-1]) == list and config[x][y-1][0] == "Proie" and config[x][y-1][2] >= Epro and config[x][y-1].count("Reproduit") == 0:
            case_4 = True
        if type(config[x][y+1]) == list and config[x][y+1][0] == "Proie" and config[x][y+1][2] >= Epro and config[x][y+1].count("Reproduit") == 0:
            case_5 = True
        if type(config[x+1][y-1]) == list and config[x+1][y-1][0] == "Proie" and config[x+1][y-1][2] >= Epro and config[x+1][y-1].count("Reproduit") == 0:
            case_6 = True
        if type(config[x+1][y]) == list and config[x+1][y][0] == "Proie" and config[x+1][y][2] >= Epro and config[x+1][y].count("Reproduit") == 0:
            case_7 = True
        if type(config[x+1][y+1]) == list and config[x+1][y+1][0] == "Proie" and config[x+1][y+1][2] >= Epro and config[x+1][y+1].count("Reproduit") == 0:
            case_8 = True

    if case_1 == case_2 == case_3 == case_4 == case_5 == case_6 == case_7 == case_8 == False:
        case = 0 # Si aucune case n'est disponible, retourner case = 0
    else: # Sinon, on choisit une des cases disponibles aléatoirement
        d = True # Variable pour arrêter la boucle
        while d: # Tant que d == True
            x = rd.randint(1, 8) # Génération d'un chiffre aléatoire entre 1 et 8 pour choisir la direction aléatoirement
            if case_1 and x == 1: # Si la case 1 est disponible et que le chiffre aléatoire est 1
                case = 1 # On retourne une valeur de 1
                d = False # Variable pour arrêter la boucle
            elif case_2 and x == 2: # Idem pour les 8 cases possibles
                case = 2
                d = False
            elif case_3 and x == 3:
                case = 3
                d = False
            elif case_4 and x == 4:
                case = 4
                d = False
            elif case_5 and x == 5:
                case = 5
                d = False
            elif case_6 and x == 6:
                case = 6
                d = False
            elif case_7 and x == 7:
                case = 7
                d = False
            elif case_8 and x == 8:
                case = 8
                d = False
    return case # Retourner la valeur de case (comprise entre 0 et 8 inclus)

# Réinitialiser la matrice
def reinitialiser():
    """Réinitialise la matrice."""
    global arret, tour, sauv_validee
    init_grille() # Création de la grille de départ
    init_proies() # Ajout de Npro proies à des coordonnées aléatoires
    init_prédateurs() # Ajout de Npre prédateurs à des coordonnées aléatoires
    bouton_start.configure(text = "Commencer") # Changer le texte du bouton start en "Commencer"
    if not arret: # Si la simulation est en cours
        arret = True # Arrêter la simulation
        canvas.after_cancel(var_chrono) # Arrêter le passage des tours
    tour = 0 # Réinitialise le numéro du tour
    label_tours.configure(text = ("Tour", tour)) # Actualise le texte du numéro de tour
    compter_animaux() # Actualiser le nombre d'animaux
    if sauv_validee: # Si le message de validation de la sauvegarde est affiché
        sauv_validee = False # Le supprimer (car la matrice affichée n'est plus celle qui a été sauvegardée dans le fichier)
        label_sauv_validee.configure(text = "") # Supprimer le texte "Sauvegarde effectuée"

# Sauvegarder la matrice
def sauvegarder():
    """Sauvegarde la matrice actuelle dans le fichier "sauvegarde"."""
    global sauv_validee
    fic = open("sauvegarde", "w") # Ouvrir le fichier "sauvegarde" en écriture
    fic.write(str(tour)) # Écrire le numéro du tour au début du fichier
    fic.write("\n\n") # Laisser la deuxième ligne vide
    for x in range(1, N + 1): # Pour chaque abscisse
        for y in range(1, N + 1): # Pour chaque ordonnée
            if config[x][y] == 0: # Si l'élément de la matrice est égal à 0
                fic.write(str(config[x][y])) # L'écrire sur cette ligne
                fic.write("\n") # Ajouter un retour à la ligne pour que le prochain élément soit sur la ligne suivante
            else: # Si c'est la liste d'un animal
                fic.write("ANIMAL\n") # Écrire "ANIMAL" sur cette ligne (avec le retour à la ligne) pour signaler le début de la liste d'un animal
                for i in range(0, len(config[x][y])): # Pour chaque élément de la liste de l'animal
                    fic.write(str(config[x][y][i])) # L'ajouter sur la ligne suivante
                    fic.write("\n")
                fic.write("FIN\n") # Puis écrire "FIN" sur la ligne suivante pour signaler la fin de la liste d'un animal
    sauv_validee = True # Variable pour indiquer que la matrice actuelle est sauvegardée
    label_sauv_validee.configure(text = "Sauvegarde effectuée") # Afficher le texte "Sauvegarde effectuée" en dessous du bouton
    fic.close() # Fermer le fichier

# Charger la matrice sauvegardée
def charger():
    """Charge la configuration sauvegardée dans le fichier "sauvegarde"."""
    global arret, tour, config
    # Réinitialisation de la matrice
    config = [[0 for x in range(N + 2)] for y in range(N + 2)] # Création de la matrice de taille N + 2 pour les bords
    config[0] = ["#" for x in range(N + 2)] # Ajout de "#" sur le bord gauche (invisible)
    config[-1] = ["#" for x in range(N + 2)] # Ajout de "#" sur le bord droit (invisible)
    for x in range(1, N + 1): # Ajout de "#" en haut et en bas de chaque colonne
        config[x][0] = "#"
        config[x][-1] = "#"

    fic = open("sauvegarde", "r") # Ouvrir le fichier "sauvegarde" en lecture
    x = y = 1 # On démarre avec une abscisse et une ordonnée égales à 1 pour ne pas compter les bords
    animal = False # Variable pour indiquer si la ligne fait partie de la liste d'un animal
    recup_tour = True # Variable pour récupérer le numéro de tour
    for ligne in fic: # Pour chaque ligne dans le fichier de sauvegarde
        if recup_tour:
            tour = int(ligne) # Récupère le numéro de tour
            recup_tour = False
        elif ligne == "0\n" and not animal: # Si la ligne est un 0 (avec \n à la fin pour le saut de ligne présent) et que le 0 n'est pas dans une liste d'animal
            config[x][y] = 0 # La case correspondante dans la matrice sera un 0
            y += 1 # On ajoute 1 à l'ordonnée pour la prochaine ligne du fichier
            if y == N + 1: # Si l'ordonnée est supérieure à la taille de la matrice
                y = 1 # On la réinitialise à 1 (on revient à la première ligne)
                x += 1 # Et on ajoute 1 à l'abscisse (on passe à la colonne à droite)
        if ligne == "ANIMAL\n": # Si la ligne est "ANIMAL" (avec le saut de ligne à la fin)
            animal = True # On entre dans la liste d'un animal
            config[x][y] = [] # Création de la liste de l'animal
        elif ligne == "FIN\n": # Si la ligne est "FIN" (avec le saut de ligne à la fin)
            animal = False # Fin de la liste de l'animal
            y += 1 # On ajoute 1 à l'ordonnée pour la prochaine ligne du fichier
            if y == N + 1: # Si l'ordonnée est supérieure à la taille de la matrice
                y = 1 # On la réinitialise à 1 (on revient à la première ligne)
                x += 1 # Et on ajoute 1 à l'abscisse (on passe à la colonne à droite)
        elif animal: # Si la ligne est dans la liste d'un animal
            if ligne == "Proie\n": # Si la ligne est "Proie"
                config[x][y].append("Proie") # On ajoute "Proie" dans la liste de l'animal
            elif ligne == "Predateur\n":
                config[x][y].append("Predateur")
            elif ligne == "Reproduit\n":
                config[x][y].append("Reproduit")
            elif ligne == "Déplacé\n":
                config[x][y].append("Déplacé")
            else: # Si c'est aucun des 4 termes possibles (donc c'est un nombre)
                config[x][y].append(int(ligne)) # On ajoute le nombre dans la liste
    fic.close() # Fermer le fichier
    affiche_grille(config) # Actualise la grille
    label_tours.configure(text = ("Tour", tour)) # Actualise le texte du numéro de tour récupéré dans le fichier
    compter_animaux() # Compter le nombre d'animaux
    bouton_start.configure(text = "Commencer") # Changer le texte du bouton start en "Commencer"
    if not arret: # Si la simulation est en cours
        arret = True # Arrêter la simulation
        canvas.after_cancel(var_chrono) # Arrêter le passage des tours

### Programme principal

# Définition des widgets
racine = tk.Tk()
racine.title("Simulation proies-prédateurs")
canvas = tk.Canvas(racine, width = LARGEUR, height = HAUTEUR)
bouton_start = tk.Button(racine, text = "Commencer", command = commencer, width = 10, font = ("bold", 12)) # Bouton pour commencer ou arrêter le passage des tours
bouton_reinit = tk.Button(racine, text = "Réinitialiser", command = reinitialiser, font = ("bold", 10)) # Bouton pour réinitialiser la matrice
bouton_sauver = tk.Button(racine, text = "Sauvegarder", command = sauvegarder, width = 10, font = ("bold", 10)) # Bouton pour sauvegarder la matrice actuelle
bouton_charger = tk.Button(racine, text = "Charger", command = charger, font = ("bold", 10)) # Bouton pour charger la matrice sauvegardée
label_tours = tk.Label(racine, text = ("Tour", tour), font = ("bold", 15)) # Texte pour afficher le numéro du tour actuel
label_sauv_validee = tk.Label(racine, width = 30, font = ("bold", 8)) # Texte pour indiquer que la matrice actuellement affichée est sauvegardée dans le fichier "sauvegarde"
label_animaux = tk.Label(racine, text = ("Nombre d'animaux : " + str((Npro + Npre))), font = ("bold", 8)) # Texte pour indiquer le nombre d'animaux en vie
label_proies = tk.Label(racine, text = ("Nombre de proies : " + str(Npro)), font = ("bold", 8)) # Texte pour indiquer le nombre de proies en vie
label_predateurs = tk.Label(racine, text = ("Nombre de prédateurs : " + str(Npre)), font = ("bold", 8))  # Texte pour indiquer le nombre de prédateurs en vie

# Fonctions
init_grille() # Création de la grille de départ
init_proies() # Ajout de Npro proies à des coordonnées aléatoires
init_prédateurs() # Ajout de Npre prédateurs à des coordonnées aléatoires

# Placement des widgets
canvas.grid(column = 1, row = 1, rowspan = 50)
label_tours.grid(column = 1, row = 0)
bouton_start.grid(column = 0, row = 5)
bouton_reinit.grid(column = 0, row = 10)
label_animaux.grid(column = 0, row = 19)
label_proies.grid(column = 0, row = 20)
label_predateurs.grid(column = 0, row = 21)
bouton_sauver.grid(column = 0, row = 30)
label_sauv_validee.grid(column = 0, row = 31)
bouton_charger.grid(column = 0, row = 33)

# Boucle principale
racine.mainloop()


def fizzBuzz(n):
    # Write your code here
    for i in range(1, n+1):
        res = ""
        if i % 3 == 0:
            res += "Fizz"
        if i % 5 == 0:
            res += "Buzz"
        if len(res) < 1:
            res = i
        print(res)

fizzBuzz(15)


class Solution:
    def majorityElement(self, nums: List[int]) -> int:
#첫번째 풀이
#        nums.sort()
#        answer = nums[len(nums)//2]
#        return answer
#두번째 풀이
        count = 0
        answer = None
        for n in nums:
            if count == 0:
                answer = n
            if n == answer:
                count = count +1
            else:
                count = count -1
        return answer


#!/usr/bin/env python2.7
from __future__ import print_function
import argparse
import fastqutil

def remove_duplicated_reads(num_qc_bp, qcutoff, dc_len, ifn, ofn):
    dc_seq_set = set()
    short_read_cnter = {}

    o_fastq_file = open(ofn, 'w')
    for seqid, seq, rseqid, qscore in fastqutil.iterate_fastq_file(ifn):
        # If the read is shorter than dc_len (dup checking len), discard the read.
        if len(seq) < dc_len:
            short_read_cnter[len(seq)] = short_read_cnter.get(len(seq), 0) + 1
        else:
            dc_seq = seq[:dc_len]
            if ((min(qscore[:num_qc_bp]) >= qcutoff) and ('N' not in seq[:num_qc_bp])
                and (dc_seq not in dc_seq_set)):
                dc_seq_set.add(dc_seq)
                o_fastq_file.write('\n'.join((seqid, seq, rseqid, qscore)) + '\n')

    o_fastq_file.close()

    print('Sequencing reads shorther than {}'.format(dc_len))
    print('Length\tCount')
    for short_read_len in sorted(short_read_cnter.keys()):
        print('{}\t{}'.format(short_read_len, short_read_cnter[short_read_len]))

    return

def main():
    arg_parser = argparse.ArgumentParser()

    arg_parser.add_argument('num_qc_bp', type = int,
                            metavar = '<number of quality checking bases>')

    arg_parser.add_argument('qc_int', type = int,
                            metavar = '<Phred quality score cutoff>',
                            help = 'FASTQ per base Phred quality score cutoff.'
                                   'Discard reads with quality score < qcutoff')

    arg_parser.add_argument('dc_len', type = int,
                            metavar = '<length of sequence for duplicate checking>')

    arg_parser.add_argument('ifn', metavar = '<input fastq file>')

    arg_parser.add_argument('ofn', metavar = '<output fastq file>',
                            help = 'The first occurence of the read passing '
                                   'quality check.')

    args = arg_parser.parse_args()

    remove_duplicated_reads(args.num_qc_bp, fastqutil.int_to_qscore(args.qc_int),
                            args.dc_len, args.ifn, args.ofn)

if __name__ == "__main__":
    main()


from collections import Counter

adapters = sorted([int(number.rstrip()) for number in open(f"input.txt").readlines()])
adapters.insert(0, 0)
adapters.append(max(adapters) + 3)
differences = []

last_adapter = 0
for adapter in adapters:
    differences.append(adapter - last_adapter)
    last_adapter = adapter

amount = Counter(differences)
print(f'Answer of part 1: {amount[1] * amount[3]}')

sol = {0: 1}
for adapter in adapters[1:]:
    sol[adapter] = sol.get(adapter - 1, 0) + sol.get(adapter - 2, 0) + sol.get(adapter - 3, 0)

print(f'Answer of part 2: {sol[max(adapters)]}')


from unittest import TestCase
from sparc.core import ParamNode, ParamGroupNode, Interval

class TestParamNode(TestCase):

    def test_init(self):
        p = ParamNode('test', 34, str, True, None)
        self.assertEqual(p.type(), str)
        self.assertEqual(p.value(), '34')

        p = ParamNode('test', 34.0, int, False, Interval(0, 100))
        self.assertEqual(p.value(), 34)

        with self.assertRaises(AttributeError):
            p.set_value(10)

        p.set_editable(True)
        with self.assertRaises(ValueError):
            p.set_value(-20)

        p = ParamNode('test', 'a', str, True, ['a', 'b', 'c'])
        self.assertEqual(p.value(), 'a')

        p.set_value('b')
        p.set_value('c')
        with self.assertRaises(ValueError):
            p.set_value('d')

    def test_name(self):
        p = ParamNode(u'Überläufer', 0, int)
        self.assertEqual(p.is_editable(), True)

    def test_editable(self):
        p = ParamNode('x', 0, int)
        self.assertEqual(p.is_editable(), True)

    def test_values(self):
        p = ParamNode('x', 0, int, validator=Interval(-1, +1, (Interval.Closed, Interval.Open)))
        with self.assertRaises(ValueError):
            p.set_value(-1)

        with self.assertRaises(ValueError):
            p.set_value('Hello World')

    def test_expression(self):
        p = ParamGroupNode('set')
        p.add_child('m', 5.0, float)
        p.add_child('a', 2.0, float)
        p.add_child('A', 4.0, float)
        p.add_child('F', '=m*a')
        p.add_child('Sigma', '=F/A')
        p.add_child('l', '=A**0.5')
        p.add_child('extern', '=A * F + x')

        self.assertEqual(p.child('F').value(), 10.0)
        self.assertEqual(p.child('Sigma').value(), 2.5)
        self.assertEqual(p.child('l').value(), 2.0)

        # context F takes precedence over sibling F!
        self.assertEqual(p.child('extern').value(context={'x': 2, 'F': 20.0}), 82.0)

        with self.assertRaises(NameError):
            p.child('extern').value()


import os.path
import pdb
import data.db_adapter as dba
import logging

from sklearn import tree as tr
from structs.app_builder import AppBuilder
from general.settings import Settings
from sklearn.externals import joblib
from general.const import Consts

LOGGER = logging.getLogger()
PKL = '.pkl'

def build_id():
    m = Settings.MALWARE_AMOUNT
    b = Settings.BENIGN_AMOUNT
    c = Settings.MALWARE_CATEGORY
    f = Settings.FEATURE_TYPE
    return f'{m}.{b}.{c}.{f}'

def build_cluster_id():
    m = Settings.MALWARE_AMOUNT
    b = Settings.BENIGN_AMOUNT
    f = Settings.FEATURE_TYPE
    return f'{m}.{b}.{f}'

def are_matrices_available():
    m_id = build_id()
    return os.path.isfile(f'{Settings.CACHE_MATRICES}{m_id}{PKL}')

def load_matrices():
    LOGGER.info(f'Load X, y from cache ...')
    m_id = build_id()
    X, y = joblib.load(f'{Settings.CACHE_MATRICES}{m_id}{PKL}')
    return X, y

def dump_matrices(X, y):
    m_id = build_id()
    joblib.dump((X, y), f'{Settings.CACHE_MATRICES}{m_id}{PKL}')

def remove_blacklisted(ids):
    blacklist = ['52dd03ca0f1480297200b625cc82b69ff20b8c6886de240836bfd7c994526e0d']
    for b in blacklist:
        if (ids.count(b) >= 1):
            ids.remove(b)
    return ids

def load_benign_ids():
    ids = load_ids('benign', Consts.DYNAMIC_INDEX_BENIGN, Settings.BENIGN_AMOUNT)
    return ids

def load_malware_ids():
    ids = load_ids('malware', Consts.DYNAMIC_INDEX_MALWARE, Settings.MALWARE_AMOUNT)
    return ids

def load_ids(type, db, amount):
    path = f'{Settings.CACHE_IDS}{type}.{amount}{PKL}'
    if os.path.isfile(path):
        ids = joblib.load(path)
    else:
        ids = dba.get_ids_from_db(db, 0, amount)
        joblib.dump(ids, path)
    return remove_blacklisted(ids)

def is_app_cached(id):
    return os.path.isfile(f'{Settings.CACHE_APPS}{id}.{Settings.FEATURE_TYPE}{PKL}')

def load_app(id, type):
    if is_app_cached(id):
        LOGGER.info(f'Load app from cache - id: {id}')
        app = joblib.load(f'{Settings.CACHE_APPS}{id}.{Settings.FEATURE_TYPE}{PKL}')
    elif (Settings.FEATURE_TYPE == 0 or Settings.FEATURE_TYPE == 1):
        LOGGER.info(f'Load app from cache - id: {id}')
        app = joblib.load(f'{Settings.CACHE_APPS}{id}.3{PKL}')
    elif (Settings.FEATURE_TYPE == 2):
        LOGGER.info(f'Load app from cache - id: {id}')
        app = joblib.load(f'{Settings.CACHE_APPS}{id}.4{PKL}')
    else:
        ab = AppBuilder()
        app = ab.build_app(id, type)
        joblib.dump(app, f'{Settings.CACHE_APPS}{id}.{Settings.FEATURE_TYPE}{PKL}')
    return app

def dump_cluster_data(scan_results):
    c_id = build_cluster_id()
    path = f'{Settings.CACHE_CLUSTERING}{c_id}{PKL}'
    joblib.dump(scan_results, path)

def load_cluster_data():
    c_id = build_cluster_id()
    path = f'{Settings.CACHE_CLUSTERING}{c_id}{PKL}'
    scan_results = joblib.load(path)
    return scan_results

def dump_feature_description(categorical_feature_names, numerical_feature_names):
    feature_names = categorical_feature_names + numerical_feature_names
    f_id = build_id()
    joblib.dump(feature_names, f'{Settings.CACHE_FEATURE_NAMES}{f_id}{PKL}')

def load_feature_description():
    f_id = build_id()
    return joblib.load(f'{Settings.CACHE_FEATURE_NAMES}{f_id}{PKL}')

def dump_graphviz(clf):
    feature_names_dirty = load_feature_description()
    feature_names = [fn.replace("->","...") for fn in feature_names_dirty]
    f_id = build_id()
    path = f'{Settings.CACHE_TREES}{f_id}{PKL}'
    dot_data = tr.export_graphviz(clf, out_file=path, feature_names=feature_names,
            filled=True, rounded=True, special_characters=True)


import json

class Store:
    def __init__(self):
        self.name = ""
        self.data = {}
        self.preferences = {}
        self.debug = False

    def set_data(self, payload):
        self.data = payload

    def set_preferences(self, payload, store):
        for user in payload:
            if user not in self.preferences:
                self.preferences[user] = {}
            self.preferences[user] = {k:v for (k,v) in payload[user][store].items()}

class CVS(Store):
    def __init__(self, debug=False):
        super().__init__()
        self.name = "CVS"
        self.debug = debug

    def set_preferences(self, payload):
        return super().set_preferences(payload, "cvs")

    def check_availability(self, user):
        availability = []
        for slot in self.data["responsePayloadData"]["data"]["NJ"]:
            if (slot["status"] != "Fully Booked"):
                availability.append(slot["city"])
        availability = list(filter(lambda x: x in self.preferences[user].keys(), availability))
        result = {
            "store": self.name,
            "availability_at": availability
        }
        return result

class RiteAid(Store):
    def __init__(self, debug=False):
        super().__init__()
        self.name = "RiteAid"
        self.debug = debug

    def set_preferences(self, payload):
        return super().set_preferences(payload, "riteaid")

    def check_availability(self, user, locations):
        availability = []
        for location in locations:
            try:
                # print(json.dumps(self.data))
                if self.data is not None and location in self.data and "Data" in self.data[location]:
                    has_availability = False
                    for slot in self.data[location]["Data"]["slots"]:
                        has_availability = has_availability and self.data[location]["Data"]["slots"][slot]
                    if has_availability:
                        availability.append(location)
            except TypeError as e:
                print(e)
                print(json.dumps(self.data))
        availability = list(filter(lambda x: x in self.preferences[user].keys(), availability))
        result = {
            "store": self.name,
            "availability_at": availability
        }
        return result

class Walgreens(Store):
    def __init__(self, debug=False):
        super().__init__()
        self.name = "Walgreens"
        self.debug = debug

    def set_preferences(self, payload):
        return super().set_preferences(payload, "walgreens")

    def check_availability(self, user):
        availability = []
        availability = list(filter(lambda x: x in self.preferences[user].keys(), availability))
        result = {
            "store": self.name,
            "availability_at": availability
        }
        return result


"""
---
title: Fine Tune GPT-NeoX
summary: >
    Fine tune GPT-NeoX biases with Fairscale pipeline parallel module
---

# Fine Tune GPT-NeoX

This shows how to fine tune GPT-NeoX with pipeline parallelism.
"""

# Imports
import fairscale
import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data
import torch.utils.data
from torch.utils.data import DataLoader, RandomSampler

from labml import tracker, experiment, monit
from neox.data import get_training_data
from neox.utils import balance_layers, LayerGenerator
from neox.utils.training import train, get_trainable_params, train_biases_only

# List of layers to load. This is used for testing.
# You can assign a subset of layers like `{0, 1}` so that it only loads
# the first to transformer layers.
LAYERS = None

def main():
    """
    ## Train GPT-NeoX
    """

    # Create the experiment for tracking
    experiment.create(name='finetune_neox_biases', comment='Pipeline parallel', writers={'screen', 'web_api'})

    # Load layers
    layers = list(LayerGenerator(is_clone_layers=True,
                                 filter_layers=LAYERS,
                                 ).load())

    # Mark `requires_grad=True` for biases using a [helper function](../utils/training.html).
    train_biases_only(layers)

    # Create the pipeline parallel model
    with monit.section('Pipe'):
        # Number of GPUs
        n_gpus = min(16, torch.cuda.device_count())
        # [Get the distribution of layers across the GPUs](../utils/__init__.py)
        balance = balance_layers(len(layers), n_gpus)
        # Get the GPU references
        devices = [torch.device(f'cuda:{i}') for i in range(n_gpus)]
        # Create the pipeline parallel model
        pipe_model = fairscale.nn.Pipe(nn.Sequential(*layers),
                                       balance=balance,
                                       devices=devices,
                                       chunks=8)

    # Load [dataset](../dataset.html)
    dataset = get_training_data(1024)

    # Create data loader
    train_dl = DataLoader(dataset,
                          batch_size=8,
                          sampler=RandomSampler(dataset, replacement=True))

    # Initialize optimizer
    optimizer = optim.Adam(get_trainable_params(pipe_model), lr=3e-4)

    # Train the model using the [helper function](../utils/training.html)
    with experiment.start():
        for epoch in monit.loop(16):
            train(pipe_model, optimizer, train_dl, torch.device('cuda:0'), 10)
            tracker.new_line()

#
if __name__ == '__main__':
    main()


from sys import argv
import os

def list_info(path):
    try:
        # Directory File List
        dir_path = os.listdir(path)
        print(dir_path)
        # Environment Variables
        for name, value in os.environ.items():
            print("{0}: {1}".format(name, value))
    except: # Error Handling
        print("Not Correct Input")


#
# Implements the training and classification workflow in a single script.
#
import os.path as P
import os
import sqlite3
import datetime

from calc_dim_01 import calc_dim
from exclude_02 import exclude_stopwords_spacy, exclude_shorter_than, exclude_non_alpha_partial, exclude_unigrams_shorter_than, exclude_ngrams_shorter_than
from prune_03 import prune
from index_04_09 import index
from mrmrnew_05 import mrmr
from svmvec_06_10 import svmvec
from svm_learn_07 import learn
from copy_dim_08 import copy_dim
from svm_classify_11 import classify
from prep_sqlitedb_00 import prep_sqlite, CSTRING
import spacy

def create_parser():
    from optparse import OptionParser
    p = OptionParser("usage: python %prog training.sqlite3 test.sqlite3 [options]")
    p.add_option("-t", "--temporary-dir", type="string", dest="temporary_dir", default=None, help="Specify the directory to use for storing temporary files")
    return p

def main():
    parser = create_parser()
    opts, args = parser.parse_args()
    if len(args) != 3:
        parser.error("invalid number of arguments")

    training_sqlite3, test_sqlite3, process_language = args

    print("Arguments: %s %s %s" % (training_sqlite3, test_sqlite3, process_language))

    #cwd = os.getcwd()
    #print "Working directory: %s" % (cwd)

    temporary_dir = opts.temporary_dir if opts.temporary_dir else P.dirname(training_sqlite3)
    if not P.isdir(temporary_dir):
        parser.error("error: temporary directory %s does not exist" % temporary_dir)

    def log(message):
        print ("[%s] %s" % (datetime.datetime.now().isoformat(), message))

    #
    # Check all tables are valid
    #
    if not P.isfile(training_sqlite3):
        print ("File not exist, ", training_sqlite3);
        return;

    if not P.isfile(test_sqlite3):
        print ("File not exist, ", test_sqlite3);
        return;

    conn = sqlite3.connect(training_sqlite3)

    c = conn.cursor();

    c.execute(''' SELECT count(name) FROM sqlite_master WHERE type='table' AND name='Dimensions' ''')
    if c.fetchone()[0] !=1 :
        print ('Dimensions table does not exist.')
        return

    c.execute(''' SELECT count(name) FROM sqlite_master WHERE type='table' AND name='Parameters' ''')
    if c.fetchone()[0]!=1 :
        print('Parameters table does not exist.')
        return;

    try:
        c.execute("""SELECT DimensionId, Term, PartOfSpeech, Exclude, IDF, MRMR
                FROM Dimensions WHERE Exclude = 0""")

        flag = False
        for row in c:
            flag = True
            break;
        if flag == False:
            print("Dimensions table is empty")
            return;

        c.execute('SELECT Name, Value FROM Parameters')

        flag = False
        for row in c:
            flag = True
            break;
        if flag == False:
            print("Parameters table is empty")
            return;
    except sqlite3.Error as error:
        print("Table schema error:", error)
        return;
    finally:
        if (conn):
            conn.close()

    nlp = spacy.load(process_language)

    #
    # Test section
    #
    log("Preparing SQLite test database")
    prep_sqlite(test_sqlite3)

    log("Copying dimensions from training database to test database")
    copy_dim(training_sqlite3, test_sqlite3)

    log("Indexing test database")

    index(test_sqlite3, nlp)

    log("Outputting test samples to temporary data file")
    test_samples = P.join(temporary_dir, "test-samples.dat")
    svmvec(test_sqlite3, test_samples)

    log("Classifying test samples")
    classifier = P.join(temporary_dir, "classifier.svm")
    classify(test_sqlite3, test_samples, classifier, False, temporary_dir)

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


import cv2
import numpy as np
from sklearn.mixture import GaussianMixture
import os

def extract_background(input_video_path):
    filename = os.path.basename(input_video_path)
    files = filename.split(".")
    vid = cv2.VideoCapture(input_video_path)
    frames = []
    frame_count = 0
    while True:
        ret, frame = vid.read()
        if frame is not None:
            frames.append(frame)
            frame_count += 1
        else:
            break
    frames = np.array(frames)
    gmm = GaussianMixture(n_components = 2)
    # initialize a dummy background image with all zeros
    background = np.zeros(shape=(frames.shape[1:]))
    for i in range(frames.shape[1]):
        for j in range(frames.shape[2]):
            for k in range(frames.shape[3]):
                X = frames[:, i, j, k]
                X = X.reshape(X.shape[0], 1)
                gmm.fit(X)
                means = gmm.means_
                covars = gmm.covariances_
                weights = gmm.weights_
                idx = np.argmax(weights)
                background[i][j][k] = int(means[idx])

    # Store the result onto disc
    print("completed background Extraction")
    path = os.path.join("extracted_background", files[0] + ".jpg")
    cv2.imwrite(path, background)
    cv2.imshow("background", background)
    cv2.waitKey(0)

extract_background(os.path.join("input_vidoes", "video_stab_input.mp4"))


import sys

with open(sys.argv[1], "r") as f:
    l = [[int(num) for num in line.strip()] for line in f]

def mostCommon(lst):

    zero = 0
    one = 0
    for i in lst:
        if i == 0:
            zero += 1

        else:
            one += 1

    if zero > one:
        return 0
    else:
        return 1

def decimal(binary):
    return sum(val * (2 ** idx) for idx, val in enumerate(reversed(binary)))

def oxygen(lst):

    for index in range(0, len(lst[0])):

        bits_at_index = [i[index] for i in lst]

        # Look for oxygen
        o = mostCommon(bits_at_index)

        lst = [i for i in lst if i[index] == o]

        if len(lst) == 1:
            return lst

def co2(lst):
    for index in range(0, len(lst[0])):

        bits_at_index = [i[index] for i in lst]

        # Look for oxygen
        o = 1 - mostCommon(bits_at_index)

        lst = [i for i in lst if i[index] == o]

        if len(lst) == 1:
            return lst

oxygen_number = decimal(oxygen(l)[0])
co2_number = decimal(co2(l)[0])

print(
    "Oxygen: {} , Co2: {} , Answer: {} ".format(
        oxygen_number, co2_number, oxygen_number * co2_number
    )
)


def get_add_subtract_list(input_str, m):
    add_list = ["ADD", "ALTOGETHER", "PLUS", "GET", "TAKE", "ADDING", "GETTING", "TAKING"]
    remove_list = ["REMOVE", "SUBTRACT", "MOVE", "OFF", "NOT", "AWAY", "DROP", "DELETE", "DELETING",
                   "REMOVING", "DROPPING"]
    inputlist = input_str.replace(", ", " ").replace(",", " ").split(" ")
    out = [[], [], []]
    i = 0
    idx = 0
    while i < len(inputlist):
        if i == len(inputlist) - 1:
            if inputlist[i] in m.keys():
                out[idx].append(inputlist[i])
        elif i < len(inputlist) - 1 and (inputlist[i] in m.keys() or str(inputlist[i] + inputlist[i + 1]) in m.keys()):
            if inputlist[i] in m.keys():
                out[idx].append(inputlist[i])
            else:
                out[idx].append(inputlist[i] + inputlist[i + 1])
        elif inputlist[i] in add_list:
            idx = 1
        elif inputlist[i] in remove_list:
            idx = 2
        i += 1
    return out, idx

def tpt_to_output_string(tpt):
    if () in tpt:
        return "Sorry, maybe you should take more courses for me to generate recommended courses."
    itm1 = tpt[0]
    itm2 = tpt[1]
    course_field_1 = itm1[0]
    course_field_2 = itm2[0]
    courses_list_1 = itm1[1]
    courses_list_2 = itm2[1]
    res = "Based on courses you have taken and the courses you are taking this semester, I recommend you to take cour" \
          "ses in " + course_field_1 + " and " + course_field_2 + ".\n\n"
    ans1 = ""
    ans1 += course_field_1
    if not courses_list_1:
        ans1 = "Sorry we are not able to provide you any course in " + course_field_1 + " field.\n\n"
    else:
        ans1 += ": "
        for course in courses_list_1:
            ans1 += course + ", "
        ans1 = ans1[:-2] + ".\n\n"
    ans2 = ""
    ans2 += course_field_2
    if not courses_list_2:
        ans2 = "Sorry we are not able to provide you any course in " + course_field_2 + " field.\n\n"
    else:
        ans2 += ": "
        for course in courses_list_2:
            ans2 += course + ", "
        ans2 = ans2[:-2] + ".\n\n"
    res += ans1 + ans2
    return res


from datetime import datetime
from RPA.Browser.Selenium import Selenium
import re

br = Selenium()

class Robot:
    def __init__(self, name):
        self.name = name
        self.final_summary = ''

    def say_hello(self):
        print("Hello, my name is " + self.name + "\n")

    def say_goodbye(self):
        print("Goodbye, my name is " + self.name)

    def save_text_to_file(self):
        try:
            filename = input("Enter the file name: ")
            if not filename.endswith(".txt"):
                filename += ".txt"
            with open(filename, "w", encoding="utf-8") as file:
                file.write(self.final_summary)
                print(f"Text saved to '{filename}' successfully!")

        except IOError:
            print(f"An error occurred while saving the text to '{filename}'.")
        except UnicodeEncodeError:
            print(f"UnicodeEncodeError: Unable to encode the text using the specified encoding. Please try a different file name.")

    def close_all_browsers(self):
        print("Closing Browser..")
        br.close_all_browsers()

    def open_webpage(self, webpage):
        try:
            br.open_available_browser(webpage)

        except Exception as e:
            error_message = str(e).split('\n')[0]
            print(f"(Error) Could not open browser: {error_message}")

    def submit_wiki_search(self, scientist):
        try:
            br.input_text("name=search", scientist)
            br.wait_and_click_button("//html/body/div[1]/header/div[2]/div/div/div/form/div/button")
            self.final_summary += scientist + "\n"

        except Exception as e:
            error_message = str(e).split('\n')[0]
            print(f"(Error) Could not submit wiki search: {error_message}")

    def get_wiki_first_paragraph(self):
        try:
            first_paragraph_element = br.get_webelement(f"//div[@id='mw-content-text']//p[ string-length(normalize-space()) > 0]")
            summary_text = br.get_text(first_paragraph_element)
            self.final_summary += "\n" + summary_text + "\n"
            print(summary_text + "\n")

        except Exception as e:
            error_message = str(e).split('\n')[0]
            print(f"(Error) Could not get Summary paragraph:  {error_message}")

    def get_scientist_age(self):
        try:
            Born = br.execute_javascript("return document.getElementsByClassName('bday')[0].textContent")
            Birth_date = datetime.strptime(Born, "%Y-%m-%d")

            Died_info_box = br.get_text("//th[contains(text(), 'Died')]/following-sibling::td")
            Date_string = re.search(r"\b(\d{1,2}\s\w+\s\d{4})\b", Died_info_box).group(1)
            # Convert the extracted date to the "1955-04-18" format
            Death_date = datetime.strptime(Date_string, "%d %B %Y")
            Died = Death_date.strftime("%Y-%m-%d")

            Age = Death_date.year - Birth_date.year
            self.final_summary += f"Born  : {Born}\nDied  : {Died}\nAge   : {Age}"
            print(f"Born  : {Born}\nDied  : {Died}\nAge   : {Age}")

        except Exception as e:
            error_message = str(e).split('\n')[0]
            print(f"(Error) Could not get scientist age:  {error_message}")


import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
lib_path = dir_path + '/../../libs'
sys.path.append(dir_path + '/../../repositories')
sys.path.append(dir_path + '/../services')
sys.path.append(lib_path)
from base_service import BaseService

class SnapshotRepository:
    pass

def fetch_allbot_with_snapshot(us, port, bot_alias):
    # bot under bot_alias
    snapshot = SnapshotRepository()
    snapshot_data = snapshot.fetch_all_bot(bot_alias)
    web_input = []
    for item in snapshot_data:
        if not item.get('bot_config'): # or not item.get('snapshot_data'):
            continue
        web_input.append({
            'bot_config': item['bot_config'],
            'own_name': item['bot_config']['own_name'],
            'time': item['bot_config']['time'],
            'uuid': item['bot_config']['uuid'],
            'pair': item['bot_config']['pair']
        })
    # bot not in user/port
    for item in web_input.copy():
        if us != item['own_name']:
            web_input.remove(item)
            continue
        elif item['bot_config'].get('port', False) and port != item['bot_config']['port']:
            web_input.remove(item)
            continue
    return web_input

def fetch_snap_shot_bot(us, port, bot_alias):
    # bot not ternimal
    snapshot = SnapshotRepository()
    snapshot_data = snapshot.fetch_data(bot_alias)
    web_input = []
    for item in snapshot_data:
        if not item or not item.get('bot_config'):
            continue
        web_input.append({
            'bot_config': item.get('bot_config'),
            'own_name': item['bot_config'].get('own_name'),
            'time': item['bot_config'].get('time'),
            'uuid': item['bot_config'].get('uuid'),
            'pair': item['bot_config'].get('pair', 'N/A'),
            'api_name': item['bot_config'].get('api_name', 'N/A'),
            'ex_id': item['bot_config'].get('pair', 'N/A'),
        })
    base_srv = BaseService()
    # bot not running
    for item in web_input.copy():
        data = base_srv.fetch_detail(bot_alias, str(item['uuid']))
        if data:
            # delete
            web_input.remove(item)
            continue
        if us != item['own_name']:
            web_input.remove(item)
            continue
        elif item['bot_config'].get('port', False) and port != item['bot_config']['port']:
            web_input.remove(item)
            continue
    return web_input

def fetch_snapshot_bot_detail(uuid: str, us, port, bot_alias, all_bot=False):
    if all_bot:
        snapshot_bots = fetch_allbot_with_snapshot(us, port, bot_alias)
    else:
        snapshot_bots = fetch_snap_shot_bot(us, port, bot_alias)

    for item in snapshot_bots:
        if uuid == item['uuid']:
            return item['bot_config']
    return None

def fetch_mode_display(modes, value):
    for item in modes:
        if item['value'] == value:
            return [item]
    return None


"""Reading some atmopsheric muon sim files and grabbing some basic information.
How to run: `python i3_to_hdf5_calc.py`
Note that an IceTray environment _must_ be loaded.
Tom Stuttard
Ammendments by Mads Ehrhorn
"""
import os
import numpy as np
from pathlib import Path
from I3Tray import I3Tray
from icecube import icetray
from icecube import dataclasses
from icecube import tensor_of_inertia
from icecube.common_variables import hit_statistics
from icecube.common_variables import direct_hits
from icecube.common_variables import hit_multiplicity
from icecube.common_variables import time_characteristics
from argparse import ArgumentParser
import datetime
import shelve
import dbm.dumb as dumbdbm
import random

parser = ArgumentParser()
parser.add_argument(
    '-i',
    '--i3_type',
    dest='i3_type',
    help='What i3 type to download'
)
parser.add_argument(
    '-n',
    '--number_of_files_to_handle',
    dest='number_of_files_to_handle',
    help='How many files to handle (0 for all)'
)

args = parser.parse_args()
i3_type = args.i3_type
number_of_files_to_handle = int(args.number_of_files_to_handle)

if i3_type == 'MuonGun_Level2_139008':
    input_dir = Path(
        '/groups/icecube/stuttard/data/oscNext/pass2/muongun/level2/139008/'
    )
    save_dir = Path(
        '/groups/hep/ehrhorn/files/icecube/shelve/MuonGun_Level2_139008'
    )
    gcd_file = Path(
        '/groups/hep/ehrhorn/files/icecube/i3_files/Jason/'
        'GeoCalibDetectorStatus_AVG_55697-57531_PASS2_SPE_withScaledNoise.i3'
    )
elif i3_type == 'oscnext-genie-level5-v01-01-pass2':
    input_dir = Path(
        '/groups/icecube/stuttard/data/oscNext/pass2/genie/level5_v01.01/'
    )
    save_dir = Path(
        '/groups/hep/ehrhorn/files/icecube/oscnext-genie-level5-v01-01-pass2/shelve_test_2'
    )
    gcd_file = Path(
        '/groups/hep/ehrhorn/files/icecube/i3_files/Jason/'
        'GeoCalibDetectorStatus_AVG_55697-57531_PASS2_SPE_withScaledNoise.i3'
    )
else:
    raise Exception('Dunno the i3 type')

save_dir.mkdir(exist_ok=True, parents=True)

if __name__ == '__main__':
    i3_files = sorted([f for f in input_dir.glob('**/*.i3*') if f.is_file()])
    if number_of_files_to_handle != 0:
        i3_files = i3_files[0:number_of_files_to_handle]
    column_names = [
        'dom_key',
        'dom_x',
        'dom_y',
        'dom_z',
        'dom_time',
        'dom_charge',
        'dom_lc',
        'dom_atwd',
        'dom_fadc',
        'dom_pulse_width',
        'dom_timelength_fwhm',
        'dom_n_hit_multiple_doms',
        'true_primary_direction_x',
        'true_primary_direction_y',
        'true_primary_direction_z',
        'true_primary_position_x',
        'true_primary_position_y',
        'true_primary_position_z',
        'true_primary_speed',
        'true_primary_time',
        'true_primary_energy',
        'linefit_direction_x',
        'linefit_direction_y',
        'linefit_direction_z',
        'linefit_point_on_line_x',
        'linefit_point_on_line_y',
        'linefit_point_on_line_z',
        'toi_direction_x',
        'toi_direction_y',
        'toi_direction_z',
        'toi_point_on_line_x',
        'toi_point_on_line_y',
        'toi_point_on_line_z',
        'toi_evalratio',
        'retro_crs_prefit_x',
        'retro_crs_prefit_y',
        'retro_crs_prefit_z',
        'retro_crs_prefit_azimuth',
        'retro_crs_prefit_zenith',
        'retro_crs_prefit_time',
        'retro_crs_prefit_energy',
        'secondary_track_length'
    ]
    mask_names = [
        'SplitInIcePulses',
        'SRTInIcePulses'
    ]
    meta_names = [
        'file',
        'index',
        'particle_code',
        'level'
    ]

    def do_things(frame):
        """Retrieve and calculate frames from an i3 file.
        Args:
            frame (i3 frame): i3 frame from i3 file.
        Returns:
            i3 object: i3 object with requested frames.
        """
        cond1 = frame['I3EventHeader'].sub_event_stream != 'InIceSplit'
        cond2 = 'LineFit' not in frame or 'ToI' not in frame
        cond3 = 'SRTInIcePulses' not in frame
        cond4 = not frame['L5_oscNext_bool']
        final_cond = cond1 or cond2 or cond3 or cond4
        if final_cond:
            return False
        else:
            linefit_result = frame['LineFit']
            linefit_fit_status = linefit_result.fit_status
            toi_result = frame['ToI']
            toi_fit_status = toi_result.fit_status
            try:
                retro_crs_prefit_result = frame[
                    'retro_crs_prefit__median__neutrino'
                ]
                retro_crs_prefit_status = frame[
                    'retro_crs_prefit__fit_status'
                ][0]
            except Exception:
                return False
            if linefit_fit_status != 0:
                return False
            elif toi_fit_status != 0:
                return False
            elif retro_crs_prefit_status != 0:
                return False

        hit_stats = frame['HitStatisticsValues']
        hit_mult = frame['HitMultiplicityValues']
        data['dom_n_hit_multiple_doms'].append(
            hit_mult.n_hit_doms - hit_mult.n_hit_doms_one_pulse
        )
        time_char = frame['TimeCharacteristicsValues']

        data['dom_timelength_fwhm'].append(time_char.timelength_fwhm)

        # TODO Could we maybe do this in a smarter, programmatic way?
        # Get the true muon particle
        # Note that the muon is really produced in the atmosphere, but for the
        # simulation it is generated at the surface of a cylinder
        # surrounding IceCube
        # <icecube.dataclasses.I3Particle>
        true_primary = dataclasses.get_most_energetic_primary(
            frame['I3MCTree']
        )
        true_muon = dataclasses.get_most_energetic_muon(frame['I3MCTree'])
        if true_muon == None:
            data['secondary_track_length'].append(np.nan)
        else:
            data['secondary_track_length'].append(true_muon.length)
        # Add the muon energy (defined at the generation cylinder) to the
        # data dicitonary
        data['true_primary_energy'].append(np.log10(true_primary.energy))

        # Direction of the muon
        # <icecube.dataclasses.I3Particle>
        true_primary_direction = true_primary.dir
        # Add the muon direction to the data dictionary
        data['true_primary_direction_x'].append(true_primary_direction.x)
        data['true_primary_direction_y'].append(true_primary_direction.y)
        data['true_primary_direction_z'].append(true_primary_direction.z)

        data['true_primary_time'].append(true_primary.time)
        data['true_primary_speed'].append(true_primary.speed)

        # Point on the generation cylinder at which the muon is produced
        # <icecube.dataclasses.I3Particle>
        true_primary_entry_position = true_primary.pos
        # Add the entry position to the data dictionary
        data['true_primary_position_x'].append(
            true_primary_entry_position.x
        )
        data['true_primary_position_y'].append(
            true_primary_entry_position.y
        )
        data['true_primary_position_z'].append(
            true_primary_entry_position.z
        )

        # Get the uncleaned pulses
        # <icecube.dataclasses.I3RecoPulseSeriesMap>
        uncleaned_pulses = frame['SplitInIcePulses'].apply(frame)
        cleaned_pulses = frame['SRTInIcePulses'].apply(frame)

        dom_geom = frame['I3Geometry'].omgeo

        # Create empty lists for holding the pulse information
        temp = np.empty((0, 11))
        dom_key_temp = []
        # dom_x_temp = np.empty(0)
        # dom_y_temp = np.empty(0)
        # dom_z_temp = np.empty(0)
        # dom_time_temp = np.empty(0)
        # dom_charge_temp = np.empty(0)
        # dom_lc_temp = np.empty(0)
        # dom_atwd_temp = np.empty(0)
        # dom_fadc_temp = np.empty(0)
        # dom_pulse_width_temp = np.empty(0)

        # Go through all pulses, get OM key and pair with time and charge info
        for entry in uncleaned_pulses.items():
            cleaned_time_list = []
            this_om_key = entry[0]
            if this_om_key in cleaned_pulses.keys():
                cleaned_temp = cleaned_pulses[this_om_key]
                for cleaned_entry in cleaned_temp:
                    cleaned_time_list.append(cleaned_entry.time)
            # This grabs you an object containing the geometry for this
            # particular OM
            this_om_geom = dom_geom[this_om_key]
            # This has x,y,z members
            this_om_position = this_om_geom.position
            for i, pulse in enumerate(entry[1]):
                if pulse.time in cleaned_time_list:
                    cleaned_mask = 1
                else:
                    cleaned_mask = 0
                # dom_x_temp = np.append(dom_x_temp, this_om_position.x)
                # dom_y_temp = np.append(dom_y_temp, this_om_position.y)
                # dom_z_temp = np.append(dom_z_temp, this_om_position.z)
                # dom_time_temp = np.append(dom_time_temp, pulse.time)
                # dom_charge_temp = np.append(dom_charge_temp, pulse.charge)
                # dom_lc_temp = np.append(dom_lc_temp, (pulse.flags & 0x1) >> 0)
                # dom_atwd_temp = np.append(
                #     dom_atwd_temp,
                #     (pulse.flags & 0x2) >> 1
                # )
                # dom_fadc_temp = np.append(
                #     dom_fadc_temp,
                #     (pulse.flags & 0x4) >> 2
                # )
                # dom_pulse_width_temp = np.append(
                #     dom_pulse_width_temp,
                #     pulse.width
                # )
                dom_key = str(this_om_key[0]) + '_' + str(this_om_key[1]) + '_' + str(this_om_key[2])
                pulses = np.array(
                    [
                        this_om_position.x,
                        this_om_position.y,
                        this_om_position.z,
                        pulse.time,
                        pulse.charge,
                        (pulse.flags & 0x1) >> 0,
                        (pulse.flags & 0x2) >> 1,
                        (pulse.flags & 0x4) >> 2,
                        pulse.width,
                        1,
                        cleaned_mask
                    ],
                    ndmin=2
                )
                temp = np.append(
                    temp,
                    pulses,
                    axis=0
                )
                dom_key_temp.append(dom_key)

        # Add Numpy arrays to data dictionary
        # data['dom_x'].append(dom_x_temp)
        # data['dom_y'].append(dom_y_temp)
        # data['dom_z'].append(dom_z_temp)
        # data['dom_time'].append(dom_time_temp)
        # data['dom_charge'].append(dom_charge_temp)
        # data['dom_lc'].append(dom_lc_temp)
        # data['dom_atwd'].append(dom_atwd_temp)
        # data['dom_fadc'].append(dom_fadc_temp)
        # data['dom_pulse_width'].append(dom_pulse_width_temp)
        # data['dom_key'].append(np.array(dom_key_temp))
        dom_key_temp = np.array(dom_key_temp)
        dom_key_temp = dom_key_temp[temp[:, 3].argsort()]
        data['dom_key'].append(dom_key_temp)
        temp = temp[temp[:, 3].argsort()]
        data['dom_x'].append(temp[:, 0])
        data['dom_y'].append(temp[:, 1])
        data['dom_z'].append(temp[:, 2])
        data['dom_time'].append(temp[:, 3])
        data['dom_charge'].append(temp[:, 4])
        data['dom_lc'].append(temp[:, 5])
        data['dom_atwd'].append(temp[:, 6])
        data['dom_fadc'].append(temp[:, 7])
        data['dom_pulse_width'].append(temp[:, 8])

        flatten = lambda l: [item for sublist in l for item in sublist]
        split_indices = np.argwhere(temp[:, 9])
        split_indices = np.array(flatten(split_indices))
        srt_indices = np.array(np.argwhere(temp[:, 10]))
        srt_indices = np.array(flatten(srt_indices))
        masks['SplitInIcePulses'].append(split_indices)
        masks['SRTInIcePulses'].append(srt_indices)

        # Get the cleaned pulses (if available)
        # <icecube.dataclasses.I3RecoPulseSeriesMap>
        # cleaned_pulses = frame['SRTInIcePulses'].apply(frame)

        # Get the LineFit reconstruction
        # The direction of the straight line
        # <icecube.dataclasses.I3Particle>
        linefit_direction = linefit_result.dir
        # Add the direction of the linefit to the data dictionary
        data['linefit_direction_x'].append(linefit_direction.x)
        data['linefit_direction_y'].append(linefit_direction.y)
        data['linefit_direction_z'].append(linefit_direction.z)

        # An arbitrary point along the line
        # <icecube.dataclasses.I3Particle>
        linefit_point_on_line = linefit_result.pos
        # Add the arbitrary point along the line to the data dictionary
        data['linefit_point_on_line_x'].append(linefit_point_on_line.x)
        data['linefit_point_on_line_y'].append(linefit_point_on_line.y)
        data['linefit_point_on_line_z'].append(linefit_point_on_line.z)

        # Some additional params
        # <icecube.recclasses.I3LineFitParams>
        # linefit_params = frame['LineFitParams']

        # Get the tensor of inertia
        # The direction of the ToI
        # <icecube.dataclasses.I3Particle>
        toi_direction = toi_result.dir
        # Add the direction to the data dictionary
        data['toi_direction_x'].append(toi_direction.x)
        data['toi_direction_y'].append(toi_direction.y)
        data['toi_direction_z'].append(toi_direction.z)

        # An arbitrary point along the line
        # <icecube.dataclasses.I3Particle>
        toi_point_on_line = toi_result.pos
        # Add arbitrary point along the line to data dictionary
        data['toi_point_on_line_x'].append(toi_point_on_line.x)
        data['toi_point_on_line_y'].append(toi_point_on_line.y)
        data['toi_point_on_line_z'].append(toi_point_on_line.z)

        # Some additional params
        # <icecube.recclasses.I3TensorOfInertiaFitParams>
        toi_params = frame['ToIParams']
        # This is the ratio of the smallest component of the ToI to the sum of
        # them all. A value close to 0. means a track-like event.
        # Addd it to the data dictionary
        data['toi_evalratio'].append(toi_params.evalratio)

        retro_crs_prefit_position = retro_crs_prefit_result.pos
        retro_crs_prefit_direction = retro_crs_prefit_result.dir

        data['retro_crs_prefit_x'].append(retro_crs_prefit_position.x)
        data['retro_crs_prefit_y'].append(retro_crs_prefit_position.y)
        data['retro_crs_prefit_z'].append(retro_crs_prefit_position.z)
        data['retro_crs_prefit_azimuth'].append(retro_crs_prefit_direction.azimuth)
        data['retro_crs_prefit_zenith'].append(retro_crs_prefit_direction.zenith)
        data['retro_crs_prefit_energy'].append(retro_crs_prefit_result.energy)
        data['retro_crs_prefit_time'].append(retro_crs_prefit_result.time)

    print('Converting i3 files:')
    db_train_file = save_dir.joinpath('train_set')
    with dumbdbm.open(str(db_train_file), 'n') as f:
        db_train = shelve.Shelf(f)
    db_val_file = save_dir.joinpath('val_set')
    with dumbdbm.open(str(db_val_file), 'n') as f:
        db_val = shelve.Shelf(f)
    db_test_file = save_dir.joinpath('test_set')
    with dumbdbm.open(str(db_test_file), 'n') as f:
        db_test = shelve.Shelf(f)
    n_events = 11308407
    indices_shuffled = np.arange(n_events)
    seed = 2912
    random.seed(seed)
    random.shuffle(indices_shuffled)
    train_indices_max = int(np.floor(0.8 * n_events))
    val_indices_max = int(n_events - (n_events - train_indices_max) * 0.5)
    train_dict = {}
    val_dict = {}
    test_dict = {}
    # db_file = save_dir.joinpath('oscnext-genie-level5-v01-01-pass2')
    # with dumbdbm.open(str(db_file), 'n') as f:
    #     db = shelve.Shelf(f)
    for i, file in enumerate(i3_files):
        # out_dict = {}
        out_name = file.stem
        out_name = out_name.replace('.i3', '')
        print('{}: converting {} --- {}/{}'.format(
            datetime.datetime.now().strftime("%H:%M:%S"),
            file.stem,
            i + 1,
            len(i3_files))
        )
        data = {}
        masks = {}
        meta = {}

        for name in column_names:
            data['{0}'.format(name)] = []
        for name in mask_names:
            masks['{0}'.format(name)] = []
        for name in meta_names:
            meta['{0}'.format(name)] = []
        # Create the tray
        tray = I3Tray()

        # Read input file(s)
        tray.AddModule(
            'I3Reader',
            'reader',
            FilenameList=[str(gcd_file)] + [str(file)]
        )

        # Calculate tensor of interatia
        # TODO use clean or unclean pulses for InputReadout?
        tray.AddModule(
            'I3TensorOfInertia',
            'tensor_of_interia',
            AmplitudeOption=1,
            AmplitudeWeight=1,
            InputReadout='SRTInIcePulses',
            InputSelection='',
            MinHits=3,
            Name='ToI'
        )

        tray.AddModule(
            hit_statistics.I3HitStatisticsCalculator,
            PulseSeriesMapName='SRTInIcePulses',
            OutputI3HitStatisticsValuesName='HitStatisticsValues',
        )
        tray.AddModule(
            hit_multiplicity.I3HitMultiplicityCalculator,
            PulseSeriesMapName='SRTInIcePulses',
            OutputI3HitMultiplicityValuesName='HitMultiplicityValues'
        )
        tray.AddModule(
            time_characteristics.I3TimeCharacteristicsCalculator,
            PulseSeriesMapName='SRTInIcePulses',
            OutputI3TimeCharacteristicsValuesName='TimeCharacteristicsValues'
        )

        # Add our own module
        tray.Add(do_things, 'do_things')
        # Actually run the tray
        tray.Execute()
        tray.Finish()

        events_list = []
        masks_list = []
        meta_list = []

        no_of_events = len(data['dom_x'])
        for j in range(no_of_events):
            temp_events = {key: data[key][j] for key in data}
            temp_masks = {key: masks[key][j] for key in masks}
            temp_meta = {
                'file': out_name + '.h5',
                'index': j,
                'particle_code': file.stem.split('.')[2],
                'level': 5
            }
            events_list.append(temp_events)
            masks_list.append(temp_masks)
            meta_list.append(temp_meta)

        taken_indices = indices_shuffled[0:no_of_events]
        indices_shuffled = np.delete(indices_shuffled, np.s_[0:no_of_events])

        for j, i_index in enumerate(taken_indices):
            if i_index <= train_indices_max:
                train_dict[str(i_index)] = {}
                train_dict[str(i_index)]['raw'] = events_list[j]
                train_dict[str(i_index)]['masks'] = masks_list[j]
                train_dict[str(i_index)]['meta'] = meta_list[j]
            elif i_index >= train_indices_max and i_index <= val_indices_max:
                val_dict[str(i_index)] = {}
                val_dict[str(i_index)]['raw'] = events_list[j]
                val_dict[str(i_index)]['masks'] = masks_list[j]
                val_dict[str(i_index)]['meta'] = meta_list[j]
            else:
                test_dict[str(i_index)] = {}
                test_dict[str(i_index)]['raw'] = events_list[j]
                test_dict[str(i_index)]['masks'] = masks_list[j]
                test_dict[str(i_index)]['meta'] = meta_list[j]

        # out_dict = data
        # out_dict['masks'] = masks
        # out_dict['meta'] = {}
        # out_dict['meta']['events'] = len(data['true_primary_energy'])

        # db[out_name] = out_dict

        if (i + 1) % 20 == 0:
            print('{}: saving to db'.format(
                datetime.datetime.now().strftime("%H:%M:%S")
            ))

            with shelve.open(str(db_train_file), 'w') as f:
                for key in train_dict:
                    f[key] = train_dict[key]
            with shelve.open(str(db_val_file), 'w') as f:
                for key in val_dict:
                    f[key] = val_dict[key]
            with shelve.open(str(db_test_file), 'w') as f:
                for key in test_dict:
                    f[key] = test_dict[key]
            train_dict = {}
            val_dict = {}
            test_dict = {}

    print('{}: saving to db'.format(
        datetime.datetime.now().strftime("%H:%M:%S")
    ))

    with shelve.open(str(db_train_file), 'w') as f:
        for key in train_dict:
            f[key] = train_dict[key]
    with shelve.open(str(db_val_file), 'w') as f:
        for key in val_dict:
            f[key] = val_dict[key]
    with shelve.open(str(db_test_file), 'w') as f:
        for key in test_dict:
            f[key] = test_dict[key]
    train_dict = {}
    val_dict = {}
    test_dict = {}

print('Done.')


import csv

tno=[]
tna=[]
days=[]
classes=[]
typ=[]
zone=[]
routen=[]
routec=[]
arr=[]
dept=[]

with open("../datasets/trains.csv","r") as readFile:
	file=csv.reader(readFile)
	for u in file:
		tno.append(u[0])
		tna.append(u[1])
		days.append(u[2])
		classes.append(u[3])
		typ.append(u[4])
		zone.append(u[5])
		routen.append(u[6])
		routec.append(u[7])
		arr.append(u[8])
		dept.append(u[9])

rt=[]
sld=[]
sd=[]
can=[]

with open("../datasets/trainHistory.csv","r") as readFile:
	file=csv.reader(readFile)
	for u in file:
		rt.append(u[0])
		sld.append(u[1])
		sd.append(u[2])
		can.append(u[3])

with open("../datasets/trainsFinal.csv","w") as writeFile:
	file=csv.writer(writeFile)
	for i in range(0,len(tno)):
		file.writerow([tno[i]]+[tna[i]]+[days[i]]+[classes[i]]+[typ[i]]+[zone[i]]+[routen[i]]+[routec[i]]+[arr[i]]+[dept[i]]+[rt[i]]+[sld[i]]+[sd[i]]+[can[i]])


from typing import List

class Solution:
    def make_signature(self, word: str) -> int:
        """
        If the signature does not depend on order
        a sum is a good way to do it.
        NOTE: we need to include things that anagrams have in common
        - the frequency in which letters appear
        - length of the string
        - we could sort the dictionary but that would significantly increase
        the time complexity with O(NlogN) operations
        """
        signature = [0] * 26
        m = {}
        for char in word:
            val = ord(char) - ord('a')
            signature[val] += 1

        return str(signature)

    def groupAnagrams(self, words: List[str]) -> List[List[str]]:
        '''
        :type words: list of str
        :rtype: list of list of str

        Complexity
        ----
        N = length of words array
        k = longest word with all unique letters
        Time : O(N*k)
        Space : O(N)
        '''

        m = {}
        for i, word in enumerate(words):
            signature = self.make_signature(word)
            if signature not in m:
                m[signature] = [i]
            else:
                m[signature].append(i)

        # return each of the groupings
        res = []
        for key in m:
            anagram_group = []
            for i in m[key]:
                anagram_group.append(words[i])
            res.append(anagram_group)
        return res

s = Solution()
words = ["eat", "bat", "ate", "tab", "tea", "eat"]
print(s.groupAnagrams(words))


import pandas as pd
import numpy as np

# 파일 불러오기, object 생성
fish = pd.read_csv('https://bit.ly/fish_csv_data')
fish.head()

# 유니크값 고유값 뽑아오기
print(pd.unique(fish['Species']))

# fish DataFrame 에서 필요한 5열을 numpy로 저장
fish_input = fish[['Weight', 'Length', 'Diagonal', 'Height', 'Width']].to_numpy()

print(fish_input[:5])

# target 만들기
fish_target = fish['Species'].to_numpy()

print(fish_target[:5])

# sklearn으로 트레인, 타깃세트 분리
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(
    fish_input, fish_target, random_state = 42
)

from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input) # 학습 데이터
test_scaled = ss.transform(test_input)   # 테스트 데이터

# k-nearest 확률 예측
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier(n_neighbors=3)
kn.fit(train_scaled, train_target)
print(kn.score(train_scaled, train_target))
print(kn.score(test_scaled, test_target))

# sklearn 에서는 키값들의 순서가 바뀌니 확인 필요
print(kn.classes_)

print(kn.predict(test_scaled[:5]))
print(test_target[:5])
proba = kn.predict_proba(test_scaled[:5])
print(np.round(proba, decimals=4))

print(kn.classes_)

distances, indexs = kn.kneighbors(test_scaled[3:4])
print(train_target[indexs])

##########################
# Logistic Regression
###
import numpy as np
import matplotlib.pyplot as plt
z = np.arange(-5, 5, 0.1)
phi = 1 / (1 + np.exp(-z))
plt.plot(z, phi)
plt.xlabel('z')
plt.ylabel('phi')
plt.show()

## 불리언 인덱싱
char_arr = np.array(['A', 'B', 'C','D', 'E'])
print(char_arr[[True, False, True, False, False]])
print(char_arr)

bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt')
train_bream_smelt = train_scaled[bream_smelt_indexes]
target_bream_smelt = train_target[bream_smelt_indexes]

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt)

print(lr.predict_proba(train_bream_smelt[:5]))

print(lr.classes_)

print(lr.coef_, lr.intercept_)

decisions = lr.decision_function(train_bream_smelt[:5])
print(decisions)

from scipy.special import expit
print(expit(decisions))

## 다중 분류 시행하기
lr = LogisticRegression(C=20, max_iter=1000)
lr.fit(train_scaled, train_target)
print(lr.score(train_scaled, train_target))
print(lr.score(test_scaled, test_target))

print(lr.predict(test_scaled[:5]))

proba = lr.predict_proba(test_scaled[:5])
print(np.round(proba, decimals=3))

print(lr.classes_)

print(lr.coef_.shape, lr.intercept_.shape)

decision = lr.decision_function(test_scaled[:5])
print(np.round(decision, decimals=2))

# 사이파이 소프트맥스
from scipy.special import softmax
proba = softmax(decision, axis = 1)
print(np.round(proba, decimals = 3))

z = np.arange(-5, 5, 0.1)
soma = softmax(z)
plt.plot(z, soma)
plt.xlabel('z')
plt.ylabel('phi')
plt.show()


from tkinter import Y
from binance.client import Client
import pandas as pd
import requests
from database import toks
from database import db
from binance_client import client
from database import toks

def get_all_24hours_pct(top):
    tickers_pc = []
    tickers = []
    prices = client.get_ticker()
    for ticker in prices:
        if 'USDT' in ticker['symbol'] and ticker['symbol']   :
            if not ('UP' and 'DOWN')in ticker['symbol'] and ticker['symbol']:
             pairs = {'Symbol':ticker['symbol'] , 'pct' :float(ticker['priceChangePercent']) }
             tickers_pc.append(pairs)
    tickers_pc = sorted(tickers_pc, key=lambda x : x['pct'], reverse=True)
    tickers_pc = tickers_pc[:top]
    for ticker in tickers_pc :
        tickers.append(ticker['Symbol'])

    return tickers
m=get_all_24hours_pct(120)

i=0
toks.rmvall("list_2")
while i<20:

    toks.add("list_2",str(m[i]))
    i=i+1
    print(i)
i=20
toks.rmvall("list_3")
while i<40:

    toks.add("list_3",str(m[i]))
    i=i+1
    print(i)
i=40
toks.rmvall("list_4")
while i<60:

    toks.add("list_4",str(m[i]))
    i=i+1
    print(i)
i=60
toks.rmvall("list_5")
while i<80:

    toks.add("list_5",str(m[i]))
    i=i+1
    print(i)
i=80
toks.rmvall("list_6")
while i<100:

    toks.add("list_6",str(m[i]))
    i=i+1
    print(i)

i=100
toks.rmvall("list_7")
while i<120:

    toks.add("list_7",str(m[i]))
    i=i+1
    print(i)


from django.contrib import admin

# Register your models here.
from .models import *

class UserDetailAdmin (admin.ModelAdmin):
    list_display = ["__unicode__", "pno", "gen", "age"]
    class Meta:
        model = UserDetail

class LawyerDetailAdmin (admin.ModelAdmin):
    list_display = ['lid', 'pno', 'age', 'gen', 'experience', 'speciality']
    class Meta:
        model = LawyerDetail

class ContactLawyerAdmin (admin.ModelAdmin):
    list_display = ['contact_id', 'uid', 'lid', 'status']
    class Meta:
        model = ContactLawyer

admin.site.register(UserDetail, UserDetailAdmin)
admin.site.register(LawyerDetail, LawyerDetailAdmin)
admin.site.register(ContactLawyer, ContactLawyerAdmin)


class insideRectColl:
    def __init__(self, name = " is inside collider"):
        self.types = ["physics"]
        self.entity = None
        self.name = name
        self.verbose = False
        self.children = []

        return

    def shouldAct(self,data):
        if self.entity == None:
            return False
        if self.entity.active == False:
            return False
        if data == None:
            return False
        return True

    def act(self, data):
        if self.shouldAct(data):
            for i in range(0,len(data.pos)):
                if data.active_particle[i]:
                    if data.pos[i][0] < self.entity.ll[0]:                                      #return halved velocity to reduce crazy bouncing
                        data.pos[i][0] = 2.0 * self.entity.ll[0] - data.pos[i][0]
                        data.vel[i][0] = -data.vel[i][0] / 2
                    elif data.pos[i][0] > self.entity.ur[0]:
                        data.pos[i][0] = 2.0*self.entity.ur[0] - data.pos[i][0]
                        data.vel[i][0] = -data.vel[i][0] / 2
                    elif data.pos[i][1] < self.entity.ll[1]:
                        data.pos[i][1] = 2.0*self.entity.ll[1] - data.pos[i][1]
                        data.vel[i][1] = -data.vel[i][1] / 2
                    elif data.pos[i][1] > self.entity.ur[1]:
                        data.pos[i][1] = 2.0*self.entity.ur[1] - data.pos[i][1] + 0.5
                        data.vel[i][1] = -data.vel[i][1] / 2
                        data.vel[i][0] *= 0.9                                                   #add drag if paricle is touching ground

            for c in self.children:
                c.act(data)

            if self.verbose:
                print(self.name +"triggered for "+ self.entity.name)


# Import native libraries
import os
from datetime import datetime

# Import project code
from grimoire.nlp.features import Features

class Document:
    def __init__(self, id, text, attributes):
        self.id = id
        self.date_added = str(datetime.now())
        self.added_by = os.getlogin()
        self.text = text
        self.attributes = attributes
        self.features = Features()

    def extract_features(self):
        self.features = Features.extract_features(self.text)