160 lines
5.8 KiB
Python
160 lines
5.8 KiB
Python
|
|
import csv
|
||
|
|
import time
|
||
|
|
|
||
|
|
# ── Chargement des données ────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
def charger_table(nom_fichier):
|
||
|
|
table = []
|
||
|
|
with open(nom_fichier, 'r', newline="", encoding="utf-8") as csvfile:
|
||
|
|
eleve_reader = csv.reader(csvfile, delimiter=";")
|
||
|
|
eleve_reader.__next__()
|
||
|
|
for eleve in eleve_reader:
|
||
|
|
table.append({
|
||
|
|
"nom": eleve[0],
|
||
|
|
"courage": int(eleve[1]),
|
||
|
|
"loyauté": int(eleve[2]),
|
||
|
|
"sagesse": int(eleve[3]),
|
||
|
|
"malice": int(eleve[4]),
|
||
|
|
"maison": eleve[5].strip()
|
||
|
|
})
|
||
|
|
return table
|
||
|
|
|
||
|
|
# ── Algorithme KNN ────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
def distance(eleve1, eleve2):
|
||
|
|
return (abs(eleve1["courage"] - eleve2["courage"]) +
|
||
|
|
abs(eleve1["loyauté"] - eleve2["loyauté"]) +
|
||
|
|
abs(eleve1["sagesse"] - eleve2["sagesse"]) +
|
||
|
|
abs(eleve1["malice"] - eleve2["malice"]))
|
||
|
|
|
||
|
|
def sept_voisins(table, nouveau):
|
||
|
|
distances = [(distance(eleve, nouveau), eleve) for eleve in table]
|
||
|
|
distances.sort(key=lambda x: x[0])
|
||
|
|
return [eleve for d, eleve in distances[:7]]
|
||
|
|
|
||
|
|
def maison_majoritaire(voisins):
|
||
|
|
frequences = {}
|
||
|
|
for eleve in voisins:
|
||
|
|
maison = eleve["maison"]
|
||
|
|
frequences[maison] = frequences.get(maison, 0) + 1
|
||
|
|
return max(frequences, key=frequences.get), frequences
|
||
|
|
|
||
|
|
# ── Affichage ─────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
MAISONS = {
|
||
|
|
"Gryffondor": {
|
||
|
|
"traits": "Courage, chevalerie et determination",
|
||
|
|
"message": "Tu es du genre a te jeter dans la bataille sans trop reflechir.\nPoudlard a besoin de toi sur le terrain de Quidditch !"
|
||
|
|
},
|
||
|
|
"Serpentard": {
|
||
|
|
"traits": "Malice, ambition et ressource",
|
||
|
|
"message": "Tu sais ce que tu veux, et tu sais comment l'obtenir.\nMefie-toi quand meme de Lord Voldemort dans les couloirs."
|
||
|
|
},
|
||
|
|
"Serdaigle": {
|
||
|
|
"traits": "Sagesse, creativite et esprit",
|
||
|
|
"message": "Tu preferes comprendre avant d'agir. La bibliotheque\nde Poudlard va devenir ton deuxieme chez-toi."
|
||
|
|
},
|
||
|
|
"Poufsouffle": {
|
||
|
|
"traits": "Loyaute, patience et equite",
|
||
|
|
"message": "On peut compter sur toi. Toujours. Sans exception.\nCedric Diggory etait de Poufsouffle — ca dit tout."
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
def afficher_banniere(maison):
|
||
|
|
largeur = 42
|
||
|
|
print()
|
||
|
|
print("=" * largeur)
|
||
|
|
print("|" + " " * (largeur - 2) + "|")
|
||
|
|
ligne = f" Le Choixpeau a decide : {maison.upper()}"
|
||
|
|
print("|" + ligne.ljust(largeur - 2) + "|")
|
||
|
|
print("|" + " " * (largeur - 2) + "|")
|
||
|
|
infos = MAISONS.get(maison, {})
|
||
|
|
traits = f" {infos.get('traits', '')}"
|
||
|
|
print("|" + traits.ljust(largeur - 2) + "|")
|
||
|
|
print("|" + " " * (largeur - 2) + "|")
|
||
|
|
print("=" * largeur)
|
||
|
|
print()
|
||
|
|
print(infos.get("message", ""))
|
||
|
|
print()
|
||
|
|
|
||
|
|
def afficher_voisins(voisins, moi):
|
||
|
|
print("-" * 42)
|
||
|
|
print(" Les 7 eleves de Poudlard qui te ressemblent le plus :")
|
||
|
|
print()
|
||
|
|
for v in voisins:
|
||
|
|
d = distance(v, moi)
|
||
|
|
print(f" {v['nom']:<12} ({v['maison']:<12}) distance : {d}")
|
||
|
|
print("-" * 42)
|
||
|
|
print()
|
||
|
|
|
||
|
|
# ── Saisie avec validation ────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
QUESTIONS = [
|
||
|
|
("courage", "Face au danger, tu fonces sans hesiter "),
|
||
|
|
("loyauté", "Tu es fidele a tes amis, quoi qu'il arrive "),
|
||
|
|
("sagesse", "Tu reflechis avant d'agir, tu observes, tu analyses "),
|
||
|
|
("malice", "Tu sais trouver des strategies pour arriver a tes fins"),
|
||
|
|
]
|
||
|
|
|
||
|
|
def poser_question(trait, description):
|
||
|
|
while True:
|
||
|
|
try:
|
||
|
|
rep = input(f" {description} (1 a 10) : ").strip()
|
||
|
|
valeur = int(rep)
|
||
|
|
if 1 <= valeur <= 10:
|
||
|
|
return valeur
|
||
|
|
print(" --> Donne une valeur entre 1 et 10.")
|
||
|
|
except ValueError:
|
||
|
|
print(" --> Entre un nombre entier.")
|
||
|
|
|
||
|
|
# ── Programme principal ───────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
def main():
|
||
|
|
print()
|
||
|
|
print("=" * 42)
|
||
|
|
print("| |")
|
||
|
|
print("| CHOIXPEAU MAGIQUE -- KNN |")
|
||
|
|
print("| |")
|
||
|
|
print("=" * 42)
|
||
|
|
print()
|
||
|
|
|
||
|
|
try:
|
||
|
|
poudlard = charger_table("choixpeauMagique.csv")
|
||
|
|
except FileNotFoundError:
|
||
|
|
print("Erreur : le fichier 'choixpeauMagique.csv' est introuvable.")
|
||
|
|
print("Place-le dans le meme dossier que ce script.")
|
||
|
|
return
|
||
|
|
|
||
|
|
prenom = input("Quel est ton prenom ? ").strip()
|
||
|
|
if not prenom:
|
||
|
|
prenom = "Mystere"
|
||
|
|
|
||
|
|
print()
|
||
|
|
print(f"Bien, {prenom}. Reponds honnêtement à ces quatre questions.")
|
||
|
|
print("Note-toi de 1 (pas du tout) à 10 (totalement).")
|
||
|
|
print()
|
||
|
|
|
||
|
|
eleve = {"nom": prenom}
|
||
|
|
for trait, description in QUESTIONS:
|
||
|
|
eleve[trait] = poser_question(trait, description)
|
||
|
|
|
||
|
|
print()
|
||
|
|
print("Le Choixpeau murmure quelque chose...")
|
||
|
|
time.sleep(1)
|
||
|
|
print("Il se tait.")
|
||
|
|
time.sleep(1)
|
||
|
|
print("Puis il crie :")
|
||
|
|
time.sleep(0.8)
|
||
|
|
|
||
|
|
voisins = sept_voisins(poudlard, eleve)
|
||
|
|
maison, frequences = maison_majoritaire(voisins)
|
||
|
|
|
||
|
|
afficher_banniere(maison)
|
||
|
|
time.sleep(0.5)
|
||
|
|
afficher_voisins(voisins, eleve)
|
||
|
|
|
||
|
|
print(f" Repartition du vote : {frequences}")
|
||
|
|
print()
|
||
|
|
|
||
|
|
main()
|