PE: qq modifs de forme (type hints, comments)

This commit is contained in:
Emmanuel Viennet 2024-01-25 21:54:22 +01:00
parent 4f10d017be
commit d991eb007c
5 changed files with 60 additions and 68 deletions

View File

@ -170,6 +170,7 @@ TOUS_LES_SEMESTRES = PARCOURS[AGGREGAT_DIPLOMANT]["aggregat"]
TOUS_LES_AGGREGATS = [cle for cle in PARCOURS.keys() if not cle.startswith("S")]
TOUS_LES_PARCOURS = list(PARCOURS.keys())
# ----------------------------------------------------------------------------------------
def calcul_age(born: datetime.date) -> int:
"""Calcule l'age connaissant la date de naissance ``born``. (L'age est calculé
@ -185,11 +186,7 @@ def calcul_age(born: datetime.date) -> int:
return None
today = datetime.date.today()
return (
today.year
- born.year
- ((today.month, today.day) < (born.month, born.day))
)
return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
def remove_accents(input_unicode_str):
@ -286,7 +283,9 @@ def add_pe_stuff_to_zip(zipfile, ziproot):
# ----------------------------------------------------------------------------------------
def get_annee_diplome_semestre(sem_base, nbre_sem_formation=6) -> int:
def get_annee_diplome_semestre(
sem_base: FormSemestre | dict, nbre_sem_formation: int = 6
) -> int:
"""Pour un semestre ``sem_base`` donné (supposé être un semestre d'une formation BUT à 6 semestres)
et connaissant le numéro du semestre, ses dates de début et de fin du semestre, prédit l'année à laquelle
sera remis le diplôme BUT des étudiants qui y sont scolarisés
@ -339,7 +338,9 @@ def get_annee_diplome_semestre(sem_base, nbre_sem_formation=6) -> int:
return annee_fin + nbreAnRestant + increment
def get_cosemestres_diplomants(annee_diplome: int, formation_id: int) -> list:
def get_cosemestres_diplomants(
annee_diplome: int, formation_id: int
) -> dict[int, FormSemestre]:
"""Ensemble des cosemestres donnant lieu à diplomation à l'``annee_diplome``
et s'intégrant à la formation donnée par son ``formation_id``.
@ -381,4 +382,3 @@ def get_cosemestres_diplomants(annee_diplome: int, formation_id: int) -> list:
cosemestres[fid] = cosem
return cosemestres

View File

@ -66,11 +66,15 @@ class EtudiantsJuryPE:
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
self.etudiants_ids = {}
"""Les étudiants inscrits dans les co-semestres (ceux du jury mais aussi d'autres ayant été réorientés ou ayant abandonnés)"""
self.cosemestres: dict[int, FormSemestre] = None
"Les cosemestres donnant lieu à même année de diplome"
def find_etudiants(self, formation_id: int):
"""Liste des étudiants à prendre en compte dans le jury PE, en les recherchant
de manière automatique par rapport à leur année de diplomation ``annee_diplome``
dans la formation ``formation_id``.
dans la formation ``formation_id``. XXX TODO voir si on garde formation_id qui n'est pas utilisé ici
Les données obtenues sont stockées dans les attributs de EtudiantsJuryPE.
@ -79,14 +83,11 @@ class EtudiantsJuryPE:
*Remarque* : ex: JuryPE.get_etudiants_in_jury()
"""
"Les cosemestres donnant lieu à même année de diplome"
cosemestres = pe_comp.get_cosemestres_diplomants(self.annee_diplome, None)
self.cosemestres = cosemestres
pe_comp.pe_print(
"1) Recherche des coSemestres -> %d trouvés" % len(cosemestres)
)
"""Les étudiants inscrits dans les co-semestres (ceux du jury mais aussi d'autres ayant été réorientés ou ayant abandonnés)"""
pe_comp.pe_print(f"1) Recherche des coSemestres -> {len(cosemestres)} trouvés")
pe_comp.pe_print("2) Liste des étudiants dans les différents co-semestres")
self.etudiants_ids = get_etudiants_dans_semestres(cosemestres)
pe_comp.pe_print(
@ -142,9 +143,13 @@ class EtudiantsJuryPE:
+ ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)])
)
# Les abandons :
self.abandons = sorted([self.cursus[etudid]['nom']
for etudid in self.cursus if etudid not in self.diplomes_ids])
self.abandons = sorted(
[
self.cursus[etudid]["nom"]
for etudid in self.cursus
if etudid not in self.diplomes_ids
]
)
def get_etudiants_diplomes(self) -> dict[int, Identite]:
"""Identités des étudiants (sous forme d'un dictionnaire `{etudid: Identite(etudid)}`
@ -201,7 +206,9 @@ class EtudiantsJuryPE:
"entree": formsemestres[-1].date_debut.year, # La date d'entrée à l'IUT
"diplome": annee_diplome(identite), # Le date prévisionnelle de son diplôme
"formsemestres": semestres_etudiant, # les semestres de l'étudiant
"nb_semestres": len(semestres_etudiant), # le nombre de semestres de l'étudiant
"nb_semestres": len(
semestres_etudiant
), # le nombre de semestres de l'étudiant
"abandon": False, # va être traité en dessous
}
@ -250,7 +257,6 @@ class EtudiantsJuryPE:
} # les semestres de n°i de l'étudiant
self.cursus[etudid][nom_sem] = semestres_i
def get_trajectoire(self, etudid: int, formsemestre_final: FormSemestre):
"""Ensemble des semestres parcourus par
un étudiant pour l'amener à un semestre terminal.
@ -417,10 +423,7 @@ def annee_diplome(identite: Identite) -> int:
formsemestres = identite.get_formsemestres()
if formsemestres:
return max(
[
pe_comp.get_annee_diplome_semestre(sem_base)
for sem_base in formsemestres
]
[pe_comp.get_annee_diplome_semestre(sem_base) for sem_base in formsemestres]
)
else:
return None
@ -502,8 +505,6 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b
return False
def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]) -> FormSemestre:
"""Renvoie le dernier semestre en **date de fin** d'un dictionnaire
de semestres (potentiellement non trié) de la forme ``{fid: FormSemestre(fid)}``.
@ -523,5 +524,3 @@ def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]) -> FormSeme
return dernier_semestre
else:
return None

View File

@ -1,4 +1,3 @@
from app.pe.pe_tabletags import TableTag
from app.pe.pe_etudiant import EtudiantsJuryPE
from app.pe.pe_trajectoire import Trajectoire, TrajectoiresJuryPE
@ -27,16 +26,14 @@ class AggregatInterclasseTag(TableTag):
trajectoires_jury_pe: TrajectoiresJuryPE,
trajectoires_taggues: dict[tuple, TrajectoireTag],
):
""""""
"""Table nommée au nom de l'aggrégat (par ex: 3S"""
# Table nommée au nom de l'aggrégat (par ex: 3S)
TableTag.__init__(self, nom_aggregat)
"""Les étudiants diplômés et leurs trajectoires (cf. trajectoires.suivis)"""
"""Les étudiants diplômés et leurs trajectoires (cf. trajectoires.suivis)""" # TODO
self.diplomes_ids = etudiants.etudiants_diplomes
self.etudiants_diplomes = {etudid for etudid in self.diplomes_ids}
"""Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
"""
# Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
self.trajectoires: dict[int, Trajectoire] = {}
for trajectoire_id in trajectoires_jury_pe.trajectoires:
trajectoire = trajectoires_jury_pe.trajectoires[trajectoire_id]
@ -49,8 +46,8 @@ class AggregatInterclasseTag(TableTag):
trajectoire_id
]
"""Les trajectoires suivies par les étudiants du jury, en ne gardant que
celles associées aux diplomés"""
# Les trajectoires suivies par les étudiants du jury, en ne gardant que
# celles associées aux diplomés
self.suivi: dict[int, Trajectoire] = {}
for etudid in self.diplomes_ids:
self.suivi[etudid] = trajectoires_jury_pe.suivi[etudid][nom_aggregat]
@ -58,10 +55,10 @@ class AggregatInterclasseTag(TableTag):
"""Les tags"""
self.tags_sorted = self.do_taglist()
"""Construit la matrice de notes"""
# Construit la matrice de notes
self.notes = self.compute_notes_matrice()
"""Synthétise les moyennes/classements par tag"""
# Synthétise les moyennes/classements par tag
self.moyennes_tags = {}
for tag in self.tags_sorted:
moy_gen_tag = self.notes[tag]
@ -79,7 +76,6 @@ class AggregatInterclasseTag(TableTag):
"""Une représentation textuelle"""
return f"Aggrégat {self.nom}"
def do_taglist(self):
"""Synthétise les tags à partir des trajectoires_tagguées
@ -87,39 +83,35 @@ class AggregatInterclasseTag(TableTag):
Une liste de tags triés par ordre alphabétique
"""
tags = []
for trajectoire_id in self.trajectoires_taggues:
trajectoire = self.trajectoires_taggues[trajectoire_id]
for trajectoire in self.trajectoires_taggues.values():
tags.extend(trajectoire.tags_sorted)
return sorted(set(tags))
def compute_notes_matrice(self):
"""Construit la matrice de notes (etudid x tags)
retraçant les moyennes obtenues par les étudiants dans les semestres associés à
l'aggrégat (une trajectoire ayant pour numéro de semestre final, celui de l'aggrégat).
"""
nb_tags = len(self.tags_sorted)
nb_etudiants = len(self.diplomes_ids)
# nb_tags = len(self.tags_sorted) unused ?
# nb_etudiants = len(self.diplomes_ids)
"""Index de la matrice (etudids -> dim 0, tags -> dim 1)"""
# Index de la matrice (etudids -> dim 0, tags -> dim 1)
etudids = list(self.diplomes_ids)
tags = self.tags_sorted
"""Partant d'un dataframe vierge"""
# Partant d'un dataframe vierge
df = pd.DataFrame(np.nan, index=etudids, columns=tags)
for trajectoire_id in self.trajectoires_taggues:
"""Charge les moyennes par tag de la trajectoire tagguée"""
notes = self.trajectoires_taggues[trajectoire_id].notes
for notes in self.trajectoires_taggues.values():
# Charge les moyennes par tag de la trajectoire tagguée
"""Etudiants/Tags communs entre la trajectoire_tagguée et les données interclassées"""
# Etudiants/Tags communs entre la trajectoire_tagguée et les données interclassées
etudids_communs = df.index.intersection(notes.index)
tags_communs = df.columns.intersection(notes.columns)
"""Injecte les notes par tag"""
# Injecte les notes par tag
df.loc[etudids_communs, tags_communs] = notes.loc[
etudids_communs, tags_communs
]
return df

