forked from ScoDoc/ScoDoc
Modifie FormSemestre.etudids_actifs: retire @cached_property. Tests OK.
This commit is contained in:
parent
4aa30a40bd
commit
635269ff36
@ -72,7 +72,15 @@ class ModuleImplResults:
|
||||
les caches sont gérés par ResultatsSemestre.
|
||||
"""
|
||||
|
||||
def __init__(self, moduleimpl: ModuleImpl):
|
||||
def __init__(
|
||||
self, moduleimpl: ModuleImpl, etudids: list[int], etudids_actifs: set[int]
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
- etudids : liste des etudids, qui donne l'index du dataframe
|
||||
(doit être tous les étudiants inscrits au semestre incluant les DEM et DEF)
|
||||
- etudids_actifs l'ensemble des étudiants inscrits au semestre, non DEM/DEF.
|
||||
"""
|
||||
self.moduleimpl_id = moduleimpl.id
|
||||
self.module_id = moduleimpl.module.id
|
||||
self.etudids = None
|
||||
@ -105,14 +113,21 @@ class ModuleImplResults:
|
||||
"""
|
||||
self.evals_etudids_sans_note = {}
|
||||
"""dict: evaluation_id : set des etudids non notés dans cette eval, sans les démissions."""
|
||||
self.load_notes()
|
||||
self.load_notes(etudids, etudids_actifs)
|
||||
self.etuds_use_session2 = pd.Series(False, index=self.evals_notes.index)
|
||||
"""1 bool par etud, indique si sa moyenne de module vient de la session2"""
|
||||
self.etuds_use_rattrapage = pd.Series(False, index=self.evals_notes.index)
|
||||
"""1 bool par etud, indique si sa moyenne de module utilise la note de rattrapage"""
|
||||
|
||||
def load_notes(self): # ré-écriture de df_load_modimpl_notes
|
||||
def load_notes(
|
||||
self, etudids: list[int], etudids_actifs: set[int]
|
||||
): # ré-écriture de df_load_modimpl_notes
|
||||
"""Charge toutes les notes de toutes les évaluations du module.
|
||||
Args:
|
||||
- etudids : liste des etudids, qui donne l'index du dataframe
|
||||
(doit être tous les étudiants inscrits au semestre incluant les DEM et DEF)
|
||||
- etudids_actifs l'ensemble des étudiants inscrits au semestre, non DEM/DEF.
|
||||
|
||||
Dataframe evals_notes
|
||||
colonnes: le nom de la colonne est l'evaluation_id (int)
|
||||
index (lignes): etudid (int)
|
||||
@ -135,12 +150,12 @@ class ModuleImplResults:
|
||||
qui ont des notes ATT.
|
||||
"""
|
||||
moduleimpl = db.session.get(ModuleImpl, self.moduleimpl_id)
|
||||
self.etudids = self._etudids()
|
||||
self.etudids = etudids
|
||||
|
||||
# --- Calcul nombre d'inscrits pour déterminer les évaluations "completes":
|
||||
# on prend les inscrits au module ET au semestre (donc sans démissionnaires)
|
||||
inscrits_module = {ins.etud.id for ins in moduleimpl.inscriptions}.intersection(
|
||||
moduleimpl.formsemestre.etudids_actifs
|
||||
etudids_actifs
|
||||
)
|
||||
self.nb_inscrits_module = len(inscrits_module)
|
||||
|
||||
@ -235,17 +250,6 @@ class ModuleImplResults:
|
||||
eval_df[str(evaluation.id)] = pd.to_numeric(eval_df[str(evaluation.id)])
|
||||
return eval_df
|
||||
|
||||
def _etudids(self):
|
||||
"""L'index du dataframe est la liste de tous les étudiants inscrits au semestre
|
||||
(incluant les DEM et DEF)
|
||||
"""
|
||||
return [
|
||||
inscr.etudid
|
||||
for inscr in db.session.get(
|
||||
ModuleImpl, self.moduleimpl_id
|
||||
).formsemestre.inscriptions
|
||||
]
|
||||
|
||||
def get_evaluations_coefs(self, modimpl: ModuleImpl) -> np.array:
|
||||
"""Coefficients des évaluations.
|
||||
Les coefs des évals incomplètes, rattrapage, session 2, bonus sont forcés à zéro.
|
||||
|
@ -99,9 +99,11 @@ def df_load_module_coefs(formation_id: int, semestre_idx: int = None) -> pd.Data
|
||||
# 0 pour modules normaux, 1. pour bonus (car par défaut, on veut qu'un bonus agisse
|
||||
# sur toutes les UE)
|
||||
default_poids = {
|
||||
mod.id: 1.0
|
||||
mod.id: (
|
||||
1.0
|
||||
if (mod.module_type == ModuleType.STANDARD) and (mod.ue.type == UE_SPORT)
|
||||
else 0.0
|
||||
)
|
||||
for mod in modules
|
||||
}
|
||||
|
||||
@ -148,10 +150,12 @@ def df_load_modimpl_coefs(
|
||||
# 0 pour modules normaux, 1. pour bonus (car par défaut, on veut qu'un bonus agisse
|
||||
# sur toutes les UE)
|
||||
default_poids = {
|
||||
modimpl.id: 1.0
|
||||
modimpl.id: (
|
||||
1.0
|
||||
if (modimpl.module.module_type == ModuleType.STANDARD)
|
||||
and (modimpl.module.ue.type == UE_SPORT)
|
||||
else 0.0
|
||||
)
|
||||
for modimpl in formsemestre.modimpls_sorted
|
||||
}
|
||||
|
||||
@ -200,8 +204,9 @@ def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple:
|
||||
modimpls_results = {}
|
||||
modimpls_evals_poids = {}
|
||||
modimpls_notes = []
|
||||
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||
for modimpl in formsemestre.modimpls_sorted:
|
||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl)
|
||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
||||
evals_poids, _ = moy_mod.load_evaluations_poids(modimpl.id)
|
||||
etuds_moy_module = mod_results.compute_module_moy(evals_poids)
|
||||
modimpls_results[modimpl.id] = mod_results
|
||||
|
@ -256,8 +256,9 @@ def notes_sem_load_matrix(formsemestre: FormSemestre) -> tuple[np.ndarray, dict]
|
||||
"""
|
||||
modimpls_results = {}
|
||||
modimpls_notes = []
|
||||
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||
for modimpl in formsemestre.modimpls_sorted:
|
||||
mod_results = moy_mod.ModuleImplResultsClassic(modimpl)
|
||||
mod_results = moy_mod.ModuleImplResultsClassic(modimpl, etudids, etudids_actifs)
|
||||
etuds_moy_module = mod_results.compute_module_moy()
|
||||
modimpls_results[modimpl.id] = mod_results
|
||||
modimpls_notes.append(etuds_moy_module)
|
||||
|
@ -936,10 +936,14 @@ class FormSemestre(models.ScoDocModel):
|
||||
partitions += [p for p in self.partitions if p.partition_name is None]
|
||||
return partitions
|
||||
|
||||
@cached_property
|
||||
def etudids_actifs(self) -> set:
|
||||
"Set des etudids inscrits non démissionnaires et non défaillants"
|
||||
return {ins.etudid for ins in self.inscriptions if ins.etat == scu.INSCRIT}
|
||||
def etudids_actifs(self) -> tuple[list[int], set[int]]:
|
||||
"""Liste les etudids inscrits (incluant DEM et DEF),
|
||||
qui ser al'index des dataframes de notes
|
||||
et donne l'ensemble des inscrits non DEM ni DEF.
|
||||
"""
|
||||
return [inscr.etudid for inscr in self.inscriptions], {
|
||||
ins.etudid for ins in self.inscriptions if ins.etat == scu.INSCRIT
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def etuds_inscriptions(self) -> dict:
|
||||
|
@ -705,7 +705,8 @@ def _add_eval_columns(
|
||||
nb_att = 0
|
||||
sum_notes = 0
|
||||
notes = [] # liste des notes numeriques, pour calcul histogramme uniquement
|
||||
inscrits = evaluation.moduleimpl.formsemestre.etudids_actifs # set d'etudids
|
||||
# actifs == inscrit au semestre, non DEM ni DEF:
|
||||
_, etudids_actifs = evaluation.moduleimpl.formsemestre.etudids_actifs()
|
||||
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation.id)
|
||||
|
||||
if evaluation.date_debut:
|
||||
@ -734,7 +735,7 @@ def _add_eval_columns(
|
||||
nb_att += 1
|
||||
# calcul moyenne SANS LES ABSENTS ni les DEMISSIONNAIRES
|
||||
if (
|
||||
(etudid in inscrits)
|
||||
(etudid in etudids_actifs)
|
||||
and val is not None
|
||||
and val != scu.NOTES_NEUTRALISE
|
||||
and val != scu.NOTES_ATTENTE
|
||||
@ -758,7 +759,7 @@ def _add_eval_columns(
|
||||
comment,
|
||||
)
|
||||
else:
|
||||
if (etudid in inscrits) and evaluation.publish_incomplete:
|
||||
if (etudid in etudids_actifs) and evaluation.publish_incomplete:
|
||||
# Note manquante mais prise en compte immédiate: affiche ATT
|
||||
val = scu.NOTES_ATTENTE
|
||||
val_fmt = "ATT"
|
||||
@ -875,8 +876,7 @@ def _add_moymod_column(
|
||||
col_id = "moymod"
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
inscrits = formsemestre.etudids_actifs
|
||||
|
||||
_, etudids_actifs = formsemestre.etudids_actifs()
|
||||
nb_notes = 0
|
||||
sum_notes = 0
|
||||
notes = [] # liste des notes numeriques, pour calcul histogramme uniquement
|
||||
@ -885,7 +885,7 @@ def _add_moymod_column(
|
||||
val = nt.get_etud_mod_moy(moduleimpl_id, etudid) # note sur 20, ou 'NA','NI'
|
||||
row[col_id] = scu.fmt_note(val, keep_numeric=keep_numeric)
|
||||
row["_" + col_id + "_td_attrs"] = ' class="moyenne" '
|
||||
if etudid in inscrits and not isinstance(val, str):
|
||||
if etudid in etudids_actifs and not isinstance(val, str):
|
||||
notes.append(val)
|
||||
if not np.isnan(val):
|
||||
nb_notes = nb_notes + 1
|
||||
@ -928,7 +928,7 @@ def _add_apc_columns(
|
||||
# on va y ajouter une clé par UE du semestre
|
||||
nt: ResultatsSemestreBUT = res_sem.load_formsemestre_results(modimpl.formsemestre)
|
||||
modimpl_results: ModuleImplResults = nt.modimpls_results[modimpl.id]
|
||||
inscrits = modimpl.formsemestre.etudids_actifs
|
||||
_, etudids_actifs = modimpl.formsemestre.etudids_actifs()
|
||||
# les UE dans lesquelles ce module a un coef non nul:
|
||||
ues_with_coef = nt.modimpl_coefs_df[modimpl.id][
|
||||
nt.modimpl_coefs_df[modimpl.id] > 0
|
||||
@ -946,7 +946,7 @@ def _add_apc_columns(
|
||||
if (
|
||||
isinstance(moy_ue, float)
|
||||
and not np.isnan(moy_ue)
|
||||
and row["etudid"] in inscrits
|
||||
and row["etudid"] in etudids_actifs
|
||||
):
|
||||
sum_by_ue[ue.id] += moy_ue
|
||||
nb_notes_by_ue[ue.id] += 1
|
||||
|
@ -541,7 +541,7 @@ def notes_add(
|
||||
)
|
||||
}
|
||||
# Les étudiants inscrits au semestre ni DEM ni DEF
|
||||
etudids_actifs = evaluation.moduleimpl.formsemestre.etudids_actifs
|
||||
_, etudids_actifs = evaluation.moduleimpl.formsemestre.etudids_actifs()
|
||||
for etudid, value in notes:
|
||||
if check_inscription and (
|
||||
(etudid not in inscrits) or (etudid not in etudids_actifs)
|
||||
|
@ -931,6 +931,9 @@ def test_etudiant_bulletin_semestre(api_headers):
|
||||
# /ScoDoc/api/etudiant/nip/12345/formsemestre/123/bulletin/long/pdf/nosi
|
||||
# TODO voir forme utilisée par ScoDoc en interne:
|
||||
# formsemestre_bulletinetud?formsemestre_id=1263&etudid=16387
|
||||
formsemestre = POST_JSON(
|
||||
f"/formsemestre/{1}/edit", {"bul_hide_xml": False}, headers=admin_header
|
||||
)
|
||||
|
||||
|
||||
def test_etudiant_groups(api_headers):
|
||||
|
@ -2,6 +2,7 @@
|
||||
Test modèles évaluations avec poids BUT
|
||||
et calcul moyennes modules
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
@ -215,7 +216,8 @@ def test_module_moy(test_client):
|
||||
etud = G.create_etud(nom="test")
|
||||
G.inscrit_etudiant(formsemestre_id, etud)
|
||||
etudid = etud["etudid"]
|
||||
evaluation1 = db.session.get(Evaluation, evaluation1_ids[0])
|
||||
evaluation1: Evaluation = db.session.get(Evaluation, evaluation1_ids[0])
|
||||
formsemestre = evaluation1.moduleimpl.formsemestre
|
||||
# Crée une deuxième évaluation dans le même moduleimpl:
|
||||
evaluation2_id = G.create_evaluation(
|
||||
moduleimpl_id=evaluation1.moduleimpl_id,
|
||||
@ -245,10 +247,10 @@ def test_module_moy(test_client):
|
||||
_ = sco_saisie_notes.notes_add(G.default_user, evaluation1.id, [(etudid, n1)])
|
||||
_ = sco_saisie_notes.notes_add(G.default_user, evaluation2.id, [(etudid, n2)])
|
||||
# Calcul de la moyenne du module
|
||||
evals_poids, ues = moy_mod.load_evaluations_poids(moduleimpl_id)
|
||||
evals_poids, _ = moy_mod.load_evaluations_poids(moduleimpl_id)
|
||||
assert evals_poids.shape == (nb_evals, nb_ues)
|
||||
|
||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl)
|
||||
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
||||
evals_notes = mod_results.evals_notes
|
||||
assert evals_notes[evaluation1.id].dtype == np.float64
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user