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.
|
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.moduleimpl_id = moduleimpl.id
|
||||||
self.module_id = moduleimpl.module.id
|
self.module_id = moduleimpl.module.id
|
||||||
self.etudids = None
|
self.etudids = None
|
||||||
@ -105,14 +113,21 @@ class ModuleImplResults:
|
|||||||
"""
|
"""
|
||||||
self.evals_etudids_sans_note = {}
|
self.evals_etudids_sans_note = {}
|
||||||
"""dict: evaluation_id : set des etudids non notés dans cette eval, sans les démissions."""
|
"""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)
|
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"""
|
"""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)
|
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"""
|
"""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.
|
"""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
|
Dataframe evals_notes
|
||||||
colonnes: le nom de la colonne est l'evaluation_id (int)
|
colonnes: le nom de la colonne est l'evaluation_id (int)
|
||||||
index (lignes): etudid (int)
|
index (lignes): etudid (int)
|
||||||
@ -135,12 +150,12 @@ class ModuleImplResults:
|
|||||||
qui ont des notes ATT.
|
qui ont des notes ATT.
|
||||||
"""
|
"""
|
||||||
moduleimpl = db.session.get(ModuleImpl, self.moduleimpl_id)
|
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":
|
# --- Calcul nombre d'inscrits pour déterminer les évaluations "completes":
|
||||||
# on prend les inscrits au module ET au semestre (donc sans démissionnaires)
|
# on prend les inscrits au module ET au semestre (donc sans démissionnaires)
|
||||||
inscrits_module = {ins.etud.id for ins in moduleimpl.inscriptions}.intersection(
|
inscrits_module = {ins.etud.id for ins in moduleimpl.inscriptions}.intersection(
|
||||||
moduleimpl.formsemestre.etudids_actifs
|
etudids_actifs
|
||||||
)
|
)
|
||||||
self.nb_inscrits_module = len(inscrits_module)
|
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)])
|
eval_df[str(evaluation.id)] = pd.to_numeric(eval_df[str(evaluation.id)])
|
||||||
return eval_df
|
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:
|
def get_evaluations_coefs(self, modimpl: ModuleImpl) -> np.array:
|
||||||
"""Coefficients des évaluations.
|
"""Coefficients des évaluations.
|
||||||
Les coefs des évals incomplètes, rattrapage, session 2, bonus sont forcés à zéro.
|
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
|
# 0 pour modules normaux, 1. pour bonus (car par défaut, on veut qu'un bonus agisse
|
||||||
# sur toutes les UE)
|
# sur toutes les UE)
|
||||||
default_poids = {
|
default_poids = {
|
||||||
mod.id: 1.0
|
mod.id: (
|
||||||
if (mod.module_type == ModuleType.STANDARD) and (mod.ue.type == UE_SPORT)
|
1.0
|
||||||
else 0.0
|
if (mod.module_type == ModuleType.STANDARD) and (mod.ue.type == UE_SPORT)
|
||||||
|
else 0.0
|
||||||
|
)
|
||||||
for mod in modules
|
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
|
# 0 pour modules normaux, 1. pour bonus (car par défaut, on veut qu'un bonus agisse
|
||||||
# sur toutes les UE)
|
# sur toutes les UE)
|
||||||
default_poids = {
|
default_poids = {
|
||||||
modimpl.id: 1.0
|
modimpl.id: (
|
||||||
if (modimpl.module.module_type == ModuleType.STANDARD)
|
1.0
|
||||||
and (modimpl.module.ue.type == UE_SPORT)
|
if (modimpl.module.module_type == ModuleType.STANDARD)
|
||||||
else 0.0
|
and (modimpl.module.ue.type == UE_SPORT)
|
||||||
|
else 0.0
|
||||||
|
)
|
||||||
for modimpl in formsemestre.modimpls_sorted
|
for modimpl in formsemestre.modimpls_sorted
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +204,9 @@ def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple:
|
|||||||
modimpls_results = {}
|
modimpls_results = {}
|
||||||
modimpls_evals_poids = {}
|
modimpls_evals_poids = {}
|
||||||
modimpls_notes = []
|
modimpls_notes = []
|
||||||
|
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||||
for modimpl in formsemestre.modimpls_sorted:
|
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)
|
evals_poids, _ = moy_mod.load_evaluations_poids(modimpl.id)
|
||||||
etuds_moy_module = mod_results.compute_module_moy(evals_poids)
|
etuds_moy_module = mod_results.compute_module_moy(evals_poids)
|
||||||
modimpls_results[modimpl.id] = mod_results
|
modimpls_results[modimpl.id] = mod_results
|
||||||
|
@ -256,8 +256,9 @@ def notes_sem_load_matrix(formsemestre: FormSemestre) -> tuple[np.ndarray, dict]
|
|||||||
"""
|
"""
|
||||||
modimpls_results = {}
|
modimpls_results = {}
|
||||||
modimpls_notes = []
|
modimpls_notes = []
|
||||||
|
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||||
for modimpl in formsemestre.modimpls_sorted:
|
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()
|
etuds_moy_module = mod_results.compute_module_moy()
|
||||||
modimpls_results[modimpl.id] = mod_results
|
modimpls_results[modimpl.id] = mod_results
|
||||||
modimpls_notes.append(etuds_moy_module)
|
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]
|
partitions += [p for p in self.partitions if p.partition_name is None]
|
||||||
return partitions
|
return partitions
|
||||||
|
|
||||||
@cached_property
|
def etudids_actifs(self) -> tuple[list[int], set[int]]:
|
||||||
def etudids_actifs(self) -> set:
|
"""Liste les etudids inscrits (incluant DEM et DEF),
|
||||||
"Set des etudids inscrits non démissionnaires et non défaillants"
|
qui ser al'index des dataframes de notes
|
||||||
return {ins.etudid for ins in self.inscriptions if ins.etat == scu.INSCRIT}
|
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
|
@cached_property
|
||||||
def etuds_inscriptions(self) -> dict:
|
def etuds_inscriptions(self) -> dict:
|
||||||
|
@ -705,7 +705,8 @@ def _add_eval_columns(
|
|||||||
nb_att = 0
|
nb_att = 0
|
||||||
sum_notes = 0
|
sum_notes = 0
|
||||||
notes = [] # liste des notes numeriques, pour calcul histogramme uniquement
|
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)
|
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation.id)
|
||||||
|
|
||||||
if evaluation.date_debut:
|
if evaluation.date_debut:
|
||||||
@ -734,7 +735,7 @@ def _add_eval_columns(
|
|||||||
nb_att += 1
|
nb_att += 1
|
||||||
# calcul moyenne SANS LES ABSENTS ni les DEMISSIONNAIRES
|
# calcul moyenne SANS LES ABSENTS ni les DEMISSIONNAIRES
|
||||||
if (
|
if (
|
||||||
(etudid in inscrits)
|
(etudid in etudids_actifs)
|
||||||
and val is not None
|
and val is not None
|
||||||
and val != scu.NOTES_NEUTRALISE
|
and val != scu.NOTES_NEUTRALISE
|
||||||
and val != scu.NOTES_ATTENTE
|
and val != scu.NOTES_ATTENTE
|
||||||
@ -758,7 +759,7 @@ def _add_eval_columns(
|
|||||||
comment,
|
comment,
|
||||||
)
|
)
|
||||||
else:
|
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
|
# Note manquante mais prise en compte immédiate: affiche ATT
|
||||||
val = scu.NOTES_ATTENTE
|
val = scu.NOTES_ATTENTE
|
||||||
val_fmt = "ATT"
|
val_fmt = "ATT"
|
||||||
@ -875,8 +876,7 @@ def _add_moymod_column(
|
|||||||
col_id = "moymod"
|
col_id = "moymod"
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
inscrits = formsemestre.etudids_actifs
|
_, etudids_actifs = formsemestre.etudids_actifs()
|
||||||
|
|
||||||
nb_notes = 0
|
nb_notes = 0
|
||||||
sum_notes = 0
|
sum_notes = 0
|
||||||
notes = [] # liste des notes numeriques, pour calcul histogramme uniquement
|
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'
|
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] = scu.fmt_note(val, keep_numeric=keep_numeric)
|
||||||
row["_" + col_id + "_td_attrs"] = ' class="moyenne" '
|
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)
|
notes.append(val)
|
||||||
if not np.isnan(val):
|
if not np.isnan(val):
|
||||||
nb_notes = nb_notes + 1
|
nb_notes = nb_notes + 1
|
||||||
@ -928,7 +928,7 @@ def _add_apc_columns(
|
|||||||
# on va y ajouter une clé par UE du semestre
|
# on va y ajouter une clé par UE du semestre
|
||||||
nt: ResultatsSemestreBUT = res_sem.load_formsemestre_results(modimpl.formsemestre)
|
nt: ResultatsSemestreBUT = res_sem.load_formsemestre_results(modimpl.formsemestre)
|
||||||
modimpl_results: ModuleImplResults = nt.modimpls_results[modimpl.id]
|
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:
|
# les UE dans lesquelles ce module a un coef non nul:
|
||||||
ues_with_coef = nt.modimpl_coefs_df[modimpl.id][
|
ues_with_coef = nt.modimpl_coefs_df[modimpl.id][
|
||||||
nt.modimpl_coefs_df[modimpl.id] > 0
|
nt.modimpl_coefs_df[modimpl.id] > 0
|
||||||
@ -946,7 +946,7 @@ def _add_apc_columns(
|
|||||||
if (
|
if (
|
||||||
isinstance(moy_ue, float)
|
isinstance(moy_ue, float)
|
||||||
and not np.isnan(moy_ue)
|
and not np.isnan(moy_ue)
|
||||||
and row["etudid"] in inscrits
|
and row["etudid"] in etudids_actifs
|
||||||
):
|
):
|
||||||
sum_by_ue[ue.id] += moy_ue
|
sum_by_ue[ue.id] += moy_ue
|
||||||
nb_notes_by_ue[ue.id] += 1
|
nb_notes_by_ue[ue.id] += 1
|
||||||
|
@ -541,7 +541,7 @@ def notes_add(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
# Les étudiants inscrits au semestre ni DEM ni DEF
|
# 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:
|
for etudid, value in notes:
|
||||||
if check_inscription and (
|
if check_inscription and (
|
||||||
(etudid not in inscrits) or (etudid not in etudids_actifs)
|
(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
|
# /ScoDoc/api/etudiant/nip/12345/formsemestre/123/bulletin/long/pdf/nosi
|
||||||
# TODO voir forme utilisée par ScoDoc en interne:
|
# TODO voir forme utilisée par ScoDoc en interne:
|
||||||
# formsemestre_bulletinetud?formsemestre_id=1263&etudid=16387
|
# 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):
|
def test_etudiant_groups(api_headers):
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
Test modèles évaluations avec poids BUT
|
Test modèles évaluations avec poids BUT
|
||||||
et calcul moyennes modules
|
et calcul moyennes modules
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -215,7 +216,8 @@ def test_module_moy(test_client):
|
|||||||
etud = G.create_etud(nom="test")
|
etud = G.create_etud(nom="test")
|
||||||
G.inscrit_etudiant(formsemestre_id, etud)
|
G.inscrit_etudiant(formsemestre_id, etud)
|
||||||
etudid = etud["etudid"]
|
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:
|
# Crée une deuxième évaluation dans le même moduleimpl:
|
||||||
evaluation2_id = G.create_evaluation(
|
evaluation2_id = G.create_evaluation(
|
||||||
moduleimpl_id=evaluation1.moduleimpl_id,
|
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, evaluation1.id, [(etudid, n1)])
|
||||||
_ = sco_saisie_notes.notes_add(G.default_user, evaluation2.id, [(etudid, n2)])
|
_ = sco_saisie_notes.notes_add(G.default_user, evaluation2.id, [(etudid, n2)])
|
||||||
# Calcul de la moyenne du module
|
# 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)
|
assert evals_poids.shape == (nb_evals, nb_ues)
|
||||||
|
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl)
|
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
||||||
evals_notes = mod_results.evals_notes
|
evals_notes = mod_results.evals_notes
|
||||||
assert evals_notes[evaluation1.id].dtype == np.float64
|
assert evals_notes[evaluation1.id].dtype == np.float64
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user