1
0
forked from ScoDoc/ScoDoc

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

View File

@ -9,6 +9,7 @@ from functools import cached_property
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from app.comp.aux import StatsMoyenne from app.comp.aux import StatsMoyenne
from app.comp.moy_mod import ModuleImplResults
from app.models import FormSemestre, ModuleImpl from app.models import FormSemestre, ModuleImpl
from app.scodoc import sco_utils as scu from app.scodoc import sco_utils as scu
from app.scodoc.sco_cache import ResultatsSemestreCache from app.scodoc.sco_cache import ResultatsSemestreCache
@ -36,11 +37,12 @@ class ResultatsSemestre:
self.formsemestre = formsemestre self.formsemestre = formsemestre
# BUT ou standard ? (apc == "approche par compétences") # BUT ou standard ? (apc == "approche par compétences")
self.is_apc = formsemestre.formation.is_apc() 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 # ResultatsSemestreBUT ou ResultatsSemestreStd
self.etud_moy_ue = {} self.etud_moy_ue = {}
self.etud_moy_gen = {} self.etud_moy_gen = {}
self.etud_moy_gen_ranks = {} self.etud_moy_gen_ranks = {}
self.modimpls_results: ModuleImplResults = None
# TODO # TODO
def load_cached(self) -> bool: def load_cached(self) -> bool:
@ -215,7 +217,7 @@ class NotesTableCompat(ResultatsSemestre):
def get_etud_moy_gen(self, etudid): # -> float | str def get_etud_moy_gen(self, etudid): # -> float | str
"""Moyenne générale de cet etudiant dans ce semestre. """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 apc, moyenne indicative.
Si pas de notes: 'NA' Si pas de notes: 'NA'
""" """
@ -241,10 +243,14 @@ class NotesTableCompat(ResultatsSemestre):
return (None, 0) # XXX unimplemented TODO return (None, 0) # XXX unimplemented TODO
def get_evals_in_mod(self, moduleimpl_id: int) -> list[dict]: 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) modimpl = ModuleImpl.query.get(moduleimpl_id)
evals_results = [] evals_results = []
for e in modimpl.evaluations: for e in modimpl.evaluations:
if self.modimpls_results[moduleimpl_id].evaluations_completes_dict[e.id]:
d = e.to_dict() d = e.to_dict()
d["heure_debut"] = e.heure_debut # datetime.time d["heure_debut"] = e.heure_debut # datetime.time
d["heure_fin"] = e.heure_fin d["heure_fin"] = e.heure_fin
@ -252,11 +258,11 @@ class NotesTableCompat(ResultatsSemestre):
d["notes"] = { d["notes"] = {
etud.id: { etud.id: {
"etudid": etud.id, "etudid": etud.id,
"value": self.results.modimpls_evals_notes[e.moduleimpl_id][e.id][ "value": self.modimpls_evals_notes[e.moduleimpl_id][e.id][
etud.id etud.id
], ],
} }
for etud in self.results.etuds for etud in self.etuds
} }
evals_results.append(d) evals_results.append(d)
return evals_results return evals_results
@ -264,7 +270,10 @@ class NotesTableCompat(ResultatsSemestre):
def get_moduleimpls_attente(self): def get_moduleimpls_attente(self):
return [] # XXX TODO 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 { return {
"moy": "-", "moy": "-",
"max": "-", "max": "-",

View File

@ -170,6 +170,7 @@ class NotesTable:
""" """
def __init__(self, formsemestre_id): def __init__(self, formsemestre_id):
# XXX breakpoint()
log(f"NotesTable( formsemestre_id={formsemestre_id} )") log(f"NotesTable( formsemestre_id={formsemestre_id} )")
if not formsemestre_id: if not formsemestre_id:
raise ValueError("invalid formsemestre_id (%s)" % 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( sem = sco_formsemestre.do_formsemestre_list(
args={"formsemestre_id": formsemestre_id} args={"formsemestre_id": formsemestre_id}
)[0] )[0]
nt = sco_cache.NotesTableCache.get(formsemestre_id) parcours = formsemestre.formation.get_parcours()
# nt = sco_cache.NotesTableCache.get(formsemestre_id)
# XXX EXPERIMENTAL # XXX EXPERIMENTAL
# nt = ResultatsSemestreClassic(formsemestre) nt = ResultatsSemestreClassic(formsemestre)
modimpls = nt.get_modimpls_dict() modimpls = nt.get_modimpls_dict()
ues = nt.get_ues_stat_dict() # incluant le(s) UE de sport 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 idx_col_moy = idx_col_gr + 1
cssclass = "recap_col_moy" cssclass = "recap_col_moy"
try: try:
if float(nsn[idx_col_moy]) < ( if float(nsn[idx_col_moy]) < (parcours.BARRE_MOY - scu.NOTES_TOLERANCE):
nt.parcours.BARRE_MOY - scu.NOTES_TOLERANCE
):
cssclass = "recap_col_moy_inf" cssclass = "recap_col_moy_inf"
except: except:
pass pass
@ -718,11 +718,11 @@ def make_formsemestre_recapcomplet(
if (ir < (nblines - 4)) or (ir == nblines - 3): if (ir < (nblines - 4)) or (ir == nblines - 3):
try: try:
if float(nsn[i]) < nt.parcours.get_barre_ue( if float(nsn[i]) < parcours.get_barre_ue(
ue["type"] ue["type"]
): # NOTES_BARRE_UE ): # NOTES_BARRE_UE
cssclass = "recap_col_ue_inf" 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" cssclass = "recap_col_ue_val"
except: except:
pass pass
@ -732,7 +732,7 @@ def make_formsemestre_recapcomplet(
ir == nblines - 3 ir == nblines - 3
): # si moyenne generale module < barre ue, surligne: ): # si moyenne generale module < barre ue, surligne:
try: 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" cssclass = "recap_col_moy_inf"
except: except:
pass pass