diff --git a/app/pe/pe_comp.py b/app/pe/pe_comp.py index 0b9000c9..bbdd2a54 100644 --- a/app/pe/pe_comp.py +++ b/app/pe/pe_comp.py @@ -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 - diff --git a/app/pe/pe_etudiant.py b/app/pe/pe_etudiant.py index 384765f3..126f112f 100644 --- a/app/pe/pe_etudiant.py +++ b/app/pe/pe_etudiant.py @@ -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,21 +83,18 @@ 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( " => %d étudiants trouvés dans les cosemestres" % len(self.etudiants_ids) ) - """Analyse des parcours étudiants pour déterminer leur année effective de diplome + """Analyse des parcours étudiants pour déterminer leur année effective de diplome avec prise en compte des redoublements, des abandons, ....""" pe_comp.pe_print("3) Analyse des parcours individuels des étudiants") @@ -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)}` @@ -198,10 +203,12 @@ class EtudiantsJuryPE: "etudid": etudid, # les infos sur l'étudiant "etat_civil": identite.etat_civil, # Ajout à la table jury "nom": identite.nom, - "entree": formsemestres[-1].date_debut.year, # La date d'entrée à l'IUT + "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. @@ -372,7 +378,7 @@ class EtudiantsJuryPE: """ nbres_semestres = [] for etudid in self.diplomes_ids: - nbres_semestres.append( self.cursus[etudid]["nb_semestres"] ) + nbres_semestres.append(self.cursus[etudid]["nb_semestres"]) return max(nbres_semestres) @@ -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 - - diff --git a/app/pe/pe_interclasstag.py b/app/pe/pe_interclasstag.py index 8fc4727b..b822ad37 100644 --- a/app/pe/pe_interclasstag.py +++ b/app/pe/pe_interclasstag.py @@ -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 - diff --git a/app/pe/pe_jury.py b/app/pe/pe_jury.py index 62129ebb..790b10f8 100644 --- a/app/pe/pe_jury.py +++ b/app/pe/pe_jury.py @@ -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) @@ -133,7 +134,7 @@ class JuryPE(object): filename, formsemestretag.str_tagtable(), path="details_semestres" ) - """Génère les trajectoires (combinaison de semestres suivis + """Génère les trajectoires (combinaison de semestres suivis par un étudiant pour atteindre le semestre final d'un aggrégat) """ pe_comp.pe_print( @@ -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,11 +280,11 @@ 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""" - df.sort_values(by=["Nom", "Prenom"], inplace = True) + # Tri par nom/prénom + df.sort_values(by=["Nom", "Prenom"], inplace=True) return df def df_tag(self, tag): @@ -348,11 +349,11 @@ 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""" - df.sort_values(by=["Nom", "Prenom"], inplace = True) + # Tri par nom/prénom + df.sort_values(by=["Nom", "Prenom"], inplace=True) return df def table_syntheseJury(self, mode="singlesheet"): # was str_syntheseJury @@ -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 diff --git a/app/pe/pe_view.py b/app/pe/pe_view.py index 5fcef5aa..86c76fe3 100644 --- a/app/pe/pe_view.py +++ b/app/pe/pe_view.py @@ -63,7 +63,7 @@ def _pe_view_sem_recap_form(formsemestre_id): target="_blank" rel="noopener noreferrer"> voir la documentation . - Cette fonction (en Scodoc9) n'est prévue que pour le BUT. + Cette fonction (en Scodoc9) n'est prévue que pour le BUT.
Rendez-vous donc sur un semestre de BUT.