Gestionnaire de Notes Étudiantes en Python
Gestionnaire de Notes Étudiantes en Python
def __str__(self):
return f"{[Link]} ({[Link]})"
class Etudiant:
_compteur = 1000
departement.ajouter_etudiant(self)
total_pondere = 0
total_coefficients = 0
def __str__(self):
return f"{[Link]} {[Link]} ({[Link]})"
class Matiere:
def __init__(self, code: str, nom: str, coefficient: float = 1.0):
[Link] = code
[Link] = nom
[Link] = coefficient
def __str__(self):
return f"{[Link]} (coeff: {[Link]})"
class Evaluation:
def __init__(self, type_eval: str, coefficient: float = 1.0):
[Link] = type_eval
[Link] = coefficient
def __str__(self):
return f"{[Link]} (coeff: {[Link]})"
class Note:
def __init__(self, etudiant: Etudiant, matiere: Matiere, evaluation:
Evaluation, valeur: float):
[Link] = etudiant
[Link] = matiere
[Link] = evaluation
[Link] = self._valider_valeur(valeur)
[Link] = [Link]()
return float(valeur)
def __str__(self):
return f"{[Link]}/20"
if nom:
[Link] = nom
if prenom:
[Link] = prenom
if niveau:
[Link] = niveau
if departement_code:
nouveau_dept = [Link](departement_code)
if nouveau_dept:
# Retirer de l'ancien département
[Link](etudiant)
# Ajouter au nouveau
[Link] = nouveau_dept
nouveau_dept.[Link](etudiant)
return True
# Retirer du département
[Link](etudiant)
# Supprimer l'étudiant
del [Link][matricule]
return True
if 'nom' in criteria:
resultats = [e for e in resultats if criteria['nom'].lower() in
[Link]()]
if 'matricule' in criteria:
resultats = [e for e in resultats if criteria['matricule'] in
[Link]]
if 'niveau' in criteria:
resultats = [e for e in resultats if [Link] == criteria['niveau']]
if 'departement' in criteria:
resultats = [e for e in resultats if [Link] ==
criteria['departement']]
return resultats
if niveau:
resultats = [e for e in resultats if [Link] == niveau]
if departement_code:
resultats = [e for e in resultats if [Link] ==
departement_code]
return resultats
if not etudiants:
return {"moyenne": 0, "nombre": 0}
total_moyennes = 0
compteur = 0
return {
"moyenne": moyenne_groupe,
"nombre_etudiants": len(etudiants),
"nombre_avec_notes": compteur
}
if not notes_matiere:
return {"moyenne": 0, "nombre": 0, "max": 0, "min": 0}
return {
"matiere": [Link][matiere_code].nom,
"moyenne": sum(valeurs) / len(valeurs),
"nombre_notes": len(valeurs),
"max": max(valeurs),
"min": min(valeurs)
}
if not notes_departement:
return {"moyenne": 0, "nombre": 0}
return {
"departement": [Link][departement_code].nom,
"moyenne": sum(valeurs) / len(valeurs),
"nombre_notes": len(valeurs),
"nombre_etudiants": len([Link][departement_code].etudiants)
}
# ==================== INTERFACE GRAPHIQUE ====================
class ApplicationGestionNotes:
def __init__(self, root):
[Link] = root
[Link]("Gestion des Notes - IFOAD")
[Link]("1100x700")
[Link] = GestionnaireNotes()
self._initialiser_donnees_test()
self._creer_menu()
self._creer_interface()
def _initialiser_donnees_test(self):
"""Initialise des données de test"""
# Créer départements
departements = [
("INFO", "Informatique"),
("MAT", "Mathématiques"),
("PHY", "Physique"),
("CHI", "Chimie")
]
# Créer matières
matieres = [
("PYT101", "Programmation Python", 2.0),
("MAT101", "Algèbre Linéaire", 1.5),
("PHY101", "Mécanique", 2.0),
("BDD101", "Bases de Données", 2.5),
("WEB101", "Développement Web", 1.5)
]
for i in range(10):
niveau = niveaux[i % len(niveaux)]
dept_code = list([Link]())[i %
len([Link])]
departement = [Link][dept_code]
etudiant = Etudiant(
f"Nom{i}",
f"Prénom{i}",
niveau,
departement
)
[Link].ajouter_etudiant(etudiant)
def _creer_menu(self):
menubar = [Link]([Link])
[Link](menu=menubar)
def _creer_interface(self):
notebook = [Link]([Link])
[Link](fill=[Link], expand=True, padx=10, pady=10)
# Onglet 3: Recherche
frame_recherche = [Link](notebook)
[Link](frame_recherche, text="Recherche")
self._creer_onglet_recherche(frame_recherche)
# Onglet 4: Statistiques
frame_stats = [Link](notebook)
[Link](frame_stats, text="Statistiques")
self._creer_onglet_statistiques(frame_stats)
# Formulaire
[Link](frame_ajout, text="Matricule (modification):").grid(row=0,
column=0, sticky=tk.W, pady=3)
self.modif_matricule_entry = [Link](frame_ajout, width=15)
self.modif_matricule_entry.grid(row=0, column=1, padx=5, pady=3)
[Link](frame_ajout, text="Nom:").grid(row=1, column=0, sticky=tk.W,
pady=3)
self.nom_entry = [Link](frame_ajout, width=20)
self.nom_entry.grid(row=1, column=1, padx=5, pady=3)
# Boutons CRUD
btn_frame = [Link](frame_ajout)
btn_frame.grid(row=3, column=0, columnspan=4, pady=10)
[Link](btn_frame, text="Ajouter",
command=self._ajouter_etudiant, width=12).pack(side=[Link],
padx=5)
[Link](btn_frame, text="Modifier",
command=self._modifier_etudiant, width=12).pack(side=[Link],
padx=5)
[Link](btn_frame, text="Supprimer",
command=self._supprimer_etudiant, width=12).pack(side=[Link],
padx=5)
[Link](btn_frame, text="Rechercher",
command=self._rechercher_etudiant_modif,
width=12).pack(side=[Link], padx=5)
# Frame liste
frame_liste = [Link](parent, text="Liste des étudiants",
padding=10)
frame_liste.pack(fill=[Link], expand=True, padx=5, pady=5)
def _ajouter_etudiant(self):
"""Ajoute un nouvel étudiant"""
try:
nom = self.nom_entry.get().strip()
prenom = self.prenom_entry.get().strip()
niveau = self.niveau_combo.get()
dept_code = self.dept_combo.get()
# Validation
if not all([nom, prenom, niveau, dept_code]):
[Link]("Champs manquants", "Veuillez remplir tous
les champs")
return
departement = [Link][dept_code]
etudiant = Etudiant(nom, prenom, niveau, departement)
if [Link].ajouter_etudiant(etudiant):
[Link]("Succès", f"Étudiant ajouté:
{[Link]}")
self._reinitialiser_formulaire()
self._actualiser_liste_etudiants()
else:
[Link]("Erreur", "Erreur lors de l'ajout")
except Exception as e:
[Link]("Erreur", str(e))
def _modifier_etudiant(self):
"""Modifie un étudiant existant"""
try:
matricule = self.modif_matricule_entry.get().strip()
if not matricule:
[Link]("Matricule manquant", "Entrez un matricule
pour modifier")
return
nom = self.nom_entry.get().strip()
prenom = self.prenom_entry.get().strip()
niveau = self.niveau_combo.get()
dept_code = self.dept_combo.get()
if not modifications:
[Link]("Aucune modification", "Aucun champ à
modifier")
return
if [Link].modifier_etudiant(matricule, **modifications):
[Link]("Succès", f"Étudiant {matricule} modifié")
self._reinitialiser_formulaire()
self._actualiser_liste_etudiants()
else:
[Link]("Erreur", "Étudiant non trouvé")
except Exception as e:
[Link]("Erreur", str(e))
def _supprimer_etudiant(self):
"""Supprime un étudiant"""
matricule = self.modif_matricule_entry.get().strip()
if not matricule:
[Link]("Matricule manquant", "Entrez un matricule")
return
def _rechercher_etudiant_modif(self):
"""Recherche un étudiant pour modification"""
matricule = self.modif_matricule_entry.get().strip()
if not matricule:
[Link]("Matricule manquant", "Entrez un matricule")
return
etudiant = [Link](matricule)
if etudiant:
self.nom_entry.delete(0, [Link])
self.nom_entry.insert(0, [Link])
self.prenom_entry.delete(0, [Link])
self.prenom_entry.insert(0, [Link])
self.niveau_combo.set([Link])
self.dept_combo.set([Link])
[Link]("Trouvé", f"Étudiant {[Link]}
{[Link]} chargé")
else:
[Link]("Non trouvé", "Étudiant non trouvé")
etudiant = [Link](matricule)
if etudiant:
self.modif_matricule_entry.delete(0, [Link])
self.modif_matricule_entry.insert(0, [Link])
self.nom_entry.delete(0, [Link])
self.nom_entry.insert(0, [Link])
self.prenom_entry.delete(0, [Link])
self.prenom_entry.insert(0, [Link])
self.niveau_combo.set([Link])
self.dept_combo.set([Link])
def _reinitialiser_formulaire(self):
"""Réinitialise le formulaire"""
self.modif_matricule_entry.delete(0, [Link])
self.nom_entry.delete(0, [Link])
self.prenom_entry.delete(0, [Link])
self.niveau_combo.set('')
self.dept_combo.set('')
def _actualiser_liste_etudiants(self):
"""Met à jour la liste des étudiants"""
for item in self.tree_etudiants.get_children():
self.tree_etudiants.delete(item)
# Frame modification/suppression
frame_modif = [Link](frame_liste)
frame_modif.pack(fill=tk.X, pady=(10, 0))
[Link](frame_modif, text="Modifier",
command=self._modifier_note_selectionnee).pack(side=[Link],
padx=(0, 5))
[Link](frame_modif, text="Supprimer",
command=self._supprimer_note_selectionnee).pack(side=[Link])
self._actualiser_listes_notes()
self.tree_notes.bind('<<TreeviewSelect>>', self._selectionner_note)
def _ajouter_note(self):
"""Ajoute une nouvelle note"""
try:
# Récupération des données
etudiant_str = self.note_etudiant_combo.get()
matiere_nom = self.note_matiere_combo.get()
type_eval = self.note_type_combo.get()
note_str = self.note_valeur_entry.get().strip()
# Validation
if not all([etudiant_str, matiere_nom, type_eval, note_str]):
[Link]("Champs manquants", "Veuillez remplir tous
les champs")
return
# Trouver l'étudiant
etudiant = None
for e in [Link]():
if str(e) == etudiant_str:
etudiant = e
break
if not etudiant:
[Link]("Erreur", "Étudiant non trouvé")
return
# Trouver la matière
matiere = None
for m in [Link]():
if [Link] == matiere_nom:
matiere = m
break
if not matiere:
[Link]("Erreur", "Matière non trouvée")
return
# Validation de la note
try:
note_valeur = float(note_str)
if not (0 <= note_valeur <= 20):
raise ValueError("La note doit être entre 0 et 20")
except ValueError as e:
[Link]("Erreur de validation", str(e))
return
# Ajouter la note
if [Link].ajouter_note(note):
[Link]("Succès", "Note ajoutée")
self.note_valeur_entry.delete(0, [Link])
self._actualiser_listes_notes()
else:
[Link]("Erreur", "Erreur lors de l'ajout")
except Exception as e:
[Link]("Erreur", f"Erreur inattendue: {str(e)}")
def _modifier_note_selectionnee(self):
"""Modifie la note sélectionnée"""
selection = self.tree_notes.selection()
if not selection:
[Link]("Aucune sélection", "Sélectionnez une note")
return
item = self.tree_notes.item(selection[0])
note_id = int(item['values'][0])
nouvelle_note_str = self.modif_note_entry.get().strip()
if not nouvelle_note_str:
[Link]("Note manquante", "Entrez une nouvelle note")
return
try:
nouvelle_note = float(nouvelle_note_str)
if not (0 <= nouvelle_note <= 20):
raise ValueError("La note doit être entre 0 et 20")
if [Link].modifier_note(note_id, nouvelle_note):
[Link]("Succès", "Note modifiée")
self.modif_note_entry.delete(0, [Link])
self._actualiser_listes_notes()
else:
[Link]("Erreur", "Erreur lors de la modification")
except ValueError as e:
[Link]("Erreur de validation", str(e))
def _supprimer_note_selectionnee(self):
"""Supprime la note sélectionnée"""
selection = self.tree_notes.selection()
if not selection:
[Link]("Aucune sélection", "Sélectionnez une note")
return
item = self.tree_notes.item(selection[0])
note_id = int(item['values'][0])
def _actualiser_listes_notes(self):
"""Met à jour les listes pour les notes"""
# Mettre à jour les combobox
etudiants_liste = [str(e) for e in [Link]()]
self.note_etudiant_combo['values'] = etudiants_liste
if etudiants_liste:
self.note_etudiant_combo.set(etudiants_liste[0])
[Link](frame_criteres, text="Rechercher",
command=self._effectuer_recherche, width=15).grid(row=2,
column=2, columnspan=2, pady=10)
# Frame résultats
frame_resultats = [Link](parent, text="Résultats de la recherche",
padding=10)
frame_resultats.pack(fill=[Link], expand=True, padx=10, pady=(0, 10))
# Informations
self.rech_info_label = [Link](frame_resultats, text="Utilisez les
critères pour effectuer une recherche")
self.rech_info_label.pack(side=[Link], fill=tk.X, pady=(5, 0))
def _effectuer_recherche(self):
"""Effectue une recherche selon les critères"""
# Préparer les critères
criteres = {}
nom = self.rech_nom_entry.get().strip()
if nom:
criteres['nom'] = nom
matricule = self.rech_matricule_entry.get().strip()
if matricule:
criteres['matricule'] = matricule
niveau = self.rech_niveau_combo.get()
if niveau:
criteres['niveau'] = niveau
departement = self.rech_dept_combo.get()
if departement:
criteres['departement'] = departement
self.stat_type_var = [Link](value="groupe")
[Link](frame_selection, text="Par groupe",
variable=self.stat_type_var,
value="groupe").pack(side=[Link], padx=5)
[Link](frame_selection, text="Par matière",
variable=self.stat_type_var,
value="matiere").pack(side=[Link], padx=5)
[Link](frame_selection, text="Par département",
variable=self.stat_type_var,
value="departement").pack(side=[Link], padx=5)
[Link](frame_selection, text="Afficher",
command=self._afficher_statistiques).pack(side=[Link], padx=(20,
0))
# Frame paramètres
self.frame_params = [Link](parent, text="Paramètres", padding=10)
self.frame_params.pack(fill=tk.X, padx=10, pady=(0, 10))
self._creer_widgets_params()
# Frame résultats
frame_resultats = [Link](parent, text="Résultats statistiques",
padding=10)
frame_resultats.pack(fill=[Link], expand=True, padx=10, pady=(0, 10))
def _creer_widgets_params(self):
"""Crée les widgets de paramètres selon le type"""
# Nettoyer le frame
for widget in self.frame_params.winfo_children():
[Link]()
stat_type = self.stat_type_var.get()
if stat_type == "groupe":
[Link](self.frame_params, text="Niveau:").grid(row=0, column=0,
sticky=tk.W, pady=5)
self.stat_niveau_combo = [Link](self.frame_params, values=["",
"L1", "L2", "L3", "M1", "M2"], width=8)
self.stat_niveau_combo.grid(row=0, column=1, padx=5, pady=5)
def _afficher_statistiques(self):
"""Affiche les statistiques selon la sélection"""
self.stat_text.config(state=[Link])
self.stat_text.delete(1.0, [Link])
stat_type = self.stat_type_var.get()
if stat_type == "groupe":
niveau = self.stat_niveau_combo.get() if hasattr(self,
'stat_niveau_combo') else ""
dept_code = self.stat_dept_combo.get() if hasattr(self,
'stat_dept_combo') else ""
stats = [Link].calculer_moyenne_groupe(
niveau if niveau else None,
dept_code if dept_code else None
)
if stats['nombre_avec_notes'] > 0:
pourcentage = (stats['nombre_avec_notes'] /
stats['nombre_etudiants']) * 100
self.stat_text.insert([Link], f"Pourcentage avec notes:
{pourcentage:.1f}%\n")
# Ajouter la mention
if stats['moyenne'] >= 10:
self.stat_text.insert([Link], "\n✅ Le groupe est en moyenne admis\
n")
else:
self.stat_text.insert([Link], "\n❌ Le groupe est en moyenne non
admis\n")
if not matiere_nom:
self.stat_text.insert(1.0, "Veuillez sélectionner une matière")
self.stat_text.config(state=[Link])
return
if matiere_code:
stats = [Link].get_statistiques_matiere(matiere_code)
# Analyse
if stats['moyenne'] >= 14:
appreciation = "Excellent"
elif stats['moyenne'] >= 12:
appreciation = "Bon"
elif stats['moyenne'] >= 10:
appreciation = "Passable"
else:
appreciation = "Insuffisant"
if not dept_code:
self.stat_text.insert(1.0, "Veuillez sélectionner un département")
self.stat_text.config(state=[Link])
return
stats = [Link].get_statistiques_departement(dept_code)
if stats['nombre_etudiants'] > 0:
notes_par_etudiant = stats['nombre_notes'] /
stats['nombre_etudiants']
self.stat_text.insert([Link], f"Moyenne de notes par étudiant:
{notes_par_etudiant:.1f}\n")
self.stat_text.config(state=[Link])
def _gerer_departements(self):
"""Fenêtre de gestion des départements"""
fenetre = [Link]([Link])
[Link]("Gestion des départements")
[Link]("500x400")
# Frame ajout
frame_ajout = [Link](fenetre, text="Ajouter un département",
padding=10)
frame_ajout.pack(fill=tk.X, padx=10, pady=10)
def ajouter():
code = code_entry.get().strip().upper()
nom = nom_entry.get().strip()
if [Link].ajouter_departement(code, nom):
[Link]("Succès", f"Département {nom} ajouté")
code_entry.delete(0, [Link])
nom_entry.delete(0, [Link])
self._actualiser_listes_departements()
actualiser_liste()
else:
[Link]("Erreur", "Ce code de département existe
déjà")
[Link](frame_ajout, text="Ajouter", command=ajouter).grid(row=1,
column=0, columnspan=4, pady=10)
# Frame liste
frame_liste = [Link](fenetre, text="Liste des départements",
padding=10)
frame_liste.pack(fill=[Link], expand=True, padx=10, pady=(0, 10))
[Link]("Code", width=80)
[Link]("Nom", width=200)
[Link]("Étudiants", width=80)
def actualiser_liste():
for item in tree.get_children():
[Link](item)
actualiser_liste()
def _gerer_matieres(self):
"""Fenêtre de gestion des matières"""
fenetre = [Link]([Link])
[Link]("Gestion des matières")
[Link]("600x400")
# Frame ajout
frame_ajout = [Link](fenetre, text="Ajouter une matière",
padding=10)
frame_ajout.pack(fill=tk.X, padx=10, pady=10)
def ajouter():
code = code_entry.get().strip().upper()
nom = nom_entry.get().strip()
coeff_str = coeff_entry.get().strip()
try:
coefficient = float(coeff_str)
if coefficient <= 0:
raise ValueError("Le coefficient doit être positif")
except ValueError as e:
[Link]("Erreur", f"Coefficient invalide: {e}")
return
if [Link].ajouter_matiere(matiere):
[Link]("Succès", f"Matière {nom} ajoutée")
code_entry.delete(0, [Link])
nom_entry.delete(0, [Link])
coeff_entry.delete(0, [Link])
coeff_entry.insert(0, "1.0")
self._actualiser_listes_matieres()
actualiser_liste()
else:
[Link]("Erreur", "Ce code de matière existe déjà")
# Frame liste
frame_liste = [Link](fenetre, text="Liste des matières",
padding=10)
frame_liste.pack(fill=[Link], expand=True, padx=10, pady=(0, 10))
def actualiser_liste():
for item in tree.get_children():
[Link](item)
actualiser_liste()
def _actualiser_listes_departements(self):
"""Met à jour les listes qui dépendent des départements"""
dept_values = list([Link]())
# Onglet étudiants
if hasattr(self, 'dept_combo'):
self.dept_combo['values'] = dept_values
# Onglet recherche
if hasattr(self, 'rech_dept_combo'):
self.rech_dept_combo['values'] = [""] + dept_values
# Onglet statistiques
if hasattr(self, 'stat_dept_combo'):
self.stat_dept_combo['values'] = [""] + dept_values
if hasattr(self, 'stat_departement_combo'):
self.stat_departement_combo['values'] = dept_values
def _actualiser_listes_matieres(self):
"""Met à jour les listes qui dépendent des matières"""
matieres_liste = [[Link] for m in [Link]()]
# Onglet notes
if hasattr(self, 'note_matiere_combo'):
self.note_matiere_combo['values'] = matieres_liste
# Onglet recherche
if hasattr(self, 'rech_matiere_combo'):
self.rech_matiere_combo['values'] = [""] + matieres_liste
# Onglet statistiques
if hasattr(self, 'stat_matiere_combo'):
self.stat_matiere_combo['values'] = matieres_liste
if __name__ == "__main__":
main()