Version 2 fonctionnelle

This commit is contained in:
Cléo Baras 2024-01-25 19:42:22 +01:00
parent decc28b896
commit cd8d73b41f
4 changed files with 53 additions and 52 deletions

View File

@ -142,7 +142,9 @@ class EtudiantsJuryPE:
+ ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)])
)
# Les abandons :
# sorted([etudiants.cursus[etudid]['nom'] for etudid in etudiants.cursus if etudid not in etudiants.diplomes_ids])
self.abandons = sorted([self.cursus[etudid]['nom']
for etudid in self.cursus if etudid not in self.diplomes_ids])
def get_etudiants_diplomes(self) -> dict[int, Identite]:
"""Identités des étudiants (sous forme d'un dictionnaire `{etudid: Identite(etudid)}`

View File

@ -71,17 +71,17 @@ import numpy as np
# ----------------------------------------------------------------------------------------
class JuryPE(object):
"""Classe mémorisant toutes les informations nécessaires pour établir un jury de PE.
Modèle basé sur NotesTable.
Modèle basé sur NotesTable.
Attributs :
Attributs :
* diplome : l'année d'obtention du diplome BUT et du jury de PE (généralement février XXXX)
* juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives +
celles des semestres valides à prendre en compte permettant le calcul des moyennes ...
``{'etudid : { 'nom', 'prenom', 'civilite', 'diplome', '', }}``
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
* diplome : l'année d'obtention du diplome BUT et du jury de PE (généralement février XXXX)
* juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives +
celles des semestres valides à prendre en compte permettant le calcul des moyennes ...
``{'etudid : { 'nom', 'prenom', 'civilite', 'diplome', '', }}``
a
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
"""
# Variables de classe décrivant les aggrégats, leur ordre d'apparition temporelle et
@ -100,8 +100,6 @@ class JuryPE(object):
meme_programme: si True, impose un même programme pour tous les étudiants participant au jury,
si False, permet des programmes differents
"""
self.promoTagDict = {}
"L'année du diplome"
self.diplome = diplome
@ -113,8 +111,6 @@ class JuryPE(object):
self.zipdata = io.BytesIO()
self.zipfile = ZipFile(self.zipdata, "w")
"""Chargement des étudiants à prendre en compte dans le jury"""
pe_comp.pe_print(
f"*** Recherche et chargement des étudiants diplômés en {self.diplome} pour la formation {self.formation_id}"
@ -187,14 +183,19 @@ class JuryPE(object):
# Export des données => mode 1 seule feuille -> supprimé
pe_comp.pe_print("*** Export du jury de synthese")
filename = "synthese_jury_" + str(self.diplome) + '.xls'
filename = "synthese_jury_" + str(self.diplome) + ".xlsx"
with pd.ExcelWriter(filename, engine="openpyxl") as writer:
for onglet in self.synthese:
df = self.synthese[onglet]
df.to_excel(writer, onglet, index=True, header=True) # écriture dans l'onglet
df.to_excel(
writer, onglet, index=True, header=True
) # écriture dans l'onglet
# worksheet = writer.sheets[onglet] # l'on
self.zipfile.write(filename)
self.add_file_to_zip(
filename,
open(filename, "rb").read(),
)
"""Fin !!!! Tada :)"""
@ -208,7 +209,7 @@ class JuryPE(object):
data: Les données du fichier
path: Un dossier dans l'arborescence du zip
"""
path_in_zip = os.path.join(self.nom_export_zip, path, filename)
path_in_zip = os.path.join(path, filename) # self.nom_export_zip,
self.zipfile.writestr(path_in_zip, data)
def get_zipped_data(self):
@ -231,7 +232,6 @@ class JuryPE(object):
tags = sorted(set(tags))
return tags
# **************************************************************************************************************** #
# Méthodes pour la synthèse du juryPE
# *****************************************************************************************************************
@ -251,7 +251,6 @@ class JuryPE(object):
synthese[tag] = self.df_tag(tag)
return synthese
def df_administratif(self):
"""Synthétise toutes les données administratives des étudiants"""
@ -270,10 +269,10 @@ class JuryPE(object):
"Nom": etudiant.nom,
"Prenom": etudiant.prenom,
"Civilite": etudiant.civilite_str,
"Age": pe_comp.calcul_age(etudiant.date_naissance),
"Age": pe_comp.calcul_age(etudiant.date_naissance),
"Date d'entree": cursus["entree"],
"Date de diplome": cursus["diplome"],
"Nbre de semestres": len(formsemestres)
"Nbre de semestres": len(formsemestres),
}
# Ajout des noms de semestres parcourus
@ -281,9 +280,11 @@ class JuryPE(object):
administratif[etudid] |= etapes
"""Construction du dataframe"""
df = pd.DataFrame.from_dict(administratif, orient='index')
return df
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):
"""Génère le DataFrame synthétisant les moyennes/classements (groupe,
@ -299,7 +300,6 @@ class JuryPE(object):
etudids = list(self.diplomes_ids)
aggregats = pe_comp.TOUS_LES_PARCOURS
donnees = {}
for etudid in etudids:
@ -315,18 +315,21 @@ class JuryPE(object):
trajectoire = self.trajectoires.suivi[etudid][aggregat]
"""Les moyennes par tag de cette trajectoire"""
if trajectoire:
trajectoire_tagguee = self.trajectoires_tagguees[trajectoire.trajectoire_id]
trajectoire_tagguee = self.trajectoires_tagguees[
trajectoire.trajectoire_id
]
bilan = trajectoire_tagguee.moyennes_tags[tag]
donnees[etudid] |= {
f"{aggregat} notes ": f"{bilan['notes'].loc[etudid]:.1f}",
f"{aggregat} class. (groupe)": f"{bilan['classements'].loc[etudid]}/{bilan['nb_inscrits']}",
f"{aggregat} min/moy/max (groupe)": f"{bilan['min']:.1f}/{bilan['moy']:.1f}/{bilan['max']:.1f}"}
f"{aggregat} min/moy/max (groupe)": f"{bilan['min']:.1f}/{bilan['moy']:.1f}/{bilan['max']:.1f}",
}
else:
donnees[etudid] |= {
f"{aggregat} notes ": "-",
f"{aggregat} class. (groupe)": "-",
f"{aggregat} min/moy/max (groupe)": "-"
f"{aggregat} min/moy/max (groupe)": "-",
}
"""L'interclassement"""
@ -335,29 +338,29 @@ class JuryPE(object):
bilan = interclass.moyennes_tags[tag]
donnees[etudid] |= {
f"{aggregat} class. (promo)": f"{bilan['classements'].loc[etudid]}/{bilan['nb_inscrits']}",
f"{aggregat} min/moy/max (promo)": f"{bilan['min']:.1f}/{bilan['moy']:.1f}/{bilan['max']:.1f}"
f"{aggregat} class. (promo)": f"{bilan['classements'].loc[etudid]}/{bilan['nb_inscrits']}",
f"{aggregat} min/moy/max (promo)": f"{bilan['min']:.1f}/{bilan['moy']:.1f}/{bilan['max']:.1f}",
}
else:
donnees[etudid] |= {
f"{aggregat} class. (promo)": "-",
f"{aggregat} min/moy/max (promo)": "-"
f"{aggregat} min/moy/max (promo)": "-",
}
# Fin de l'aggrégat
"""Construction du dataFrame"""
df = pd.DataFrame.from_dict(donnees, orient="index")
df = pd.DataFrame.from_dict(donnees, orient='index')
"""Tri par nom/prénom"""
df.sort_values(by=["Nom", "Prenom"], inplace = True)
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:

View File

@ -93,9 +93,6 @@ class TrajectoireTag(TableTag):
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.cursus = {
etudid: donnees_etudiants.cursus[etudid] for etudid in self.etudiants
}
"""Les tags extraits de tous les semestres"""
self.tags_sorted = self.do_taglist()
@ -104,7 +101,7 @@ class TrajectoireTag(TableTag):
self.notes_cube = self.compute_notes_cube()
"""Calcul les moyennes par tag sous forme d'un dataframe"""
etudids = self.get_etudids()
etudids = list(self.etudiants.keys())
self.notes = compute_tag_moy(self.notes_cube, etudids, self.tags_sorted)
"""Synthétise les moyennes/classements par tag"""
@ -166,8 +163,7 @@ class TrajectoireTag(TableTag):
return etudids_x_tags_x_semestres
def get_etudids(self):
return list(self.etudiants.keys())
def do_taglist(self):
"""Synthétise les tags à partir des semestres (taggués) aggrégés

View File

@ -45,8 +45,8 @@ from app.scodoc import sco_formsemestre
from app.scodoc import html_sco_header
from app.scodoc import sco_preferences
from app.pe import pe_tools
from app.pe import pe_jurype
from app.pe import pe_comp
from app.pe import pe_jury
from app.pe import pe_avislatex
@ -75,7 +75,7 @@ def _pe_view_sem_recap_form(formsemestre_id):
return "\n".join(H) + html_sco_header.sco_footer()
# L'année du diplome
diplome = pe_tools.get_annee_diplome_semestre(sem_base)
diplome = pe_comp.get_annee_diplome_semestre(sem_base)
H = [
html_sco_header.sco_header(page_title="Avis de poursuite d'études"),
@ -136,12 +136,12 @@ def pe_view_sem_recap(
)
# L'année du diplome
diplome = pe_tools.get_annee_diplome_semestre(sem_base)
diplome = pe_comp.get_annee_diplome_semestre(sem_base)
jury = pe_jurype.JuryPE(diplome, sem_base.formation.formation_id)
jury = pe_jury.JuryPE(diplome, sem_base.formation.formation_id)
# Ajout avis LaTeX au même zip:
etudids = list(jury.syntheseJury.keys())
# etudids = list(jury.syntheseJury.keys())
# Récupération du template latex, du footer latex et du tag identifiant les annotations relatives aux PE
# (chaines unicodes, html non quoté)
@ -187,11 +187,11 @@ def pe_view_sem_recap(
)
# Ajout des annotations PE dans un fichier excel
sT = pe_avislatex.table_syntheseAnnotationPE(jury.syntheseJury, tag_annotation_pe)
if sT:
jury.add_file_to_zip(
jury.nom_export_zip + "_annotationsPE" + scu.XLSX_SUFFIX, sT.excel()
)
# sT = pe_avislatex.table_syntheseAnnotationPE(jury.syntheseJury, tag_annotation_pe)
# if sT:
# jury.add_file_to_zip(
# jury.nom_export_zip + "_annotationsPE" + scu.XLSX_SUFFIX, sT.excel()
# )
if False:
latex_pages = {} # Dictionnaire de la forme nom_fichier => contenu_latex