import app.pe.rcss.pe_rcf as pe_rcf import app.pe.rcss.pe_rcrcf as pe_rcrcf import app.pe.pe_etudiant as pe_etudiant import app.pe.pe_comp as pe_comp import app.pe.rcss.rcss_constantes as rcss_constantes from app.models import FormSemestre from app.pe import pe_affichage class RCSsJuryPE: """Classe centralisant tous les regroupements cohérents de semestres (RCS) des étudiants à prendre en compte dans un jury PE Args: annee_diplome: L'année de diplomation """ def __init__(self, annee_diplome: int): self.annee_diplome = annee_diplome """Année de diplômation""" self.rcss: dict[tuple(int, str): pe_rcf.RCF] = {} """Ensemble des RCS recensés""" self.rcss_suivis: dict[int:dict] = {} """Dictionnaire associant, pour chaque étudiant et pour chaque type de RCS, son RCS : {etudid: {nom_RCS: RCS}}""" self.rcfs: dict[tuple(int, str) : pe_rcf.RCF] = {} """Ensemble des RCF recensés : {(nom_RCS, fid_terminal): RCF}""" self.rcfs_suivis: dict[int:dict] = {} """Dictionnaire associant, pour chaque étudiant et pour chaque type de RCS, son RCS : {etudid: {nom_RCS: RCF}}""" self.rcrcfs: dict[tuple(int, str) : pe_rcrcf.RCRCF] = {} """Ensemble des RCS recensés : {(nom_RCS, fid_terminal): RCRCF}""" self.rcrcfs_suivis: dict[int:str] = {} """Dictionnaire associant, pour chaque étudiant et pour chaque type de RCS, son RCRCF : {etudid: {nom_RCS: RCSx}}""" def cree_rcss(self, etudiants: pe_etudiant.EtudiantsJuryPE): """Créé tous les RCS, au regard du cursus des étudiants analysés + les mémorise dans les données de l'étudiant Args: etudiants: Les étudiants à prendre en compte dans le Jury PE """ tous_les_aggregats = rcss_constantes.TOUS_LES_SEMESTRES + rcss_constantes.TOUS_LES_RCS_AVEC_PLUSIEURS_SEM for etudid in etudiants.trajectoires: self.rcss_suivis[etudid] = { aggregat: None for aggregat in tous_les_aggregats } for nom_rcs in tous_les_aggregats: # L'aggrégat considéré (par ex: 3S=S1+S2+S3), son nom de son semestre # terminal (par ex: S3) et son numéro (par ex: 3) noms_semestre_de_aggregat = rcss_constantes.TYPES_RCS[nom_rcs]["aggregat"] nom_semestre_terminal = noms_semestre_de_aggregat[-1] for etudid in etudiants.trajectoires: # Le formsemestre terminal (dernier en date) associé au # semestre marquant la fin de l'aggrégat # (par ex: son dernier S3 en date) trajectoire = etudiants.trajectoires[etudid][nom_semestre_terminal] if trajectoire: formsemestre_final = pe_etudiant.get_dernier_semestre_en_date(trajectoire) # Ajout ou récupération du RCS associé rcs_id = (nom_rcs, formsemestre_final.formsemestre_id) if rcs_id not in self.rcss: self.rcss[rcs_id] = pe_rcf.RCF(nom_rcs, formsemestre_final) rcs = self.rcss[rcs_id] # La liste des semestres de l'étudiant à prendre en compte # pour cette trajectoire semestres_a_aggreger = get_rcs_etudiant( etudiants.trajectoires[etudid], formsemestre_final, nom_rcs ) # Ajout des semestres au RCS rcs.add_semestres_a_aggreger(semestres_a_aggreger) # Mémorise le RCS suivi par l'étudiant self.rcss_suivis[etudid][nom_rcs] = rcs # Affichage pour debug jeunes = list(enumerate(self.rcss_suivis)) for no_etud, etudid in jeunes[:20]: pe_affichage.pe_print(f"--> {etudiants.identites[etudid].nomprenom} (#{etudid}) :") for nom_rcs, rcs in self.rcss_suivis[etudid].items(): if rcs: pe_affichage.pe_print(f" > RCS {nom_rcs}: {rcs.get_repr()}") def cree_rcfs(self, etudiants: pe_etudiant.EtudiantsJuryPE): """Créé les RCFs en ne conservant dans les RCS que les regroupements de type Sx""" self.rcfs = {} for rcs_id, rcs in self.rcss.items(): if rcs and rcs.nom in rcss_constantes.TOUS_LES_SEMESTRES: self.rcfs[rcs_id] = rcs for etudid in self.rcss_suivis: for nom_rcs, rcs in self.rcss_suivis[etudid].items(): if rcs and nom_rcs in rcss_constantes.TOUS_LES_SEMESTRES: if etudid not in self.rcfs_suivis: self.rcfs_suivis[etudid] = {} self.rcfs_suivis[etudid][nom_rcs] = rcs # Affichage pour debug jeunes = list(enumerate(self.rcfs_suivis)) for no_etud, etudid in jeunes[:20]: pe_affichage.pe_print(f"-> {etudiants.identites[etudid].nomprenom} :") for nom_rcs, rcs in self.rcfs_suivis[etudid].items(): if rcs: pe_affichage.pe_print(f" > RCSValid {nom_rcs}: {rcs.get_repr()}") else: pe_affichage.pe_print(f" > RCSValid {nom_rcs}: ") def cree_rcrcfs(self, etudiants: pe_etudiant.EtudiantsJuryPE): """Créé tous les RCRCF, au regard du cursus des étudiants analysés (trajectoires traduisant son parcours dans les différents semestres) + les mémorise dans les données de l'étudiant """ # Pour tous les étudiants du jury for etudid in self.rcss_suivis: self.rcrcfs_suivis[etudid] = {} for nom_rcs, rcf in self.rcfs_suivis[etudid].items(): # Pour chaque RCS semestres_a_aggreger = rcf.semestres_aggreges # Tri des semestres par rang semestres_tries = pe_comp.tri_semestres_par_rang(semestres_a_aggreger) # Récupére les RCFs de type Sx traduisant sa trajectoire rcfs_a_aggreger = {} for semestres_du_rang in semestres_tries.values(): if semestres_du_rang: rcf_id = get_rcf_from_semestres_aggreges( self.rcfs, semestres_du_rang ) if not rcf_id: raise ValueError( "Il manque un RCF pour créer les RCRCFs dans cree_rcrcfs" ) rcfs_a_aggreger[rcf_id] = self.rcfs[rcf_id] # Ajout du RCRCF if rcf_id not in self.rcrcfs: rcf_nom = rcf_id[0] self.rcrcfs[rcf_id] = pe_rcrcf.RCRCF(rcf_nom, rcf.formsemestre_final) rcrcf = self.rcrcfs[rcf_id] # Ajout des RCFs au RCRCF rcrcf.add_rcfs_a_aggreger(rcfs_a_aggreger) # Mémoire la trajectoire RCRCF suivie par l'étudiant nom_rcs = rcrcf.nom self.rcrcfs_suivis[etudid][nom_rcs] = rcrcf # Affichage pour debug jeunes = list(enumerate(self.rcrcfs_suivis)) for no_etud, etudid in jeunes[:20]: pe_affichage.pe_print(f"-> {etudiants.identites[etudid].nomprenom} :") for nom_rcs, rcs in self.rcrcfs_suivis[etudid].items(): if rcs: pe_affichage.pe_print(f" > RCRCF {nom_rcs}: {rcs.get_repr()}") else: pe_affichage.pe_print(f" > RCRCF {nom_rcs}: !!! ") def get_rcs_etudiant( semestres: dict[int:FormSemestre], formsemestre_final: FormSemestre, nom_rcs: str ) -> dict[int, FormSemestre]: """Ensemble des semestres parcourus (trajectoire) par un étudiant dans le cadre d'un RCS de type Sx, iA ou iS et ayant pour semestre terminal `formsemestre_final`. Par ex: pour un RCS "3S", dont le formsemestre_terminal est un S3, regroupe le ou les S1 qu'il a suivi (1 ou 2 si redoublement) + le ou les S2 + le ou les S3. Les semestres parcourus sont antérieurs (en terme de date de fin) au formsemestre_terminal. Args: cursus: Dictionnaire {fid: Formsemestre} donnant l'ensemble des semestres dans lesquels l'étudiant a été inscrit formsemestre_final: le semestre final visé nom_rcs: Nom du RCS visé """ numero_semestre_terminal = formsemestre_final.semestre_id # semestres_significatifs = self.get_semestres_significatifs(etudid) semestres_significatifs = {} for i in range(1, pe_comp.NBRE_SEMESTRES_DIPLOMANT + 1): semestres_significatifs = semestres_significatifs | semestres[f"S{i}"] if nom_rcs.startswith("S"): # les semestres numero_semestres_possibles = [numero_semestre_terminal] elif nom_rcs.endswith("A"): # les années numero_semestres_possibles = [ int(sem[-1]) for sem in rcss_constantes.TYPES_RCS[nom_rcs]["aggregat"] ] assert numero_semestre_terminal in numero_semestres_possibles else: # les xS = tous les semestres jusqu'à Sx (eg S1, S2, S3 pour un S3 terminal) numero_semestres_possibles = list(range(1, numero_semestre_terminal + 1)) semestres_aggreges = {} for fid, semestre in semestres_significatifs.items(): # Semestres parmi ceux de n° possibles & qui lui sont antérieurs if ( semestre.semestre_id in numero_semestres_possibles and semestre.date_fin <= formsemestre_final.date_fin ): semestres_aggreges[fid] = semestre return semestres_aggreges def get_rcf_from_semestres_aggreges( rcfs: dict[(str, int):pe_rcf.RCF], semestres_a_aggreges: list[FormSemestre] ) -> (str, int): """Partant d'un dictionnaire de RCFs (de la forme ``{ (nom_rcs, fid): RCF }, et connaissant une liste de (form)semestres à aggréger, renvoie l'identifiant (nom_rcs, fid) du RCFs qui lui correspond (c'est à dire celui dont les semestres_aggregés par le RCF sont les même que les semestres_a_aggreger. Returns: rcf_id: L'identifiant du RCF trouvé """ fids_semestres_a_aggreger = set( [frms.formsemestre_id for frms in semestres_a_aggreges] ) for rcf_id, rcf in rcfs.items(): fids_rcf = set(rcf.semestres_aggreges) if fids_rcf == fids_semestres_a_aggreger: return rcf_id return None