forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -39,15 +39,6 @@ Created on 17/01/2024
|
|||||||
import app.pe.pe_tools as pe_tools
|
import app.pe.pe_tools as pe_tools
|
||||||
from app.models import FormSemestre, Identite
|
from app.models import FormSemestre, Identite
|
||||||
from app.pe.pe_tools import pe_print
|
from app.pe.pe_tools import pe_print
|
||||||
from app.scodoc import (
|
|
||||||
sco_etud,
|
|
||||||
codes_cursus,
|
|
||||||
sco_formsemestre,
|
|
||||||
sco_formsemestre_inscriptions,
|
|
||||||
sco_report,
|
|
||||||
)
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
|
|
||||||
class EtudiantsJuryPE:
|
class EtudiantsJuryPE:
|
||||||
"""Classe centralisant la gestion des étudiants à prendre en compte dans un jury de PE"""
|
"""Classe centralisant la gestion des étudiants à prendre en compte dans un jury de PE"""
|
||||||
@ -63,19 +54,16 @@ class EtudiantsJuryPE:
|
|||||||
|
|
||||||
"Les identités des étudiants traités pour le jury"
|
"Les identités des étudiants traités pour le jury"
|
||||||
self.identites = {} # ex. ETUDINFO_DICT
|
self.identites = {} # ex. ETUDINFO_DICT
|
||||||
"Les cursus (semestres suivis, abandons, dernier S1, S2, ...) des étudiants"
|
"Les cursus (semestres suivis, abandons) des étudiants"
|
||||||
self.cursus = {}
|
self.cursus = {}
|
||||||
"""Les aggrégats des semestres suivis (par ex: 3S=S1+S2+S3 à prendre en compte avec d'éventuels redoublements) des étudiants"""
|
"""Les aggrégats des semestres suivis (par ex: 3S=S1+S2+S3 à prendre en compte avec d'éventuels redoublements) des étudiants"""
|
||||||
self.aggregats = {}
|
self.trajectoires = {}
|
||||||
|
|
||||||
"Les etudids des étudiants à considérer au jury (ceux qui seront effectivement diplômés)"
|
"Les etudids des étudiants à considérer au jury (ceux qui seront effectivement diplômés)"
|
||||||
self.diplomes_ids = {}
|
self.diplomes_ids = {}
|
||||||
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
|
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
|
||||||
self.etudiants_ids = {}
|
self.etudiants_ids = {}
|
||||||
|
|
||||||
"Les formsemestres dont il faut calculer les moyennes par tag"
|
|
||||||
self.formsemestres_jury_ids = {}
|
|
||||||
|
|
||||||
def find_etudiants(self, formation_id: int):
|
def find_etudiants(self, formation_id: int):
|
||||||
"""Liste des étudiants à prendre en compte dans le jury PE, en les recherchant
|
"""Liste des étudiants à prendre en compte dans le jury PE, en les recherchant
|
||||||
de manière automatique par rapport à leur année de diplomation ``annee_diplome``
|
de manière automatique par rapport à leur année de diplomation ``annee_diplome``
|
||||||
@ -116,7 +104,7 @@ class EtudiantsJuryPE:
|
|||||||
self.analyse_etat_etudiant(etudid, cosemestres)
|
self.analyse_etat_etudiant(etudid, cosemestres)
|
||||||
|
|
||||||
"""L'analyse de son parcours pour atteindre chaque semestre de la formation"""
|
"""L'analyse de son parcours pour atteindre chaque semestre de la formation"""
|
||||||
self.analyse_parcours_etudiant_dans_semestres(etudid)
|
self.structure_cursus_etudiant(etudid)
|
||||||
|
|
||||||
if (no_etud + 1) % 10 == 0:
|
if (no_etud + 1) % 10 == 0:
|
||||||
pe_tools.pe_print((no_etud + 1), " ", end="")
|
pe_tools.pe_print((no_etud + 1), " ", end="")
|
||||||
@ -130,7 +118,7 @@ class EtudiantsJuryPE:
|
|||||||
self.etudiants_ids = {etudid for etudid in self.identites}
|
self.etudiants_ids = {etudid for etudid in self.identites}
|
||||||
|
|
||||||
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
|
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
|
||||||
self.formsemestres_jury_ids = self.get_formsemestres_jury()
|
self.formsemestres_jury_ids = self.get_formsemestres()
|
||||||
|
|
||||||
# Synthèse
|
# Synthèse
|
||||||
pe_tools.pe_print(
|
pe_tools.pe_print(
|
||||||
@ -210,61 +198,37 @@ class EtudiantsJuryPE:
|
|||||||
""" 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 analyse_parcours_etudiant_dans_semestres(self, etudid: int):
|
def get_semestres_significatifs(self, etudid: int):
|
||||||
"""Structure les informations sur les semestres suivis par un
|
"""Ensemble des semestres d'un étudiant, qui l'auraient amené à être diplomé
|
||||||
étudiant, pour identifier les semestres qui seront pris en compte lors de ses calculs
|
l'année visée (supprime les semestres qui conduisent à une diplomation
|
||||||
de moyennes PE.
|
postérieure à celle du jury visé)
|
||||||
|
|
||||||
Cette structuration (cf. attribut self.cursus) s'appuie sur les numéros de semestre: pour chaque Si, stocke :
|
Args:
|
||||||
le dernier semestre (en date) de numéro i qu'il a suivi (1 ou 0 si pas encore suivi). Ce semestre influera les
|
etudid: L'identifiant d'un étudiant
|
||||||
interclassement par semestre dans la promo.
|
|
||||||
|
|
||||||
Elle calcule également sur les aggrégats (cf. attribut self.aggregats):
|
Returns:
|
||||||
|
Un dictionnaire ``{fid: FormSemestre(fid)`` dans lequel les semestres
|
||||||
* pour un semestre de type Si, elle stocke le (ou les) formsemestres de numéro i qu'a suivi un étudiant
|
amènent à une diplomation avant l'annee de diplomation du jury
|
||||||
(2 si redoublant) dans self.aggregats
|
|
||||||
* pour des aggrégats de type iS ou iA (par ex, 3A=S1+S2+S3), elle identifie les semestres que l'étudiant
|
|
||||||
a suivi pour l'amener jusqu'au semestre terminal de l'aggrégat. Ce parcours peut être :
|
|
||||||
** S1+S2+S1+S2+S3 si redoublement de la 1ère année
|
|
||||||
** S1+S2+(année de césure)+S3 si césure, ...
|
|
||||||
|
|
||||||
Par ex: M. N..z (redoublant en 2ème année) au moment de son 2ème S3 :
|
|
||||||
{'1A': {26: {18: <FormSemestre 18 BUT Réseaux et Télécommunications semestre 1 FI 2021-2022>,
|
|
||||||
26: <FormSemestre 26 BUT Réseaux et Télécommunications semestre 2 FI 2022>}},
|
|
||||||
'2A': {79: {18: <FormSemestre 18 BUT Réseaux et Télécommunications semestre 1 FI 2021-2022>,
|
|
||||||
26: <FormSemestre 26 BUT Réseaux et Télécommunications semestre 2 FI 2022>,
|
|
||||||
56: <FormSemestre 56 BUT Réseaux et Télécommunications semestre 3 FI 2022-2023>,
|
|
||||||
79: <FormSemestre 79 BUT Réseaux et Télécommunications semestre 4 FI 2023>}},
|
|
||||||
'3A': {},
|
|
||||||
'3S': {112: {18: <FormSemestre 18 BUT Réseaux et Télécommunications semestre 1 FI 2021-2022>,
|
|
||||||
26: <FormSemestre 26 BUT Réseaux et Télécommunications semestre 2 FI 2022>,
|
|
||||||
56: <FormSemestre 56 BUT Réseaux et Télécommunications semestre 3 FI 2022-2023>,
|
|
||||||
112: <FormSemestre 112 BUT Réseaux et Télécommunications 2023 semestre 3 FI 2023-2024>}},
|
|
||||||
'4S': {79: {18: <FormSemestre 18 BUT Réseaux et Télécommunications semestre 1 FI 2021-2022>,
|
|
||||||
26: <FormSemestre 26 BUT Réseaux et Télécommunications semestre 2 FI 2022>,
|
|
||||||
56: <FormSemestre 56 BUT Réseaux et Télécommunications semestre 3 FI 2022-2023>,
|
|
||||||
79: <FormSemestre 79 BUT Réseaux et Télécommunications semestre 4 FI 2023>}},
|
|
||||||
'5S': {},
|
|
||||||
'6S': {},
|
|
||||||
'S1': {18: {18: <FormSemestre 18 BUT Réseaux et Télécommunications semestre 1 FI 2021-2022>}},
|
|
||||||
'S2': {26: {26: <FormSemestre 26 BUT Réseaux et Télécommunications semestre 2 FI 2022>}},
|
|
||||||
'S3': {112: {56: <FormSemestre 56 BUT Réseaux et Télécommunications semestre 3 FI 2022-2023>,
|
|
||||||
112: <FormSemestre 112 BUT Réseaux et Télécommunications 2023 semestre 3 FI 2023-2024>}},
|
|
||||||
'S4': {79: {79: <FormSemestre 79 BUT Réseaux et Télécommunications semestre 4 FI 2023>}},
|
|
||||||
'S5': {},
|
|
||||||
'S6': {}
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
semestres_etudiant = self.cursus[etudid]["formsemestres"]
|
|
||||||
|
|
||||||
"""Ne conserve que les semestres qui l'auraient amené à être diplomé l'année visée"""
|
semestres_etudiant = self.cursus[etudid]["formsemestres"]
|
||||||
semestres_significatifs = {}
|
semestres_significatifs = {}
|
||||||
for fid in semestres_etudiant:
|
for fid in semestres_etudiant:
|
||||||
semestre = semestres_etudiant[fid]
|
semestre = semestres_etudiant[fid]
|
||||||
if pe_tools.get_annee_diplome_semestre(semestre) <= self.annee_diplome:
|
if pe_tools.get_annee_diplome_semestre(semestre) <= self.annee_diplome:
|
||||||
semestres_significatifs[fid] = semestre
|
semestres_significatifs[fid] = semestre
|
||||||
|
return semestres_significatifs
|
||||||
|
|
||||||
self.aggregats[etudid] = {}
|
def structure_cursus_etudiant(self, etudid: int):
|
||||||
|
"""Structure les informations sur les semestres suivis par un
|
||||||
|
étudiant, pour identifier les semestres qui seront pris en compte lors de ses calculs
|
||||||
|
de moyennes PE.
|
||||||
|
|
||||||
|
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
|
||||||
|
interclassement par semestre dans la promo.
|
||||||
|
"""
|
||||||
|
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_tools.TOUS_LES_SEMESTRES:
|
for nom_sem in pe_tools.TOUS_LES_SEMESTRES:
|
||||||
@ -274,33 +238,26 @@ class EtudiantsJuryPE:
|
|||||||
for fid in semestres_significatifs
|
for fid in semestres_significatifs
|
||||||
if semestres_significatifs[fid].semestre_id == i
|
if semestres_significatifs[fid].semestre_id == i
|
||||||
} # les semestres de n°i de l'étudiant
|
} # les semestres de n°i de l'étudiant
|
||||||
dernier_semestre_i = get_dernier_semestre(semestres_i)
|
self.cursus[etudid][nom_sem] = semestres_i
|
||||||
self.cursus[etudid][nom_sem] = dernier_semestre_i
|
|
||||||
self.aggregats[etudid][nom_sem] = {}
|
|
||||||
if dernier_semestre_i:
|
|
||||||
fid_dernier_semestre_i = list(dernier_semestre_i.keys())[0]
|
|
||||||
self.aggregats[etudid][nom_sem][fid_dernier_semestre_i] = semestres_i
|
|
||||||
|
|
||||||
|
|
||||||
"""Tri des semestres par aggrégat et par semestre terminal"""
|
def get_trajectoire(self, etudid: int, formsemestre_final: FormSemestre):
|
||||||
for aggregat in pe_tools.TOUS_LES_AGGREGATS:
|
"""Ensemble des semestres parcourus par
|
||||||
self.aggregats[etudid][aggregat] = {}
|
un étudiant pour l'amener à un semestre terminal.
|
||||||
|
|
||||||
"""L'aggrégat considéré (par ex: 3S), son nom de son semestre terminal (par ex: S3) et son numéro (par ex: 3)"""
|
Par ex: si formsemestre_terminal est un S3, ensemble des S1,
|
||||||
noms_semestre_de_aggregat = pe_tools.PARCOURS[aggregat]["aggregat"]
|
S2, S3 suivi pour l'amener au S3 (il peut y avoir plusieurs S1,
|
||||||
nom_semestre_terminal = noms_semestre_de_aggregat[-1]
|
ou S2, ou S3 s'il a redoublé).
|
||||||
numero_semestre_terminal = int(nom_semestre_terminal[-1])
|
|
||||||
|
|
||||||
"""Le formsemestre terminal de l'aggrégat (par ex: son dernier S3 en date)"""
|
Les semestres parcourus sont antérieurs (en terme de date de fin)
|
||||||
dernier_formsemestre_terminal = self.cursus[etudid][nom_semestre_terminal]
|
au formsemestre_terminal.
|
||||||
|
|
||||||
# for formsem_id_term in formsemestres_terminal:
|
Args:
|
||||||
if dernier_formsemestre_terminal: # ne considérant que le dernier
|
etudid: L'identifiant de l'étudiant
|
||||||
formsem_id_term = list(dernier_formsemestre_terminal.keys())[0]
|
formsemestre_final: le semestre final visé
|
||||||
|
"""
|
||||||
formsemestre_terminal = self.cursus[etudid]["formsemestres"][
|
numero_semestre_terminal = formsemestre_final.semestre_id
|
||||||
formsem_id_term
|
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 = {}
|
||||||
@ -308,15 +265,10 @@ class EtudiantsJuryPE:
|
|||||||
semestre = semestres_significatifs[fid]
|
semestre = semestres_significatifs[fid]
|
||||||
if (
|
if (
|
||||||
semestre.semestre_id <= numero_semestre_terminal
|
semestre.semestre_id <= numero_semestre_terminal
|
||||||
and semestre.date_fin <= formsemestre_terminal.date_fin
|
and semestre.date_fin <= formsemestre_final.date_fin
|
||||||
):
|
):
|
||||||
semestres_aggreges[fid] = semestre
|
semestres_aggreges[fid] = semestre
|
||||||
|
return semestres_aggreges
|
||||||
self.aggregats[etudid][aggregat][formsem_id_term] = semestres_aggreges
|
|
||||||
|
|
||||||
"""Vérifications"""
|
|
||||||
dernier_semestre_aggregat = get_dernier_semestre(semestres_aggreges)
|
|
||||||
assert dernier_semestre_aggregat == dernier_formsemestre_terminal
|
|
||||||
|
|
||||||
def get_formsemestres_terminaux_aggregat(self, aggregat: str):
|
def get_formsemestres_terminaux_aggregat(self, aggregat: str):
|
||||||
"""Pour un aggrégat donné, ensemble des formsemestres terminaux possibles pour l'aggrégat
|
"""Pour un aggrégat donné, ensemble des formsemestres terminaux possibles pour l'aggrégat
|
||||||
@ -333,47 +285,25 @@ class EtudiantsJuryPE:
|
|||||||
aggregat: L'aggrégat
|
aggregat: L'aggrégat
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Un dictionnaire {fid: FormSemestre(fid)}
|
Un dictionnaire ``{fid: FormSemestre(fid)}``
|
||||||
"""
|
"""
|
||||||
formsemestres_terminaux = {}
|
formsemestres_terminaux = {}
|
||||||
for etudid in self.aggregats:
|
for etudid in self.trajectoires:
|
||||||
if self.aggregats[etudid][aggregat]:
|
if self.trajectoires[etudid][aggregat]:
|
||||||
print(self.aggregats[etudid][aggregat])
|
trajectoire = self.trajectoires[etudid][aggregat]
|
||||||
"""Le formsemestre_id du semestre terminal de l'étudiant (s'il existe)"""
|
"""Le semestre terminal de l'étudiant de l'aggrégat"""
|
||||||
fid = list(self.aggregats[etudid][aggregat].keys())[0]
|
fid = trajectoire.semestre_final.formsemestre_id
|
||||||
"""Le formsemestre associé (en le prenant dans l'aggrégat)"""
|
formsemestres_terminaux[fid] = trajectoire.semestre_final
|
||||||
formsemestres_terminaux[fid] = self.aggregats[etudid][aggregat][fid][
|
|
||||||
fid
|
|
||||||
]
|
|
||||||
return formsemestres_terminaux
|
return formsemestres_terminaux
|
||||||
|
|
||||||
def get_semestres_a_aggreger(self, aggregat: str, formsemestre_id_terminal: int):
|
def get_formsemestres(self, semestres_recherches=None):
|
||||||
"""Pour un aggrégat donné associé à un formsemestre terminal cible, renvoie l'ensemble des semestres à
|
|
||||||
prendre en compte dans l'aggrégat sous la forme d'un dictionnaire {fid: FormSemestre(fid)}.
|
|
||||||
|
|
||||||
Fusionne les cursus individuels des étudiants, dont le cursus correspond à l'aggrégat visé.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
aggregat: Un aggrégat (par ex. 1A, 2A, 3S, 6S)
|
|
||||||
formsemestre_id_terminal: L'identifiant du formsemestre terminal de l'aggrégat, devant correspondre au
|
|
||||||
dernier semestre de l'aggrégat
|
|
||||||
"""
|
|
||||||
noms_semestres_aggreges = pe_tools.PARCOURS[aggregat]["aggregat"]
|
|
||||||
|
|
||||||
formsemestres = {}
|
|
||||||
for etudid in self.cursus:
|
|
||||||
cursus_etudiant = self.cursus[etudid][aggregat]
|
|
||||||
if formsemestre_id_terminal in cursus_etudiant:
|
|
||||||
formsemestres_etudiant = cursus_etudiant[formsemestre_id_terminal]
|
|
||||||
formsemestres = formsemestres | formsemestres_etudiant
|
|
||||||
return formsemestres
|
|
||||||
|
|
||||||
def get_formsemestres_jury(self, semestres_recherches=None):
|
|
||||||
"""Ayant connaissance des étudiants dont il faut calculer les moyennes pour
|
"""Ayant connaissance des étudiants dont il faut calculer les moyennes pour
|
||||||
le jury PE (attribut `self.etudiant_ids) et de leur cursus,
|
le jury PE (attribut `self.etudiant_ids) et de leur cursus (semestres
|
||||||
renvoie un dictionnaire `{fid: FormSemestre(fid)}`
|
parcourus),
|
||||||
contenant l'ensemble des formsemestres de leur cursus, dont il faudra calculer
|
renvoie un dictionnaire ``{fid: FormSemestre(fid)}``
|
||||||
la moyenne. Les formsemestres sont limités à ceux indiqués dans ``semestres_recherches``.
|
contenant l'ensemble des formsemestres de leurs cursus, dont il faudra calculer
|
||||||
|
la moyenne.
|
||||||
|
Les formsemestres sont limités à ceux indiqués dans ``semestres_recherches``.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
semestres_recherches: Une liste ou une chaine de caractères parmi :
|
semestres_recherches: Une liste ou une chaine de caractères parmi :
|
||||||
@ -384,20 +314,20 @@ class EtudiantsJuryPE:
|
|||||||
* '3S', '4S' : pour obtenir les combinaisons de semestres définies par les aggrégats
|
* '3S', '4S' : pour obtenir les combinaisons de semestres définies par les aggrégats
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Un dictionnaire de la forme {fid: FormSemestre(fid)}
|
Un dictionnaire de la forme ``{fid: FormSemestre(fid)}``
|
||||||
|
|
||||||
Remarque:
|
Remarque:
|
||||||
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_jury(pe_tools.AGGREGAT_DIPLOMANT)
|
semestres = self.get_formsemestres(pe_tools.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_jury(elmt)
|
semestres_elmt = self.get_formsemestres(elmt)
|
||||||
semestres = semestres | semestres_elmt
|
semestres = semestres | semestres_elmt
|
||||||
return semestres
|
return semestres
|
||||||
elif (
|
elif (
|
||||||
@ -405,7 +335,7 @@ class EtudiantsJuryPE:
|
|||||||
and semestres_recherches in pe_tools.TOUS_LES_AGGREGATS
|
and semestres_recherches in pe_tools.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_jury(
|
semestres = self.get_formsemestres(
|
||||||
pe_tools.PARCOURS[semestres_recherches]["aggregat"]
|
pe_tools.PARCOURS[semestres_recherches]["aggregat"]
|
||||||
)
|
)
|
||||||
return semestres
|
return semestres
|
||||||
@ -420,24 +350,21 @@ class EtudiantsJuryPE:
|
|||||||
nom_sem = semestres_recherches
|
nom_sem = semestres_recherches
|
||||||
semestres = {}
|
semestres = {}
|
||||||
for etudid in self.etudiants_ids:
|
for etudid in self.etudiants_ids:
|
||||||
for sem_terminal in self.aggregats[etudid]:
|
if self.cursus[etudid][nom_sem]:
|
||||||
for sem in self.aggregats[etudid][sem_terminal]:
|
semestres = semestres | self.cursus[etudid][nom_sem]
|
||||||
semestres = semestres | self.aggregats[etudid][sem_terminal][sem]
|
|
||||||
return semestres
|
return semestres
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError("Probleme de paramètres d'appel dans get_formsemestreids")
|
||||||
"Probleme de paramètres d'appel dans get_formsemestreids_du_jury"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_etudiants_dans_semestres(semestres: dict[FormSemestre]) -> set:
|
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
|
||||||
ensemble d'identifiant de semestres
|
ensemble d'identifiant de semestres
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -521,7 +448,8 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b
|
|||||||
etudid = identite.etudid
|
etudid = identite.etudid
|
||||||
|
|
||||||
"""Son dernier semestre en date"""
|
"""Son dernier semestre en date"""
|
||||||
dernier_formsemestre = identite.get_formsemestres()[0]
|
semestres = {sem.semestre_id: sem for sem in identite.get_formsemestres()}
|
||||||
|
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"""
|
||||||
@ -555,27 +483,22 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_dernier_semestre(semestres: dict[int, FormSemestre]):
|
def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]):
|
||||||
"""Renvoie le dernier semestre en date (de fin) d'un dictionnaire
|
"""Renvoie le dernier semestre en **date de fin** d'un dictionnaire
|
||||||
de semestres de la forme {fid: FormSemestre(fid)}.
|
de semestres de la forme ``{fid: FormSemestre(fid)}``.
|
||||||
La date prise en compte est celle marquant la **fin** des semestres.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
semestres: Un dictionnaire de semestres
|
semestres: Un dictionnaire de semestres
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
Un dictionnaire {fid: FormSemestre(fid)} contenant le semestre le plus récent
|
Le FormSemestre du semestre le plus récent
|
||||||
"""
|
"""
|
||||||
if semestres:
|
if semestres:
|
||||||
fid_dernier_semestre = list(semestres.keys())[0]
|
fid_dernier_semestre = list(semestres.keys())[0]
|
||||||
dernier_semestre = {fid_dernier_semestre: semestres[fid_dernier_semestre]}
|
dernier_semestre: FormSemestre = semestres[fid_dernier_semestre]
|
||||||
for fid in semestres:
|
for fid in semestres:
|
||||||
if (
|
if semestres[fid].date_fin > dernier_semestre.date_fin:
|
||||||
semestres[fid].date_fin
|
dernier_semestre = semestres[fid]
|
||||||
> dernier_semestre[fid_dernier_semestre].date_fin
|
|
||||||
):
|
|
||||||
dernier_semestre = {fid: semestres[fid]}
|
|
||||||
fid_dernier_semestre = fid
|
|
||||||
return dernier_semestre
|
return dernier_semestre
|
||||||
else:
|
else:
|
||||||
return {}
|
return None
|
||||||
|
124
app/pe/pe_interclassetag.py
Normal file
124
app/pe/pe_interclassetag.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from app.pe import pe_tagtable
|
||||||
|
from app.pe.pe_tools import PE_DEBUG, pe_print
|
||||||
|
import app.pe.pe_etudiant as pe_etudiant
|
||||||
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
|
from app.pe.pe_trajectoire import Trajectoire, TrajectoiresJuryPE
|
||||||
|
from app.comp import moy_sem
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
class AggregatInterclasseTag(pe_tagtable.TableTag):
|
||||||
|
"""Interclasse l'ensemble des étudiants diplômés à une année
|
||||||
|
donnée (celle du jury), pour un aggrégat donné (par ex: 'S2', '3S')
|
||||||
|
en reportant :
|
||||||
|
|
||||||
|
* les moyennes obtenues sur la trajectoire qu'il ont suivi pour atteindre le numéro de semestre de fin de l'aggrégat (indépendamment de son
|
||||||
|
formsemestres)
|
||||||
|
* calculant le classement sur les étudiants diplômes
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------------------------------------------
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
nom_aggregat: str,
|
||||||
|
etudiants: EtudiantsJuryPE,
|
||||||
|
trajectoires_jury_pe: TrajectoiresJuryPE,
|
||||||
|
trajectoires_taggues: dict[tuple, TrajectoireTag],
|
||||||
|
):
|
||||||
|
""""""
|
||||||
|
"""Table nommée au nom de l'aggrégat (par ex: 3S"""
|
||||||
|
pe_tagtable.TableTag.__init__(self, nom_aggregat)
|
||||||
|
|
||||||
|
"""Les étudiants diplômés et leurs trajectoires (cf. trajectoires.suivis)"""
|
||||||
|
self.diplomes_ids = etudiants.diplomes_ids
|
||||||
|
self.etudiants_diplomes = {etudid for etudid in self.diplomes_ids}
|
||||||
|
|
||||||
|
"""Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
|
||||||
|
"""
|
||||||
|
self.trajectoires: dict[int, Trajectoire] = {}
|
||||||
|
for trajectoire_id in trajectoires_jury_pe.trajectoires:
|
||||||
|
trajectoire = trajectoires_jury_pe.trajectoires[trajectoire_id]
|
||||||
|
if trajectoire_id[0] == nom_aggregat:
|
||||||
|
self.trajectoires[trajectoire_id] = trajectoire
|
||||||
|
|
||||||
|
self.trajectoires_taggues: dict[int, Trajectoire] = {}
|
||||||
|
for trajectoire_id in self.trajectoires:
|
||||||
|
self.trajectoires_taggues[trajectoire_id] = trajectoires_taggues[
|
||||||
|
trajectoire_id
|
||||||
|
]
|
||||||
|
|
||||||
|
"""Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
||||||
|
celles associées aux diplomés"""
|
||||||
|
self.suivis: dict[int, Trajectoire] = {}
|
||||||
|
for etudid in self.diplomes_ids:
|
||||||
|
self.suivis[etudid] = trajectoires_jury_pe.suivis[etudid][nom_aggregat]
|
||||||
|
|
||||||
|
"""Les tags"""
|
||||||
|
self.tags_sorted = self.do_taglist()
|
||||||
|
|
||||||
|
"""Construit la matrice de notes"""
|
||||||
|
self.notes = self.compute_notes_matrice()
|
||||||
|
|
||||||
|
"""Synthétise les moyennes/classements par tag"""
|
||||||
|
self.moyennes_tags = {}
|
||||||
|
for tag in self.tags_sorted:
|
||||||
|
moy_gen_tag = self.notes[tag]
|
||||||
|
class_gen_tag = moy_sem.comp_ranks_series(moy_gen_tag)[1] # en int
|
||||||
|
self.moyennes_tags[tag] = {
|
||||||
|
"notes": moy_gen_tag,
|
||||||
|
"classements": class_gen_tag,
|
||||||
|
"min": moy_gen_tag.min(),
|
||||||
|
"max": moy_gen_tag.max(),
|
||||||
|
"moy": moy_gen_tag.mean(),
|
||||||
|
"nb_inscrits": len(moy_gen_tag),
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_taglist(self):
|
||||||
|
"""Synthétise les tags à partir des trajectoires_tagguées
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Une liste de tags triés par ordre alphabétique
|
||||||
|
"""
|
||||||
|
tags = []
|
||||||
|
for trajectoire_id in self.trajectoires_taggues:
|
||||||
|
trajectoire = self.trajectoires_taggues[trajectoire_id]
|
||||||
|
tags.extend(trajectoire.tags_sorted)
|
||||||
|
return sorted(set(tags))
|
||||||
|
|
||||||
|
def get_etudids(self):
|
||||||
|
return list(self.etudiants_diplomes.keys())
|
||||||
|
|
||||||
|
def compute_notes_matrice(self):
|
||||||
|
"""Construit la matrice de notes (etudid x tags)
|
||||||
|
retraçant les moyennes obtenues par les étudiants dans les semestres associés à
|
||||||
|
l'aggrégat (une trajectoire ayant pour numéro de semestre final, celui de l'aggrégat).
|
||||||
|
"""
|
||||||
|
nb_tags = len(self.tags_sorted)
|
||||||
|
nb_etudiants = len(self.diplomes_ids)
|
||||||
|
|
||||||
|
"""Index de la matrice (etudids -> dim 0, tags -> dim 1)"""
|
||||||
|
etudids = [etud.etudid for etud in self.diplomes_ids]
|
||||||
|
tags = self.tags_sorted
|
||||||
|
|
||||||
|
"""Partant d'un dataframe vierge"""
|
||||||
|
df = pd.DataFrame(np.nan, index=etudids, columns=tags)
|
||||||
|
|
||||||
|
for trajectoire_id in self.trajectoires_taggues:
|
||||||
|
"""Charge les moyennes par tag de la trajectoire tagguée"""
|
||||||
|
notes = self.trajectoires_taggues[trajectoire_id].notes
|
||||||
|
|
||||||
|
"""Etudiants/Tags communs entre la trajectoire_tagguée et les données interclassées"""
|
||||||
|
etudids_communs = df.index.intersection(notes.index)
|
||||||
|
tags_communs = df.columns.intersection(notes.columns)
|
||||||
|
|
||||||
|
"""Injecte les notes par tag"""
|
||||||
|
df.loc[etudids_communs, tags_communs] = notes.loc[
|
||||||
|
etudids_communs, tags_communs
|
||||||
|
]
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
@ -68,8 +68,9 @@ from app.scodoc import sco_formsemestre
|
|||||||
from app.pe import pe_tagtable
|
from app.pe import pe_tagtable
|
||||||
from app.pe import pe_tools
|
from app.pe import pe_tools
|
||||||
from app.pe import pe_semestretag
|
from app.pe import pe_semestretag
|
||||||
from app.pe import pe_settag
|
from app.pe import pe_trajectoiretag
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
|
from app.pe.pe_trajectoire import TrajectoiresJuryPE
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------
|
||||||
@ -154,17 +155,24 @@ class JuryPE(object):
|
|||||||
filename, formsemestretag.str_tagtable(), path="details_semestres"
|
filename, formsemestretag.str_tagtable(), path="details_semestres"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
"""Génère les trajectoires (combinaison de semestres suivis
|
||||||
|
par un étudiant pour atteindre le semestre final d'un aggrégat)
|
||||||
|
"""
|
||||||
|
self.trajectoires = TrajectoiresJuryPE(self.diplome)
|
||||||
|
self.trajectoires.cree_trajectoires(self.etudiants)
|
||||||
|
|
||||||
|
|
||||||
"""Génère les aggrégats de semestre (par ex: 1A, 3S, 5S) avec calcul
|
"""Génère les aggrégats de semestre (par ex: 1A, 3S, 5S) avec calcul
|
||||||
des moyennes pour le jury"""
|
des moyennes pour le jury"""
|
||||||
self.aggregats_taggues = compute_aggregats_tag(
|
self.trajectoires_tagguees = compute_trajectoires_tag(
|
||||||
self.etudiants, self.semestres_taggues
|
self.etudiants, self.semestres_taggues
|
||||||
)
|
)
|
||||||
|
|
||||||
if pe_tools.PE_DEBUG:
|
if pe_tools.PE_DEBUG:
|
||||||
"""Intègre le bilan des aggrégats de semestres au zip final"""
|
"""Intègre le bilan des aggrégats de semestres au zip final"""
|
||||||
for aggregat in self.aggregats_taggues:
|
for aggregat in self.trajectoires_tagguees:
|
||||||
for fid in self.aggregats_taggues[aggregat]:
|
for fid in self.trajectoires_tagguees[aggregat]:
|
||||||
set_tag = self.aggregats_taggues[aggregat][fid]
|
set_tag = self.trajectoires_tagguees[aggregat][fid]
|
||||||
filename = set_tag.nom.replace(" ", "_") + ".csv"
|
filename = set_tag.nom.replace(" ", "_") + ".csv"
|
||||||
pe_tools.pe_print(f" - Export csv de {filename} ")
|
pe_tools.pe_print(f" - Export csv de {filename} ")
|
||||||
self.add_file_to_zip(
|
self.add_file_to_zip(
|
||||||
@ -174,7 +182,7 @@ class JuryPE(object):
|
|||||||
"""Génère les interclassements par (nom d') aggrégat"""
|
"""Génère les interclassements par (nom d') aggrégat"""
|
||||||
self.aggregats_taggues_interclasses = compute_interclassements(
|
self.aggregats_taggues_interclasses = compute_interclassements(
|
||||||
self.etudiants, #
|
self.etudiants, #
|
||||||
self.aggregats_taggues,
|
self.trajectoires_tagguees,
|
||||||
)
|
)
|
||||||
# Les interclassements
|
# Les interclassements
|
||||||
# --------------------
|
# --------------------
|
||||||
@ -276,7 +284,7 @@ class JuryPE(object):
|
|||||||
self.etudiants.cursus[etudid][nom]
|
self.etudiants.cursus[etudid][nom]
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
tagtable = self.aggregats_taggues[nom][
|
tagtable = self.trajectoires_tagguees[nom][
|
||||||
self.etudiants.cursus[etudid][nom]
|
self.etudiants.cursus[etudid][nom]
|
||||||
]
|
]
|
||||||
for tag in tagtable.get_all_tags():
|
for tag in tagtable.get_all_tags():
|
||||||
@ -630,7 +638,7 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE):
|
|||||||
"""Création des semestres taggués, de type 'S1', 'S2', ..."""
|
"""Création des semestres taggués, de type 'S1', 'S2', ..."""
|
||||||
pe_tools.pe_print("*** Création des semestres taggués")
|
pe_tools.pe_print("*** Création des semestres taggués")
|
||||||
|
|
||||||
formsemestres = etudiants.get_formsemestres_jury(
|
formsemestres = etudiants.get_formsemestres(
|
||||||
semestres_recherches=pe_tools.TOUS_LES_SEMESTRES
|
semestres_recherches=pe_tools.TOUS_LES_SEMESTRES
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -655,14 +663,18 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE):
|
|||||||
return semestres_tags
|
return semestres_tags
|
||||||
|
|
||||||
|
|
||||||
def compute_aggregats_tag(etudiants: EtudiantsJuryPE, semestres_tag: dict[SemestreTag]):
|
def compute_trajectoires_tag(trajectoires: TrajectoiresJuryPE,
|
||||||
"""Créé les combinaisons de semestres (aggrégats), en calculant les moyennes et les
|
etudiants: EtudiantsJuryPE,
|
||||||
classements par tag pour chacune. Chaque combinaison (aggrégat) est identifiée
|
semestres_taggues: dict[int, SemestreTag]):
|
||||||
par un formsemestre terminal.
|
"""Créée les trajectoires tagguées (combinaison aggrégeant plusieurs semestres au sens
|
||||||
|
d'un aggrégat (par ex: '3S')),
|
||||||
|
en calculant les moyennes et les classements par tag pour chacune.
|
||||||
|
|
||||||
|
Pour rappel : Chaque trajectoire est identifiée un nom d'aggrégat et par un formsemestre terminal.
|
||||||
|
|
||||||
Par exemple :
|
Par exemple :
|
||||||
|
|
||||||
* combinaisons '3S' : S1+S2+S3 en prenant en compte tous les S3 qu'ont fréquentés les
|
* combinaisons '3S' : S1+S2+S3 en prenant en compte tous les S3 qu'ont fréquenté les
|
||||||
étudiants du jury PE. Ces S3 marquent les formsemestre terminal de chaque combinaison.
|
étudiants du jury PE. Ces S3 marquent les formsemestre terminal de chaque combinaison.
|
||||||
|
|
||||||
* combinaisons 'S2' : 1 seul S2 pour des étudiants n'ayant pas redoublé, 2 pour des redoublants (dont les
|
* combinaisons 'S2' : 1 seul S2 pour des étudiants n'ayant pas redoublé, 2 pour des redoublants (dont les
|
||||||
@ -680,53 +692,24 @@ def compute_aggregats_tag(etudiants: EtudiantsJuryPE, semestres_tag: dict[Semest
|
|||||||
|
|
||||||
pe_tools.pe_print(" *** Création des aggrégats ")
|
pe_tools.pe_print(" *** Création des aggrégats ")
|
||||||
|
|
||||||
sets_tags = {}
|
trajectoires_tagguees = {}
|
||||||
|
|
||||||
for aggregat in pe_tools.TOUS_LES_SEMESTRES + pe_tools.TOUS_LES_AGGREGATS:
|
for trajectoire_id in trajectoires_tagguees:
|
||||||
sets_tags[aggregat] = {}
|
trajectoire = trajectoires[trajectoire_id]
|
||||||
|
nom = trajectoire.get_repr()
|
||||||
|
|
||||||
"""Semestres aggrégés"""
|
pe_tools.pe_print(f" --> Fusion {nom}")
|
||||||
if aggregat in pe_tools.TOUS_LES_SEMESTRES: # par ex. 'S2'
|
|
||||||
noms_semestres_aggreges = [aggregat]
|
|
||||||
else: # par ex. "5S"
|
|
||||||
noms_semestres_aggreges = pe_tools.PARCOURS[aggregat]["aggregat"]
|
|
||||||
nom_semestre_terminal = noms_semestres_aggreges[-1]
|
|
||||||
|
|
||||||
pe_tools.pe_print(f"* {aggregat}: " + "+".join(noms_semestres_aggreges))
|
"""Création de la trajectoire_tagguee associée"""
|
||||||
|
trajectoire_tagguee = pe_trajectoiretag.TrajectoireTag(
|
||||||
"""Les formsemestres terminaux des aggrégats"""
|
nom, trajectoire, semestres_taggues, etudiants
|
||||||
formsemestres_terminal = etudiants.get_formsemestres_terminaux_aggregat(
|
|
||||||
aggregat
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for frmsem_id in formsemestres_terminal:
|
"""Mémorise le résultat"""
|
||||||
formsemestre_terminal = formsemestres_terminal[frmsem_id]
|
trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee
|
||||||
"""Nom du set_tag"""
|
|
||||||
nom = "Aggrégat %s %d %s %d-%d" % (
|
|
||||||
aggregat,
|
|
||||||
frmsem_id,
|
|
||||||
"+".join(noms_semestres_aggreges),
|
|
||||||
formsemestre_terminal.date_debut.year,
|
|
||||||
formsemestre_terminal.date_fin.year,
|
|
||||||
)
|
|
||||||
|
|
||||||
"""Semestres à aggreger dans l'aggrégat ayant amené des étudiants jusqu'au formsemestre_terminal"""
|
return trajectoires_tagguees
|
||||||
semestres_aggreges = etudiants.get_semestres_a_aggreger(aggregat, frmsem_id)
|
|
||||||
|
|
||||||
pe_tools.pe_print(" --> Fusion de :")
|
|
||||||
for fid in semestres_aggreges:
|
|
||||||
pe_tools.pe_print(str(semestres_aggreges[fid]))
|
|
||||||
|
|
||||||
"""Création du settag associé"""
|
|
||||||
settag = pe_settag.SetTag(
|
|
||||||
nom, formsemestre_terminal, semestres_aggreges, semestres_tag, etudiants
|
|
||||||
)
|
|
||||||
|
|
||||||
settag.compute_notes_cube() # Calcul les moyennes, les rangs, ..
|
|
||||||
|
|
||||||
sets_tags[aggregat][fid] = settag # Mémorise le résultat
|
|
||||||
|
|
||||||
return sets_tags
|
|
||||||
|
|
||||||
|
|
||||||
def compute_interclassements(
|
def compute_interclassements(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from app.pe import pe_tagtable
|
from app.pe import pe_tagtable
|
||||||
from app.pe.pe_tools import PE_DEBUG, pe_print
|
from app.pe.pe_tools import PE_DEBUG, pe_print
|
||||||
import app.pe.pe_etudiant as pe_etudiant
|
import app.pe.pe_etudiant as pe_etudiant
|
||||||
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
|
|
||||||
class SetTagInterClasse(pe_tagtable.TableTag):
|
class SetTagInterClasse(pe_tagtable.TableTag):
|
||||||
"""Interclasse les étudiants d'une promo (ceux diplômé) par aggrégat de même nom
|
"""Interclasse les étudiants d'une promo (ceux diplômé) par aggrégat de même nom
|
||||||
|
149
app/pe/pe_trajectoire.py
Normal file
149
app/pe/pe_trajectoire.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import app.pe.pe_tools as pe_tools
|
||||||
|
from app.models import FormSemestre
|
||||||
|
from app.pe.pe_etudiant import EtudiantsJuryPE, get_dernier_semestre_en_date
|
||||||
|
|
||||||
|
|
||||||
|
class Trajectoire:
|
||||||
|
"""Modélise, pour un aggrégat visé (par ex: 'S2', '3S', '2A')
|
||||||
|
et un ensemble d'étudiants donnés,
|
||||||
|
la combinaison des formsemestres des étudiants amenant à un semestre
|
||||||
|
terminal visé.
|
||||||
|
|
||||||
|
Si l'aggrégat est un semestre de type Si, elle stocke le (ou les)
|
||||||
|
formsemestres de numéro i qu'ont suivis l'étudiant pour atteindre le Si
|
||||||
|
(en général 1 si personnes n'a redoublé, mais 2 s'il y a des redoublants)
|
||||||
|
|
||||||
|
Pour des aggrégats de type iS ou iA (par ex, 3A=S1+S2+S3), elle identifie
|
||||||
|
les semestres que les étudiants ont suivis pour les amener jusqu'au semestre
|
||||||
|
terminal de la trajectoire (par ex: ici un S3).
|
||||||
|
Ces semestres peuvent être :
|
||||||
|
* des S1+S2+S1+S2+S3 si redoublement de la 1ère année
|
||||||
|
* des S1+S2+(année de césure)+S3 si césure, ...
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, nom_aggregat: str, semestre_final: FormSemestre):
|
||||||
|
"""Modélise un ensemble de formsemestres d'étudiants
|
||||||
|
amenant à un semestre terminal
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nom_aggregat: Un nom d'aggrégat (par ex: '5S')
|
||||||
|
semestre_final: Le semestre final de l'aggrégat
|
||||||
|
"""
|
||||||
|
self.nom = nom_aggregat
|
||||||
|
self.semestre_final = semestre_final
|
||||||
|
self.trajectoire_id = (nom_aggregat, semestre_final.formsemestre_id)
|
||||||
|
|
||||||
|
"""Les semestres à aggréger"""
|
||||||
|
self.semestres_aggreges = {}
|
||||||
|
|
||||||
|
|
||||||
|
def add_semestres_a_aggreger(self, semestres: dict[int: FormSemestre]):
|
||||||
|
"""Ajoute des semestres au semestre à aggréger
|
||||||
|
|
||||||
|
Args:
|
||||||
|
semestres: Dictionnaire ``{fid: FormSemestre(fid)} à ajouter``
|
||||||
|
"""
|
||||||
|
self.semestres_aggreges = self.semestres_aggreges | semestres
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_repr(self):
|
||||||
|
"""Représentation textuelle d'une trajectoire
|
||||||
|
basée sur ses semestres aggrégés"""
|
||||||
|
noms = []
|
||||||
|
for fid in self.semestres_aggreges:
|
||||||
|
semestre = self.semestres_aggreges[fid]
|
||||||
|
noms.append(f"S{semestre.semestre_id}({fid})")
|
||||||
|
noms = sorted(noms)
|
||||||
|
repr = f"{self.nom} ({self.semestre_final.formsemestre_id}) {self.semestre_final.date_fin.year}"
|
||||||
|
if noms:
|
||||||
|
repr += " - " + "+".join(noms)
|
||||||
|
return repr
|
||||||
|
|
||||||
|
|
||||||
|
class TrajectoiresJuryPE:
|
||||||
|
"""Centralise toutes les trajectoires du jury PE"""
|
||||||
|
|
||||||
|
def __init__(self, annee_diplome: int):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
annee_diplome: L'année de diplomation
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.annee_diplome = annee_diplome
|
||||||
|
"""Toutes les trajectoires possibles"""
|
||||||
|
self.trajectoires: dict[tuple: Trajectoire] = {}
|
||||||
|
"""Quelle trajectoires pour quel étudiant :
|
||||||
|
dictionnaire {etudid: {nom_aggregat: Trajectoire}}"""
|
||||||
|
self.suivi: dict[int: str] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def cree_trajectoires(self, etudiants: EtudiantsJuryPE):
|
||||||
|
"""Créé toutes les trajectoires, au regard du cursus des étudiants
|
||||||
|
analysés + les mémorise dans les données de l'étudiant
|
||||||
|
"""
|
||||||
|
|
||||||
|
for nom_aggregat in pe_tools.TOUS_LES_SEMESTRES + pe_tools.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 = pe_tools.PARCOURS[nom_aggregat]["aggregat"]
|
||||||
|
nom_semestre_terminal = noms_semestre_de_aggregat[-1]
|
||||||
|
|
||||||
|
for etudid in etudiants.cursus:
|
||||||
|
if etudid not in self.suivi:
|
||||||
|
self.suivi[etudid] = {}
|
||||||
|
|
||||||
|
"""Le formsemestre terminal (dernier en date) associé au
|
||||||
|
semestre marquant la fin de l'aggrégat
|
||||||
|
(par ex: son dernier S3 en date)"""
|
||||||
|
semestres = etudiants.cursus[etudid][nom_semestre_terminal]
|
||||||
|
if semestres:
|
||||||
|
formsemestre_final = get_dernier_semestre_en_date(semestres)
|
||||||
|
|
||||||
|
"""Ajout ou récupération de la trajectoire"""
|
||||||
|
trajectoire_id = (nom_aggregat, formsemestre_final.formsemestre_id)
|
||||||
|
if trajectoire_id not in self.trajectoires:
|
||||||
|
trajectoire = Trajectoire(nom_aggregat, formsemestre_final)
|
||||||
|
self.trajectoires[trajectoire_id] = trajectoire
|
||||||
|
else:
|
||||||
|
trajectoire = self.trajectoires[trajectoire_id]
|
||||||
|
|
||||||
|
"""La liste des semestres de l'étudiant à prendre en compte
|
||||||
|
pour cette trajectoire"""
|
||||||
|
semestres_a_aggreger = etudiants.get_trajectoire(etudid, formsemestre_final)
|
||||||
|
|
||||||
|
"""Ajout des semestres à la trajectoire"""
|
||||||
|
trajectoire.add_semestres_a_aggreger(semestres_a_aggreger)
|
||||||
|
|
||||||
|
"""Mémoire la trajectoire suivie par l'étudiant"""
|
||||||
|
self.suivi[etudid][nom_aggregat] = trajectoire
|
||||||
|
|
||||||
|
"""Vérifications"""
|
||||||
|
# dernier_semestre_aggregat = get_dernier_semestre_en_date(semestres_aggreges)
|
||||||
|
# assert dernier_semestre_aggregat == formsemestre_terminal
|
||||||
|
|
||||||
|
|
||||||
|
def get_semestres_a_aggreger(self, aggregat: str, formsemestre_id_terminal: int):
|
||||||
|
"""Pour un nom d'aggrégat donné (par ex: 'S3') et un semestre terminal cible
|
||||||
|
identifié par son formsemestre_id (par ex: 'S3 2022-2023'),
|
||||||
|
renvoie l'ensemble des semestres à prendre en compte dans
|
||||||
|
l'aggrégat sous la forme d'un dictionnaire {fid: FormSemestre(fid)}.
|
||||||
|
|
||||||
|
Fusionne les cursus individuels des étudiants, dont le cursus correspond
|
||||||
|
à l'aggrégat visé.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
aggregat: Un aggrégat (par ex. 1A, 2A, 3S, 6S)
|
||||||
|
formsemestre_id_terminal: L'identifiant du formsemestre terminal de l'aggrégat, devant correspondre au
|
||||||
|
dernier semestre de l'aggrégat
|
||||||
|
"""
|
||||||
|
noms_semestres_aggreges = pe_tools.PARCOURS[aggregat]["aggregat"]
|
||||||
|
|
||||||
|
formsemestres = {}
|
||||||
|
for etudid in self.cursus:
|
||||||
|
cursus_etudiant = self.cursus[etudid][aggregat]
|
||||||
|
if formsemestre_id_terminal in cursus_etudiant:
|
||||||
|
formsemestres_etudiant = cursus_etudiant[formsemestre_id_terminal]
|
||||||
|
formsemestres = formsemestres | formsemestres_etudiant
|
||||||
|
return formsemestres
|
||||||
|
|
@ -35,6 +35,7 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
|
|
||||||
@author: barasc
|
@author: barasc
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from app.comp import moy_sem
|
from app.comp import moy_sem
|
||||||
from app.comp.res_sem import load_formsemestre_results
|
from app.comp.res_sem import load_formsemestre_results
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
@ -42,35 +43,43 @@ from app.pe.pe_semestretag import SemestreTag
|
|||||||
from app.pe import pe_tagtable
|
from app.pe import pe_tagtable
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from app.pe.pe_trajectoire import Trajectoire
|
||||||
|
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
|
from app.pe.pe_trajectoire import TrajectoiresJuryPE
|
||||||
|
|
||||||
|
|
||||||
class SetTag(pe_tagtable.TableTag):
|
class TrajectoireTag(pe_tagtable.TableTag):
|
||||||
"""Agrège plusieurs semestres (ou settag) taggués (SemestreTag/Settag de 1 à 4) pour extraire des moyennes
|
"""Calcule les moyennes par tag d'une combinaison de semestres
|
||||||
et des classements par tag pour un groupe d'étudiants donnés.
|
(trajectoires), identifiée par un nom d'aggrégat (par ex: '3S') et
|
||||||
par. exemple fusion d'un parcours ['S1', 'S2', 'S3'] donnant un nom_combinaison = '3S'
|
par un semestre terminal, pour extraire les classements par tag pour un
|
||||||
Le settag est identifié sur la base du dernier semestre (ici le 'S3') ;
|
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
||||||
les étudiants considérés sont donc ceux inscrits dans ce S3
|
participé au semestre terminal.
|
||||||
à condition qu'ils disposent d'un parcours sur tous les semestres fusionnés valides (par. ex
|
|
||||||
un etudiant non inscrit dans un S1 mais dans un S2 et un S3 n'est pas pris en compte).
|
Par ex: fusion d'un parcours ['S1', 'S2', 'S3'] donnant un nom_combinaison = '3S'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------------------------------------------------
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
nom,
|
nom: str,
|
||||||
formsemestre_terminal: FormSemestre,
|
trajectoire: Trajectoire,
|
||||||
semestres_aggreges: dict[int, FormSemestre],
|
|
||||||
semestres_taggues: dict[int, SemestreTag],
|
semestres_taggues: dict[int, SemestreTag],
|
||||||
donnees_etudiants: EtudiantsJuryPE,
|
donnees_etudiants: EtudiantsJuryPE,
|
||||||
):
|
):
|
||||||
pe_tagtable.TableTag.__init__(self, nom)
|
""" """
|
||||||
|
pe_tagtable.TableTag.__init__(self, nom=nom)
|
||||||
|
|
||||||
|
"""La trajectoire associée"""
|
||||||
|
self.trajectoire_id = trajectoire.trajectoire_id
|
||||||
|
self.trajectoire = trajectoire
|
||||||
|
|
||||||
"""Le formsemestre terminal et les semestres aggrégés"""
|
"""Le formsemestre terminal et les semestres aggrégés"""
|
||||||
self.formsemestre_terminal = formsemestre_terminal
|
self.formsemestre_terminal = trajectoire.semestre_final
|
||||||
nt = load_formsemestre_results(formsemestre_terminal)
|
nt = load_formsemestre_results(self.formsemestre_terminal)
|
||||||
self.semestres_aggreges = semestres_aggreges
|
|
||||||
|
self.semestres_aggreges = trajectoire.semestres_aggreges
|
||||||
|
|
||||||
"""Les semestres tags associés aux semestres aggrégés"""
|
"""Les semestres tags associés aux semestres aggrégés"""
|
||||||
try:
|
try:
|
||||||
@ -83,6 +92,7 @@ class SetTag(pe_tagtable.TableTag):
|
|||||||
|
|
||||||
"""Les étudiants (état civil + cursus connu)"""
|
"""Les étudiants (état civil + cursus connu)"""
|
||||||
self.etuds = nt.etuds
|
self.etuds = nt.etuds
|
||||||
|
# assert self.etuds == trajectoire.suivi # manque-t-il des étudiants ?
|
||||||
self.etudiants = {etud.etudid: etud.etat_civil for etud in self.etuds}
|
self.etudiants = {etud.etudid: etud.etat_civil for etud in self.etuds}
|
||||||
self.cursus = {
|
self.cursus = {
|
||||||
etudid: donnees_etudiants.cursus[etudid] for etudid in self.etudiants
|
etudid: donnees_etudiants.cursus[etudid] for etudid in self.etudiants
|
||||||
@ -155,7 +165,6 @@ class SetTag(pe_tagtable.TableTag):
|
|||||||
def get_etudids(self):
|
def get_etudids(self):
|
||||||
return list(self.etudiants.keys())
|
return list(self.etudiants.keys())
|
||||||
|
|
||||||
# -------------------------------------------------------------------------------------------------------------------
|
|
||||||
def do_taglist(self):
|
def do_taglist(self):
|
||||||
"""Synthétise les tags à partir des semestres (taggués) aggrégés
|
"""Synthétise les tags à partir des semestres (taggués) aggrégés
|
||||||
|
|
Loading…
Reference in New Issue
Block a user