diff --git a/app/pe/pe_jury.py b/app/pe/pe_jury.py index 030e3ea73..7bfbf8ec9 100644 --- a/app/pe/pe_jury.py +++ b/app/pe/pe_jury.py @@ -108,8 +108,8 @@ class JuryPE(object): self._gen_trajectoires() self._gen_semXs() self._gen_xls_sxtags(zipfile) - # self._gen_rcsemxs() - # self._gen_xls_rcrcss_tags(zipfile) + self._gen_rcsemxs() + self._gen_xls_rcstags(zipfile) # self._gen_xls_interclassements_rcss(zipfile) # self._gen_xls_synthese_jury_par_tag(zipfile) # self._gen_xls_synthese_par_etudiant(zipfile) @@ -255,7 +255,7 @@ class JuryPE(object): self.rcss_jury.cree_rcsemxs(self.etudiants) self.rcss_jury._aff_rcsemxs_suivis(self.etudiants) - def _gen_xls_rcrcss_tags(self, zipfile: ZipFile): + def _gen_xls_rcstags(self, zipfile: ZipFile): """Génère les RCS taggués traduisant les moyennes (orientées compétences) de regroupements de semestre de type Sx, xA ou xS. @@ -278,8 +278,8 @@ class JuryPE(object): pe_affichage.pe_print("*** Calcule les moyennes des RC de RCFS") self.rcss_tags = {} - for rcs_id, rcrcf in self.rcss_jury.rcsemxs.items(): - self.rcss_tags[rcs_id] = RCSTag(rcrcf, self.sxtags) + for rcs_id, rcsemx in self.rcss_jury.rcsemxs.items(): + self.rcss_tags[rcs_id] = RCSTag(rcsemx, self.sxtags) # Intègre le bilan des trajectoires tagguées au zip final output = io.BytesIO() diff --git a/app/pe/pe_rcss_jury.py b/app/pe/pe_rcss_jury.py index 65e423b03..6b0fe5f62 100644 --- a/app/pe/pe_rcss_jury.py +++ b/app/pe/pe_rcss_jury.py @@ -142,22 +142,25 @@ class RCSsJuryPE: analysés (trajectoires traduisant son parcours dans les différents semestres) + les mémorise dans les données de l'étudiant """ - self.rcsemxs_suivis = {nom_rcs: None for nom_rcs in pe_rcs.TOUS_LES_RCS} + self.rcsemxs_suivis = {} self.rcsemxs = {} # Pour tous les étudiants du jury for etudid in self.trajectoires_suivies: - self.rcsemxs_suivis[etudid] = {} + self.rcsemxs_suivis[etudid] = { + nom_rcs: None for nom_rcs in pe_rcs.TOUS_LES_RCS_AVEC_PLUSIEURS_SEM + } - # Recopie des SemX & des suivis associés - for nom_rcs in pe_rcs.TOUS_LES_SEMESTRES: - trajectoire = self.semXs_suivis[etudid][nom_rcs] - if trajectoire: - self.rcsemxs[trajectoire.rcs_id] = trajectoire - self.rcsemxs_suivis[etudid][nom_rcs] = trajectoire + # Recopie des SemX & des suivis associés => est-ce utile ? + # for nom_rcs in pe_rcs.TOUS_LES_SEMESTRES: + # trajectoire = self.semXs_suivis[etudid][nom_rcs] + # if trajectoire: + # self.rcsemxs[trajectoire.rcs_id] = trajectoire + # self.rcsemxs_suivis[etudid][nom_rcs] = trajectoire # Pour chaque aggréggat de type xA ou Sx - for nom_rcs in pe_rcs.TOUS_LES_RCS_AVEC_PLUSIEURS_SEM: + tous_les_agregats = pe_rcs.TOUS_LES_RCS + for nom_rcs in tous_les_agregats: trajectoire = self.trajectoires_suivies[etudid][nom_rcs] if not trajectoire: self.rcsemxs_suivis[etudid][nom_rcs] = None @@ -179,16 +182,20 @@ class RCSsJuryPE: semxs_a_aggreger = {} for Sx in noms_sems_aggregat: semestres_etudiants = etudiants.cursus[etudid][Sx] - - semx_id = get_semx_from_semestres_aggreges( - self.semXs, semestres_etudiants - ) - if not semx_id: - raise ( - "Il manque un SemX pour créer les RCSemX dans cree_rcsemxs" + if not semestres_etudiants: + pe_affichage.pe_print( + f"-> ⚠ Pas de semestres {Sx} pour {etudiants.identites[etudid].etat_civil}" ) - # Les SemX à ajouter au RCSemX - semxs_a_aggreger[semx_id] = self.semXs[semx_id] + else: + semx_id = get_semx_from_semestres_aggreges( + self.semXs, semestres_etudiants + ) + if not semx_id: + raise ( + "Il manque un SemX pour créer les RCSemX dans cree_rcsemxs" + ) + # Les SemX à ajouter au RCSemX + semxs_a_aggreger[semx_id] = self.semXs[semx_id] # Ajout des SemX à ceux à aggréger dans le RCSemX rcsemx = self.rcsemxs[tid] @@ -200,15 +207,16 @@ class RCSsJuryPE: def _aff_rcsemxs_suivis(self, etudiants): """Affiche les RCSemX suivis par les étudiants""" # Affichage pour debug - jeunes = list(enumerate(self.rcsemxs_suivis)) + jeunes = list(enumerate(self.rcsemxs_suivis.keys())) vides = [] - for no_etud, etudid in jeunes[:20]: - pe_affichage.pe_print(f"-> {etudiants.identites[etudid].nomprenom} :") - for nom_rcs, rcs in self.rcsemxs_suivis[etudid].items(): - if rcs: - pe_affichage.pe_print(f" > RCSemX {nom_rcs}: {rcs.get_repr()}") - else: - vides += [f"{nom_rcs}"] + for no_etud, etudid in jeunes: + if etudid not in etudiants.abandons_ids: + pe_affichage.pe_print(f"-> {etudiants.identites[etudid].nomprenom} :") + for nom_rcs, rcs in self.rcsemxs_suivis[etudid].items(): + if rcs: + pe_affichage.pe_print(f" > RCSemX {nom_rcs}: {rcs.get_repr()}") + else: + vides += [f"{nom_rcs}"] pe_affichage.pe_print(f"-> ⚠ RCSemX vides : {', '.join(list(set(vides)))}") diff --git a/app/pe/pe_rcstag.py b/app/pe/pe_rcstag.py index d675483f4..f8f6b9dc7 100644 --- a/app/pe/pe_rcstag.py +++ b/app/pe/pe_rcstag.py @@ -41,8 +41,7 @@ from app.models import FormSemestre from app.pe import pe_affichage import pandas as pd import numpy as np -import app.pe.rcss.pe_rcs as pe_rcs -import app.pe.rcss.pe_rcsemx as pe_rcrcf +from app.pe.rcss import pe_rcs, pe_rcsemx import app.pe.pe_sxtag as pe_sxtag import app.pe.pe_comp as pe_comp from app.pe.pe_tabletags import TableTag @@ -50,7 +49,9 @@ from app.pe.pe_moytag import MoyennesTag class RCSTag(TableTag): - def __init__(self, rcrcf: pe_rcs.RCS, sxstags: dict[(str, int) : pe_sxtag.SxTag]): + def __init__( + self, rcsemx: pe_rcsemx.RCSemX, sxstags: dict[(str, int) : pe_sxtag.SxTag] + ): """Calcule les moyennes par tag (orientées compétences) d'un regroupement de SxTag (RCRCF), pour extraire les classements par tag pour un @@ -58,42 +59,43 @@ class RCSTag(TableTag): participé au même semestre terminal. Args: - rcs: Un RCS (identifié par un nom et l'id de son semestre terminal) - sxstags: Les données sur les RCF taggués + rcsemx: Le RCSemX (identifié par un nom et l'id de son semestre terminal) + sxstags: Les données sur les SemX taggués """ TableTag.__init__(self) - self.rcs_id: tuple(str, int) = rcrcf.rcs_id - """Identifiant du RCS taggué (identique au RCS sur lequel il s'appuie)""" + self.rcs_id: tuple(str, int) = rcsemx.rcs_id + """Identifiant du RCSTag (identique au RCSemX sur lequel il s'appuie)""" - self.rcrcf: pe_rcrcf.RCSemX = rcrcf - """RCRCF associé au RCS taggué""" + self.rcsemx: pe_rcsemx.RCSemX = rcsemx + """RCSemX associé au RCSTag""" self.nom = self.get_repr() - """Représentation textuelle du RCS taggué""" + """Représentation textuelle du RSCtag""" # Les données du semestre final - self.formsemestre_terminal: FormSemestre = rcrcf.formsemestre_final + self.formsemestre_final: FormSemestre = rcsemx.formsemestre_final """Le semestre final""" - self.fid_final: int = rcrcf.formsemestre_final.formsemestre_id + self.fid_final: int = rcsemx.formsemestre_final.formsemestre_id """Le fid du semestre final""" # Affichage pour debug pe_affichage.pe_print(f"-> {self.get_repr(verbose=True)}") # Les données aggrégés (RCRCF + SxTags - self.rcsemxs_aggreges = rcrcf.rcsemxs_aggreges - """Les RCFs aggrégés""" + self.semXs_aggreges: dict[(str, int) : pe_rcsemx.RCSemX] = rcsemx.semXs_aggreges + """Les SemX aggrégés""" self.sxstags = {} - """Les SxTag associés aux RCF aggrégés""" + """Les SxTag associés aux SemX aggrégés""" try: - for rcf_id in self.rcsemxs_aggreges: + for rcf_id in self.semXs_aggreges: self.sxstags[rcf_id] = sxstags[rcf_id] except: raise ValueError("Semestres SxTag manquants") # Les étudiants (etuds, états civils & etudis) - sxtag_final = self.sxstags[self.rcs_id] + sems_dans_aggregat = pe_rcs.TYPES_RCS[self.rcs_id[0]]["aggregat"] + sxtag_final = self.sxstags[(sems_dans_aggregat[-1], self.rcs_id[1])] self.etuds = sxtag_final.etuds """Les étudiants (extraits du semestre final)""" self.add_etuds(self.etuds) @@ -106,7 +108,10 @@ class RCSTag(TableTag): pe_affichage.pe_print( f"* Association UEs -> compétences : {self.acronymes_ues_to_competences}" ) - self.competences_sorted = sorted(self.acronymes_ues_to_competences.values()) + self.competences_sorted = sorted( + set(self.acronymes_ues_to_competences.values()) + ) + """Compétences (triées par nom, extraites des SxTag aggrégés)""" pe_affichage.pe_print(f"* Compétences : {', '.join(self.competences_sorted)}") @@ -119,6 +124,7 @@ class RCSTag(TableTag): self.moyennes_tags: dict[str, MoyennesTag] = {} """Synthétise les moyennes/classements par tag (qu'ils soient personnalisé ou de compétences)""" for tag in self.tags_sorted: + print(tag) # Cube de notes (etudids_sorted x compétences_sorted x sxstags) notes_df, notes_cube = self.compute_notes_comps_cube( tag, self.etudids_sorted, self.competences_sorted, self.sxstags @@ -153,7 +159,7 @@ class RCSTag(TableTag): """Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle est basée)""" if verbose: - return self.rcrcf.get_repr(verbose=verbose) + return self.rcsemx.get_repr(verbose=verbose) else: return f"{self.__class__.__name__} ({self.rcs_id})" @@ -182,26 +188,29 @@ class RCSTag(TableTag): np.nan, index=etudids_sorted, columns=competences_sorted ) # Charge les notes du semestre tag (copie car changement de nom de colonnes à venir) - moys_tag = sxtag.moyennes_tags[tag] - notes = moys_tag.matrice_notes.copy() # avec une copie + if tag in sxtag.moyennes_tags: # si le tag est présent dans le semestre + moys_tag = sxtag.moyennes_tags[tag] - # Traduction des acronymes d'UE en compétences - acronymes_ues_columns = notes.columns - acronymes_to_comps = [ - self.acronymes_ues_to_competences[acro] - for acro in acronymes_ues_columns - ] - notes.columns = acronymes_to_comps + notes = moys_tag.matrice_notes.copy() # avec une copie - # Les étudiants et les compétences communes - etudids_communs, comp_communes = pe_comp.find_index_and_columns_communs( - notes_df, notes - ) + # Traduction des acronymes d'UE en compétences + acronymes_ues_columns = notes.columns + acronymes_to_comps = [ + self.acronymes_ues_to_competences[acro] + for acro in acronymes_ues_columns + ] + notes.columns = acronymes_to_comps - # Recopie des notes et des coeffs - notes_df.loc[etudids_communs, comp_communes] = notes.loc[ - etudids_communs, comp_communes - ] + # Les étudiants et les compétences communes + ( + etudids_communs, + comp_communes, + ) = pe_comp.find_index_and_columns_communs(notes_df, notes) + + # Recopie des notes et des coeffs + notes_df.loc[etudids_communs, comp_communes] = notes.loc[ + etudids_communs, comp_communes + ] # Supprime tout ce qui n'est pas numérique # for col in notes_df.columns: @@ -242,29 +251,29 @@ class RCSTag(TableTag): coeffs_df = pd.DataFrame( np.nan, index=etudids_sorted, columns=competences_sorted ) + if tag in sxtag.moyennes_tags: + moys_tag = sxtag.moyennes_tags[tag] - moys_tag = sxtag.moyennes_tags[tag] + # Charge les notes et les coeffs du semestre tag + coeffs = moys_tag.matrice_coeffs_moy_gen.copy() # les coeffs - # Charge les notes et les coeffs du semestre tag - coeffs = moys_tag.matrice_coeffs_moy_gen.copy() # les coeffs + # Traduction des acronymes d'UE en compétences + acronymes_ues_columns = coeffs.columns + acronymes_to_comps = [ + self.acronymes_ues_to_competences[acro] + for acro in acronymes_ues_columns + ] + coeffs.columns = acronymes_to_comps - # Traduction des acronymes d'UE en compétences - acronymes_ues_columns = coeffs.columns - acronymes_to_comps = [ - self.acronymes_ues_to_competences[acro] - for acro in acronymes_ues_columns - ] - coeffs.columns = acronymes_to_comps + # Les étudiants et les compétences communes + etudids_communs, comp_communes = pe_comp.find_index_and_columns_communs( + coeffs_df, coeffs + ) - # Les étudiants et les compétences communes - etudids_communs, comp_communes = pe_comp.find_index_and_columns_communs( - coeffs_df, coeffs - ) - - # Recopie des notes et des coeffs - coeffs_df.loc[etudids_communs, comp_communes] = coeffs.loc[ - etudids_communs, comp_communes - ] + # Recopie des notes et des coeffs + coeffs_df.loc[etudids_communs, comp_communes] = coeffs.loc[ + etudids_communs, comp_communes + ] # Stocke les dfs coeffs_dfs[sxtag_id] = coeffs_df