Merge branch 'pe-BUT-v2' of https://scodoc.org/git/cleo/ScoDoc-PE
This commit is contained in:
commit
af659d5f09
@ -1,5 +1,3 @@
|
||||
from app.models import Formation, FormSemestre
|
||||
from app.scodoc import codes_cursus
|
||||
from app import log
|
||||
|
||||
PE_DEBUG = 0
|
||||
@ -9,71 +7,13 @@ if not PE_DEBUG:
|
||||
def pe_print(*a, **kw):
|
||||
# kw is ignored. log always add a newline
|
||||
log(" ".join(a))
|
||||
|
||||
else:
|
||||
pe_print = print # print function
|
||||
|
||||
|
||||
def nom_semestre_etape(semestre: FormSemestre, avec_fid=False) -> str:
|
||||
"""Nom d'un semestre à afficher dans le descriptif des étapes de la scolarité
|
||||
d'un étudiant.
|
||||
|
||||
Par ex: Pour un S2, affiche ``"Semestre 2 FI S014-2015 (129)"`` avec :
|
||||
|
||||
* 2 le numéro du semestre,
|
||||
* FI la modalité,
|
||||
* 2014-2015 les dates
|
||||
|
||||
Args:
|
||||
semestre: Un ``FormSemestre``
|
||||
avec_fid: Ajoute le n° du semestre à la description
|
||||
|
||||
Returns:
|
||||
La chaine de caractères décrivant succintement le semestre
|
||||
"""
|
||||
formation: Formation = semestre.formation
|
||||
parcours = codes_cursus.get_cursus_from_code(formation.type_parcours)
|
||||
|
||||
description = [
|
||||
parcours.SESSION_NAME.capitalize(),
|
||||
str(semestre.semestre_id),
|
||||
semestre.modalite, # eg FI ou FC
|
||||
f"{semestre.date_debut.year}-{semestre.date_fin.year}",
|
||||
]
|
||||
if avec_fid:
|
||||
description.append(f"({semestre.formsemestre_id})")
|
||||
|
||||
return " ".join(description)
|
||||
# Affichage dans le tableur pe en cas d'absence de notes
|
||||
SANS_NOTE = "-"
|
||||
NOM_STAT_GROUPE = "statistiques du groupe"
|
||||
NOM_STAT_PROMO = "statistiques de la promo"
|
||||
|
||||
|
||||
def etapes_du_cursus(semestres: dict[int, FormSemestre], nbre_etapes_max: int) -> list[str]:
|
||||
"""Partant d'un dictionnaire de semestres (qui retrace
|
||||
la scolarité d'un étudiant), liste les noms des
|
||||
semestres (en version abbrégée)
|
||||
qu'un étudiant a suivi au cours de sa scolarité à l'IUT.
|
||||
Les noms des semestres sont renvoyés dans un dictionnaire
|
||||
``{"etape i": nom_semestre_a_etape_i}``
|
||||
avec i variant jusqu'à nbre_semestres_max. (S'il n'y a pas de semestre à l'étape i,
|
||||
le nom affiché est vide.
|
||||
|
||||
La fonction suppose la liste des semestres triées par ordre
|
||||
décroissant de date.
|
||||
|
||||
Args:
|
||||
semestres: une liste de ``FormSemestre``
|
||||
nbre_etapes_max: le nombre d'étapes max prise en compte
|
||||
|
||||
Returns:
|
||||
Une liste de nom de semestre (dans le même ordre que les ``semestres``)
|
||||
|
||||
See also:
|
||||
app.pe.pe_affichage.nom_semestre_etape
|
||||
"""
|
||||
assert len(semestres) <= nbre_etapes_max
|
||||
|
||||
noms = [nom_semestre_etape(sem, avec_fid=False) for (fid, sem) in semestres.items()]
|
||||
noms = noms[::-1] # trie par ordre croissant
|
||||
|
||||
dico = {f"Etape {i+1}": "" for i in range(nbre_etapes_max)}
|
||||
for (i, nom) in enumerate(noms): # Charge les noms de semestres
|
||||
dico[f"Etape {i+1}"] = nom
|
||||
return dico
|
||||
|
@ -75,81 +75,55 @@ TODO:: A améliorer si BUT en moins de 6 semestres
|
||||
PARCOURS = {
|
||||
"S1": {
|
||||
"aggregat": ["S1"],
|
||||
"ordre": 1,
|
||||
"affichage_court": "S1",
|
||||
"affichage_long": "Semestre 1",
|
||||
"descr": "Semestre 1 (S1)",
|
||||
},
|
||||
"S2": {
|
||||
"aggregat": ["S2"],
|
||||
"ordre": 2,
|
||||
"affichage_court": "S2",
|
||||
"affichage_long": "Semestre 2",
|
||||
"descr": "Semestre 2 (S2)",
|
||||
},
|
||||
"1A": {
|
||||
"aggregat": ["S1", "S2"],
|
||||
"ordre": 3,
|
||||
"affichage_court": "1A",
|
||||
"affichage_long": "1ère année",
|
||||
"descr": "BUT1 (S1+S2)",
|
||||
},
|
||||
"S3": {
|
||||
"aggregat": ["S3"],
|
||||
"ordre": 4,
|
||||
"affichage_court": "S3",
|
||||
"affichage_long": "Semestre 3",
|
||||
"descr": "Semestre 3 (S3)",
|
||||
},
|
||||
"S4": {
|
||||
"aggregat": ["S4"],
|
||||
"ordre": 5,
|
||||
"affichage_court": "S4",
|
||||
"affichage_long": "Semestre 4",
|
||||
"descr": "Semestre 4 (S4)",
|
||||
},
|
||||
"2A": {
|
||||
"aggregat": ["S3", "S4"],
|
||||
"ordre": 6,
|
||||
"affichage_court": "2A",
|
||||
"affichage_long": "2ème année",
|
||||
"descr": "BUT2 (S3+S4)",
|
||||
},
|
||||
"3S": {
|
||||
"aggregat": ["S1", "S2", "S3"],
|
||||
"ordre": 7,
|
||||
"affichage_court": "S1+S2+S3",
|
||||
"affichage_long": "BUT du semestre 1 au semestre 3",
|
||||
"descr": "Moyenne du semestre 1 au semestre 3 (S1+S2+S3)",
|
||||
},
|
||||
"4S": {
|
||||
"aggregat": ["S1", "S2", "S3", "S4"],
|
||||
"ordre": 8,
|
||||
"affichage_court": "BUT",
|
||||
"affichage_long": "BUT du semestre 1 au semestre 4",
|
||||
"descr": "Moyenne du semestre 1 au semestre 4 (S1+S2+S3+S4)",
|
||||
},
|
||||
"S5": {
|
||||
"aggregat": ["S5"],
|
||||
"ordre": 9,
|
||||
"affichage_court": "S5",
|
||||
"affichage_long": "Semestre 5",
|
||||
"descr": "Semestre 5 (S5)",
|
||||
},
|
||||
"S6": {
|
||||
"aggregat": ["S6"],
|
||||
"ordre": 10,
|
||||
"affichage_court": "S6",
|
||||
"affichage_long": "Semestre 6",
|
||||
"descr": "Semestre 6 (S6)",
|
||||
},
|
||||
"3A": {
|
||||
"aggregat": ["S5", "S6"],
|
||||
"ordre": 11,
|
||||
"affichage_court": "3A",
|
||||
"affichage_long": "3ème année",
|
||||
"descr": "3ème année (S5+S6)",
|
||||
},
|
||||
"5S": {
|
||||
"aggregat": ["S1", "S2", "S3", "S4", "S5"],
|
||||
"ordre": 12,
|
||||
"affichage_court": "S1+S2+S3+S4+S5",
|
||||
"affichage_long": "BUT du semestre 1 au semestre 5",
|
||||
"descr": "Moyenne du semestre 1 au semestre 5 (S1+S2+S3+S4+S5)",
|
||||
},
|
||||
"6S": {
|
||||
"aggregat": ["S1", "S2", "S3", "S4", "S5", "S6"],
|
||||
"ordre": 13,
|
||||
"affichage_court": "BUT",
|
||||
"affichage_long": "BUT (tout semestre inclus)",
|
||||
"descr": "Moyenne globale BUT (S1+S2+S3+S4+S5+S6)",
|
||||
},
|
||||
}
|
||||
NBRE_SEMESTRES_DIPLOMANT = 6
|
||||
|
@ -37,8 +37,9 @@ Created on 17/01/2024
|
||||
"""
|
||||
import pandas as pd
|
||||
|
||||
from app.models import FormSemestre, Identite
|
||||
from app.models import FormSemestre, Identite, Formation
|
||||
from app.pe import pe_comp, pe_affichage
|
||||
from app.scodoc import codes_cursus
|
||||
|
||||
|
||||
class EtudiantsJuryPE:
|
||||
@ -467,7 +468,7 @@ class EtudiantsJuryPE:
|
||||
}
|
||||
|
||||
# Ajout des noms de semestres parcourus
|
||||
etapes = pe_affichage.etapes_du_cursus(formsemestres, nbre_semestres_max)
|
||||
etapes = etapes_du_cursus(formsemestres, nbre_semestres_max)
|
||||
administratif[etudid] |= etapes
|
||||
|
||||
# Construction du dataframe
|
||||
@ -647,3 +648,71 @@ def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]) -> FormSeme
|
||||
dernier_semestre = semestres[fid]
|
||||
return dernier_semestre
|
||||
return None
|
||||
|
||||
|
||||
def etapes_du_cursus(
|
||||
semestres: dict[int, FormSemestre], nbre_etapes_max: int
|
||||
) -> list[str]:
|
||||
"""Partant d'un dictionnaire de semestres (qui retrace
|
||||
la scolarité d'un étudiant), liste les noms des
|
||||
semestres (en version abbrégée)
|
||||
qu'un étudiant a suivi au cours de sa scolarité à l'IUT.
|
||||
Les noms des semestres sont renvoyés dans un dictionnaire
|
||||
``{"etape i": nom_semestre_a_etape_i}``
|
||||
avec i variant jusqu'à nbre_semestres_max. (S'il n'y a pas de semestre à l'étape i,
|
||||
le nom affiché est vide.
|
||||
|
||||
La fonction suppose la liste des semestres triées par ordre
|
||||
décroissant de date.
|
||||
|
||||
Args:
|
||||
semestres: une liste de ``FormSemestre``
|
||||
nbre_etapes_max: le nombre d'étapes max prise en compte
|
||||
|
||||
Returns:
|
||||
Une liste de nom de semestre (dans le même ordre que les ``semestres``)
|
||||
|
||||
See also:
|
||||
app.pe.pe_affichage.nom_semestre_etape
|
||||
"""
|
||||
assert len(semestres) <= nbre_etapes_max
|
||||
|
||||
noms = [nom_semestre_etape(sem, avec_fid=False) for (fid, sem) in semestres.items()]
|
||||
noms = noms[::-1] # trie par ordre croissant
|
||||
|
||||
dico = {f"Etape {i+1}": "" for i in range(nbre_etapes_max)}
|
||||
for i, nom in enumerate(noms): # Charge les noms de semestres
|
||||
dico[f"Etape {i+1}"] = nom
|
||||
return dico
|
||||
|
||||
|
||||
def nom_semestre_etape(semestre: FormSemestre, avec_fid=False) -> str:
|
||||
"""Nom d'un semestre à afficher dans le descriptif des étapes de la scolarité
|
||||
d'un étudiant.
|
||||
|
||||
Par ex: Pour un S2, affiche ``"Semestre 2 FI S014-2015 (129)"`` avec :
|
||||
|
||||
* 2 le numéro du semestre,
|
||||
* FI la modalité,
|
||||
* 2014-2015 les dates
|
||||
|
||||
Args:
|
||||
semestre: Un ``FormSemestre``
|
||||
avec_fid: Ajoute le n° du semestre à la description
|
||||
|
||||
Returns:
|
||||
La chaine de caractères décrivant succintement le semestre
|
||||
"""
|
||||
formation: Formation = semestre.formation
|
||||
parcours = codes_cursus.get_cursus_from_code(formation.type_parcours)
|
||||
|
||||
description = [
|
||||
parcours.SESSION_NAME.capitalize(),
|
||||
str(semestre.semestre_id),
|
||||
semestre.modalite, # eg FI ou FC
|
||||
f"{semestre.date_debut.year}-{semestre.date_fin.year}",
|
||||
]
|
||||
if avec_fid:
|
||||
description.append(f"({semestre.formsemestre_id})")
|
||||
|
||||
return " ".join(description)
|
||||
|
@ -46,6 +46,12 @@ import io
|
||||
import os
|
||||
from zipfile import ZipFile
|
||||
|
||||
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_tabletags import TableTag
|
||||
from app.scodoc.gen_tables import SeqGenTable
|
||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||
from app.pe.pe_trajectoire import TrajectoiresJuryPE, Trajectoire
|
||||
@ -116,7 +122,9 @@ class JuryPE(object):
|
||||
self._gen_xls_semestre_taggues(zipfile)
|
||||
self._gen_xls_trajectoires(zipfile)
|
||||
self._gen_xls_aggregats(zipfile)
|
||||
self._gen_xls_synthese(zipfile)
|
||||
self._gen_xls_synthese_jury_par_tag(zipfile)
|
||||
self._gen_xls_synthese_par_etudiant(zipfile)
|
||||
|
||||
|
||||
# Fin !!!! Tada :)
|
||||
|
||||
@ -234,13 +242,13 @@ class JuryPE(object):
|
||||
path="details",
|
||||
)
|
||||
|
||||
def _gen_xls_synthese(self, zipfile: ZipFile):
|
||||
"""Synthèse des éléments du jury PE"""
|
||||
def _gen_xls_synthese_jury_par_tag(self, zipfile: ZipFile):
|
||||
"""Synthèse des éléments du jury PE tag par tag"""
|
||||
# Synthèse des éléments du jury PE
|
||||
self.synthese = self.synthetise_juryPE()
|
||||
self.synthese = self.synthetise_jury_par_tags()
|
||||
|
||||
# Export des données => mode 1 seule feuille -> supprimé
|
||||
pe_affichage.pe_print("*** Export du jury de synthese")
|
||||
pe_affichage.pe_print("*** Export du jury de synthese par tags")
|
||||
output = io.BytesIO()
|
||||
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
|
||||
output, engine="openpyxl"
|
||||
@ -251,7 +259,27 @@ class JuryPE(object):
|
||||
output.seek(0)
|
||||
|
||||
self.add_file_to_zip(
|
||||
zipfile, f"synthese_jury_{self.diplome}.xlsx", output.read()
|
||||
zipfile, f"synthese_jury_{self.diplome}_par_tag.xlsx", output.read()
|
||||
)
|
||||
|
||||
def _gen_xls_synthese_par_etudiant(self, zipfile: ZipFile):
|
||||
"""Synthèse des éléments du jury PE, étudiant par étudiant"""
|
||||
# Synthèse des éléments du jury PE
|
||||
synthese = self.synthetise_jury_par_etudiants()
|
||||
|
||||
# Export des données => mode 1 seule feuille -> supprimé
|
||||
pe_affichage.pe_print("*** Export du jury de synthese par étudiants")
|
||||
output = io.BytesIO()
|
||||
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
|
||||
output, engine="openpyxl"
|
||||
) as writer:
|
||||
for onglet, df in 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}_par_etudiant.xlsx", output.read()
|
||||
)
|
||||
|
||||
def add_file_to_zip(self, zipfile: ZipFile, filename: str, data, path=""):
|
||||
@ -289,10 +317,11 @@ class JuryPE(object):
|
||||
# Méthodes pour la synthèse du juryPE
|
||||
# *****************************************************************************************************************
|
||||
|
||||
def synthetise_juryPE(self):
|
||||
"""Synthétise tous les résultats du jury PE dans des dataframes"""
|
||||
def synthetise_jury_par_tags(self) -> dict[pd.DataFrame]:
|
||||
"""Synthétise tous les résultats du jury PE dans des dataframes,
|
||||
dont les onglets sont les tags"""
|
||||
|
||||
pe_affichage.pe_print("*** Synthèse finale des moyennes ***")
|
||||
pe_affichage.pe_print("*** Synthèse finale des moyennes par tag***")
|
||||
|
||||
synthese = {}
|
||||
pe_affichage.pe_print(" -> Synthèse des données administratives")
|
||||
@ -323,56 +352,108 @@ class JuryPE(object):
|
||||
for etudid in etudids:
|
||||
etudiant = self.etudiants.identites[etudid]
|
||||
donnees[etudid] = {
|
||||
"Nom": etudiant.nom,
|
||||
"Prenom": etudiant.prenom,
|
||||
"Civilite": etudiant.civilite_str,
|
||||
("Identité", "", "Civilite"): etudiant.civilite_str,
|
||||
("Identité", "", "Nom"): etudiant.nom,
|
||||
("Identité", "", "Prenom"): etudiant.prenom,
|
||||
}
|
||||
|
||||
for aggregat in aggregats:
|
||||
# Le dictionnaire par défaut des moyennes
|
||||
donnees[etudid] |= get_defaut_dict_synthese_aggregat(aggregat, self.diplome)
|
||||
|
||||
# La trajectoire de l'étudiant sur l'aggrégat
|
||||
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
||||
|
||||
# Les moyennes par tag de cette trajectoire
|
||||
donnees[etudid] |= {
|
||||
f"{aggregat} notes ": "-",
|
||||
f"{aggregat} class. (groupe)": "-",
|
||||
f"{aggregat} min | moy | max (groupe)": "-",
|
||||
}
|
||||
if trajectoire:
|
||||
trajectoire_tagguee = self.trajectoires_tagguees[
|
||||
trajectoire.trajectoire_id
|
||||
]
|
||||
if tag in trajectoire_tagguee.moyennes_tags:
|
||||
bilan = trajectoire_tagguee.moyennes_tags[tag]
|
||||
else:
|
||||
trajectoire_tagguee = None
|
||||
|
||||
donnees[etudid] |= {
|
||||
f"{aggregat} notes ": round(bilan["notes"].loc[etudid], 2),
|
||||
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}",
|
||||
}
|
||||
|
||||
"""L'interclassement"""
|
||||
# L'interclassement
|
||||
interclass = self.interclassements_taggues[aggregat]
|
||||
donnees[etudid] |= {
|
||||
f"{aggregat} class. (promo)": "-",
|
||||
f"{aggregat} min | moy | max (promo)": "-",
|
||||
}
|
||||
if tag in interclass.moyennes_tags:
|
||||
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}",
|
||||
}
|
||||
# Injection des données dans un dictionnaire
|
||||
donnees[etudid] |= get_dict_synthese_aggregat(aggregat, trajectoire_tagguee, interclass, etudid, tag, self.diplome)
|
||||
|
||||
|
||||
|
||||
# Fin de l'aggrégat
|
||||
# Construction du dataFrame
|
||||
df = pd.DataFrame.from_dict(donnees, orient="index")
|
||||
|
||||
# Tri par nom/prénom
|
||||
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
||||
df.sort_values(
|
||||
by=[("Identité", "", "Nom"), ("Identité", "", "Prenom")], inplace=True
|
||||
)
|
||||
return df
|
||||
|
||||
def synthetise_jury_par_etudiants(self) -> dict[pd.DataFrame]:
|
||||
"""Synthétise tous les résultats du jury PE dans des dataframes,
|
||||
dont les onglets sont les étudiants"""
|
||||
pe_affichage.pe_print("*** Synthèse finale des moyennes par étudiants***")
|
||||
|
||||
synthese = {}
|
||||
pe_affichage.pe_print(" -> Synthèse des données administratives")
|
||||
synthese["administratif"] = self.etudiants.df_administratif(self.diplomes_ids)
|
||||
|
||||
etudids = list(self.diplomes_ids)
|
||||
|
||||
for etudid in etudids:
|
||||
etudiant = self.etudiants.identites[etudid]
|
||||
nom = etudiant.nom
|
||||
prenom = etudiant.prenom[0] # initial du prénom
|
||||
|
||||
onglet = f"{nom} {prenom}. ({etudid})"
|
||||
if len(onglet) > 32: # limite sur la taille des onglets
|
||||
fin_onglet = f"{prenom}. ({etudid})"
|
||||
onglet = f"{nom[:32-len(fin_onglet)-2]}." + fin_onglet
|
||||
|
||||
pe_affichage.pe_print(f" -> Synthèse de l'étudiant {etudid}")
|
||||
synthese[onglet] = self.df_synthese_etudiant(etudid)
|
||||
return synthese
|
||||
|
||||
def df_synthese_etudiant(self, etudid: int) -> pd.DataFrame:
|
||||
"""Créé un DataFrame pour un étudiant donné par son etudid, retraçant
|
||||
toutes ses moyennes aux différents tag et aggrégats"""
|
||||
tags = self.do_tags_list(self.interclassements_taggues)
|
||||
aggregats = pe_comp.TOUS_LES_PARCOURS
|
||||
|
||||
donnees = {}
|
||||
|
||||
for tag in tags:
|
||||
# Une ligne pour le tag
|
||||
donnees[tag] = {("", "", "tag"): tag}
|
||||
|
||||
for aggregat in aggregats:
|
||||
# Le dictionnaire par défaut des moyennes
|
||||
donnees[tag] |= get_defaut_dict_synthese_aggregat(aggregat, self.diplome)
|
||||
|
||||
# La trajectoire de l'étudiant sur l'aggrégat
|
||||
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
||||
if trajectoire:
|
||||
trajectoire_tagguee = self.trajectoires_tagguees[
|
||||
trajectoire.trajectoire_id
|
||||
]
|
||||
else:
|
||||
trajectoire_tagguee = None
|
||||
|
||||
# L'interclassement
|
||||
interclass = self.interclassements_taggues[aggregat]
|
||||
|
||||
# Injection des données dans un dictionnaire
|
||||
donnees[tag] |= get_dict_synthese_aggregat(aggregat, trajectoire_tagguee, interclass, etudid, tag, self.diplome)
|
||||
|
||||
|
||||
# Fin de l'aggrégat
|
||||
# Construction du dataFrame
|
||||
df = pd.DataFrame.from_dict(donnees, orient="index")
|
||||
|
||||
# Tri par nom/prénom
|
||||
df.sort_values(
|
||||
by=[("", "", "tag")], inplace=True
|
||||
)
|
||||
return df
|
||||
|
||||
def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
|
||||
"""Créé les semestres taggués, de type 'S1', 'S2', ..., pour un groupe d'étudiants donnés.
|
||||
@ -466,3 +547,122 @@ def compute_interclassements(
|
||||
)
|
||||
aggregats_interclasses_taggues[nom_aggregat] = interclass
|
||||
return aggregats_interclasses_taggues
|
||||
|
||||
|
||||
def get_defaut_dict_synthese_aggregat(aggregat: str, diplome: int) -> dict:
|
||||
"""Renvoie le dictionnaire de synthèse (à intégrer dans
|
||||
un tableur excel) pour décrire les résultats d'un aggrégat"""
|
||||
# L'affichage de l'aggrégat dans le tableur excel
|
||||
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
||||
|
||||
nom_stat_promo = f"{NOM_STAT_PROMO} {diplome}"
|
||||
donnees = {
|
||||
(descr, "", "note"): SANS_NOTE,
|
||||
# Les stat du groupe
|
||||
(descr, NOM_STAT_GROUPE, "class."): SANS_NOTE,
|
||||
(descr, NOM_STAT_GROUPE, "min"): SANS_NOTE,
|
||||
(descr, NOM_STAT_GROUPE, "moy"): SANS_NOTE,
|
||||
(descr, NOM_STAT_GROUPE, "max"): SANS_NOTE,
|
||||
# Les stats de l'interclassement dans la promo
|
||||
(descr, nom_stat_promo, "class."): SANS_NOTE,
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"min",
|
||||
): SANS_NOTE,
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"moy",
|
||||
): SANS_NOTE,
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"max",
|
||||
): SANS_NOTE,
|
||||
}
|
||||
return donnees
|
||||
|
||||
|
||||
def get_dict_synthese_aggregat(
|
||||
aggregat: str,
|
||||
trajectoire_tagguee: TrajectoireTag,
|
||||
interclassement_taggue: AggregatInterclasseTag,
|
||||
etudid: int,
|
||||
tag: str,
|
||||
diplome: int
|
||||
):
|
||||
"""Renvoie le dictionnaire (à intégrer au tableur excel de synthese)
|
||||
traduisant les résultats (moy/class) d'un étudiant à une trajectoire tagguée associée
|
||||
à l'aggrégat donné et pour un tag donné"""
|
||||
donnees = {}
|
||||
# L'affichage de l'aggrégat dans le tableur excel
|
||||
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
||||
|
||||
# La note de l'étudiant (chargement à venir)
|
||||
note = np.nan
|
||||
|
||||
# Les données de la trajectoire tagguée pour le tag considéré
|
||||
if trajectoire_tagguee and tag in trajectoire_tagguee.moyennes_tags:
|
||||
bilan = trajectoire_tagguee.moyennes_tags[tag]
|
||||
|
||||
# La moyenne de l'étudiant
|
||||
note = TableTag.get_note_for_df(bilan, etudid)
|
||||
|
||||
# Statistiques sur le groupe
|
||||
if note != np.nan:
|
||||
# Les moyennes de cette trajectoire
|
||||
donnees |= {
|
||||
(descr, "", "note"): note,
|
||||
(
|
||||
descr,
|
||||
NOM_STAT_GROUPE,
|
||||
"class.",
|
||||
): TableTag.get_class_for_df(bilan, etudid),
|
||||
(
|
||||
descr,
|
||||
NOM_STAT_GROUPE,
|
||||
"min",
|
||||
): TableTag.get_min_for_df(bilan),
|
||||
(
|
||||
descr,
|
||||
NOM_STAT_GROUPE,
|
||||
"moy",
|
||||
): TableTag.get_moy_for_df(bilan),
|
||||
(
|
||||
descr,
|
||||
NOM_STAT_GROUPE,
|
||||
"max",
|
||||
): TableTag.get_max_for_df(bilan),
|
||||
}
|
||||
|
||||
# L'interclassement
|
||||
if tag in interclassement_taggue.moyennes_tags:
|
||||
bilan = interclassement_taggue.moyennes_tags[tag]
|
||||
|
||||
if note != np.nan:
|
||||
nom_stat_promo = f"{NOM_STAT_PROMO} {diplome}"
|
||||
|
||||
donnees |= {
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"class.",
|
||||
): TableTag.get_class_for_df(bilan, etudid),
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"min",
|
||||
): TableTag.get_min_for_df(bilan),
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"moy",
|
||||
): TableTag.get_moy_for_df(bilan),
|
||||
(
|
||||
descr,
|
||||
nom_stat_promo,
|
||||
"max",
|
||||
): TableTag.get_max_for_df(bilan),
|
||||
}
|
||||
return donnees
|
||||
|
@ -35,7 +35,7 @@ Created on Fri Sep 9 09:15:05 2016
|
||||
|
||||
@author: barasc
|
||||
"""
|
||||
|
||||
import app.pe.pe_etudiant
|
||||
from app import db, log
|
||||
from app.comp import res_sem, moy_ue, moy_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
@ -133,7 +133,7 @@ class SemestreTag(TableTag):
|
||||
|
||||
def get_repr(self):
|
||||
"""Nom affiché pour le semestre taggué"""
|
||||
return pe_affichage.nom_semestre_etape(self.formsemestre, avec_fid=True)
|
||||
return app.pe.pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True)
|
||||
|
||||
def compute_moyenne_tag(self, tag: str) -> list:
|
||||
"""Calcule la moyenne des étudiants pour le tag indiqué,
|
||||
|
@ -48,8 +48,6 @@ TAGS_RESERVES = ["but"]
|
||||
|
||||
|
||||
class TableTag(object):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
"""Classe centralisant différentes méthodes communes aux
|
||||
SemestreTag, TrajectoireTag, AggregatInterclassTag
|
||||
@ -105,3 +103,36 @@ class TableTag(object):
|
||||
df = df.join(self.moyennes_tags[tag]["classements"].rename(f"class {tag}"))
|
||||
|
||||
return df.to_csv(sep=";")
|
||||
|
||||
@classmethod
|
||||
def get_min_for_df(cls, bilan: dict) -> float:
|
||||
"""Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné,
|
||||
revoie le min renseigné pour affichage dans un df"""
|
||||
return round(bilan["min"], 2)
|
||||
|
||||
@classmethod
|
||||
def get_max_for_df(cls, bilan: dict) -> float:
|
||||
"""Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné,
|
||||
renvoie le max renseigné pour affichage dans un df"""
|
||||
return round(bilan["max"], 2)
|
||||
|
||||
@classmethod
|
||||
def get_moy_for_df(cls, bilan: dict) -> float:
|
||||
"""Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné,
|
||||
renvoie la moyenne renseignée pour affichage dans un df"""
|
||||
return round(bilan["moy"], 2)
|
||||
|
||||
@classmethod
|
||||
def get_class_for_df(cls, bilan: dict, etudid: int) -> str:
|
||||
"""Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné,
|
||||
renvoie le classement ramené au nombre d'inscrits,
|
||||
pour un étudiant donné par son etudid"""
|
||||
return f"{bilan['classements'].loc[etudid]}/{bilan['nb_inscrits']}"
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_note_for_df(cls, bilan: dict, etudid: int):
|
||||
"""Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné,
|
||||
renvoie la note (moyenne)
|
||||
pour un étudiant donné par son etudid"""
|
||||
return round(bilan["notes"].loc[etudid], 2)
|
Loading…
Reference in New Issue
Block a user