0% ont trouvé ce document utile (0 vote)
6 vues25 pages

Gestionnaire de Notes Étudiantes en Python

Le document présente une application de gestion des notes d'étudiants, incluant des classes pour les départements, étudiants, matières, évaluations et notes. Il permet d'ajouter, modifier, supprimer et rechercher des étudiants et leurs notes, ainsi que de calculer des statistiques. L'interface graphique est construite avec Tkinter et inclut des fonctionnalités pour gérer les départements, matières et effectuer des recherches.

Transféré par

savadogoamiir
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats TXT, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
6 vues25 pages

Gestionnaire de Notes Étudiantes en Python

Le document présente une application de gestion des notes d'étudiants, incluant des classes pour les départements, étudiants, matières, évaluations et notes. Il permet d'ajouter, modifier, supprimer et rechercher des étudiants et leurs notes, ainsi que de calculer des statistiques. L'interface graphique est construite avec Tkinter et inclut des fonctionnalités pour gérer les départements, matières et effectuer des recherches.

Transféré par

savadogoamiir
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats TXT, PDF, TXT ou lisez en ligne sur Scribd

import tkinter as tk

from tkinter import ttk, messagebox


import datetime
from typing import List, Dict, Optional
import csv

# ==================== CLASSES DE BASE ====================


class Departement:
def __init__(self, code: str, nom: str):
[Link] = code
[Link] = nom
[Link] = []

def ajouter_etudiant(self, etudiant):


[Link](etudiant)

def __str__(self):
return f"{[Link]} ({[Link]})"

class Etudiant:
_compteur = 1000

def __init__(self, nom: str, prenom: str, niveau: str, departement:


Departement):
[Link] = nom
[Link] = prenom
[Link] = niveau
[Link] = departement
Etudiant._compteur += 1
[Link] = f"ETU{Etudiant._compteur}"
[Link] = []

departement.ajouter_etudiant(self)

def ajouter_note(self, note):


[Link](note)

def get_moyenne(self) -> float:


if not [Link]:
return 0.0

total_pondere = 0
total_coefficients = 0

for note in [Link]:


ponderation = [Link] * [Link] *
[Link]
total_pondere += ponderation
total_coefficients += [Link] *
[Link]

return total_pondere / total_coefficients if total_coefficients > 0 else


0.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]()

def _valider_valeur(self, valeur: float) -> float:


"""Validation des données saisies"""
if not isinstance(valeur, (int, float)):
raise ValueError("La note doit être un nombre")

if not (0 <= valeur <= 20):


raise ValueError("La note doit être entre 0 et 20")

return float(valeur)

def get_valeur_ponderee(self) -> float:


return [Link] * [Link] * [Link]

def __str__(self):
return f"{[Link]}/20"

# ==================== GESTIONNAIRE PRINCIPAL ====================


class GestionnaireNotes:
def __init__(self):
[Link]: Dict[str, Departement] = {}
[Link]: Dict[str, Etudiant] = {}
[Link]: Dict[str, Matiere] = {}
[Link]: List[Note] = []
[Link] = [
Evaluation("Contrôle", 0.4),
Evaluation("Travaux Pratiques", 0.3),
Evaluation("Examen", 0.6)
]

# ========== CRUD COMPLET ==========


def ajouter_departement(self, code: str, nom: str) -> bool:
if code in [Link]:
return False
[Link][code] = Departement(code, nom)
return True

def ajouter_etudiant(self, etudiant: Etudiant) -> bool:


if [Link] in [Link]:
return False
[Link][[Link]] = etudiant
return True

def ajouter_matiere(self, matiere: Matiere) -> bool:


if [Link] in [Link]:
return False
[Link][[Link]] = matiere
return True

def ajouter_note(self, note: Note) -> bool:


[Link](note)
[Link].ajouter_note(note)
return True

def modifier_etudiant(self, matricule: str, nom: str = None, prenom: str =


None,
niveau: str = None, departement_code: str = None) -> bool:
etudiant = [Link](matricule)
if not etudiant:
return False

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

def modifier_note(self, note_id: int, nouvelle_valeur: float) -> bool:


