Merge branch 'scodoc-master' into pe-BUT-v2

# Conflicts:
#	app/pe/pe_etudiant.py
This commit is contained in:
Cléo Baras 2024-01-26 09:53:32 +01:00
commit cf415763b3
2 changed files with 49 additions and 47 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
@ -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
@ -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,10 +410,9 @@ 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 d'inscription (pour un BUT). """L'année de diplôme prévue d'un étudiant en fonction de ses semestres
d'inscription (pour un BUT).
Les semestres utilisés pour le calcul sont limités à ceux d'une formation apc.
Args: Args:
identite: L'identité d'un étudiant identite: L'identité d'un étudiant
@ -422,7 +423,7 @@ def annee_diplome(identite: Identite) -> int:
formsemestres_apc = get_semestres_apc(identite) formsemestres_apc = get_semestres_apc(identite)
if formsemestres_apc: if formsemestres_apc:
dates_possibles_diplome: int = [] dates_possibles_diplome = []
"""Années de diplômation prédites en fonction des semestres (d'une formation APC) d'un étudiant""" """Années de diplômation prédites en fonction des semestres (d'une formation APC) d'un étudiant"""
for sem_base in formsemestres_apc: for sem_base in formsemestres_apc:
annee = pe_comp.get_annee_diplome_semestre(sem_base) annee = pe_comp.get_annee_diplome_semestre(sem_base)
@ -451,7 +452,7 @@ def get_semestres_apc(identite: Identite) -> list:
return semestres_apc return semestres_apc
def arret_de_formation(identite: Identite, cosemestres: dict[int, 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
@ -480,7 +481,7 @@ def arret_de_formation(identite: Identite, cosemestres: dict[int, FormSemestre])
dans lequel il aurait pu s'inscrire mais ne l'a pas fait. dans lequel il aurait pu s'inscrire mais ne l'a pas fait.
Args: Args:
identite: L'identité d'un étudiant etud: L'identité d'un étudiant
cosemestres: Les semestres donnant lieu à diplômation (sans redoublement) en date du jury cosemestres: Les semestres donnant lieu à diplômation (sans redoublement) en date du jury
Returns: Returns:
@ -491,7 +492,7 @@ def arret_de_formation(identite: Identite, cosemestres: dict[int, FormSemestre])
""" """
# Les semestres APC de l'étudiant # Les semestres APC de l'étudiant
semestres = get_semestres_apc(identite) semestres = get_semestres_apc(etud)
semestres_apc = {sem.semestre_id: sem for sem in semestres} semestres_apc = {sem.semestre_id: sem for sem in semestres}
if not semestres_apc: if not semestres_apc:
return True return True
@ -501,12 +502,12 @@ def arret_de_formation(identite: Identite, cosemestres: dict[int, FormSemestre])
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(
range(numero_dernier_formsemestre + 1, pe_comp.NBRE_SEMESTRES_DIPLOMANT) range(numero_dernier_formsemestre + 1, pe_comp.NBRE_SEMESTRES_DIPLOMANT)
) )
## semestre pair => passage en année supérieure ou redoublement # semestre pair => passage en année supérieure ou redoublement
else: # else: #
numeros_possibles = list( numeros_possibles = list(
range( range(
@ -522,7 +523,9 @@ def arret_de_formation(identite: Identite, cosemestres: dict[int, FormSemestre])
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:
@ -548,5 +551,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"