recapcomplet sans NotesTable

This commit is contained in:
Emmanuel Viennet 2022-01-07 10:37:48 +01:00
parent 6b1ccfe400
commit af48eb8fb8
5 changed files with 58 additions and 25 deletions

View File

@ -69,6 +69,8 @@ class ModuleImplResults:
"nombre d'inscrits (non DEM) au module"
self.evaluations_completes = []
"séquence de booléens, indiquant les évals à prendre en compte."
self.evaluations_completes_dict = {}
"{ evaluation.id : bool } indique si à prendre en compte ou non."
self.evaluations_etat = {}
"{ evaluation_id: EvaluationEtat }"
#
@ -122,6 +124,7 @@ class ModuleImplResults:
# dataFrame vide, index = tous les inscrits au SEMESTRE
evals_notes = pd.DataFrame(index=self.etudids, dtype=float)
self.evaluations_completes = []
self.evaluations_completes_dict = {}
for evaluation in moduleimpl.evaluations:
eval_df = self._load_evaluation_notes(evaluation)
# is_complete ssi tous les inscrits (non dem) au semestre ont une note
@ -131,6 +134,7 @@ class ModuleImplResults:
== self.nb_inscrits_module
) or evaluation.publish_incomplete # immédiate
self.evaluations_completes.append(is_complete)
self.evaluations_completes_dict[evaluation.id] = is_complete
# NULL en base => ABS (= -999)
eval_df.fillna(scu.NOTES_ABSENCE, inplace=True)

View File

@ -60,6 +60,25 @@ class ResultatsSemestreClassic(NotesTableCompat):
"""
return self.modimpls_results[moduleimpl_id].etuds_moy_module.get(etudid, "NI")
def get_mod_stats(self, moduleimpl_id: int) -> dict:
"""Stats sur les notes obtenues dans un modimpl"""
notes_series: pd.Series = self.modimpls_results[moduleimpl_id].etuds_moy_module
nb_notes = len(notes_series)
if not nb_notes:
super().get_mod_stats(moduleimpl_id)
return {
# Series: Statistical methods from ndarray have been overridden to automatically
# exclude missing data (currently represented as NaN)
"moy": notes_series.mean(), # donc sans prendre en compte les NaN
"max": notes_series.max(),
"min": notes_series.min(),
"nb_notes": nb_notes,
"nb_missing": sum(notes_series.isna()),
"nb_valid_evals": sum(
self.modimpls_results[moduleimpl_id].evaluations_completes
),
}
def notes_sem_load_matrix(formsemestre: FormSemestre) -> tuple:
"""Calcule la matrice des notes du semestre

View File