if 0 <= note_id < len([Link]):
try:
[Link][note_id].valeur =
[Link][note_id]._valider_valeur(nouvelle_valeur)
return True
except ValueError:
return False
return False

def supprimer_etudiant(self, matricule: str) -> bool:


etudiant = [Link](matricule)
if not etudiant:
return False

# Supprimer les notes de l'étudiant


[Link] = [n for n in [Link] if [Link] != matricule]

# Retirer du département
[Link](etudiant)

# Supprimer l'étudiant
del [Link][matricule]

return True

def supprimer_note(self, note_id: int) -> bool:


if 0 <= note_id < len([Link]):
note = [Link][note_id]
[Link](note)
del [Link][note_id]
return True
return False

# ========== RECHERCHES ==========


def rechercher_etudiants(self, **criteria) -> List[Etudiant]:
resultats = list([Link]())

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

def rechercher_notes_par_matiere(self, matiere_code: str) -> List[Note]:


return [n for n in [Link] if [Link] == matiere_code]

def rechercher_notes_par_departement(self, departement_code: str) ->


List[Note]:
notes_departement = []
for etudiant in [Link]():
if [Link] == departement_code:
notes_departement.extend([Link])
return notes_departement

def rechercher_groupe_etudiants(self, niveau: str = None, departement_code: str


= None) -> List[Etudiant]:
resultats = list([Link]())

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

# ========== CALCULS ET STATISTIQUES ==========


def calculer_moyenne_groupe(self, niveau: str = None, departement_code: str =
None) -> Dict:
etudiants = self.rechercher_groupe_etudiants(niveau, departement_code)

if not etudiants:
return {"moyenne": 0, "nombre": 0}

total_moyennes = 0
compteur = 0

for etudiant in etudiants:


moyenne = etudiant.get_moyenne()
if moyenne > 0: # Ne compter que les étudiants avec des notes
total_moyennes += moyenne
compteur += 1

moyenne_groupe = total_moyennes / compteur if compteur > 0 else 0

return {
"moyenne": moyenne_groupe,
"nombre_etudiants": len(etudiants),
"nombre_avec_notes": compteur
}

def get_statistiques_matiere(self, matiere_code: str) -> Dict:


notes_matiere = self.rechercher_notes_par_matiere(matiere_code)

if not notes_matiere:
return {"moyenne": 0, "nombre": 0, "max": 0, "min": 0}

valeurs = [[Link] for n in notes_matiere]

return {
"matiere": [Link][matiere_code].nom,
"moyenne": sum(valeurs) / len(valeurs),
"nombre_notes": len(valeurs),
"max": max(valeurs),
"min": min(valeurs)
}

def get_statistiques_departement(self, departement_code: str) -> Dict:


notes_departement = self.rechercher_notes_par_departement(departement_code)

if not notes_departement:
return {"moyenne": 0, "nombre": 0}

valeurs = [[Link] for n in notes_departement]

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")
]

for code, nom in departements:


[Link].ajouter_departement(code, nom)

# 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 code, nom, coeff in matieres:


[Link].ajouter_matiere(Matiere(code, nom, coeff))

# Créer quelques étudiants


niveaux = ["L1", "L2", "L3", "M1", "M2"]

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)

# Ajouter des notes de test


import random
for etudiant in [Link]():
for matiere in list([Link]())[:3]: # 3
matières par étudiant
eval_type = [Link]([Link])
note_valeur = [Link](8, 18)
note = Note(etudiant, matiere, eval_type, note_valeur)
[Link].ajouter_note(note)

def _creer_menu(self):
menubar = [Link]([Link])
[Link](menu=menubar)

menu_fichier = [Link](menubar, tearoff=0)


menubar.add_cascade(label="Fichier", menu=menu_fichier)
menu_fichier.add_command(label="Quitter", command=[Link])

menu_gestion = [Link](menubar, tearoff=0)


menubar.add_cascade(label="Gestion", menu=menu_gestion)
menu_gestion.add_command(label="Gérer les départements",
command=self._gerer_departements)
menu_gestion.add_command(label="Gérer les matières",
command=self._gerer_matieres)

