Fix: pe_etudiant.py

This commit is contained in:
Emmanuel Viennet 2024-01-26 09:29:36 +01:00
parent 4f7da8bfa4
commit 33f2afb04b
2 changed files with 52 additions and 50 deletions

View File

@ -94,20 +94,20 @@ class EtudiantsJuryPE:
" => %d étudiants trouvés dans les cosemestres" % len(self.etudiants_ids) " => %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, ....""" # avec prise en compte des redoublements, des abandons, ....
pe_comp.pe_print("3) Analyse des parcours individuels des étudiants") pe_comp.pe_print("3) Analyse des parcours individuels des étudiants")
no_etud = 0 no_etud = 0
for no_etud, etudid in enumerate(self.etudiants_ids): for no_etud, etudid in enumerate(self.etudiants_ids):
"""L'identité de l'étudiant"""
identite = Identite.get_etud(etudid) identite = Identite.get_etud(etudid)
self.identites[etudid] = identite self.identites[etudid] = identite
"""identités des étudiants"""
"""L'analyse de son cursus""" # Analyse son cursus
self.analyse_etat_etudiant(etudid, cosemestres) self.analyse_etat_etudiant(etudid, cosemestres)
"""L'analyse de son parcours pour atteindre chaque semestre de la formation""" # Analyse son parcours pour atteindre chaque semestre de la formation
self.structure_cursus_etudiant(etudid) self.structure_cursus_etudiant(etudid)
if (no_etud + 1) % 10 == 0: if (no_etud + 1) % 10 == 0:
@ -115,15 +115,15 @@ class EtudiantsJuryPE:
no_etud += 1 no_etud += 1
pe_comp.pe_print() pe_comp.pe_print()
"""Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris""" # Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris
self.etudiants_diplomes = self.get_etudiants_diplomes() self.etudiants_diplomes = self.get_etudiants_diplomes()
self.diplomes_ids = set(self.etudiants_diplomes.keys()) self.diplomes_ids = set(self.etudiants_diplomes.keys())
self.etudiants_ids = set(self.identites)
"""Les étudiants dont il faut calculer les moyennes""" """Les étudiants dont il faut calculer les moyennes"""
self.etudiants_ids = {etudid for etudid in self.identites}
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
self.formsemestres_jury_ids = self.get_formsemestres() self.formsemestres_jury_ids = self.get_formsemestres()
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
# Synthèse # Synthèse
pe_comp.pe_print( pe_comp.pe_print(
@ -135,18 +135,18 @@ class EtudiantsJuryPE:
f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne" f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne"
) )
pe_comp.pe_print( pe_comp.pe_print(
f" => quelques étudiants futurs diplômés : " " => quelques étudiants futurs diplômés : "
+ ", ".join([str(etudid) for etudid in list(self.etudiants_diplomes)[:10]]) + ", ".join([str(etudid) for etudid in list(self.etudiants_diplomes)[:10]])
) )
pe_comp.pe_print( pe_comp.pe_print(
f" => semestres dont il faut calculer les moyennes : " " => semestres dont il faut calculer les moyennes : "
+ ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)]) + ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)])
) )
# Les abandons : # Les abandons :
self.abandons = sorted( self.abandons = sorted(
[ [
self.cursus[etudid]["nom"] cursus["nom"]
for etudid in self.cursus for etudid, cursus in self.cursus.items()
if etudid not in self.diplomes_ids if etudid not in self.diplomes_ids
] ]
) )
@ -164,7 +164,7 @@ class EtudiantsJuryPE:
etudid etudid
for etudid in self.cursus for etudid in self.cursus
if self.cursus[etudid]["diplome"] == self.annee_diplome if self.cursus[etudid]["diplome"] == self.annee_diplome
and self.cursus[etudid]["abandon"] == False and self.cursus[etudid]["abandon"] is False
] ]
etudiants = {etudid: self.identites[etudid] for etudid in etudids} etudiants = {etudid: self.identites[etudid] for etudid in etudids}
return etudiants return etudiants
@ -190,7 +190,7 @@ class EtudiantsJuryPE:
""" """
identite = Identite.get_etud(etudid) identite = Identite.get_etud(etudid)
"""Le cursus global de l'étudiant (restreint aux semestres APC)""" # Le cursus global de l'étudiant (restreint aux semestres APC)
formsemestres = identite.get_formsemestres() formsemestres = identite.get_formsemestres()
semestres_etudiant = { semestres_etudiant = {
@ -204,7 +204,9 @@ class EtudiantsJuryPE:
"etat_civil": identite.etat_civil, # Ajout à la table jury "etat_civil": identite.etat_civil, # Ajout à la table jury
"nom": identite.nom, "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 "diplome": get_annee_diplome(
identite
), # Le date prévisionnelle de son diplôme
"formsemestres": semestres_etudiant, # les semestres de l'étudiant "formsemestres": semestres_etudiant, # les semestres de l'étudiant
"nb_semestres": len( "nb_semestres": len(
semestres_etudiant semestres_etudiant
@ -212,7 +214,7 @@ class EtudiantsJuryPE:
"abandon": False, # va être traité en dessous "abandon": False, # va être traité en dessous
} }
""" Est-il réorienté / démissionnaire ou a-t-il arrêté volontairement sa formation ?""" # Est-il réorienté / démissionnaire ou a-t-il arrêté volontairement sa formation ?
self.cursus[etudid]["abandon"] = arret_de_formation(identite, cosemestres) self.cursus[etudid]["abandon"] = arret_de_formation(identite, cosemestres)
def get_semestres_significatifs(self, etudid: int): def get_semestres_significatifs(self, etudid: int):
@ -242,12 +244,12 @@ class EtudiantsJuryPE:
de moyennes PE. de moyennes PE.
Cette structuration s'appuie sur les numéros de semestre: pour chaque Si, stocke : Cette structuration s'appuie sur les numéros de semestre: pour chaque Si, stocke :
le dernier semestre (en date) de numéro i qu'il a suivi (1 ou 0 si pas encore suivi). Ce semestre influera les le dernier semestre (en date) de numéro i qu'il a suivi (1 ou 0 si pas encore suivi).
interclassement par semestre dans la promo. Ce semestre influera les interclassement par semestre dans la promo.
""" """
semestres_significatifs = self.get_semestres_significatifs(etudid) semestres_significatifs = self.get_semestres_significatifs(etudid)
"""Tri des semestres par numéro de semestre""" # Tri des semestres par numéro de semestre
for nom_sem in pe_comp.TOUS_LES_SEMESTRES: for nom_sem in pe_comp.TOUS_LES_SEMESTRES:
i = int(nom_sem[1]) # le n° du semestre i = int(nom_sem[1]) # le n° du semestre
semestres_i = { semestres_i = {
@ -275,10 +277,10 @@ class EtudiantsJuryPE:
numero_semestre_terminal = formsemestre_final.semestre_id numero_semestre_terminal = formsemestre_final.semestre_id
semestres_significatifs = self.get_semestres_significatifs(etudid) semestres_significatifs = self.get_semestres_significatifs(etudid)
"""Semestres de n° inférieur (pax ex: des S1, S2, S3 pour un S3 terminal) et qui lui sont antérieurs""" # Semestres de n° inférieur (pax ex: des S1, S2, S3 pour un S3 terminal)
# et qui lui sont antérieurs
semestres_aggreges = {} semestres_aggreges = {}
for fid in semestres_significatifs: for fid, semestre in semestres_significatifs.items():
semestre = semestres_significatifs[fid]
if ( if (
semestre.semestre_id <= numero_semestre_terminal semestre.semestre_id <= numero_semestre_terminal
and semestre.date_fin <= formsemestre_final.date_fin and semestre.date_fin <= formsemestre_final.date_fin
@ -304,10 +306,10 @@ class EtudiantsJuryPE:
Un dictionnaire ``{fid: FormSemestre(fid)}`` Un dictionnaire ``{fid: FormSemestre(fid)}``
""" """
formsemestres_terminaux = {} formsemestres_terminaux = {}
for etudid in self.trajectoires: for trajectoire_aggr in self.trajectoires.values():
if self.trajectoires[etudid][aggregat]: trajectoire = trajectoire_aggr[aggregat]
trajectoire = self.trajectoires[etudid][aggregat] if trajectoire:
"""Le semestre terminal de l'étudiant de l'aggrégat""" # Le semestre terminal de l'étudiant de l'aggrégat
fid = trajectoire.semestre_final.formsemestre_id fid = trajectoire.semestre_final.formsemestre_id
formsemestres_terminaux[fid] = trajectoire.semestre_final formsemestres_terminaux[fid] = trajectoire.semestre_final
return formsemestres_terminaux return formsemestres_terminaux
@ -336,11 +338,11 @@ class EtudiantsJuryPE:
Une liste de la forme ``[ 'Si', 'iA' , ... ]`` (combinant les formats précédents) est possible. Une liste de la forme ``[ 'Si', 'iA' , ... ]`` (combinant les formats précédents) est possible.
""" """
if semestres_recherches is None: if semestres_recherches is None:
"""Appel récursif pour obtenir tous les semestres (validants)""" # Appel récursif pour obtenir tous les semestres (validants)
semestres = self.get_formsemestres(pe_comp.AGGREGAT_DIPLOMANT) semestres = self.get_formsemestres(pe_comp.AGGREGAT_DIPLOMANT)
return semestres return semestres
elif isinstance(semestres_recherches, list): elif isinstance(semestres_recherches, list):
"""Appel récursif sur tous les éléments de la liste""" # Appel récursif sur tous les éléments de la liste
semestres = {} semestres = {}
for elmt in semestres_recherches: for elmt in semestres_recherches:
semestres_elmt = self.get_formsemestres(elmt) semestres_elmt = self.get_formsemestres(elmt)
@ -350,7 +352,7 @@ class EtudiantsJuryPE:
isinstance(semestres_recherches, str) isinstance(semestres_recherches, str)
and semestres_recherches in pe_comp.TOUS_LES_AGGREGATS and semestres_recherches in pe_comp.TOUS_LES_AGGREGATS
): ):
"""Cas d'un aggrégat avec appel récursif sur toutes les entrées de l'aggrégat""" # Cas d'un aggrégat avec appel récursif sur toutes les entrées de l'aggrégat
semestres = self.get_formsemestres( semestres = self.get_formsemestres(
pe_comp.PARCOURS[semestres_recherches]["aggregat"] pe_comp.PARCOURS[semestres_recherches]["aggregat"]
) )
@ -359,10 +361,9 @@ class EtudiantsJuryPE:
isinstance(semestres_recherches, str) isinstance(semestres_recherches, str)
and semestres_recherches in pe_comp.TOUS_LES_SEMESTRES and semestres_recherches in pe_comp.TOUS_LES_SEMESTRES
): ):
"""semestres_recherches est un nom de semestre de type S1, # semestres_recherches est un nom de semestre de type S1,
pour une recherche parmi les étudiants à prendre en compte # pour une recherche parmi les étudiants à prendre en compte
dans le jury (diplômé et redoublants non diplômé) # dans le jury (diplômé et redoublants non diplômé)
"""
nom_sem = semestres_recherches nom_sem = semestres_recherches
semestres = {} semestres = {}
for etudid in self.etudiants_ids: for etudid in self.etudiants_ids:
@ -386,7 +387,8 @@ def get_etudiants_dans_semestres(semestres: dict[int, FormSemestre]) -> set:
"""Ensemble d'identifiants des étudiants (identifiés via leur ``etudid``) """Ensemble d'identifiants des étudiants (identifiés via leur ``etudid``)
inscrits à l'un des semestres de la liste de ``semestres``. inscrits à l'un des semestres de la liste de ``semestres``.
Remarque : Les ``cosemestres`` sont généralement obtenus avec ``sco_formsemestre.do_formsemestre_list()`` Remarque : Les ``cosemestres`` sont généralement obtenus avec
``sco_formsemestre.do_formsemestre_list()``
Args: Args:
semestres: Un dictionnaire ``{fid: Formsemestre(fid)}`` donnant un semestres: Un dictionnaire ``{fid: Formsemestre(fid)}`` donnant un
@ -397,7 +399,7 @@ def get_etudiants_dans_semestres(semestres: dict[int, FormSemestre]) -> set:
""" """
etudiants_ids = set() etudiants_ids = set()
for fid, sem in semestres.items(): # pour chacun des semestres de la liste for sem in semestres.values(): # pour chacun des semestres de la liste
etudiants_du_sem = {ins.etudid for ins in sem.inscriptions} etudiants_du_sem = {ins.etudid for ins in sem.inscriptions}
pe_print(f" --> {sem} : {len(etudiants_du_sem)} etudiants") pe_print(f" --> {sem} : {len(etudiants_du_sem)} etudiants")
@ -408,7 +410,7 @@ def get_etudiants_dans_semestres(semestres: dict[int, FormSemestre]) -> set:
return etudiants_ids return etudiants_ids
def annee_diplome(identite: Identite) -> int: def get_annee_diplome(etud: Identite) -> int:
"""L'année de diplôme prévue d'un étudiant en fonction de ses semestres """L'année de diplôme prévue d'un étudiant en fonction de ses semestres
d'inscription (pour un BUT). d'inscription (pour un BUT).
@ -420,16 +422,16 @@ def annee_diplome(identite: Identite) -> int:
NOTE: Pourrait être déplacé dans app.models.etudiants.Identite NOTE: Pourrait être déplacé dans app.models.etudiants.Identite
""" """
formsemestres = identite.get_formsemestres() formsemestres = etud.get_formsemestres()
if formsemestres: if formsemestres:
return max( return max(
[pe_comp.get_annee_diplome_semestre(sem_base) for sem_base in formsemestres] (pe_comp.get_annee_diplome_semestre(sem_base) or -1)
for sem_base in formsemestres
) )
else: return None
return None
def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> bool: def arret_de_formation(etud: Identite, cosemestres: list[FormSemestre]) -> bool:
"""Détermine si un étudiant a arrêté sa formation. Il peut s'agir : """Détermine si un étudiant a arrêté sa formation. Il peut s'agir :
* d'une réorientation à l'initiative du jury de semestre ou d'une démission (on pourrait * d'une réorientation à l'initiative du jury de semestre ou d'une démission (on pourrait
@ -467,14 +469,13 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b
TODO:: A reprendre pour le cas des étudiants à l'étranger TODO:: A reprendre pour le cas des étudiants à l'étranger
TODO:: A reprendre si BUT avec semestres décalés TODO:: A reprendre si BUT avec semestres décalés
""" """
etudid = identite.etudid
"""Son dernier semestre en date""" # Son dernier semestre en date
semestres = {sem.semestre_id: sem for sem in identite.get_formsemestres()} semestres = {sem.semestre_id: sem for sem in etud.get_formsemestres()}
dernier_formsemestre = get_dernier_semestre_en_date(semestres) dernier_formsemestre = get_dernier_semestre_en_date(semestres)
numero_dernier_formsemestre = dernier_formsemestre.semestre_id numero_dernier_formsemestre = dernier_formsemestre.semestre_id
"""Les numéro de semestres possible dans lesquels il pourrait s'incrire""" # Les numéro de semestres possible dans lesquels il pourrait s'incrire
# semestre impair => passage de droit en semestre pair suivant (effet de l'annualisation) # semestre impair => passage de droit en semestre pair suivant (effet de l'annualisation)
if numero_dernier_formsemestre % 2 == 1: if numero_dernier_formsemestre % 2 == 1:
numeros_possibles = list( numeros_possibles = list(
@ -489,14 +490,16 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b
) )
) )
"""Y-a-t-il des cosemestres dans lesquels il aurait pu s'incrire ?""" # Y-a-t-il des cosemestres dans lesquels il aurait pu s'incrire ?
formsestres_superieurs_possibles = [] formsestres_superieurs_possibles = []
for fid, sem in cosemestres.items(): # Les semestres ayant des inscrits for fid, sem in cosemestres.items(): # Les semestres ayant des inscrits
if ( if (
fid != dernier_formsemestre.formsemestre_id fid != dernier_formsemestre.formsemestre_id
and sem.semestre_id in numeros_possibles and sem.semestre_id in numeros_possibles
and sem.date_debut.year >= dernier_formsemestre.date_debut.year and sem.date_debut.year >= dernier_formsemestre.date_debut.year
): # date de debut des semestres possibles postérieur au dernier semestre de l'étudiant et de niveau plus élevé que le dernier semestre valide de l'étudiant ):
# date de debut des semestres possibles postérieur au dernier semestre de l'étudiant
# et de niveau plus élevé que le dernier semestre valide de l'étudiant
formsestres_superieurs_possibles.append(fid) formsestres_superieurs_possibles.append(fid)
if len(formsestres_superieurs_possibles) > 0: if len(formsestres_superieurs_possibles) > 0:
@ -522,5 +525,4 @@ def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]) -> FormSeme
if semestres[fid].date_fin > dernier_semestre.date_fin: if semestres[fid].date_fin > dernier_semestre.date_fin:
dernier_semestre = semestres[fid] dernier_semestre = semestres[fid]
return dernier_semestre return dernier_semestre
else: return None
return None

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "9.6.85" SCOVERSION = "9.6.86"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"