@ -9,6 +9,7 @@ from functools import cached_property
import numpy as np
import pandas as pd
from app.comp.aux import StatsMoyenne
from app.comp.moy_mod import ModuleImplResults
from app.models import FormSemestre, ModuleImpl
from app.scodoc import sco_utils as scu
from app.scodoc.sco_cache import ResultatsSemestreCache
@ -36,11 +37,12 @@ class ResultatsSemestre:
self.formsemestre = formsemestre
# BUT ou standard ? (apc == "approche par compétences")
self.is_apc = formsemestre.formation.is_apc()
# Attributs "virtuels", définis pas les sous-classes
# Attributs "virtuels", définis dans les sous-classes
# ResultatsSemestreBUT ou ResultatsSemestreStd
self.etud_moy_ue = {}
self.etud_moy_gen = {}
self.etud_moy_gen_ranks = {}
self.modimpls_results: ModuleImplResults = None
# TODO
def load_cached(self) -> bool:
@ -215,7 +217,7 @@ class NotesTableCompat(ResultatsSemestre):
def get_etud_moy_gen(self, etudid): # -> float | str
"""Moyenne générale de cet etudiant dans ce semestre.
Prend en compte les UE capitalisées. (TODO)
Prend(ra) en compte les UE capitalisées. (TODO) XXX
Si apc, moyenne indicative.
Si pas de notes: 'NA'
"""
@ -241,30 +243,37 @@ class NotesTableCompat(ResultatsSemestre):
return (None, 0) # XXX unimplemented TODO
def get_evals_in_mod(self, moduleimpl_id: int) -> list[dict]:
"liste des évaluations valides dans un module"
"""Liste d'informations (compat NotesTable) sur évaluations completes
de ce module.
Évaluation "complete" ssi toutes notes saisies ou en attente.
"""
modimpl = ModuleImpl.query.get(moduleimpl_id)
evals_results = []
for e in modimpl.evaluations:
d = e.to_dict()
d["heure_debut"] = e.heure_debut # datetime.time
d["heure_fin"] = e.heure_fin
d["jour"] = e.jour # datetime
d["notes"] = {
etud.id: {
"etudid": etud.id,
"value": self.results.modimpls_evals_notes[e.moduleimpl_id][e.id][
etud.id
],
if self.modimpls_results[moduleimpl_id].evaluations_completes_dict[e.id]:
d = e.to_dict()
d["heure_debut"] = e.heure_debut # datetime.time
d["heure_fin"] = e.heure_fin
d["jour"] = e.jour # datetime
d["notes"] = {
etud.id: {
"etudid": etud.id,
"value": self.modimpls_evals_notes[e.moduleimpl_id][e.id][
etud.id
],
}
for etud in self.etuds
}
for etud in self.results.etuds
}
evals_results.append(d)
evals_results.append(d)
return evals_results
def get_moduleimpls_attente(self):
return [] # XXX TODO
def get_mod_stats(self, moduleimpl_id):
def get_mod_stats(self, moduleimpl_id: int) -> dict:
"""Stats sur les notes obtenues dans un modimpl
Vide en APC
"""
return {
"moy": "-",
"max": "-",

View File

@ -170,6 +170,7 @@ class NotesTable:
"""
def __init__(self, formsemestre_id):
# XXX breakpoint()
log(f"NotesTable( formsemestre_id={formsemestre_id} )")
if not formsemestre_id:
raise ValueError("invalid formsemestre_id (%s)" % formsemestre_id)

View File

@ -303,9 +303,11 @@ def make_formsemestre_recapcomplet(
sem = sco_formsemestre.do_formsemestre_list(
args={"formsemestre_id": formsemestre_id}
)[0]
nt = sco_cache.NotesTableCache.get(formsemestre_id)
parcours = formsemestre.formation.get_parcours()
# nt = sco_cache.NotesTableCache.get(formsemestre_id)
# XXX EXPERIMENTAL
# nt = ResultatsSemestreClassic(formsemestre)
nt = ResultatsSemestreClassic(formsemestre)
modimpls = nt.get_modimpls_dict()
ues = nt.get_ues_stat_dict() # incluant le(s) UE de sport
#
@ -701,9 +703,7 @@ def make_formsemestre_recapcomplet(
idx_col_moy = idx_col_gr + 1
cssclass = "recap_col_moy"
try:
if float(nsn[idx_col_moy]) < (
nt.parcours.BARRE_MOY - scu.NOTES_TOLERANCE
):
if float(nsn[idx_col_moy]) < (parcours.BARRE_MOY - scu.NOTES_TOLERANCE):
cssclass = "recap_col_moy_inf"
except:
pass
@ -718,11 +718,11 @@ def make_formsemestre_recapcomplet(
if (ir < (nblines - 4)) or (ir == nblines - 3):
try:
if float(nsn[i]) < nt.parcours.get_barre_ue(
if float(nsn[i]) < parcours.get_barre_ue(
ue["type"]
): # NOTES_BARRE_UE
cssclass = "recap_col_ue_inf"
elif float(nsn[i]) >= nt.parcours.NOTES_BARRE_VALID_UE:
elif float(nsn[i]) >= parcours.NOTES_BARRE_VALID_UE:
cssclass = "recap_col_ue_val"
except:
pass
@ -732,7 +732,7 @@ def make_formsemestre_recapcomplet(
ir == nblines - 3
): # si moyenne generale module < barre ue, surligne:
try:
if float(nsn[i]) < nt.parcours.get_barre_ue(ue["type"]):
if float(nsn[i]) < parcours.get_barre_ue(ue["type"]):
cssclass = "recap_col_moy_inf"
except:
pass