def _creer_interface(self):
notebook = [Link]([Link])
[Link](fill=[Link], expand=True, padx=10, pady=10)

# Onglet 1: Gestion des étudiants


frame_etudiants = [Link](notebook)
[Link](frame_etudiants, text="Gestion Étudiants")
self._creer_onglet_etudiants(frame_etudiants)

# Onglet 2: Gestion des notes


frame_notes = [Link](notebook)
[Link](frame_notes, text="Gestion Notes")
self._creer_onglet_notes(frame_notes)

# 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)

def _creer_onglet_etudiants(self, parent):


"""Onglet de gestion des étudiants (CRUD complet)"""
# Frame d'ajout
frame_ajout = [Link](parent, text="Ajouter/Modifier un étudiant",
padding=10)
frame_ajout.pack(fill=tk.X, padx=5, pady=5)

# 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)

[Link](frame_ajout, text="Prénom:").grid(row=1, column=2, sticky=tk.W,


pady=3)
self.prenom_entry = [Link](frame_ajout, width=20)
self.prenom_entry.grid(row=1, column=3, padx=5, pady=3)

[Link](frame_ajout, text="Niveau:").grid(row=2, column=0, sticky=tk.W,


pady=3)
self.niveau_combo = [Link](frame_ajout, values=["L1", "L2", "L3",
"M1", "M2"], width=10)
self.niveau_combo.grid(row=2, column=1, padx=5, pady=3)

[Link](frame_ajout, text="Département:").grid(row=2, column=2,


sticky=tk.W, pady=3)
dept_values = list([Link]())
self.dept_combo = [Link](frame_ajout, values=dept_values, width=10)
self.dept_combo.grid(row=2, column=3, 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)

columns = ("Matricule", "Nom", "Prénom", "Niveau", "Département",


"Moyenne")
self.tree_etudiants = [Link](frame_liste, columns=columns,
show="headings", height=15)

for col in columns:


self.tree_etudiants.heading(col, text=col)
self.tree_etudiants.column(col, width=100)

scrollbar = [Link](frame_liste, orient=[Link],


command=self.tree_etudiants.yview)
self.tree_etudiants.configure(yscrollcommand=[Link])

self.tree_etudiants.pack(side=[Link], fill=[Link], expand=True)


[Link](side=[Link], fill=tk.Y)
self._actualiser_liste_etudiants()

# Double-clic pour modifier


self.tree_etudiants.bind('<Double-1>', self._selectionner_etudiant)

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

if not dept_code in [Link]:


[Link]("Erreur", "Département invalide")
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()

# Préparer les modifications


modifications = {}
if nom:
modifications['nom'] = nom
if prenom:
modifications['prenom'] = prenom
if niveau:
modifications['niveau'] = niveau
if dept_code and dept_code in [Link]:
modifications['departement_code'] = dept_code

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

if [Link]("Confirmation", f"Supprimer l'étudiant


{matricule} ?"):
if [Link].supprimer_etudiant(matricule):
[Link]("Succès", "Étudiant supprimé")
self._reinitialiser_formulaire()
self._actualiser_liste_etudiants()
else:
[Link]("Erreur", "Étudiant non trouvé")

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é")

def _selectionner_etudiant(self, event):


"""Sélectionne un étudiant depuis la liste"""
selection = self.tree_etudiants.selection()
if selection:
item = self.tree_etudiants.item(selection[0])
matricule = item['values'][0]

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)

for etudiant in [Link]():


moyenne = etudiant.get_moyenne()
self.tree_etudiants.insert("", [Link], values=(
[Link],
[Link],
[Link],
[Link],
[Link],
f"{moyenne:.2f}" if moyenne > 0 else "N/A"
))

def _creer_onglet_notes(self, parent):


"""Onglet de gestion des notes"""
# Frame d'ajout
frame_ajout = [Link](parent, text="Ajouter une note", padding=10)
frame_ajout.pack(fill=tk.X, padx=5, pady=5)

