ScoDoc-PE/app/but/bulletin_but.py

228 lines
9.2 KiB
Python
Raw Normal View History

2021-12-05 20:21:51 +01:00
##############################################################################
# ScoDoc
2022-01-01 14:49:42 +01:00
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
2021-12-05 20:21:51 +01:00
# See LICENSE
##############################################################################
2021-12-26 19:15:47 +01:00
"""Génération bulletin BUT
"""
2021-12-05 20:21:51 +01:00
import datetime
2021-12-06 22:37:49 +01:00
from flask import url_for, g
2021-12-05 20:21:51 +01:00
from app.scodoc import sco_utils as scu
from app.scodoc import sco_bulletins_json
2021-12-05 21:54:04 +01:00
from app.scodoc import sco_preferences
2021-12-26 19:15:47 +01:00
from app.scodoc.sco_utils import fmt_note
2021-12-30 23:58:38 +01:00
from app.comp.res_but import ResultatsSemestreBUT
2021-12-05 20:21:51 +01:00
2021-12-24 00:08:25 +01:00
class BulletinBUT(ResultatsSemestreBUT):
"""Génération du bulletin BUT.
Cette classe génère des dictionnaires avec toutes les informations
du bulletin, qui sont immédiatement traduisibles en JSON.
"""
2021-12-05 20:21:51 +01:00
def etud_ue_mod_results(self, etud, ue, modimpls) -> dict:
"dict synthèse résultats dans l'UE pour les modules indiqués"
d = {}
etud_idx = self.etud_index[etud.id]
ue_idx = self.modimpl_coefs_df.index.get_loc(ue.id)
etud_moy_module = self.sem_cube[etud_idx] # module x UE
2021-12-26 19:15:47 +01:00
for modimpl in modimpls:
if self.modimpl_inscr_df[str(modimpl.id)][etud.id]: # si inscrit
coef = self.modimpl_coefs_df[modimpl.id][ue.id]
if coef > 0:
d[modimpl.module.code] = {
"id": modimpl.id,
"coef": coef,
"moyenne": fmt_note(
etud_moy_module[
self.modimpl_coefs_df.columns.get_loc(modimpl.id)
][ue_idx]
),
}
2021-12-05 20:21:51 +01:00
return d
def etud_ue_results(self, etud, ue):
"dict synthèse résultats UE"
d = {
"id": ue.id,
2021-12-10 01:54:11 +01:00
"numero": ue.numero,
2021-12-05 20:21:51 +01:00
"ECTS": {
"acquis": 0, # XXX TODO voir jury
"total": ue.ects,
},
"competence": None, # XXX TODO lien avec référentiel
"moyenne": {
"value": fmt_note(self.etud_moy_ue[ue.id][etud.id]),
"min": fmt_note(self.etud_moy_ue[ue.id].min()),
"max": fmt_note(self.etud_moy_ue[ue.id].max()),
"moy": fmt_note(self.etud_moy_ue[ue.id].mean()),
},
2021-12-08 22:33:32 +01:00
"bonus": None, # XXX TODO
2021-12-05 20:21:51 +01:00
"malus": None, # XXX TODO voir ce qui est ici
"capitalise": None, # "AAAA-MM-JJ" TODO
"ressources": self.etud_ue_mod_results(etud, ue, self.ressources),
"saes": self.etud_ue_mod_results(etud, ue, self.saes),
}
return d
def etud_mods_results(self, etud, modimpls) -> dict:
"""dict synthèse résultats des modules indiqués,
avec évaluations de chacun."""
d = {}
2021-12-18 12:16:49 +01:00
# etud_idx = self.etud_index[etud.id]
2021-12-26 19:15:47 +01:00
for modimpl in modimpls:
2021-12-18 12:16:49 +01:00
# mod_idx = self.modimpl_coefs_df.columns.get_loc(mi.id)
# # moyennes indicatives (moyennes de moyennes d'UE)
# try:
# moyennes_etuds = np.nan_to_num(
# np.nanmean(self.sem_cube[:, mod_idx, :], axis=1),
# copy=False,
# )
# except RuntimeWarning: # all nans in np.nanmean (sur certains etuds sans notes valides)
# pass
# try:
# moy_indicative_mod = np.nanmean(self.sem_cube[etud_idx, mod_idx])
# except RuntimeWarning: # all nans in np.nanmean
# pass
2021-12-26 19:15:47 +01:00
modimpl_results = self.modimpls_results[modimpl.id]
if self.modimpl_inscr_df[str(modimpl.id)][etud.id]: # si inscrit
d[modimpl.module.code] = {
"id": modimpl.id,
"titre": modimpl.module.titre,
"code_apogee": modimpl.module.code_apogee,
"url": url_for(
"notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept,
moduleimpl_id=modimpl.id,
),
"moyenne": {
# # moyenne indicative de module: moyenne des UE, ignorant celles sans notes (nan)
# "value": fmt_note(moy_indicative_mod),
# "min": fmt_note(moyennes_etuds.min()),
# "max": fmt_note(moyennes_etuds.max()),
# "moy": fmt_note(moyennes_etuds.mean()),
},
"evaluations": [
self.etud_eval_results(etud, e)
for e in modimpl.evaluations
if e.visibulletin
and modimpl_results.evaluations_etat[e.id].is_complete
],
}
2021-12-05 20:21:51 +01:00
return d
def etud_eval_results(self, etud, e) -> dict:
"dict resultats d'un étudiant à une évaluation"
2021-12-26 19:15:47 +01:00
# eval_notes est une pd.Series avec toutes les notes des étudiants inscrits
eval_notes = self.modimpls_results[e.moduleimpl_id].evals_notes[e.id]
2021-12-11 10:56:40 +01:00
notes_ok = eval_notes.where(eval_notes > scu.NOTES_ABSENCE).dropna()
2021-12-05 20:21:51 +01:00
d = {
"id": e.id,
"description": e.description,
"date": e.jour.isoformat() if e.jour else None,
2021-12-05 20:21:51 +01:00
"heure_debut": e.heure_debut.strftime("%H:%M") if e.heure_debut else None,
"heure_fin": e.heure_fin.strftime("%H:%M") if e.heure_debut else None,
"coef": e.coefficient,
"poids": {p.ue.acronyme: p.poids for p in e.ue_poids},
"note": {
2021-12-06 10:57:10 +01:00
"value": fmt_note(
2021-12-26 19:15:47 +01:00
eval_notes[etud.id],
note_max=e.note_max,
2021-12-05 20:21:51 +01:00
),
2021-12-06 10:57:10 +01:00
"min": fmt_note(notes_ok.min()),
"max": fmt_note(notes_ok.max()),
"moy": fmt_note(notes_ok.mean()),
2021-12-05 20:21:51 +01:00
},
"url": url_for(
"notes.evaluation_listenotes",
scodoc_dept=g.scodoc_dept,
evaluation_id=e.id,
),
2021-12-05 20:21:51 +01:00
}
return d
def bulletin_etud(self, etud, formsemestre) -> dict:
"""Le bulletin de l'étudiant dans ce semestre"""
2021-12-16 12:41:37 +01:00
etat_inscription = etud.etat_inscription(formsemestre.id)
2021-12-05 20:21:51 +01:00
d = {
"version": "0",
"type": "BUT",
"date": datetime.datetime.utcnow().isoformat() + "Z",
"etudiant": etud.to_dict_bul(),
"formation": {
"id": formsemestre.formation.id,
"acronyme": formsemestre.formation.acronyme,
"titre_officiel": formsemestre.formation.titre_officiel,
"titre": formsemestre.formation.titre,
},
"formsemestre_id": formsemestre.id,
2021-12-16 12:41:37 +01:00
"etat_inscription": etat_inscription,
2021-12-24 00:08:25 +01:00
"options": sco_preferences.bulletin_option_affichage(formsemestre.id),
2021-12-05 20:21:51 +01:00
}
2021-12-16 12:41:37 +01:00
semestre_infos = {
"etapes": [str(x.etape_apo) for x in formsemestre.etapes if x.etape_apo],
2021-12-16 12:41:37 +01:00
"date_debut": formsemestre.date_debut.isoformat(),
"date_fin": formsemestre.date_fin.isoformat(),
"annee_universitaire": self.formsemestre.annee_scolaire_str(),
"inscription": "TODO-MM-JJ", # XXX TODO
"numero": formsemestre.semestre_id,
"groupes": [], # XXX TODO
"absences": { # XXX TODO
2021-12-26 19:15:47 +01:00
"injustifie": -1,
"total": -1,
2021-12-16 12:41:37 +01:00
},
}
semestre_infos.update(
sco_bulletins_json.dict_decision_jury(etud.id, formsemestre.id)
)
2021-12-16 12:41:37 +01:00
if etat_inscription == scu.INSCRIT:
semestre_infos.update(
{
"notes": { # moyenne des moyennes générales du semestre
"value": fmt_note(self.etud_moy_gen[etud.id]),
"min": fmt_note(self.etud_moy_gen.min()),
"moy": fmt_note(self.etud_moy_gen.mean()),
"max": fmt_note(self.etud_moy_gen.max()),
},
"rang": { # classement wrt moyenne général, indicatif
"value": self.etud_moy_gen_ranks[etud.id],
"total": len(self.etuds),
},
},
)
d.update(
{
"ressources": self.etud_mods_results(etud, self.ressources),
"saes": self.etud_mods_results(etud, self.saes),
"ues": {
ue.acronyme: self.etud_ue_results(etud, ue) for ue in self.ues
},
"semestre": semestre_infos,
},
)
else:
semestre_infos.update(
{
"notes": {
"value": "DEM",
"min": "",
"moy": "",
"max": "",
},
"rang": {"value": "DEM", "total": len(self.etuds)},
}
)
d.update(
{
"semestre": semestre_infos,
"ressources": {},
"saes": {},
"ues": {},
}
)
2021-12-05 20:21:51 +01:00
return d