Commit c1b1649a authored by HURE GABRIELLE's avatar HURE GABRIELLE
Browse files

Merge branch 'gabrielle' into 'master'

banche Gabrielle à master

See merge request !1
parents 97bb3cca 3f01dfb3
.idea
__pycache__
\ No newline at end of file
# Default ignored files
/shelf/
/workspace.xml
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Default" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (qui-est-ce)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/qui-est-ce.iml" filepath="$PROJECT_DIR$/.idea/qui-est-ce.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
"""
Projet : Qui-est-ce ?
Auteurs : Pauline MELEDO, Yoann KLEIN, Mickaël MACHADO VICENTE, Gabrielle HURE
Ecole : Télécom Physique Strasbourg
Ce fichier permet de définir l'objet capteur
"""
class Capteur:
"""
Classe définissant un capteur.
"""
def __init__(self, numero_capteur, tag_lu):
"""
Définit un capteur.
:param numero_capteur: [int] l'identificateur du capteur.
:param tag_lu: [string] le tag renvoyé par le capteur physique en question
"""
self.numero_capteur = numero_capteur
self.tag_lu = tag_lu
No preview for this file type
"""
Projet : Qui-est-ce ?
Auteurs : Pauline MELEDO, Yoann KLEIN, Mickaël MACHADO VICENTE, Gabrielle HURE
Ecole : Télécom Physique Strasbourg
Ce fichier permet de lire une base de données excel ayant un format spécifique (voir README.md) et de créer des
Personnages et des Questions qui y sont associés. LecteurBd contient ensuite la liste de Personnages et Questions
qui ont été lus.
"""
import pandas as pd
class Personnage:
"""
Classe définissant un personnage.
"""
def __init__(self, numero, tag, dict_questions_reponse):
"""
Définit un personnage.
:param numero: [string] numéro du personnage.
:param tag: [string] tag RFID associé au personnage.
:param dict_questions_reponse: [dict(string,int)] Dictionnaire contenant en clef les tags des questions
et en valeur la réponse à la question (1 pour oui,0 pour non).
"""
self.numero = numero
self.tag = tag
self.dict_questions_reponse = dict_questions_reponse
class Question:
"""
Classe définissant une question.
"""
def __init__(self, numero, tag, question):
"""
Définit une question.
:param numero: [string] numéro de la question.
:param tag: [string] tag RFID associé à la question.
:param question: [string] question posée.
"""
self.numero = numero
self.tag = tag
self.question = question
class LecteurBd:
"""
lit la base de données excel et créé les personnages et questions qui y sont enregistrés.
"""
def __init__(self, chemin_fichier_bd):
"""
Lit la base de données excel et créé une liste de personnages et une liste de questions.
:param chemin_fichier_bd: [string] chemin du fichier excel contenant la base de données.
"""
self.fichier_bd = chemin_fichier_bd
self.liste_personnages = self.__lecture_personnages()
self.liste_question = self.__lecture_questions()
def __lecture_personnages(self):
"""
lit self.fichier_bd et créé une liste de personnages.
:return: [list[Personnage]]La liste de personnages.
"""
# lecture du de la feuille "personnages" du fichier excel et conversion en dataframe Pandas
db_personnages = pd.read_excel(self.fichier_bd, sheet_name="personnages", header=0, index_col=0)
liste_personnage = []
# iteration dans la data frame Pandas et récupération des tags des questions,
# de la liste de réponses et du tag et du numéro du personnage
for idx_ligne, ligne in db_personnages.iterrows():
dict_questions_reponse = {}
for idx_col, valeur in enumerate(ligne):
if idx_col >= 1:
dict_questions_reponse[db_personnages.columns.values[idx_col]] = valeur
# ajout du Personnage créé dans la liste
liste_personnage.append(Personnage(numero=idx_ligne, tag=ligne[0], dict_questions_reponse=dict_questions_reponse))
return liste_personnage
def __lecture_questions(self):
"""
lit self.fichier_bd et créé une liste de questions.
:return: [list[Question]]La liste de questions.
"""
# lecture de la feuille "questions" du fichier excel et conversion en dataframe Pandas
db_questions = pd.read_excel(self.fichier_bd, sheet_name="questions", header=0, index_col=0)
liste_questions = []
# iteration dans la data frame Pandas et récupération des numéros de tags des questions et la question elle même
for idx_ligne, ligne in db_questions.iterrows():
liste_questions.append(Question(numero=idx_ligne, tag=ligne[0], question=ligne[1]))
return liste_questions
"""
Projet : Qui-est-ce ?
Auteurs : Pauline MELEDO, Yoann KLEIN, Mickaël MACHADO VICENTE, Gabrielle HURE
Ecole : Télécom Physique Strasbourg
Ce fichier est le script qui doit être lancé.
La Base de données y est lue.
L'arbre est testé grace aux tags des capteurs qui doivent être donnés au script.
L'état des LEDs doit être renvoyé à l'Arduino
"""
from lecteur_bd import *
from verification_elements import *
import os
from pathlib import Path
"""
Lecture base de données
"""
chemin_bd = Path(os.getcwd()).joinpath("data/base_donees.xlsx")
lecteur_bd = LecteurBd(chemin_bd)
"""
Creation liste de capteurs et tags lus comme exemple
"""
tag_faux = ["0001q", "0002q", "0001p", "0003q", "0002p", "0004q", "0003p",
"0004p", "0005q", "", "", "0007q", "0006p", "0008q", "0007p"]
capteurs = []
for i in range(1, 16):
capteurs.append(Capteur(i, tag_faux[i - 1]))
"""
Test de la vérification
"""
verif = VerificationElements(lecteur_bd.liste_personnages, lecteur_bd.liste_question, capteurs)
verif.verification_globale()
print("nb étage = {}".format(verif.nb_etage))
print("Etat des LEDs:")
for idx, valeur in enumerate(verif.resultat_leds):
print("Index de la LED : ", idx, " --> valeur de la LED : ", valeur)
"""
Projet : Qui-est-ce ?
Auteurs : Pauline MELEDO, Yoann KLEIN, Mickaël MACHADO VICENTE, Gabrielle HURE
Ecole : Télécom Physique Strasbourg
Ce fichier effectue la vérification du positionnement des élements dans l'arbre de décision.
"""
from lecteur_bd import *
from capteur import *
import math
class VerificationElements:
"""
Vérifit le bon placement des différents élements posés dans l'arbre.
Le résultat se trouve dans self.resultat_leds. Cet attribut comporte l'état des LEDS qui doit être envoyé à
l'Arduino par la suite (-1 pour blanc ou non allumé, 0 pour rouge et 1 pour vert).
"""
def __init__(self, liste_personnages, liste_questions, liste_tags):
"""
Initialise le verificateur avec les Personnages et Question lus dans la base de données ainsi
qu'avec les Capteurs renvoyés par l'Arduino.
:param liste_personnages: [list[Personnage]] une liste comprenant des objects de type Personnage.
:param liste_questions: [list[Question]] une liste comprenant des objects de types Question.
:param liste_tags: [list[Capteur]] un liste comprenant des objects de type Capteur.
"""
self.liste_personnages = liste_personnages
self.liste_questions = liste_questions
self.liste_tags = liste_tags
self.nb_etage = self.__calcul_nb_etages()
self.resultat_leds = [-1] * (len(self.liste_tags) - 1) # initialisation avec des LEDs éteintes ou blanches
self.liste_objects_lus, \
self.liste_index_personnage, \
self.liste_index_questions = self.__association_tags_lu_avec_bd()
def __calcul_nb_etages(self):
"""
Calcule le nombre d'étages de l'arbre évalué.
:return: [int] le nombre d'étages.
"""
conteur_etage = 0
if self.liste_tags:
a = len(self.liste_tags)
while math.ceil(a / 2) > 1:
conteur_etage += 1
a = math.ceil(a / 2)
conteur_etage += 1 # si la liste de tags n'est pas vide, alors il existe au moins le premier niveau
return conteur_etage
def __association_tags_lu_avec_bd(self):
"""
Associe à chaque tag lu par les Capteurs un Personnage, une Question ou rien si le tag n'est pas
dans la base de données.
:return: [list[Peronnages/Question/""]] la liste des object associés aux tags lus,
[list[int]] la liste des emplacements (index) où sont trouvés des Personnages
[list[int]] la liste des emplacements (index) où sont trouvés des Questions.
"""
liste_index_personnage = []
liste_index_questions = []
liste_objects_lus = []
for index, capteur in enumerate(self.liste_tags):
trouve = False # initialisation tag non trouvée dans la liste des Personnages et des Questions.
tag = capteur.tag_lu
for question in self.liste_questions: # recherche du tag lu dans la liste des Questions
if tag == question.tag:
liste_objects_lus.append(question)
liste_index_questions.append(index)
trouve = True
break
if not trouve: # si le tag n'est pas trouvé dans la liste des Questions
for personnage in self.liste_personnages: # recherche du tag lu dans la liste des Personnages
if tag == personnage.tag:
liste_objects_lus.append(personnage)
liste_index_personnage.append(index)
trouve = True
break
if not trouve: # si le tag n'est pas trouvé dans la liste des Questions ni des Personnages
liste_objects_lus.append(None)
return liste_objects_lus, liste_index_personnage, liste_index_questions
def __validite_branche_recursif(self, index, validite):
"""
Verifie que chaque type d'object est placé correctement dans l'arbre
(aucune Question ou Personnage après un Personnage, que des Questions avant un Personnage, ...).
Cette fonction est recursive pour se déplacer à travers l'arbre.
:param index: [int] index de l'object en question.
:param validite: [dict(int, int)] dictionnaire contenant en clef l'indice d'un élément et
en valeur la validité de cet élément.
:return: [dict(int, int)] la validité d'une branche contenant en clef l'indice d'un élément et en valeur
la validité de cet élément.
"""
# Si l'élement est un personnage, on regarde si des éléments sont placés après lui sur la branche.
if index in self.liste_index_personnage:
# index d'un élément placé après sur la branche du personnage
index_suivant = (index + 1) * 2
# verifier que cet élément suivant fait bien partie de l'arbre
if index_suivant < len(self.liste_tags):
# tester si cet élément suivant est un personnage ou une question
if self.liste_objects_lus[index_suivant]:
validite[index_suivant] = 0
else:
validite[index_suivant] = -1
# tester que l'élément voisin à l'élément suivant soit un personnage ou une question
if self.liste_objects_lus[index_suivant - 1]:
validite[index_suivant - 1] = 0
else:
validite[index_suivant - 1] = -1
# pour tous les types d'éléments, on vérifie qu'il soit bien placé par rapport à l'élement qui est
# plus loin que lui sur la branche
index_precedent = math.floor((index + 1) / 2) - 1
if index_precedent in self.liste_index_questions:
validite[index_precedent] = 1
elif index_precedent in self.liste_index_personnage:
validite[index_precedent] = 0
else:
validite[index_precedent] = -1
# remonter la branche en direction du tronc tant qu'on voit des questions et que l'indice soit > 0.
if index_precedent != 0 and index_precedent in self.liste_index_questions:
validite = self.__validite_branche_recursif(index_precedent, validite)
return validite
def verification_personnages(self, index_personnage, validite_branche):
"""
Vérifier que les attributs d'un Personnage répondent bien aux Questions situées sur la branche de ce Personnage.
:param index_personnage: [int] index dans l'arbre du Personnage testé.
:param validite_branche: [dict(int, int)] la validité de la branche issue du Personnage contenant en clef
l'indice d'un élément et en valeur la validité de cet élément.
:return: [dict(int, int)] la validité de la branche issue du Personnage contenant en clef
l'indice d'un élément et en valeur la validité de cet élément (0 si le Personnage ne répond pas à la question
sinon 1) ou un dictionnaire vide si le paramètre validite_branche contient des 0.
[bool] true si le personnage répond à toutes les questions de sa branche, faux sinon.
"""
compte_faux = 0
verification_question_personnage = {}
personnage = self.liste_objects_lus[index_personnage]
# True si l'(index + 1) du personnage et impaire sinon False
impaire_precedent = bool((index_personnage + 1) % 2)
# itération sur tous les élements de la branche
for index in validite_branche:
# itérer seulement sur les éléments qui sont avant le personnage
if index < index_personnage:
# si l'élement de la branche ne doit dans tous les cas pas être placé ici,
# on retourne faux avec un dictionnaire vide
if validite_branche[index] == 0:
return {}, False
# récupérer le tag de la Question
tag_question = self.liste_objects_lus[index].tag
# quand l'élément observé avant est impaire et que la réponse à la Question actuelle est 1 ou que
# l'élément observé avant est paire et que la réponse à la Question actuelle est 0 alors,
# la réponse est fausse sinon elle est vraie.
if (personnage.dict_questions_reponse[tag_question] == 0 and not impaire_precedent)\
or (personnage.dict_questions_reponse[tag_question] == 1 and impaire_precedent):
compte_faux += 1
verification_question_personnage[index] = 0
else:
verification_question_personnage[index] = 1
impaire_precedent = bool((index + 1) % 2)
return verification_question_personnage, compte_faux == 0
def verification_globale(self):
"""
Vérifie la validitée totale de l'arbre en modifiant la valeur que doivent prendre les LEDs.
"""
# iterration à travers les personnages seulement
for index_personnage in self.liste_index_personnage:
validite = {}
# dictionnaire de validité des éléments de la branche accrochée au personnage
validite_branche = self.__validite_branche_recursif(index_personnage, validite)
# le Personnage correspond-t-il aux questions de la branche ?
verification_question_personnage, \
perso_correspond_questions = self.verification_personnages(index_personnage, validite_branche)
# si la branche allant au Personnage est complètement bonne
if perso_correspond_questions == True:
# LED accrochée au Personnage = 1
self.resultat_leds[index_personnage - 1] = 1
for index in validite_branche:
# LEDs accrochées à toutes les Questions allant au Personnage = 1
# sauf pour la Question avec l'index 0
if 0 < index < index_personnage:
self.resultat_leds[index - 1] = 1
# S'il y a des éléments après le personnage, alors les LEDs associées = 0
if index > index_personnage and validite_branche[index] != -1:
self.resultat_leds[index - 1] = 0
else:
# si la branche comporte des élements qui ne doivent pas être de ce type,
# LEDs de tous les éléments = 0 sauf pour l'élément qui a le plus petit index sur la branche.
if len(verification_question_personnage) == 0:
dernier_index_de_branche = list(validite_branche.keys())[-1]
self.resultat_leds[index_personnage - 1] = 0
for index in validite_branche:
if index != dernier_index_de_branche:
self.resultat_leds[index - 1] = 0
# si la branche comporte des élements qui sont du bon type mais qu'il y a des erreurs par rapport
# aux réponses aux Questions
else:
# la LED associée au Personnage = 0
self.resultat_leds[index_personnage - 1] = 0
for index in validite_branche:
# Questions allant au Personnage = 1 sauf pour la Question avec l'index 0
if 0 < index < index_personnage:
self.resultat_leds[index - 1] = 1
# S'il y a des éléments après le personnage, alors les LEDs associées = 0
if index > index_personnage and validite_branche[index] != -1:
self.resultat_leds[index - 1] = 0
# pour tous les index où les led == -1
for index_led in [i for i, j in enumerate(self.resultat_leds) if j == -1]:
# si l'objet à (index_led + 1) est une question
if isinstance(self.liste_objects_lus[index_led + 1], Question):
debut = len(self.liste_tags) - 2 ** (self.nb_etage - 1) # si 4 etages : 15 - 2^(4-1) = 15 - 8 = 7
fin = len(self.liste_tags) # si 4 étages : 15
# l'élément associé à la LED est sur la dernière ligne, LED = 0
if (index_led + 1) in range(debut, fin):
self.resultat_leds[index_led] = 0
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment