forked from ScoDoc/ScoDoc
Ajoute un tableur pour visualiser les étudiants traités par le jury (diplômé ou redoublants/démissionnaires)
This commit is contained in:
parent
9c6d988fc3
commit
fce23aa066
@ -35,41 +35,56 @@ Created on 17/01/2024
|
|||||||
|
|
||||||
@author: barasc
|
@author: barasc
|
||||||
"""
|
"""
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
from app.models import FormSemestre, Identite
|
from app.models import FormSemestre, Identite
|
||||||
import app.pe.pe_affichage as pe_affichage
|
import app.pe.pe_affichage as pe_affichage
|
||||||
import app.pe.pe_comp as pe_comp
|
import app.pe.pe_comp as pe_comp
|
||||||
|
from app.pe import pe_comp, pe_affichage
|
||||||
|
|
||||||
|
|
||||||
class EtudiantsJuryPE:
|
class EtudiantsJuryPE:
|
||||||
"""Classe centralisant la gestion des étudiants à prendre en compte dans un jury de PE"""
|
|
||||||
|
|
||||||
def __init__(self, annee_diplome: int):
|
def __init__(self, annee_diplome: int):
|
||||||
"""
|
"""
|
||||||
|
Classe centralisant la gestion des étudiants à prendre en compte dans un jury de PE
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
annee_diplome: L'année de diplomation
|
annee_diplome: L'année de diplomation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.annee_diplome = annee_diplome
|
self.annee_diplome = annee_diplome
|
||||||
|
"""L'année du diplôme"""
|
||||||
|
|
||||||
"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) des étudiants"
|
"Les identités des étudiants traités pour le jury"
|
||||||
|
|
||||||
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 cursus (semestres suivis, abandons) des étudiants"
|
||||||
|
|
||||||
self.trajectoires = {}
|
self.trajectoires = {}
|
||||||
|
"""Les trajectoires/chemins de semestres suivis par les étudiants
|
||||||
|
pour atteindre un aggrégat donné
|
||||||
|
(par ex: 3S=S1+S2+S3 à prendre en compte avec d'éventuels redoublements)"""
|
||||||
|
|
||||||
"Les etudids des étudiants à considérer au jury (ceux qui seront effectivement diplômés)"
|
|
||||||
self.etudiants_diplomes = {}
|
self.etudiants_diplomes = {}
|
||||||
self.diplomes_ids = {}
|
"""Les identités des étudiants à considérer au jury (ceux qui seront effectivement diplômés)"""
|
||||||
|
|
||||||
|
self.diplomes_ids = {}
|
||||||
|
"""Les etudids des étudiants diplômés"""
|
||||||
|
|
||||||
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
|
|
||||||
self.etudiants_ids = {}
|
self.etudiants_ids = {}
|
||||||
"""Les étudiants inscrits dans les co-semestres (ceux du jury mais aussi d'autres ayant été réorientés ou ayant abandonnés)"""
|
"""Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons).
|
||||||
|
Il s'agit des étudiants inscrits dans les co-semestres (ceux du jury mais aussi d'autres ayant
|
||||||
|
été réorientés ou ayant abandonnés)"""
|
||||||
|
|
||||||
self.cosemestres: dict[int, FormSemestre] = None
|
self.cosemestres: dict[int, FormSemestre] = None
|
||||||
"Les cosemestres donnant lieu à même année de diplome"
|
"Les cosemestres donnant lieu à même année de diplome"
|
||||||
|
|
||||||
|
self.abandons = {}
|
||||||
|
"""Les étudiants qui ne seront pas diplômés à ce jury (redoublants/réorientés)"""
|
||||||
|
self.abandons_ids = {}
|
||||||
|
"""Les etudids des étudiants redoublants/réorientés"""
|
||||||
|
|
||||||
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``
|
||||||
@ -85,7 +100,9 @@ class EtudiantsJuryPE:
|
|||||||
cosemestres = pe_comp.get_cosemestres_diplomants(self.annee_diplome, None)
|
cosemestres = pe_comp.get_cosemestres_diplomants(self.annee_diplome, None)
|
||||||
self.cosemestres = cosemestres
|
self.cosemestres = cosemestres
|
||||||
|
|
||||||
pe_affichage.pe_print(f"1) Recherche des coSemestres -> {len(cosemestres)} trouvés")
|
pe_affichage.pe_print(
|
||||||
|
f"1) Recherche des coSemestres -> {len(cosemestres)} trouvés"
|
||||||
|
)
|
||||||
|
|
||||||
pe_affichage.pe_print("2) Liste des étudiants dans les différents co-semestres")
|
pe_affichage.pe_print("2) Liste des étudiants dans les différents co-semestres")
|
||||||
self.etudiants_ids = get_etudiants_dans_semestres(cosemestres)
|
self.etudiants_ids = get_etudiants_dans_semestres(cosemestres)
|
||||||
@ -109,23 +126,30 @@ class EtudiantsJuryPE:
|
|||||||
# Analyse son parcours pour atteindre chaque semestre de la formation
|
# Analyse son parcours pour atteindre chaque semestre de la formation
|
||||||
self.structure_cursus_etudiant(etudid)
|
self.structure_cursus_etudiant(etudid)
|
||||||
|
|
||||||
|
|
||||||
# Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris
|
# Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris
|
||||||
self.etudiants_diplomes = self.get_etudiants_diplomes()
|
self.etudiants_diplomes = self.get_etudiants_diplomes()
|
||||||
self.diplomes_ids = set(self.etudiants_diplomes.keys())
|
self.diplomes_ids = set(self.etudiants_diplomes.keys())
|
||||||
|
|
||||||
self.etudiants_ids = set(self.identites)
|
self.etudiants_ids = set(self.identites.keys())
|
||||||
"""Les étudiants dont il faut calculer les moyennes"""
|
"""Les étudiants dont il faut calculer les moyennes"""
|
||||||
|
|
||||||
self.formsemestres_jury_ids = self.get_formsemestres()
|
self.formsemestres_jury_ids = self.get_formsemestres()
|
||||||
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
|
"""Les formsemestres (des étudiants) dont il faut calculer les moyennes"""
|
||||||
|
|
||||||
|
# Les abandons (pour debug)
|
||||||
|
self.abandons = self.get_etudiants_redoublants_ou_reorientes()
|
||||||
|
self.abandons_ids = set(self.abandons)
|
||||||
|
|
||||||
# Synthèse
|
# Synthèse
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
f" => {len(self.etudiants_diplomes)} étudiants à diplômer en {self.annee_diplome}"
|
f" => {len(self.etudiants_diplomes)} étudiants à diplômer en {self.annee_diplome}"
|
||||||
)
|
)
|
||||||
nbre_abandons = len(self.etudiants_ids) - len(self.etudiants_diplomes)
|
nbre_abandons = len(self.etudiants_ids) - len(self.etudiants_diplomes)
|
||||||
pe_affichage.pe_print(f" => {nbre_abandons} étudiants non considérés (redoublement, réorientation, abandon")
|
assert nbre_abandons == len(self.abandons_ids)
|
||||||
|
|
||||||
|
pe_affichage.pe_print(
|
||||||
|
f" => {nbre_abandons} étudiants non considérés (redoublement, réorientation, abandon"
|
||||||
|
)
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne"
|
f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne"
|
||||||
)
|
)
|
||||||
@ -137,14 +161,8 @@ class EtudiantsJuryPE:
|
|||||||
# " => semestres dont il faut calculer les moyennes : "
|
# " => semestres dont il faut calculer les moyennes : "
|
||||||
# + ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)])
|
# + ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)])
|
||||||
# )
|
# )
|
||||||
# Les abandons (pour debug)
|
|
||||||
self.abandons = sorted(
|
|
||||||
[
|
|
||||||
cursus["nom"]
|
|
||||||
for etudid, cursus in self.cursus.items()
|
|
||||||
if etudid not in self.diplomes_ids
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_etudiants_diplomes(self) -> dict[int, Identite]:
|
def get_etudiants_diplomes(self) -> dict[int, Identite]:
|
||||||
"""Identités des étudiants (sous forme d'un dictionnaire `{etudid: Identite(etudid)}`
|
"""Identités des étudiants (sous forme d'un dictionnaire `{etudid: Identite(etudid)}`
|
||||||
@ -164,6 +182,23 @@ class EtudiantsJuryPE:
|
|||||||
etudiants = {etudid: self.identites[etudid] for etudid in etudids}
|
etudiants = {etudid: self.identites[etudid] for etudid in etudids}
|
||||||
return etudiants
|
return etudiants
|
||||||
|
|
||||||
|
def get_etudiants_redoublants_ou_reorientes(self) -> dict[int, Identite]:
|
||||||
|
"""Identités des étudiants (sous forme d'un dictionnaire `{etudid: Identite(etudid)}`
|
||||||
|
dont les notes seront prises en compte (pour les classements) mais qui n'apparaitront
|
||||||
|
pas dans le jury car diplômé une autre année (redoublants) ou réorienté ou démissionnaire.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Un dictionnaire `{etudid: Identite(etudid)}`
|
||||||
|
"""
|
||||||
|
etudids = [
|
||||||
|
etudid
|
||||||
|
for etudid in self.cursus
|
||||||
|
if self.cursus[etudid]["diplome"] != self.annee_diplome
|
||||||
|
or self.cursus[etudid]["abandon"] is True
|
||||||
|
]
|
||||||
|
etudiants = {etudid: self.identites[etudid] for etudid in etudids}
|
||||||
|
return etudiants
|
||||||
|
|
||||||
def analyse_etat_etudiant(self, etudid: int, cosemestres: dict[int, FormSemestre]):
|
def analyse_etat_etudiant(self, etudid: int, cosemestres: dict[int, FormSemestre]):
|
||||||
"""Analyse le cursus d'un étudiant pouvant être :
|
"""Analyse le cursus d'un étudiant pouvant être :
|
||||||
|
|
||||||
@ -254,7 +289,9 @@ class EtudiantsJuryPE:
|
|||||||
} # les semestres de n°i de l'étudiant
|
} # les semestres de n°i de l'étudiant
|
||||||
self.cursus[etudid][nom_sem] = semestres_i
|
self.cursus[etudid][nom_sem] = semestres_i
|
||||||
|
|
||||||
def get_trajectoire(self, etudid: int, formsemestre_final: FormSemestre, nom_aggregat: str):
|
def get_trajectoire(
|
||||||
|
self, etudid: int, formsemestre_final: FormSemestre, nom_aggregat: str
|
||||||
|
):
|
||||||
"""Ensemble des semestres parcourus par
|
"""Ensemble des semestres parcourus par
|
||||||
un étudiant pour l'amener à un semestre terminal.
|
un étudiant pour l'amener à un semestre terminal.
|
||||||
|
|
||||||
@ -279,13 +316,15 @@ class EtudiantsJuryPE:
|
|||||||
numero_semestre_terminal = formsemestre_final.semestre_id
|
numero_semestre_terminal = formsemestre_final.semestre_id
|
||||||
semestres_significatifs = self.get_semestres_significatifs(etudid)
|
semestres_significatifs = self.get_semestres_significatifs(etudid)
|
||||||
|
|
||||||
if nom_aggregat.startswith("S"): # les semestres
|
if nom_aggregat.startswith("S"): # les semestres
|
||||||
numero_semestres_possibles =[numero_semestre_terminal]
|
numero_semestres_possibles = [numero_semestre_terminal]
|
||||||
elif nom_aggregat.endswith("A"): # les années
|
elif nom_aggregat.endswith("A"): # les années
|
||||||
numero_semestres_possibles = [int(sem[-1]) for sem in pe_comp.PARCOURS[nom_aggregat]["aggregat"]]
|
numero_semestres_possibles = [
|
||||||
|
int(sem[-1]) for sem in pe_comp.PARCOURS[nom_aggregat]["aggregat"]
|
||||||
|
]
|
||||||
assert numero_semestre_terminal in numero_semestres_possibles
|
assert numero_semestre_terminal in numero_semestres_possibles
|
||||||
else: # les xS = tous les semestres jusqu'à Sx (pax ex: des S1, S2, S3 pour un S3 terminal)
|
else: # les xS = tous les semestres jusqu'à Sx (pax ex: des S1, S2, S3 pour un S3 terminal)
|
||||||
numero_semestres_possibles = list(range(1, numero_semestre_terminal+1))
|
numero_semestres_possibles = list(range(1, numero_semestre_terminal + 1))
|
||||||
|
|
||||||
semestres_aggreges = {}
|
semestres_aggreges = {}
|
||||||
for fid, semestre in semestres_significatifs.items():
|
for fid, semestre in semestres_significatifs.items():
|
||||||
@ -382,14 +421,65 @@ class EtudiantsJuryPE:
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Probleme de paramètres d'appel dans get_formsemestreids")
|
raise ValueError("Probleme de paramètres d'appel dans get_formsemestreids")
|
||||||
|
|
||||||
def nbre_etapes_max_diplomes(self):
|
def nbre_etapes_max_diplomes(self, etudids: list[int]) -> int:
|
||||||
"""Connaissant les étudiants diplomes du jury PE,
|
"""Partant d'un ensemble d'étudiants,
|
||||||
nombre de semestres (étapes) maximum suivis par les étudiants du jury.
|
nombre de semestres (étapes) maximum suivis par les étudiants du jury.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
etudids: Liste d'étudid d'étudiants
|
||||||
"""
|
"""
|
||||||
nbres_semestres = []
|
nbres_semestres = []
|
||||||
for etudid in self.diplomes_ids:
|
for etudid in etudids:
|
||||||
nbres_semestres.append(self.cursus[etudid]["nb_semestres"])
|
nbres_semestres.append(self.cursus[etudid]["nb_semestres"])
|
||||||
return max(nbres_semestres)
|
if not nbres_semestres:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return max(nbres_semestres)
|
||||||
|
|
||||||
|
def df_administratif(self, etudids: list[int]) -> pd.DataFrame:
|
||||||
|
"""Synthétise toutes les données administratives d'un groupe
|
||||||
|
d'étudiants fournis par les etudid dans un dataFrame
|
||||||
|
|
||||||
|
Args:
|
||||||
|
etudids: La liste des étudiants à prendre en compte
|
||||||
|
"""
|
||||||
|
|
||||||
|
etudids = list(etudids)
|
||||||
|
|
||||||
|
# Récupération des données des étudiants
|
||||||
|
administratif = {}
|
||||||
|
nbre_semestres_max = self.nbre_etapes_max_diplomes(etudids)
|
||||||
|
|
||||||
|
for etudid in etudids:
|
||||||
|
etudiant = self.identites[etudid]
|
||||||
|
cursus = self.cursus[etudid]
|
||||||
|
formsemestres = cursus["formsemestres"]
|
||||||
|
|
||||||
|
if cursus["diplome"]:
|
||||||
|
diplome = cursus["diplome"]
|
||||||
|
else:
|
||||||
|
diplome = "indéterminé"
|
||||||
|
|
||||||
|
administratif[etudid] = {
|
||||||
|
"Nom": etudiant.nom,
|
||||||
|
"Prenom": etudiant.prenom,
|
||||||
|
"Civilite": etudiant.civilite_str,
|
||||||
|
"Age": pe_comp.calcul_age(etudiant.date_naissance),
|
||||||
|
"Date d'entree": cursus["entree"],
|
||||||
|
"Date de diplome": diplome,
|
||||||
|
"Nbre de semestres": len(formsemestres),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ajout des noms de semestres parcourus
|
||||||
|
etapes = pe_affichage.etapes_du_cursus(formsemestres, nbre_semestres_max)
|
||||||
|
administratif[etudid] |= etapes
|
||||||
|
|
||||||
|
# Construction du dataframe
|
||||||
|
df = pd.DataFrame.from_dict(administratif, orient="index")
|
||||||
|
|
||||||
|
# Tri par nom/prénom
|
||||||
|
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
||||||
|
return df
|
||||||
|
|
||||||
|
|
||||||
def get_etudiants_dans_semestres(semestres: dict[int, FormSemestre]) -> set:
|
def get_etudiants_dans_semestres(semestres: dict[int, FormSemestre]) -> set:
|
||||||
|
@ -50,7 +50,6 @@ from app.scodoc.gen_tables import SeqGenTable
|
|||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
from app.pe.pe_trajectoire import TrajectoiresJuryPE, Trajectoire
|
from app.pe.pe_trajectoire import TrajectoiresJuryPE, Trajectoire
|
||||||
import app.pe.pe_comp as pe_comp
|
import app.pe.pe_comp as pe_comp
|
||||||
import app.pe.pe_affichage as pe_affichage
|
|
||||||
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 TrajectoireTag
|
||||||
@ -100,6 +99,7 @@ class JuryPE(object):
|
|||||||
"Nom du zip où ranger les fichiers générés"
|
"Nom du zip où ranger les fichiers générés"
|
||||||
|
|
||||||
self.zipdata = io.BytesIO()
|
self.zipdata = io.BytesIO()
|
||||||
|
|
||||||
with ZipFile(self.zipdata, "w") as zipfile:
|
with ZipFile(self.zipdata, "w") as zipfile:
|
||||||
# Chargement des étudiants à prendre en compte dans le jury
|
# Chargement des étudiants à prendre en compte dans le jury
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
@ -112,100 +112,125 @@ class JuryPE(object):
|
|||||||
self.etudiants.find_etudiants(self.formation_id)
|
self.etudiants.find_etudiants(self.formation_id)
|
||||||
self.diplomes_ids = self.etudiants.diplomes_ids
|
self.diplomes_ids = self.etudiants.diplomes_ids
|
||||||
|
|
||||||
# Génère les semestres taggués (avec le calcul des moyennes) pour le jury PE
|
|
||||||
pe_affichage.pe_print("*** Génère les semestres taggués")
|
|
||||||
self.semestres_taggues = compute_semestres_tag(self.etudiants)
|
|
||||||
|
|
||||||
# Intègre le bilan des semestres taggués au zip final
|
# Intègre le bilan des semestres taggués au zip final
|
||||||
output = io.BytesIO()
|
output = io.BytesIO()
|
||||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||||
for formsemestretag in self.semestres_taggues.values():
|
if self.diplomes_ids:
|
||||||
onglet = formsemestretag.nom
|
onglet = "diplômés"
|
||||||
df = formsemestretag.df_moyennes_et_classements()
|
df_diplome = self.etudiants.df_administratif(self.diplomes_ids)
|
||||||
# écriture dans l'onglet
|
df_diplome.to_excel(writer, onglet, index=True, header=True)
|
||||||
df.to_excel(writer, onglet, index=True, header=True)
|
if self.etudiants.abandons_ids:
|
||||||
|
onglet = "redoublants-réorientés"
|
||||||
|
df_abandon = self.etudiants.df_administratif(
|
||||||
|
self.etudiants.abandons_ids
|
||||||
|
)
|
||||||
|
df_abandon.to_excel(writer, onglet, index=True, header=True)
|
||||||
output.seek(0)
|
output.seek(0)
|
||||||
|
|
||||||
self.add_file_to_zip(
|
self.add_file_to_zip(
|
||||||
zipfile,
|
zipfile,
|
||||||
f"semestres_taggues_{self.diplome}.xlsx",
|
f"etudiants_{self.diplome}.xlsx",
|
||||||
output.read(),
|
output.read(),
|
||||||
path="details",
|
path="details",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Génère les trajectoires (combinaison de semestres suivis
|
if not self.diplomes_ids:
|
||||||
# par un étudiant pour atteindre le semestre final d'un aggrégat)
|
pe_affichage.pe_tools("*** Aucun étudiant diplômé")
|
||||||
pe_affichage.pe_print(
|
else:
|
||||||
"*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
|
# Génère les semestres taggués (avec le calcul des moyennes) pour le jury PE
|
||||||
)
|
pe_affichage.pe_print("*** Génère les semestres taggués")
|
||||||
self.trajectoires = TrajectoiresJuryPE(self.diplome)
|
self.semestres_taggues = compute_semestres_tag(self.etudiants)
|
||||||
self.trajectoires.cree_trajectoires(self.etudiants)
|
|
||||||
|
|
||||||
# Génère les moyennes par tags des trajectoires
|
# Intègre le bilan des semestres taggués au zip final
|
||||||
pe_affichage.pe_print(
|
output = io.BytesIO()
|
||||||
"*** Calcule les moyennes par tag des trajectoires possibles"
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||||
)
|
for formsemestretag in self.semestres_taggues.values():
|
||||||
self.trajectoires_tagguees = compute_trajectoires_tag(
|
onglet = formsemestretag.nom
|
||||||
self.trajectoires, self.etudiants, self.semestres_taggues
|
df = formsemestretag.df_moyennes_et_classements()
|
||||||
)
|
|
||||||
|
|
||||||
# Intègre le bilan des trajectoires tagguées au zip final
|
|
||||||
output = io.BytesIO()
|
|
||||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
|
||||||
for trajectoire_tagguee in self.trajectoires_tagguees.values():
|
|
||||||
onglet = trajectoire_tagguee.get_repr()
|
|
||||||
df = trajectoire_tagguee.df_moyennes_et_classements()
|
|
||||||
# écriture dans l'onglet
|
|
||||||
df.to_excel(writer, onglet, index=True, header=True)
|
|
||||||
output.seek(0)
|
|
||||||
|
|
||||||
self.add_file_to_zip(
|
|
||||||
zipfile,
|
|
||||||
f"trajectoires_taggues_{self.diplome}.xlsx",
|
|
||||||
output.read(),
|
|
||||||
path="details",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Génère les interclassements (par promo et) par (nom d') aggrégat
|
|
||||||
pe_affichage.pe_print("*** Génère les interclassements par aggrégat")
|
|
||||||
self.interclassements_taggues = compute_interclassements(
|
|
||||||
self.etudiants, self.trajectoires, self.trajectoires_tagguees
|
|
||||||
)
|
|
||||||
|
|
||||||
# Intègre le bilan des aggrégats (interclassé par promo) au zip final
|
|
||||||
output = io.BytesIO()
|
|
||||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
|
||||||
for interclass_tag in self.interclassements_taggues.values():
|
|
||||||
if interclass_tag.significatif: # Avec des notes
|
|
||||||
onglet = interclass_tag.get_repr()
|
|
||||||
df = interclass_tag.df_moyennes_et_classements()
|
|
||||||
# écriture dans l'onglet
|
# écriture dans l'onglet
|
||||||
df.to_excel(writer, onglet, index=True, header=True)
|
df.to_excel(writer, onglet, index=True, header=True)
|
||||||
output.seek(0)
|
output.seek(0)
|
||||||
|
|
||||||
self.add_file_to_zip(
|
self.add_file_to_zip(
|
||||||
zipfile,
|
zipfile,
|
||||||
f"interclassements_taggues_{self.diplome}.xlsx",
|
f"semestres_taggues_{self.diplome}.xlsx",
|
||||||
output.read(),
|
output.read(),
|
||||||
path="details",
|
path="details",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Synthèse des éléments du jury PE
|
# Génère les trajectoires (combinaison de semestres suivis
|
||||||
self.synthese = self.synthetise_juryPE()
|
# par un étudiant pour atteindre le semestre final d'un aggrégat)
|
||||||
|
pe_affichage.pe_print(
|
||||||
|
"*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
|
||||||
|
)
|
||||||
|
self.trajectoires = TrajectoiresJuryPE(self.diplome)
|
||||||
|
self.trajectoires.cree_trajectoires(self.etudiants)
|
||||||
|
|
||||||
# Export des données => mode 1 seule feuille -> supprimé
|
# Génère les moyennes par tags des trajectoires
|
||||||
pe_affichage.pe_print("*** Export du jury de synthese")
|
pe_affichage.pe_print(
|
||||||
output = io.BytesIO()
|
"*** Calcule les moyennes par tag des trajectoires possibles"
|
||||||
|
)
|
||||||
|
self.trajectoires_tagguees = compute_trajectoires_tag(
|
||||||
|
self.trajectoires, self.etudiants, self.semestres_taggues
|
||||||
|
)
|
||||||
|
|
||||||
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
# Intègre le bilan des trajectoires tagguées au zip final
|
||||||
for onglet, df in self.synthese.items():
|
output = io.BytesIO()
|
||||||
# écriture dans l'onglet:
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||||
df.to_excel(writer, onglet, index=True, header=True)
|
for trajectoire_tagguee in self.trajectoires_tagguees.values():
|
||||||
output.seek(0)
|
onglet = trajectoire_tagguee.get_repr()
|
||||||
|
df = trajectoire_tagguee.df_moyennes_et_classements()
|
||||||
|
# écriture dans l'onglet
|
||||||
|
df.to_excel(writer, onglet, index=True, header=True)
|
||||||
|
output.seek(0)
|
||||||
|
|
||||||
self.add_file_to_zip(
|
self.add_file_to_zip(
|
||||||
zipfile, f"synthese_jury_{self.diplome}.xlsx", output.read()
|
zipfile,
|
||||||
)
|
f"trajectoires_taggues_{self.diplome}.xlsx",
|
||||||
|
output.read(),
|
||||||
|
path="details",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Génère les interclassements (par promo et) par (nom d') aggrégat
|
||||||
|
pe_affichage.pe_print("*** Génère les interclassements par aggrégat")
|
||||||
|
self.interclassements_taggues = compute_interclassements(
|
||||||
|
self.etudiants, self.trajectoires, self.trajectoires_tagguees
|
||||||
|
)
|
||||||
|
|
||||||
|
# Intègre le bilan des aggrégats (interclassé par promo) au zip final
|
||||||
|
output = io.BytesIO()
|
||||||
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||||
|
for interclass_tag in self.interclassements_taggues.values():
|
||||||
|
if interclass_tag.significatif: # Avec des notes
|
||||||
|
onglet = interclass_tag.get_repr()
|
||||||
|
df = interclass_tag.df_moyennes_et_classements()
|
||||||
|
# écriture dans l'onglet
|
||||||
|
df.to_excel(writer, onglet, index=True, header=True)
|
||||||
|
output.seek(0)
|
||||||
|
|
||||||
|
self.add_file_to_zip(
|
||||||
|
zipfile,
|
||||||
|
f"interclassements_taggues_{self.diplome}.xlsx",
|
||||||
|
output.read(),
|
||||||
|
path="details",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Synthèse des éléments du jury PE
|
||||||
|
self.synthese = self.synthetise_juryPE()
|
||||||
|
|
||||||
|
# Export des données => mode 1 seule feuille -> supprimé
|
||||||
|
pe_affichage.pe_print("*** Export du jury de synthese")
|
||||||
|
output = io.BytesIO()
|
||||||
|
|
||||||
|
with pd.ExcelWriter(output, engine="openpyxl") as writer:
|
||||||
|
for onglet, df in self.synthese.items():
|
||||||
|
# écriture dans l'onglet:
|
||||||
|
df.to_excel(writer, onglet, index=True, header=True)
|
||||||
|
output.seek(0)
|
||||||
|
|
||||||
|
self.add_file_to_zip(
|
||||||
|
zipfile, f"synthese_jury_{self.diplome}.xlsx", output.read()
|
||||||
|
)
|
||||||
|
|
||||||
# Fin !!!! Tada :)
|
# Fin !!!! Tada :)
|
||||||
|
|
||||||
@ -251,7 +276,7 @@ class JuryPE(object):
|
|||||||
|
|
||||||
synthese = {}
|
synthese = {}
|
||||||
pe_affichage.pe_print(" -> Synthèse des données administratives")
|
pe_affichage.pe_print(" -> Synthèse des données administratives")
|
||||||
synthese["administratif"] = self.df_administratif()
|
synthese["administratif"] = self.etudiants.df_administratif(self.diplomes_ids)
|
||||||
|
|
||||||
tags = self.do_tags_list(self.interclassements_taggues)
|
tags = self.do_tags_list(self.interclassements_taggues)
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
@ -259,46 +284,6 @@ class JuryPE(object):
|
|||||||
synthese[tag] = self.df_tag(tag)
|
synthese[tag] = self.df_tag(tag)
|
||||||
return synthese
|
return synthese
|
||||||
|
|
||||||
def df_administratif(self):
|
|
||||||
"""Synthétise toutes les données administratives des étudiants"""
|
|
||||||
|
|
||||||
etudids = list(self.diplomes_ids)
|
|
||||||
|
|
||||||
# Récupération des données des étudiants
|
|
||||||
administratif = {}
|
|
||||||
nbre_semestres_max = self.etudiants.nbre_etapes_max_diplomes()
|
|
||||||
|
|
||||||
for etudid in etudids:
|
|
||||||
etudiant = self.etudiants.identites[etudid]
|
|
||||||
cursus = self.etudiants.cursus[etudid]
|
|
||||||
formsemestres = cursus["formsemestres"]
|
|
||||||
|
|
||||||
if cursus["diplome"]:
|
|
||||||
diplome = cursus["diplome"]
|
|
||||||
else:
|
|
||||||
diplome = "indéterminé"
|
|
||||||
|
|
||||||
administratif[etudid] = {
|
|
||||||
"Nom": etudiant.nom,
|
|
||||||
"Prenom": etudiant.prenom,
|
|
||||||
"Civilite": etudiant.civilite_str,
|
|
||||||
"Age": pe_comp.calcul_age(etudiant.date_naissance),
|
|
||||||
"Date d'entree": cursus["entree"],
|
|
||||||
"Date de diplome": diplome,
|
|
||||||
"Nbre de semestres": len(formsemestres),
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ajout des noms de semestres parcourus
|
|
||||||
etapes = pe_affichage.etapes_du_cursus(formsemestres, nbre_semestres_max)
|
|
||||||
administratif[etudid] |= etapes
|
|
||||||
|
|
||||||
# Construction du dataframe
|
|
||||||
df = pd.DataFrame.from_dict(administratif, orient="index")
|
|
||||||
|
|
||||||
# Tri par nom/prénom
|
|
||||||
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
|
||||||
return df
|
|
||||||
|
|
||||||
def df_tag(self, tag):
|
def df_tag(self, tag):
|
||||||
"""Génère le DataFrame synthétisant les moyennes/classements (groupe,
|
"""Génère le DataFrame synthétisant les moyennes/classements (groupe,
|
||||||
interclassement promo) pour tous les aggrégats prévus,
|
interclassement promo) pour tous les aggrégats prévus,
|
||||||
@ -368,17 +353,6 @@ class JuryPE(object):
|
|||||||
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def table_syntheseJury(self, mode="singlesheet"): # was str_syntheseJury
|
|
||||||
"""Table(s) du jury
|
|
||||||
mode: singlesheet ou multiplesheet pour export excel
|
|
||||||
"""
|
|
||||||
sT = SeqGenTable() # le fichier excel à générer
|
|
||||||
|
|
||||||
if mode == "singlesheet":
|
|
||||||
return sT.get_genTable("singlesheet")
|
|
||||||
else:
|
|
||||||
return sT
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
|
Loading…
Reference in New Issue
Block a user