[Link](frame_ajout, text="Étudiant:").grid(row=0, column=0, sticky=tk.W,


pady=3)
self.note_etudiant_combo = [Link](frame_ajout, width=30)
self.note_etudiant_combo.grid(row=0, column=1, padx=5, pady=3)

[Link](frame_ajout, text="Matière:").grid(row=0, column=2, sticky=tk.W,


pady=3)
self.note_matiere_combo = [Link](frame_ajout, width=20)
self.note_matiere_combo.grid(row=0, column=3, padx=5, pady=3)

[Link](frame_ajout, text="Type évaluation:").grid(row=1, column=0,


sticky=tk.W, pady=3)
self.note_type_combo = [Link](frame_ajout, values=["Contrôle",
"Travaux Pratiques", "Examen"], width=15)
self.note_type_combo.grid(row=1, column=1, padx=5, pady=3)
[Link](frame_ajout, text="Note (0-20):").grid(row=1, column=2,
sticky=tk.W, pady=3)
self.note_valeur_entry = [Link](frame_ajout, width=10)
self.note_valeur_entry.grid(row=1, column=3, padx=5, pady=3)

[Link](frame_ajout, text="Ajouter la note",


command=self._ajouter_note).grid(row=2, column=0, columnspan=4,
pady=10)

# Frame liste des notes


frame_liste = [Link](parent, text="Liste des notes (clic pour
modifier/supprimer)", padding=10)
frame_liste.pack(fill=[Link], expand=True, padx=5, pady=5)

columns = ("ID", "Étudiant", "Matière", "Type", "Note", "Date")


self.tree_notes = [Link](frame_liste, columns=columns,
show="headings", height=12)

for col in columns:


self.tree_notes.heading(col, text=col)
self.tree_notes.column(col, width=100)

scrollbar = [Link](frame_liste, orient=[Link],


command=self.tree_notes.yview)
self.tree_notes.configure(yscrollcommand=[Link])

self.tree_notes.pack(side=[Link], fill=[Link], expand=True)


[Link](side=[Link], fill=tk.Y)

# Frame modification/suppression
frame_modif = [Link](frame_liste)
frame_modif.pack(fill=tk.X, pady=(10, 0))

[Link](frame_modif, text="Nouvelle note:").pack(side=[Link], padx=(0,


5))
self.modif_note_entry = [Link](frame_modif, width=10)
self.modif_note_entry.pack(side=[Link], padx=(0, 10))

[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

# Créer l'évaluation et la note


evaluation = Evaluation(type_eval, 1.0) # Coefficient par défaut
note = Note(etudiant, matiere, evaluation, note_valeur)

# 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])

if [Link]("Confirmation", "Supprimer cette note ?"):


if [Link].supprimer_note(note_id):
[Link]("Succès", "Note supprimée")
self._actualiser_listes_notes()
else:
[Link]("Erreur", "Erreur lors de la suppression")

def _selectionner_note(self, event):


"""Sélectionne une note"""
selection = self.tree_notes.selection()
if selection:
item = self.tree_notes.item(selection[0])
note_valeur = item['values'][4]
self.modif_note_entry.delete(0, [Link])
self.modif_note_entry.insert(0, note_valeur)

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])

matieres_liste = [[Link] for m in [Link]()]


self.note_matiere_combo['values'] = matieres_liste
if matieres_liste:
self.note_matiere_combo.set(matieres_liste[0])
if [Link]:
self.note_type_combo.set("Contrôle")

# Mettre à jour la liste des notes


for item in self.tree_notes.get_children():
self.tree_notes.delete(item)

for i, note in enumerate([Link]):


self.tree_notes.insert("", [Link], values=(
i,
str([Link]),
[Link],
[Link],
f"{[Link]:.2f}",
[Link]("%d/%m/%Y")
))

def _creer_onglet_recherche(self, parent):


"""Onglet de recherche"""
# Frame critères de recherche
frame_criteres = [Link](parent, text="Critères de recherche",
padding=10)
frame_criteres.pack(fill=tk.X, padx=10, pady=10)

