forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -47,6 +47,7 @@ from flask import g
|
|||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
|
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
|
from app.pe.pe_rcs import TYPES_RCS
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc.sco_logos import find_logo
|
from app.scodoc.sco_logos import find_logo
|
||||||
|
|
||||||
@ -72,67 +73,11 @@ Descriptif d'un parcours classique BUT
|
|||||||
TODO:: A améliorer si BUT en moins de 6 semestres
|
TODO:: A améliorer si BUT en moins de 6 semestres
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PARCOURS = {
|
|
||||||
"S1": {
|
|
||||||
"aggregat": ["S1"],
|
|
||||||
"descr": "Semestre 1 (S1)",
|
|
||||||
},
|
|
||||||
"S2": {
|
|
||||||
"aggregat": ["S2"],
|
|
||||||
"descr": "Semestre 2 (S2)",
|
|
||||||
},
|
|
||||||
"1A": {
|
|
||||||
"aggregat": ["S1", "S2"],
|
|
||||||
"descr": "BUT1 (S1+S2)",
|
|
||||||
},
|
|
||||||
"S3": {
|
|
||||||
"aggregat": ["S3"],
|
|
||||||
"descr": "Semestre 3 (S3)",
|
|
||||||
},
|
|
||||||
"S4": {
|
|
||||||
"aggregat": ["S4"],
|
|
||||||
"descr": "Semestre 4 (S4)",
|
|
||||||
},
|
|
||||||
"2A": {
|
|
||||||
"aggregat": ["S3", "S4"],
|
|
||||||
"descr": "BUT2 (S3+S4)",
|
|
||||||
},
|
|
||||||
"3S": {
|
|
||||||
"aggregat": ["S1", "S2", "S3"],
|
|
||||||
"descr": "Moyenne du semestre 1 au semestre 3 (S1+S2+S3)",
|
|
||||||
},
|
|
||||||
"4S": {
|
|
||||||
"aggregat": ["S1", "S2", "S3", "S4"],
|
|
||||||
"descr": "Moyenne du semestre 1 au semestre 4 (S1+S2+S3+S4)",
|
|
||||||
},
|
|
||||||
"S5": {
|
|
||||||
"aggregat": ["S5"],
|
|
||||||
"descr": "Semestre 5 (S5)",
|
|
||||||
},
|
|
||||||
"S6": {
|
|
||||||
"aggregat": ["S6"],
|
|
||||||
"descr": "Semestre 6 (S6)",
|
|
||||||
},
|
|
||||||
"3A": {
|
|
||||||
"aggregat": ["S5", "S6"],
|
|
||||||
"descr": "3ème année (S5+S6)",
|
|
||||||
},
|
|
||||||
"5S": {
|
|
||||||
"aggregat": ["S1", "S2", "S3", "S4", "S5"],
|
|
||||||
"descr": "Moyenne du semestre 1 au semestre 5 (S1+S2+S3+S4+S5)",
|
|
||||||
},
|
|
||||||
"6S": {
|
|
||||||
"aggregat": ["S1", "S2", "S3", "S4", "S5", "S6"],
|
|
||||||
"descr": "Moyenne globale BUT (S1+S2+S3+S4+S5+S6)",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
NBRE_SEMESTRES_DIPLOMANT = 6
|
NBRE_SEMESTRES_DIPLOMANT = 6
|
||||||
AGGREGAT_DIPLOMANT = (
|
AGGREGAT_DIPLOMANT = (
|
||||||
"6S" # aggrégat correspondant à la totalité des notes pour le diplôme
|
"6S" # aggrégat correspondant à la totalité des notes pour le diplôme
|
||||||
)
|
)
|
||||||
TOUS_LES_SEMESTRES = PARCOURS[AGGREGAT_DIPLOMANT]["aggregat"]
|
TOUS_LES_SEMESTRES = TYPES_RCS[AGGREGAT_DIPLOMANT]["aggregat"]
|
||||||
TOUS_LES_AGGREGATS = [cle for cle in PARCOURS.keys() if not cle.startswith("S")]
|
|
||||||
TOUS_LES_PARCOURS = list(PARCOURS.keys())
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------
|
||||||
|
@ -37,6 +37,7 @@ Created on 17/01/2024
|
|||||||
"""
|
"""
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
import app.pe.pe_rcs
|
||||||
from app.models import FormSemestre, Identite, Formation
|
from app.models import FormSemestre, Identite, Formation
|
||||||
from app.pe import pe_comp, pe_affichage
|
from app.pe import pe_comp, pe_affichage
|
||||||
from app.scodoc import codes_cursus
|
from app.scodoc import codes_cursus
|
||||||
@ -121,16 +122,20 @@ class EtudiantsJuryPE:
|
|||||||
|
|
||||||
# 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()
|
||||||
|
"""Les identités des étudiants diplômés"""
|
||||||
|
|
||||||
self.diplomes_ids = set(self.etudiants_diplomes.keys())
|
self.diplomes_ids = set(self.etudiants_diplomes.keys())
|
||||||
|
"""Les identifiants des étudiants diplômés"""
|
||||||
|
|
||||||
self.etudiants_ids = set(self.identites.keys())
|
self.etudiants_ids = set(self.identites.keys())
|
||||||
|
"""Les identifiants des étudiants (diplômés, redoublants ou ayant abandonnés) à traiter"""
|
||||||
self.formsemestres_jury_ids = self.get_formsemestres()
|
|
||||||
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
|
|
||||||
|
|
||||||
# Les abandons (pour debug)
|
# Les abandons (pour debug)
|
||||||
self.abandons = self.get_etudiants_redoublants_ou_reorientes()
|
self.abandons = self.get_etudiants_redoublants_ou_reorientes()
|
||||||
|
"""Les identités des étudiants ayant redoublés ou ayant abandonnés"""
|
||||||
|
|
||||||
self.abandons_ids = set(self.abandons)
|
self.abandons_ids = set(self.abandons)
|
||||||
|
"""Les identifiants des étudiants ayant redoublés ou ayant abandonnés"""
|
||||||
|
|
||||||
# Synthèse
|
# Synthèse
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
@ -142,9 +147,6 @@ class EtudiantsJuryPE:
|
|||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
f" => {nbre_abandons} étudiants non considérés (redoublement, réorientation, abandon"
|
f" => {nbre_abandons} étudiants non considérés (redoublement, réorientation, abandon"
|
||||||
)
|
)
|
||||||
pe_affichage.pe_print(
|
|
||||||
f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne"
|
|
||||||
)
|
|
||||||
# pe_affichage.pe_print(
|
# pe_affichage.pe_print(
|
||||||
# " => 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]])
|
||||||
@ -270,62 +272,16 @@ class EtudiantsJuryPE:
|
|||||||
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 i in range(1, pe_comp.NBRE_SEMESTRES_DIPLOMANT+1):
|
||||||
i = int(nom_sem[1]) # le n° du semestre
|
|
||||||
# les semestres de n°i de l'étudiant:
|
# les semestres de n°i de l'étudiant:
|
||||||
semestres_i = {
|
semestres_i = {
|
||||||
fid: sem_sig
|
fid: sem_sig
|
||||||
for fid, sem_sig in semestres_significatifs.items()
|
for fid, sem_sig in semestres_significatifs.items()
|
||||||
if sem_sig.semestre_id == i
|
if sem_sig.semestre_id == i
|
||||||
}
|
}
|
||||||
self.cursus[etudid][nom_sem] = semestres_i
|
self.cursus[etudid][f"S{i}"] = semestres_i
|
||||||
|
|
||||||
def get_trajectoire(
|
|
||||||
self, etudid: int, formsemestre_final: FormSemestre, nom_aggregat: str
|
|
||||||
):
|
|
||||||
"""Ensemble des semestres parcourus par
|
|
||||||
un étudiant pour l'amener à un semestre terminal.
|
|
||||||
|
|
||||||
Si nom_aggregat est de type "Si", limite les semestres à ceux de numéro i.
|
|
||||||
Par ex: si formsemestre_terminal est un S3 et nom_agrregat "S3", ne prend en compte que les
|
|
||||||
semestres 3.
|
|
||||||
|
|
||||||
Si nom_aggregat est de type "iA" ou "iS" (incluant plusieurs numéros de semestres), prend en
|
|
||||||
compte les dit numéros de semestres.
|
|
||||||
|
|
||||||
Par ex: si formsemestre_terminal est un S3, ensemble des S1,
|
|
||||||
S2, S3 suivi pour l'amener au S3 (il peut y avoir plusieurs S1,
|
|
||||||
ou S2, ou S3 s'il a redoublé).
|
|
||||||
|
|
||||||
Les semestres parcourus sont antérieurs (en terme de date de fin)
|
|
||||||
au formsemestre_terminal.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
etudid: L'identifiant de l'étudiant
|
|
||||||
formsemestre_final: le semestre final visé
|
|
||||||
"""
|
|
||||||
numero_semestre_terminal = formsemestre_final.semestre_id
|
|
||||||
semestres_significatifs = self.get_semestres_significatifs(etudid)
|
|
||||||
|
|
||||||
if nom_aggregat.startswith("S"): # les semestres
|
|
||||||
numero_semestres_possibles = [numero_semestre_terminal]
|
|
||||||
elif nom_aggregat.endswith("A"): # les années
|
|
||||||
numero_semestres_possibles = [
|
|
||||||
int(sem[-1]) for sem in pe_comp.PARCOURS[nom_aggregat]["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_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
|
||||||
@ -353,64 +309,6 @@ class EtudiantsJuryPE:
|
|||||||
formsemestres_terminaux[fid] = trajectoire.formsemestre_final
|
formsemestres_terminaux[fid] = trajectoire.formsemestre_final
|
||||||
return formsemestres_terminaux
|
return formsemestres_terminaux
|
||||||
|
|
||||||
def get_formsemestres(self, semestres_recherches=None):
|
|
||||||
"""Ayant connaissance des étudiants dont il faut calculer les moyennes pour
|
|
||||||
le jury PE (attribut `self.etudiant_ids) et de leur cursus (semestres
|
|
||||||
parcourus),
|
|
||||||
renvoie un dictionnaire ``{fid: FormSemestre(fid)}``
|
|
||||||
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:
|
|
||||||
semestres_recherches: Une liste ou une chaine de caractères parmi :
|
|
||||||
|
|
||||||
* None : pour obtenir tous les formsemestres du jury
|
|
||||||
* 'Si' : pour obtenir les semestres de n° i (par ex. 'S1')
|
|
||||||
* 'iA' : pour obtenir les semestres de l'année i (par ex. '1A' donne ['S1, 'S2'])
|
|
||||||
* '3S', '4S' : pour obtenir les combinaisons de semestres définies par les aggrégats
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Un dictionnaire de la forme `{fid: FormSemestre(fid)}`
|
|
||||||
|
|
||||||
Remarque:
|
|
||||||
Une liste de la forme `[ 'Si', 'iA' , ... ]` (combinant les formats précédents) est possible.
|
|
||||||
"""
|
|
||||||
if semestres_recherches is None:
|
|
||||||
# Appel récursif pour obtenir tous les semestres (validants)
|
|
||||||
semestres = self.get_formsemestres(pe_comp.AGGREGAT_DIPLOMANT)
|
|
||||||
return semestres
|
|
||||||
if isinstance(semestres_recherches, list):
|
|
||||||
# Appel récursif sur tous les éléments de la liste
|
|
||||||
semestres = {}
|
|
||||||
for elmt in semestres_recherches:
|
|
||||||
semestres_elmt = self.get_formsemestres(elmt)
|
|
||||||
semestres = semestres | semestres_elmt
|
|
||||||
return semestres
|
|
||||||
if (
|
|
||||||
isinstance(semestres_recherches, str)
|
|
||||||
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
|
|
||||||
semestres = self.get_formsemestres(
|
|
||||||
pe_comp.PARCOURS[semestres_recherches]["aggregat"]
|
|
||||||
)
|
|
||||||
return semestres
|
|
||||||
if (
|
|
||||||
isinstance(semestres_recherches, str)
|
|
||||||
and semestres_recherches in pe_comp.TOUS_LES_SEMESTRES
|
|
||||||
):
|
|
||||||
# semestres_recherches est un nom de semestre de type S1,
|
|
||||||
# pour une recherche parmi les étudiants à prendre en compte
|
|
||||||
# dans le jury (diplômé et redoublants non diplômé)
|
|
||||||
nom_sem = semestres_recherches
|
|
||||||
semestres = {}
|
|
||||||
for etudid in self.etudiants_ids:
|
|
||||||
if self.cursus[etudid][nom_sem]:
|
|
||||||
semestres = semestres | self.cursus[etudid][nom_sem]
|
|
||||||
return semestres
|
|
||||||
|
|
||||||
raise ValueError("Probleme de paramètres d'appel dans get_formsemestreids")
|
|
||||||
|
|
||||||
def nbre_etapes_max_diplomes(self, etudids: list[int]) -> int:
|
def nbre_etapes_max_diplomes(self, etudids: list[int]) -> int:
|
||||||
"""Partant d'un ensemble d'étudiants,
|
"""Partant d'un ensemble d'étudiants,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from app.comp import moy_sem
|
from app.comp import moy_sem
|
||||||
from app.pe.pe_tabletags import TableTag, MoyenneTag
|
from app.pe.pe_tabletags import TableTag, MoyenneTag
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
from app.pe.pe_trajectoire import Trajectoire, TrajectoiresJuryPE
|
from app.pe.pe_rcs import RCS, RCSsJuryPE
|
||||||
from app.pe.pe_trajectoiretag import TrajectoireTag
|
from app.pe.pe_trajectoiretag import RCSTag
|
||||||
|
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -15,8 +15,8 @@ class AggregatInterclasseTag(TableTag):
|
|||||||
self,
|
self,
|
||||||
nom_aggregat: str,
|
nom_aggregat: str,
|
||||||
etudiants: EtudiantsJuryPE,
|
etudiants: EtudiantsJuryPE,
|
||||||
trajectoires_jury_pe: TrajectoiresJuryPE,
|
trajectoires_jury_pe: RCSsJuryPE,
|
||||||
trajectoires_taggues: dict[tuple, TrajectoireTag],
|
trajectoires_taggues: dict[tuple, RCSTag],
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Interclasse l'ensemble des étudiants diplômés à une année
|
Interclasse l'ensemble des étudiants diplômés à une année
|
||||||
@ -44,14 +44,14 @@ class AggregatInterclasseTag(TableTag):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
|
# Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
|
||||||
self.trajectoires: dict[int, Trajectoire] = {}
|
self.trajectoires: dict[int, RCS] = {}
|
||||||
"""Ensemble des trajectoires associées à l'aggrégat"""
|
"""Ensemble des trajectoires associées à l'aggrégat"""
|
||||||
for trajectoire_id in trajectoires_jury_pe.trajectoires:
|
for trajectoire_id in trajectoires_jury_pe.rcss:
|
||||||
trajectoire = trajectoires_jury_pe.trajectoires[trajectoire_id]
|
trajectoire = trajectoires_jury_pe.rcss[trajectoire_id]
|
||||||
if trajectoire_id[0] == nom_aggregat:
|
if trajectoire_id[0] == nom_aggregat:
|
||||||
self.trajectoires[trajectoire_id] = trajectoire
|
self.trajectoires[trajectoire_id] = trajectoire
|
||||||
|
|
||||||
self.trajectoires_taggues: dict[int, Trajectoire] = {}
|
self.trajectoires_taggues: dict[int, RCS] = {}
|
||||||
"""Ensemble des trajectoires tagguées associées à l'aggrégat"""
|
"""Ensemble des trajectoires tagguées associées à l'aggrégat"""
|
||||||
for trajectoire_id in self.trajectoires:
|
for trajectoire_id in self.trajectoires:
|
||||||
self.trajectoires_taggues[trajectoire_id] = trajectoires_taggues[
|
self.trajectoires_taggues[trajectoire_id] = trajectoires_taggues[
|
||||||
@ -60,7 +60,7 @@ class AggregatInterclasseTag(TableTag):
|
|||||||
|
|
||||||
# Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
# Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
||||||
# celles associées aux diplomés
|
# celles associées aux diplomés
|
||||||
self.suivi: dict[int, Trajectoire] = {}
|
self.suivi: dict[int, RCS] = {}
|
||||||
"""Association entre chaque étudiant et la trajectoire tagguée à prendre en
|
"""Association entre chaque étudiant et la trajectoire tagguée à prendre en
|
||||||
compte pour l'aggrégat"""
|
compte pour l'aggrégat"""
|
||||||
for etudid in self.diplomes_ids:
|
for etudid in self.diplomes_ids:
|
||||||
|
@ -48,17 +48,14 @@ from zipfile import ZipFile
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from app.pe import pe_comp
|
|
||||||
from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE
|
from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE
|
||||||
|
|
||||||
from app.pe.pe_tabletags import TableTag
|
from app.pe.pe_etudiant import *
|
||||||
from app.scodoc.gen_tables import SeqGenTable
|
from app.pe.pe_rcs import *
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
|
||||||
from app.pe.pe_trajectoire import TrajectoiresJuryPE, Trajectoire
|
|
||||||
import app.pe.pe_comp as pe_comp
|
import app.pe.pe_comp as pe_comp
|
||||||
from app.pe.pe_semtag import SemestreTag
|
from app.pe.pe_semtag import SemestreTag
|
||||||
from app.pe.pe_interclasstag import AggregatInterclasseTag
|
from app.pe.pe_interclasstag import AggregatInterclasseTag
|
||||||
from app.pe.pe_trajectoiretag import TrajectoireTag
|
from app.pe.pe_trajectoiretag import RCSTag
|
||||||
import app.pe.pe_affichage as pe_affichage
|
import app.pe.pe_affichage as pe_affichage
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -160,8 +157,8 @@ class JuryPE(object):
|
|||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
"*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
|
"*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
|
||||||
)
|
)
|
||||||
self.trajectoires = TrajectoiresJuryPE(self.diplome)
|
self.trajectoires = RCSsJuryPE(self.diplome)
|
||||||
self.trajectoires.cree_trajectoires(self.etudiants)
|
self.trajectoires.cree_rcss(self.etudiants)
|
||||||
|
|
||||||
# Génère les moyennes par tags des trajectoires
|
# Génère les moyennes par tags des trajectoires
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
@ -334,10 +331,8 @@ class JuryPE(object):
|
|||||||
df_synthese = pd.DataFrame.from_dict(donnees_etudiants, orient="index")
|
df_synthese = pd.DataFrame.from_dict(donnees_etudiants, orient="index")
|
||||||
|
|
||||||
# Ajout des aggrégats
|
# Ajout des aggrégats
|
||||||
aggregats = pe_comp.TOUS_LES_PARCOURS
|
for aggregat in TOUS_LES_RCS:
|
||||||
|
descr = TYPES_RCS[aggregat]["descr"]
|
||||||
for aggregat in aggregats:
|
|
||||||
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
|
||||||
|
|
||||||
# Les trajectoires (tagguées) suivies par les étudiants pour l'aggrégat et le tag
|
# Les trajectoires (tagguées) suivies par les étudiants pour l'aggrégat et le tag
|
||||||
# considéré
|
# considéré
|
||||||
@ -345,7 +340,7 @@ class JuryPE(object):
|
|||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
||||||
if trajectoire:
|
if trajectoire:
|
||||||
tid = trajectoire.trajectoire_id
|
tid = trajectoire.rcs_id
|
||||||
trajectoire_tagguee = self.trajectoires_tagguees[tid]
|
trajectoire_tagguee = self.trajectoires_tagguees[tid]
|
||||||
if (
|
if (
|
||||||
tag in trajectoire_tagguee.moyennes_tags
|
tag in trajectoire_tagguee.moyennes_tags
|
||||||
@ -476,7 +471,6 @@ class JuryPE(object):
|
|||||||
"""Créé un DataFrame pour un étudiant donné par son etudid, retraçant
|
"""Créé un DataFrame pour un étudiant donné par son etudid, retraçant
|
||||||
toutes ses moyennes aux différents tag et aggrégats"""
|
toutes ses moyennes aux différents tag et aggrégats"""
|
||||||
tags = self.do_tags_list(self.interclassements_taggues)
|
tags = self.do_tags_list(self.interclassements_taggues)
|
||||||
aggregats = pe_comp.TOUS_LES_PARCOURS
|
|
||||||
|
|
||||||
donnees = {}
|
donnees = {}
|
||||||
|
|
||||||
@ -484,7 +478,7 @@ class JuryPE(object):
|
|||||||
# Une ligne pour le tag
|
# Une ligne pour le tag
|
||||||
donnees[tag] = {("", "", "tag"): tag}
|
donnees[tag] = {("", "", "tag"): tag}
|
||||||
|
|
||||||
for aggregat in aggregats:
|
for aggregat in TOUS_LES_RCS:
|
||||||
# Le dictionnaire par défaut des moyennes
|
# Le dictionnaire par défaut des moyennes
|
||||||
donnees[tag] |= get_defaut_dict_synthese_aggregat(
|
donnees[tag] |= get_defaut_dict_synthese_aggregat(
|
||||||
aggregat, self.diplome
|
aggregat, self.diplome
|
||||||
@ -494,7 +488,7 @@ class JuryPE(object):
|
|||||||
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
||||||
if trajectoire:
|
if trajectoire:
|
||||||
trajectoire_tagguee = self.trajectoires_tagguees[
|
trajectoire_tagguee = self.trajectoires_tagguees[
|
||||||
trajectoire.trajectoire_id
|
trajectoire.rcs_id
|
||||||
]
|
]
|
||||||
if tag in trajectoire_tagguee.moyennes_tags:
|
if tag in trajectoire_tagguee.moyennes_tags:
|
||||||
# L'interclassement
|
# L'interclassement
|
||||||
@ -518,6 +512,27 @@ class JuryPE(object):
|
|||||||
df.sort_values(by=[("", "", "tag")], inplace=True)
|
df.sort_values(by=[("", "", "tag")], inplace=True)
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
def get_formsemestres_etudiants(etudiants: EtudiantsJuryPE) -> dict:
|
||||||
|
"""Ayant connaissance des étudiants dont il faut calculer les moyennes pour
|
||||||
|
le jury PE (attribut `self.etudiant_ids) et de leur cursus (semestres
|
||||||
|
parcourus),
|
||||||
|
renvoie un dictionnaire ``{fid: FormSemestre(fid)}``
|
||||||
|
contenant l'ensemble des formsemestres de leurs cursus, dont il faudra calculer
|
||||||
|
la moyenne.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
etudiants: Les étudiants du jury PE
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Un dictionnaire de la forme `{fid: FormSemestre(fid)}`
|
||||||
|
|
||||||
|
"""
|
||||||
|
semestres = {}
|
||||||
|
for etudid in etudiants.etudiants_ids:
|
||||||
|
for cle in etudiants.cursus[etudid]:
|
||||||
|
if cle.startswith("S"):
|
||||||
|
semestres = semestres | etudiants.cursus[etudid][cle]
|
||||||
|
return semestres
|
||||||
|
|
||||||
def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
|
def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
|
||||||
"""Créé les semestres taggués, de type 'S1', 'S2', ..., pour un groupe d'étudiants donnés.
|
"""Créé les semestres taggués, de type 'S1', 'S2', ..., pour un groupe d'étudiants donnés.
|
||||||
@ -536,9 +551,7 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
|
|||||||
"""Création des semestres taggués, de type 'S1', 'S2', ..."""
|
"""Création des semestres taggués, de type 'S1', 'S2', ..."""
|
||||||
pe_affichage.pe_print("*** Création des semestres taggués")
|
pe_affichage.pe_print("*** Création des semestres taggués")
|
||||||
|
|
||||||
formsemestres = etudiants.get_formsemestres(
|
formsemestres = get_formsemestres_etudiants(etudiants)
|
||||||
semestres_recherches=pe_comp.TOUS_LES_SEMESTRES
|
|
||||||
)
|
|
||||||
|
|
||||||
semestres_tags = {}
|
semestres_tags = {}
|
||||||
for frmsem_id, formsemestre in formsemestres.items():
|
for frmsem_id, formsemestre in formsemestres.items():
|
||||||
@ -554,7 +567,7 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def compute_trajectoires_tag(
|
def compute_trajectoires_tag(
|
||||||
trajectoires: TrajectoiresJuryPE,
|
trajectoires: RCSsJuryPE,
|
||||||
etudiants: EtudiantsJuryPE,
|
etudiants: EtudiantsJuryPE,
|
||||||
semestres_taggues: dict[int, SemestreTag],
|
semestres_taggues: dict[int, SemestreTag],
|
||||||
):
|
):
|
||||||
@ -583,11 +596,11 @@ def compute_trajectoires_tag(
|
|||||||
"""
|
"""
|
||||||
trajectoires_tagguees = {}
|
trajectoires_tagguees = {}
|
||||||
|
|
||||||
for trajectoire_id, trajectoire in trajectoires.trajectoires.items():
|
for trajectoire_id, trajectoire in trajectoires.rcss.items():
|
||||||
nom = trajectoire.get_repr()
|
nom = trajectoire.get_repr()
|
||||||
pe_affichage.pe_print(f" --> Aggrégat {nom}")
|
pe_affichage.pe_print(f" --> Aggrégat {nom}")
|
||||||
# Trajectoire_tagguee associée
|
# Trajectoire_tagguee associée
|
||||||
trajectoire_tagguee = TrajectoireTag(trajectoire, semestres_taggues)
|
trajectoire_tagguee = RCSTag(trajectoire, semestres_taggues)
|
||||||
# Mémorise le résultat
|
# Mémorise le résultat
|
||||||
trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee
|
trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee
|
||||||
|
|
||||||
@ -596,15 +609,15 @@ def compute_trajectoires_tag(
|
|||||||
|
|
||||||
def compute_interclassements(
|
def compute_interclassements(
|
||||||
etudiants: EtudiantsJuryPE,
|
etudiants: EtudiantsJuryPE,
|
||||||
trajectoires_jury_pe: TrajectoiresJuryPE,
|
trajectoires_jury_pe: RCSsJuryPE,
|
||||||
trajectoires_tagguees: dict[tuple, Trajectoire],
|
trajectoires_tagguees: dict[tuple, RCS],
|
||||||
):
|
):
|
||||||
"""Interclasse les étudiants, (nom d') aggrégat par aggrégat,
|
"""Interclasse les étudiants, (nom d') aggrégat par aggrégat,
|
||||||
pour fournir un classement sur la promo. Le classement est établi au regard du nombre
|
pour fournir un classement sur la promo. Le classement est établi au regard du nombre
|
||||||
d'étudiants ayant participé au même aggrégat.
|
d'étudiants ayant participé au même aggrégat.
|
||||||
"""
|
"""
|
||||||
aggregats_interclasses_taggues = {}
|
aggregats_interclasses_taggues = {}
|
||||||
for nom_aggregat in pe_comp.TOUS_LES_SEMESTRES + pe_comp.TOUS_LES_AGGREGATS:
|
for nom_aggregat in TOUS_LES_RCS:
|
||||||
pe_affichage.pe_print(f" --> Interclassement {nom_aggregat}")
|
pe_affichage.pe_print(f" --> Interclassement {nom_aggregat}")
|
||||||
interclass = AggregatInterclasseTag(
|
interclass = AggregatInterclasseTag(
|
||||||
nom_aggregat, etudiants, trajectoires_jury_pe, trajectoires_tagguees
|
nom_aggregat, etudiants, trajectoires_jury_pe, trajectoires_tagguees
|
||||||
@ -613,11 +626,16 @@ def compute_interclassements(
|
|||||||
return aggregats_interclasses_taggues
|
return aggregats_interclasses_taggues
|
||||||
|
|
||||||
|
|
||||||
def get_defaut_dict_synthese_aggregat(aggregat: str, diplome: int) -> dict:
|
def get_defaut_dict_synthese_aggregat(nom_rcs: str, diplome: int) -> dict:
|
||||||
"""Renvoie le dictionnaire de synthèse (à intégrer dans
|
"""Renvoie le dictionnaire de synthèse (à intégrer dans
|
||||||
un tableur excel) pour décrire les résultats d'un aggrégat"""
|
un tableur excel) pour décrire les résultats d'un aggrégat
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nom_rcs : Le nom du RCS visé
|
||||||
|
diplôme : l'année du diplôme
|
||||||
|
"""
|
||||||
# L'affichage de l'aggrégat dans le tableur excel
|
# L'affichage de l'aggrégat dans le tableur excel
|
||||||
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
descr = get_descr_rcs(nom_rcs)
|
||||||
|
|
||||||
nom_stat_promo = f"{NOM_STAT_PROMO} {diplome}"
|
nom_stat_promo = f"{NOM_STAT_PROMO} {diplome}"
|
||||||
donnees = {
|
donnees = {
|
||||||
@ -650,7 +668,7 @@ def get_defaut_dict_synthese_aggregat(aggregat: str, diplome: int) -> dict:
|
|||||||
|
|
||||||
def get_dict_synthese_aggregat(
|
def get_dict_synthese_aggregat(
|
||||||
aggregat: str,
|
aggregat: str,
|
||||||
trajectoire_tagguee: TrajectoireTag,
|
trajectoire_tagguee: RCSTag,
|
||||||
interclassement_taggue: AggregatInterclasseTag,
|
interclassement_taggue: AggregatInterclasseTag,
|
||||||
etudid: int,
|
etudid: int,
|
||||||
tag: str,
|
tag: str,
|
||||||
@ -661,7 +679,7 @@ def get_dict_synthese_aggregat(
|
|||||||
à l'aggrégat donné et pour un tag donné"""
|
à l'aggrégat donné et pour un tag donné"""
|
||||||
donnees = {}
|
donnees = {}
|
||||||
# L'affichage de l'aggrégat dans le tableur excel
|
# L'affichage de l'aggrégat dans le tableur excel
|
||||||
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
descr = get_descr_rcs(aggregat)
|
||||||
|
|
||||||
# La note de l'étudiant (chargement à venir)
|
# La note de l'étudiant (chargement à venir)
|
||||||
note = np.nan
|
note = np.nan
|
||||||
|
253
app/pe/pe_rcs.py
Normal file
253
app/pe/pe_rcs.py
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
import app.pe.pe_comp as pe_comp
|
||||||
|
import app.pe.pe_affichage as pe_affichage
|
||||||
|
|
||||||
|
from app.models import FormSemestre
|
||||||
|
from app.pe.pe_etudiant import EtudiantsJuryPE, get_dernier_semestre_en_date
|
||||||
|
|
||||||
|
|
||||||
|
TYPES_RCS = {
|
||||||
|
"S1": {
|
||||||
|
"aggregat": ["S1"],
|
||||||
|
"descr": "Semestre 1 (S1)",
|
||||||
|
},
|
||||||
|
"S2": {
|
||||||
|
"aggregat": ["S2"],
|
||||||
|
"descr": "Semestre 2 (S2)",
|
||||||
|
},
|
||||||
|
"1A": {
|
||||||
|
"aggregat": ["S1", "S2"],
|
||||||
|
"descr": "BUT1 (S1+S2)",
|
||||||
|
},
|
||||||
|
"S3": {
|
||||||
|
"aggregat": ["S3"],
|
||||||
|
"descr": "Semestre 3 (S3)",
|
||||||
|
},
|
||||||
|
"S4": {
|
||||||
|
"aggregat": ["S4"],
|
||||||
|
"descr": "Semestre 4 (S4)",
|
||||||
|
},
|
||||||
|
"2A": {
|
||||||
|
"aggregat": ["S3", "S4"],
|
||||||
|
"descr": "BUT2 (S3+S4)",
|
||||||
|
},
|
||||||
|
"3S": {
|
||||||
|
"aggregat": ["S1", "S2", "S3"],
|
||||||
|
"descr": "Moyenne du semestre 1 au semestre 3 (S1+S2+S3)",
|
||||||
|
},
|
||||||
|
"4S": {
|
||||||
|
"aggregat": ["S1", "S2", "S3", "S4"],
|
||||||
|
"descr": "Moyenne du semestre 1 au semestre 4 (S1+S2+S3+S4)",
|
||||||
|
},
|
||||||
|
"S5": {
|
||||||
|
"aggregat": ["S5"],
|
||||||
|
"descr": "Semestre 5 (S5)",
|
||||||
|
},
|
||||||
|
"S6": {
|
||||||
|
"aggregat": ["S6"],
|
||||||
|
"descr": "Semestre 6 (S6)",
|
||||||
|
},
|
||||||
|
"3A": {
|
||||||
|
"aggregat": ["S5", "S6"],
|
||||||
|
"descr": "3ème année (S5+S6)",
|
||||||
|
},
|
||||||
|
"5S": {
|
||||||
|
"aggregat": ["S1", "S2", "S3", "S4", "S5"],
|
||||||
|
"descr": "Moyenne du semestre 1 au semestre 5 (S1+S2+S3+S4+S5)",
|
||||||
|
},
|
||||||
|
"6S": {
|
||||||
|
"aggregat": ["S1", "S2", "S3", "S4", "S5", "S6"],
|
||||||
|
"descr": "Moyenne globale (S1+S2+S3+S4+S5+S6)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
"""Dictionnaire détaillant les différents regroupements cohérents
|
||||||
|
de semestres (RCS), en leur attribuant un nom et en détaillant
|
||||||
|
le nom des semestres qu'ils regroupement et l'affichage qui en sera fait
|
||||||
|
dans les tableurs de synthèse"""
|
||||||
|
|
||||||
|
TOUS_LES_RCS_AVEC_PLUSIEURS_SEM = [cle for cle in TYPES_RCS.keys() if not cle.startswith("S")]
|
||||||
|
TOUS_LES_RCS = list(TYPES_RCS.keys())
|
||||||
|
TOUS_LES_SEMESTRES = [cle for cle in TYPES_RCS.keys() if cle.startswith("S")]
|
||||||
|
|
||||||
|
|
||||||
|
class RCS:
|
||||||
|
def __init__(self, nom_rcs: str, semestre_final: FormSemestre):
|
||||||
|
"""Modélise un ensemble de semestres d'étudiants
|
||||||
|
associé à un type de regroupement cohérent de semestres
|
||||||
|
donné (par ex: 'S2', '3S', '2A').
|
||||||
|
|
||||||
|
Si le RCS est un semestre de type Si, stocke le (ou les)
|
||||||
|
formsemestres de numéro i qu'ont suivi 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 le RCS 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, ...
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nom_rcs: Un nom du RCS (par ex: '5S')
|
||||||
|
semestre_final: Le semestre final du RCS
|
||||||
|
"""
|
||||||
|
self.nom = nom_rcs
|
||||||
|
"""Nom du RCS"""
|
||||||
|
|
||||||
|
self.formsemestre_final = semestre_final
|
||||||
|
"""FormSemestre terminal du RCS"""
|
||||||
|
|
||||||
|
self.rcs_id = (nom_rcs, semestre_final.formsemestre_id)
|
||||||
|
"""Identifiant du RCS sous forme (nom_rcs, id du semestre_terminal)"""
|
||||||
|
|
||||||
|
self.semestres_aggreges = {}
|
||||||
|
"""Semestres regroupés dans le RCS"""
|
||||||
|
|
||||||
|
def add_semestres_a_aggreger(self, semestres: dict[int:FormSemestre]):
|
||||||
|
"""Ajout de semestres aux semestres à regrouper
|
||||||
|
|
||||||
|
Args:
|
||||||
|
semestres: Dictionnaire ``{fid: FormSemestre(fid)}`` à ajouter
|
||||||
|
"""
|
||||||
|
self.semestres_aggreges = self.semestres_aggreges | semestres
|
||||||
|
|
||||||
|
def get_repr(self, verbose=True) -> str:
|
||||||
|
"""Représentation textuelle d'un RCS
|
||||||
|
basé 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.formsemestre_final.formsemestre_id}) {self.formsemestre_final.date_fin.year}"
|
||||||
|
if verbose and noms:
|
||||||
|
repr += " - " + "+".join(noms)
|
||||||
|
return repr
|
||||||
|
|
||||||
|
|
||||||
|
class RCSsJuryPE:
|
||||||
|
def __init__(self, annee_diplome: int):
|
||||||
|
"""Classe centralisant toutes les regroupements cohérents de
|
||||||
|
semestres (RCS) des étudiants à prendre en compte dans un jury PE
|
||||||
|
|
||||||
|
Args:
|
||||||
|
annee_diplome: L'année de diplomation
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.annee_diplome = annee_diplome
|
||||||
|
"""Année de diplômation"""
|
||||||
|
|
||||||
|
self.rcss: dict[tuple:RCS] = {}
|
||||||
|
"""Ensemble des RCS recensés : {(nom_RCS, fid_terminal): RCS}"""
|
||||||
|
|
||||||
|
self.suivi: dict[int:str] = {}
|
||||||
|
"""Dictionnaire associant, pour chaque étudiant et pour chaque type de RCS,
|
||||||
|
son RCS : {etudid: {nom_RCS: RCS}}"""
|
||||||
|
|
||||||
|
def cree_rcss(self, etudiants: 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
|
||||||
|
"""
|
||||||
|
|
||||||
|
for nom_rcs in pe_comp.TOUS_LES_SEMESTRES + TOUS_LES_RCS_AVEC_PLUSIEURS_SEM:
|
||||||
|
"""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 = TYPES_RCS[nom_rcs]["aggregat"]
|
||||||
|
nom_semestre_terminal = noms_semestre_de_aggregat[-1]
|
||||||
|
|
||||||
|
for etudid in etudiants.cursus:
|
||||||
|
if etudid not in self.suivi:
|
||||||
|
self.suivi[etudid] = {
|
||||||
|
aggregat: None
|
||||||
|
for aggregat in pe_comp.TOUS_LES_SEMESTRES
|
||||||
|
+ TOUS_LES_RCS_AVEC_PLUSIEURS_SEM
|
||||||
|
}
|
||||||
|
|
||||||
|
"""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_rcs, formsemestre_final.formsemestre_id)
|
||||||
|
if trajectoire_id not in self.rcss:
|
||||||
|
trajectoire = RCS(nom_rcs, formsemestre_final)
|
||||||
|
self.rcss[trajectoire_id] = trajectoire
|
||||||
|
else:
|
||||||
|
trajectoire = self.rcss[trajectoire_id]
|
||||||
|
|
||||||
|
"""La liste des semestres de l'étudiant à prendre en compte
|
||||||
|
pour cette trajectoire"""
|
||||||
|
semestres_a_aggreger = get_rcs_etudiant(
|
||||||
|
etudiants.cursus[etudid], formsemestre_final, nom_rcs
|
||||||
|
)
|
||||||
|
|
||||||
|
"""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_rcs] = trajectoire
|
||||||
|
|
||||||
|
|
||||||
|
def get_rcs_etudiant(semestres: dict[int:FormSemestre], formsemestre_final: FormSemestre, nom_rcs: str
|
||||||
|
):
|
||||||
|
"""Ensemble des semestres parcourus par un étudiant, connaissant
|
||||||
|
les semestres de son cursus,
|
||||||
|
dans le cadre du RCS visé et ayant pour semestre terminal `formsemestre_final`.
|
||||||
|
|
||||||
|
Si le RCS est de type "Si", limite les semestres à ceux de numéro i.
|
||||||
|
Par ex: si formsemestre_terminal est un S3 et nom_agrregat "S3", ne prend en compte que les
|
||||||
|
semestres 3.
|
||||||
|
|
||||||
|
Si le RCS est de type "iA" ou "iS" (incluant plusieurs numéros de semestres), prend en
|
||||||
|
compte les dit numéros de semestres.
|
||||||
|
|
||||||
|
Par ex: si formsemestre_terminal est un S3, ensemble des S1,
|
||||||
|
S2, S3 suivi pour l'amener au S3 (il peut y avoir plusieurs S1,
|
||||||
|
ou S2, ou S3 s'il a redoublé).
|
||||||
|
|
||||||
|
Les semestres parcourus sont antérieurs (en terme de date de fin)
|
||||||
|
au formsemestre_terminal.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cursus: Dictionnaire {fid: FormSemestre(fid)} 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 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_descr_rcs(nom_rcs: str) -> str:
|
||||||
|
"""Renvoie la description pour les tableurs de synthèse
|
||||||
|
Excel d'un nom de RCS"""
|
||||||
|
return TYPES_RCS[nom_rcs]["descr"]
|
@ -1,145 +0,0 @@
|
|||||||
import app.pe.pe_comp as pe_comp
|
|
||||||
import app.pe.pe_affichage as pe_affichage
|
|
||||||
|
|
||||||
from app.models import FormSemestre
|
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE, get_dernier_semestre_en_date
|
|
||||||
|
|
||||||
|
|
||||||
class Trajectoire:
|
|
||||||
def __init__(self, nom_aggregat: str, semestre_final: FormSemestre):
|
|
||||||
"""Modélise un ensemble de formsemestres d'étudiants
|
|
||||||
amenant à un semestre terminal, au sens d'un aggrégat (par ex: 'S2', '3S', '2A').
|
|
||||||
|
|
||||||
Si l'aggrégat est un semestre de type Si, elle stocke le (ou les)
|
|
||||||
formsemestres de numéro i qu'ont suivi 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, ...
|
|
||||||
|
|
||||||
Args:
|
|
||||||
nom_aggregat: Un nom d'aggrégat (par ex: '5S')
|
|
||||||
semestre_final: Le semestre final de l'aggrégat
|
|
||||||
"""
|
|
||||||
self.nom = nom_aggregat
|
|
||||||
"""Nom de l'aggrégat"""
|
|
||||||
|
|
||||||
self.formsemestre_final = semestre_final
|
|
||||||
"""FormSemestre terminal de la trajectoire"""
|
|
||||||
|
|
||||||
self.trajectoire_id = (nom_aggregat, semestre_final.formsemestre_id)
|
|
||||||
"""Identifiant de la trajectoire"""
|
|
||||||
|
|
||||||
self.semestres_aggreges = {}
|
|
||||||
"""Semestres aggrégés"""
|
|
||||||
|
|
||||||
def add_semestres_a_aggreger(self, semestres: dict[int:FormSemestre]):
|
|
||||||
"""Ajout de semestres aux semestres à aggréger
|
|
||||||
|
|
||||||
Args:
|
|
||||||
semestres: Dictionnaire ``{fid: FormSemestre(fid)}`` à ajouter
|
|
||||||
"""
|
|
||||||
self.semestres_aggreges = self.semestres_aggreges | semestres
|
|
||||||
|
|
||||||
def get_repr(self, verbose=True) -> str:
|
|
||||||
"""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.formsemestre_final.formsemestre_id}) {self.formsemestre_final.date_fin.year}"
|
|
||||||
if verbose and noms:
|
|
||||||
repr += " - " + "+".join(noms)
|
|
||||||
return repr
|
|
||||||
|
|
||||||
|
|
||||||
class TrajectoiresJuryPE:
|
|
||||||
def __init__(self, annee_diplome: int):
|
|
||||||
"""Classe centralisant toutes les trajectoires des étudiants à prendre
|
|
||||||
en compte dans un jury PE
|
|
||||||
|
|
||||||
Args:
|
|
||||||
annee_diplome: L'année de diplomation
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.annee_diplome = annee_diplome
|
|
||||||
"""Toutes les trajectoires possibles"""
|
|
||||||
|
|
||||||
self.trajectoires: dict[tuple:Trajectoire] = {}
|
|
||||||
"""Ensemble des trajectoires recensées : {(aggregat, fid_terminal): Trajectoire}"""
|
|
||||||
|
|
||||||
self.suivi: dict[int:str] = {}
|
|
||||||
"""Dictionnaire associant, pour chaque étudiant et pour chaque aggrégat,
|
|
||||||
sa trajectoire : {etudid: {nom_aggregat: Trajectoire}}"""
|
|
||||||
|
|
||||||
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_comp.TOUS_LES_SEMESTRES + pe_comp.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_comp.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] = {
|
|
||||||
aggregat: None
|
|
||||||
for aggregat in pe_comp.TOUS_LES_SEMESTRES
|
|
||||||
+ pe_comp.TOUS_LES_AGGREGATS
|
|
||||||
}
|
|
||||||
|
|
||||||
"""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, nom_aggregat
|
|
||||||
)
|
|
||||||
|
|
||||||
"""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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_trajectoires_etudid(trajectoires, etudid):
|
|
||||||
"""Fonction pour débuggage: renvoie la liste des trajectoires_id des
|
|
||||||
trajectoires suivies par un étudiant
|
|
||||||
"""
|
|
||||||
if etudid not in trajectoires.suivi:
|
|
||||||
pe_affichage.pe_print(f"{etudid} fait-il bien partie du jury ?")
|
|
||||||
|
|
||||||
liste = []
|
|
||||||
for aggregat in pe_comp.TOUS_LES_PARCOURS:
|
|
||||||
trajet = trajectoires.suivi[etudid][aggregat]
|
|
||||||
if trajet:
|
|
||||||
liste.append(trajet.trajectoire_id)
|
|
||||||
return liste
|
|
||||||
|
|
||||||
|
|
@ -36,51 +36,48 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
@author: barasc
|
@author: barasc
|
||||||
"""
|
"""
|
||||||
|
|
||||||
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.pe.pe_semtag import SemestreTag
|
from app.pe.pe_semtag import SemestreTag
|
||||||
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_rcs import RCS
|
||||||
|
|
||||||
from app.pe.pe_tabletags import TableTag, MoyenneTag
|
from app.pe.pe_tabletags import TableTag, MoyenneTag
|
||||||
|
|
||||||
|
|
||||||
class TrajectoireTag(TableTag):
|
class RCSTag(TableTag):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, trajectoire: Trajectoire, semestres_taggues: dict[int, SemestreTag]
|
self, rcs: RCS, semestres_taggues: dict[int, SemestreTag]
|
||||||
):
|
):
|
||||||
"""Calcule les moyennes par tag d'une combinaison de semestres
|
"""Calcule les moyennes par tag d'une combinaison de semestres
|
||||||
(trajectoires), identifiée par un nom d'aggrégat (par ex: '3S') et
|
(RCS), pour extraire les classements par tag pour un
|
||||||
par un semestre terminal, pour extraire les classements par tag pour un
|
|
||||||
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
||||||
participé au semestre terminal.
|
participé au semestre terminal.
|
||||||
|
|
||||||
Par ex: fusion d'un parcours ['S1', 'S2', 'S3'] donnant un nom_combinaison = '3S'
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
trajectoire: Une trajectoire (aggrégat+semestre terminal)
|
rcs: Un RCS (identifié par un nom et l'id de son semestre terminal)
|
||||||
semestres_taggues: Les données sur les semestres taggués
|
semestres_taggues: Les données sur les semestres taggués
|
||||||
"""
|
"""
|
||||||
TableTag.__init__(self)
|
TableTag.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
self.trajectoire_id = trajectoire.trajectoire_id
|
self.rcs_id = rcs.rcs_id
|
||||||
"""Identifiant de la trajectoire tagguée"""
|
"""Identifiant du RCS taggué (identique au RCS sur lequel il s'appuie)"""
|
||||||
|
|
||||||
self.trajectoire = trajectoire
|
self.rcs = rcs
|
||||||
"""Trajectoire associée à la trajectoire tagguée"""
|
"""RCS associé au RCS taggué"""
|
||||||
|
|
||||||
self.nom = self.get_repr()
|
self.nom = self.get_repr()
|
||||||
"""Représentation textuelle de la trajectoire tagguée"""
|
"""Représentation textuelle du RCS taggué"""
|
||||||
|
|
||||||
self.formsemestre_terminal = trajectoire.formsemestre_final
|
self.formsemestre_terminal = rcs.formsemestre_final
|
||||||
"""Le formsemestre terminal"""
|
"""Le formsemestre terminal"""
|
||||||
|
|
||||||
# Les résultats du formsemestre terminal
|
# Les résultats du formsemestre terminal
|
||||||
nt = load_formsemestre_results(self.formsemestre_terminal)
|
nt = load_formsemestre_results(self.formsemestre_terminal)
|
||||||
|
|
||||||
self.semestres_aggreges = trajectoire.semestres_aggreges
|
self.semestres_aggreges = rcs.semestres_aggreges
|
||||||
"""Les semestres aggrégés"""
|
"""Les semestres aggrégés"""
|
||||||
|
|
||||||
self.semestres_tags_aggreges = {}
|
self.semestres_tags_aggreges = {}
|
||||||
@ -114,13 +111,13 @@ class TrajectoireTag(TableTag):
|
|||||||
self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_tag)
|
self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_tag)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""Egalité de 2 trajectoires tagguées sur la base de leur identifiant"""
|
"""Egalité de 2 RCS taggués sur la base de leur identifiant"""
|
||||||
return self.trajectoire_id == other.trajectoire_id
|
return self.rcs_id == other.rcs_id
|
||||||
|
|
||||||
def get_repr(self, verbose=False) -> str:
|
def get_repr(self, verbose=False) -> str:
|
||||||
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||||
est basée)"""
|
est basée)"""
|
||||||
return self.trajectoire.get_repr(verbose=verbose)
|
return self.rcs.get_repr(verbose=verbose)
|
||||||
|
|
||||||
def compute_notes_cube(self):
|
def compute_notes_cube(self):
|
||||||
"""Construit le cube de notes (etudid x tags x semestre_aggregé)
|
"""Construit le cube de notes (etudid x tags x semestre_aggregé)
|
||||||
|
Loading…
Reference in New Issue
Block a user