View File

@ -107,13 +107,14 @@ class JuryPE(object):
self.formation_id = formation_id
"Un zip où ranger les fichiers générés"
self.nom_export_zip = "Jury_PE_%s" % self.diplome
self.nom_export_zip = f"Jury_PE_{self.diplome}"
self.zipdata = io.BytesIO()
self.zipfile = ZipFile(self.zipdata, "w")
"""Chargement des étudiants à prendre en compte dans le jury"""
pe_comp.pe_print(
f"*** Recherche et chargement des étudiants diplômés en {self.diplome} pour la formation {self.formation_id}"
f"""*** Recherche et chargement des étudiants diplômés en {
self.diplome} pour la formation {self.formation_id}"""
)
self.etudiants = EtudiantsJuryPE(self.diplome) # Les infos sur les étudiants
self.etudiants.find_etudiants(self.formation_id)
@ -197,7 +198,7 @@ class JuryPE(object):
open(filename, "rb").read(),
)
"""Fin !!!! Tada :)"""
# Fin !!!! Tada :)
def add_file_to_zip(self, filename: str, data, path=""):
"""Add a file to our zip
@ -256,7 +257,7 @@ class JuryPE(object):
etudids = list(self.diplomes_ids)
"""Récupération des données des étudiants"""
# Récupération des données des étudiants
administratif = {}
nbre_semestres_max = self.etudiants.nbre_etapes_max_diplomes()
@ -279,10 +280,10 @@ class JuryPE(object):
etapes = pe_affichage.etapes_du_cursus(formsemestres, nbre_semestres_max)
administratif[etudid] |= etapes
"""Construction du dataframe"""
# Construction du dataframe
df = pd.DataFrame.from_dict(administratif, orient="index")
"""Tri par nom/prénom"""
# Tri par nom/prénom
df.sort_values(by=["Nom", "Prenom"], inplace=True)
return df
@ -348,10 +349,10 @@ class JuryPE(object):
}
# Fin de l'aggrégat
"""Construction du dataFrame"""
# Construction du dataFrame
df = pd.DataFrame.from_dict(donnees, orient="index")
"""Tri par nom/prénom"""
# Tri par nom/prénom
df.sort_values(by=["Nom", "Prenom"], inplace=True)
return df
@ -400,10 +401,10 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
pe_comp.pe_print(f" --> Semestre taggué {nom} sur la base de {formsemestre}")
"""Créé le semestre_tag et exécute les calculs de moyennes"""
# Crée le semestre_tag et exécute les calculs de moyennes
formsemestretag = SemestreTag(nom, frmsem_id)
"""Stocke le semestre taggué"""
# Stocke le semestre taggué
semestres_tags[frmsem_id] = formsemestretag
return semestres_tags