[Link](frame_criteres, text="Nom étudiant:").grid(row=0, column=0,


sticky=tk.W, pady=5)
self.rech_nom_entry = [Link](frame_criteres, width=20)
self.rech_nom_entry.grid(row=0, column=1, padx=5, pady=5)

[Link](frame_criteres, text="Matricule:").grid(row=0, column=2,


sticky=tk.W, pady=5)
self.rech_matricule_entry = [Link](frame_criteres, width=15)
self.rech_matricule_entry.grid(row=0, column=3, padx=5, pady=5)

[Link](frame_criteres, text="Niveau:").grid(row=1, column=0,


sticky=tk.W, pady=5)
self.rech_niveau_combo = [Link](frame_criteres, values=["", "L1",
"L2", "L3", "M1", "M2"], width=8)
self.rech_niveau_combo.grid(row=1, column=1, padx=5, pady=5)

[Link](frame_criteres, text="Département:").grid(row=1, column=2,


sticky=tk.W, pady=5)
dept_values = [""] + list([Link]())
self.rech_dept_combo = [Link](frame_criteres, values=dept_values,
width=10)
self.rech_dept_combo.grid(row=1, column=3, padx=5, pady=5)

[Link](frame_criteres, text="Matière:").grid(row=2, column=0,


sticky=tk.W, pady=5)
mat_values = [""] + [[Link] for m in [Link]()]
self.rech_matiere_combo = [Link](frame_criteres, values=mat_values,
width=20)
self.rech_matiere_combo.grid(row=2, column=1, padx=5, pady=5)

[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))

columns = ("Matricule", "Nom", "Prénom", "Niveau", "Département",


"Matière", "Note", "Type")
self.tree_recherche = [Link](frame_resultats, columns=columns,
show="headings", height=15)

for col in columns:


self.tree_recherche.heading(col, text=col)
self.tree_recherche.column(col, width=100)

scrollbar = [Link](frame_resultats, orient=[Link],


command=self.tree_recherche.yview)
self.tree_recherche.configure(yscrollcommand=[Link])

self.tree_recherche.pack(side=[Link], fill=[Link], expand=True)


[Link](side=[Link], fill=tk.Y)

# 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

# Rechercher les étudiants


etudiants = [Link].rechercher_etudiants(**criteres)

# Filtrer par matière si spécifiée


matiere_nom = self.rech_matiere_combo.get()

# Afficher les résultats


for item in self.tree_recherche.get_children():
self.tree_recherche.delete(item)

for etudiant in etudiants:


if matiere_nom:
# Afficher seulement les notes de la matière spécifiée
for note in [Link]:
if [Link] == matiere_nom:
self.tree_recherche.insert("", [Link], values=(
[Link],
[Link],
[Link],
[Link],
[Link],
[Link],
f"{[Link]:.2f}",
[Link]
))
else:
# Afficher toutes les notes ou juste l'étudiant si pas de notes
if [Link]:
for note in [Link]:
self.tree_recherche.insert("", [Link], values=(
[Link],
[Link],
[Link],
[Link],
[Link],
[Link],
f"{[Link]:.2f}",
[Link]
))
else:
self.tree_recherche.insert("", [Link], values=(
[Link],
[Link],
[Link],
[Link],
[Link],
"Aucune",
"N/A",
"N/A"
))

# Mettre à jour l'information


count = len(self.tree_recherche.get_children())
self.rech_info_label.config(text=f"{count} résultat(s) trouvé(s)")

def _creer_onglet_statistiques(self, parent):


"""Onglet de statistiques"""
# Frame sélection
frame_selection = [Link](parent, text="Sélection des statistiques",
padding=10)
frame_selection.pack(fill=tk.X, padx=10, pady=10)

[Link](frame_selection, text="Type de statistiques:").pack(side=[Link],


padx=(0, 10))

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))

self.stat_text = [Link](frame_resultats, height=15, wrap=[Link])


scrollbar = [Link](frame_resultats, orient=[Link],
command=self.stat_text.yview)
self.stat_text.configure(yscrollcommand=[Link])

self.stat_text.pack(side=[Link], fill=[Link], expand=True)


