ScoDoc-Lille/app/pe/pe_rcss_jury.py

245 lines
10 KiB
Python

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}: <vide>")
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:
self.rcrcfs[rcf_id] = pe_rcrcf.RCRCF(rcf_id, 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}: <vide> !!! ")
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