[Link](side=[Link], fill=tk.Y)

self.stat_text.insert(1.0, "Sélectionnez un type de statistique et cliquez


sur 'Afficher'")
self.stat_text.config(state=[Link])

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)

[Link](self.frame_params, text="Département:").grid(row=0, column=2,


sticky=tk.W, pady=5)
dept_values = [""] + list([Link]())
self.stat_dept_combo = [Link](self.frame_params,
values=dept_values, width=10)
self.stat_dept_combo.grid(row=0, column=3, padx=5, pady=5)

elif stat_type == "matiere":


[Link](self.frame_params, text="Matière:").grid(row=0, column=0,
sticky=tk.W, pady=5)
mat_values = [[Link] for m in [Link]()]
self.stat_matiere_combo = [Link](self.frame_params,
values=mat_values, width=20)
self.stat_matiere_combo.grid(row=0, column=1, padx=5, pady=5)
if mat_values:
self.stat_matiere_combo.set(mat_values[0])

elif stat_type == "departement":


[Link](self.frame_params, text="Département:").grid(row=0, column=0,
sticky=tk.W, pady=5)
dept_values = list([Link]())
self.stat_departement_combo = [Link](self.frame_params,
values=dept_values, width=15)
self.stat_departement_combo.grid(row=0, column=1, padx=5, pady=5)
if dept_values:
self.stat_departement_combo.set(dept_values[0])

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
)

titre = "Statistiques pour "


if niveau and dept_code:
titre += f"le niveau {niveau} du département {dept_code}"
elif niveau:
titre += f"le niveau {niveau} (tous départements)"
elif dept_code:
titre += f"le département {dept_code} (tous niveaux)"
else:
titre += "tous les étudiants"

self.stat_text.insert(1.0, f"=== {[Link]()} ===\n\n")


self.stat_text.insert([Link], f"Moyenne du groupe:
{stats['moyenne']:.2f}/20\n")
self.stat_text.insert([Link], f"Nombre total d'étudiants:
{stats['nombre_etudiants']}\n")
self.stat_text.insert([Link], f"Nombre d'étudiants avec notes:
{stats['nombre_avec_notes']}\n")

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")

elif stat_type == "matiere":


matiere_nom = self.stat_matiere_combo.get() if hasattr(self,
'stat_matiere_combo') else ""

if not matiere_nom:
self.stat_text.insert(1.0, "Veuillez sélectionner une matière")
self.stat_text.config(state=[Link])
return

# Trouver le code de la matière


matiere_code = None
for code, mat in [Link]():
if [Link] == matiere_nom:
matiere_code = code
break

if matiere_code:
stats = [Link].get_statistiques_matiere(matiere_code)

self.stat_text.insert(1.0, f"=== STATISTIQUES POUR


{matiere_nom.upper()} ===\n\n")
self.stat_text.insert([Link], f"Moyenne: {stats['moyenne']:.2f}/20\
n")
self.stat_text.insert([Link], f"Nombre de notes:
{stats['nombre_notes']}\n")
self.stat_text.insert([Link], f"Note maximale:
{stats['max']:.2f}/20\n")
self.stat_text.insert([Link], f"Note minimale:
{stats['min']:.2f}/20\n")

# Analyse
if stats['moyenne'] >= 14:
appreciation = "Excellent"
elif stats['moyenne'] >= 12:
appreciation = "Bon"
elif stats['moyenne'] >= 10:
appreciation = "Passable"
else:
appreciation = "Insuffisant"

self.stat_text.insert([Link], f"\nAppréciation: {appreciation}\n")


else:
self.stat_text.insert(1.0, "Matière non trouvée")

elif stat_type == "departement":


dept_code = self.stat_departement_combo.get() if hasattr(self,
'stat_departement_combo') else ""

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)

self.stat_text.insert(1.0, f"=== STATISTIQUES POUR


{stats['departement'].upper()} ===\n\n")
self.stat_text.insert([Link], f"Moyenne générale:
{stats['moyenne']:.2f}/20\n")
self.stat_text.insert([Link], f"Nombre total de notes:
{stats['nombre_notes']}\n")
self.stat_text.insert([Link], f"Nombre d'étudiants:
{stats['nombre_etudiants']}\n")

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)

[Link](frame_ajout, text="Code:").grid(row=0, column=0, sticky=tk.W,


pady=5)
code_entry = [Link](frame_ajout, width=15)
code_entry.grid(row=0, column=1, padx=5, pady=5)

[Link](frame_ajout, text="Nom:").grid(row=0, column=2, sticky=tk.W,


pady=5)
nom_entry = [Link](frame_ajout, width=25)
nom_entry.grid(row=0, column=3, padx=5, pady=5)

def ajouter():
code = code_entry.get().strip().upper()
nom = nom_entry.get().strip()

if not code or not nom:


[Link]("Champs manquants", "Veuillez remplir le
code et le nom")
return

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))

tree = [Link](frame_liste, columns=("Code", "Nom", "Étudiants"),


show="headings", height=10)
[Link]("Code", text="Code")
[Link]("Nom", text="Nom")
[Link]("Étudiants", text="Étudiants")

[Link]("Code", width=80)
[Link]("Nom", width=200)
[Link]("Étudiants", width=80)

scrollbar = [Link](frame_liste, orient=[Link],


command=[Link])
[Link](yscrollcommand=[Link])

[Link](side=[Link], fill=[Link], expand=True)


[Link](side=[Link], fill=tk.Y)

def actualiser_liste():
for item in tree.get_children():
[Link](item)

for dept in [Link]():


[Link]("", [Link], values=(
[Link],
[Link],
len([Link])
))

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)

[Link](frame_ajout, text="Code:").grid(row=0, column=0, sticky=tk.W,


pady=5)
code_entry = [Link](frame_ajout, width=15)
code_entry.grid(row=0, column=1, padx=5, pady=5)

[Link](frame_ajout, text="Nom:").grid(row=0, column=2, sticky=tk.W,


pady=5)
nom_entry = [Link](frame_ajout, width=25)
nom_entry.grid(row=0, column=3, padx=5, pady=5)
[Link](frame_ajout, text="Coefficient:").grid(row=1, column=0,
sticky=tk.W, pady=5)
coeff_entry = [Link](frame_ajout, width=10)
coeff_entry.insert(0, "1.0")
coeff_entry.grid(row=1, column=1, padx=5, pady=5)

def ajouter():
code = code_entry.get().strip().upper()
nom = nom_entry.get().strip()
coeff_str = coeff_entry.get().strip()

if not all([code, nom, coeff_str]):


[Link]("Champs manquants", "Veuillez remplir tous
les champs")
return

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

matiere = Matiere(code, nom, coefficient)

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à")

[Link](frame_ajout, text="Ajouter", command=ajouter).grid(row=2,


column=0, columnspan=4, pady=10)

# 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))

tree = [Link](frame_liste, columns=("Code", "Nom", "Coefficient",


"Notes"), show="headings", height=10)
[Link]("Code", text="Code")
[Link]("Nom", text="Nom")
[Link]("Coefficient", text="Coefficient")
[Link]("Notes", text="Notes")

for col in ("Code", "Nom", "Coefficient", "Notes"):


[Link](col, width=100)

scrollbar = [Link](frame_liste, orient=[Link],


command=[Link])
[Link](yscrollcommand=[Link])
[Link](side=[Link], fill=[Link], expand=True)
[Link](side=[Link], fill=tk.Y)

def actualiser_liste():
for item in tree.get_children():
[Link](item)

# Compter les notes par matière


notes_par_matiere = {}
for note in [Link]:
code = [Link]
notes_par_matiere[code] = notes_par_matiere.get(code, 0) + 1

for matiere in [Link]():


nb_notes = notes_par_matiere.get([Link], 0)
[Link]("", [Link], values=(
[Link],
[Link],
[Link],
nb_notes
))

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

# ==================== LANCEMENT DE L'APPLICATION ====================


def main():
root = [Link]()
app = ApplicationGestionNotes(root)
[Link]()

if __name__ == "__main__":
main()

Vous aimerez peut-être aussi