forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -113,6 +113,8 @@ 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.evals_type = {}
|
||||||
|
"""Type de chaque eval { evaluation.id : evaluation.evaluation_type }"""
|
||||||
self.load_notes(etudids, etudids_actifs)
|
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"""
|
||||||
@ -164,7 +166,10 @@ class ModuleImplResults:
|
|||||||
self.evaluations_completes = []
|
self.evaluations_completes = []
|
||||||
self.evaluations_completes_dict = {}
|
self.evaluations_completes_dict = {}
|
||||||
self.etudids_attente = set() # empty
|
self.etudids_attente = set() # empty
|
||||||
|
self.evals_type = {}
|
||||||
|
evaluation: Evaluation
|
||||||
for evaluation in moduleimpl.evaluations:
|
for evaluation in moduleimpl.evaluations:
|
||||||
|
self.evals_type[evaluation.id] = evaluation.evaluation_type
|
||||||
eval_df = self._load_evaluation_notes(evaluation)
|
eval_df = self._load_evaluation_notes(evaluation)
|
||||||
# is_complete ssi
|
# is_complete ssi
|
||||||
# tous les inscrits (non dem) au module ont une note
|
# tous les inscrits (non dem) au module ont une note
|
||||||
@ -270,6 +275,26 @@ class ModuleImplResults:
|
|||||||
* self.evaluations_completes
|
* self.evaluations_completes
|
||||||
).reshape(-1, 1)
|
).reshape(-1, 1)
|
||||||
|
|
||||||
|
def get_evaluations_session2_coefs(self, modimpl: ModuleImpl) -> np.array:
|
||||||
|
"""Coefficients des évaluations de session 2.
|
||||||
|
Les évals de session 2 sont réputées "complètes": elles sont toujours
|
||||||
|
prises en compte mais seules les notes numériques et ABS sont utilisées.
|
||||||
|
Résultat: 2d-array of floats, shape (nb_evals, 1)
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
np.array(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
e.coefficient
|
||||||
|
if e.evaluation_type == Evaluation.EVALUATION_SESSION2
|
||||||
|
else 0.0
|
||||||
|
)
|
||||||
|
for e in modimpl.evaluations
|
||||||
|
],
|
||||||
|
dtype=float,
|
||||||
|
)
|
||||||
|
).reshape(-1, 1)
|
||||||
|
|
||||||
# was _list_notes_evals_titles
|
# was _list_notes_evals_titles
|
||||||
def get_evaluations_completes(self, moduleimpl: ModuleImpl) -> list[Evaluation]:
|
def get_evaluations_completes(self, moduleimpl: ModuleImpl) -> list[Evaluation]:
|
||||||
"Liste des évaluations complètes"
|
"Liste des évaluations complètes"
|
||||||
@ -310,18 +335,15 @@ class ModuleImplResults:
|
|||||||
return eval_list[0]
|
return eval_list[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_evaluation_session2(self, moduleimpl: ModuleImpl) -> Evaluation | None:
|
def get_evaluations_session2(self, moduleimpl: ModuleImpl) -> list[Evaluation]:
|
||||||
"""L'évaluation de deuxième session de ce module, ou None s'il n'en a pas.
|
"""Les évaluations de deuxième session de ce module, ou None s'il n'en a pas.
|
||||||
Session 2: remplace la note de moyenne des autres évals.
|
La moyenne des notes de Session 2 remplace la note de moyenne des autres évals.
|
||||||
"""
|
"""
|
||||||
eval_list = [
|
return [
|
||||||
e
|
e
|
||||||
for e in moduleimpl.evaluations
|
for e in moduleimpl.evaluations
|
||||||
if e.evaluation_type == Evaluation.EVALUATION_SESSION2
|
if e.evaluation_type == Evaluation.EVALUATION_SESSION2
|
||||||
]
|
]
|
||||||
if eval_list:
|
|
||||||
return eval_list[0]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_evaluations_bonus(self, modimpl: ModuleImpl) -> list[Evaluation]:
|
def get_evaluations_bonus(self, modimpl: ModuleImpl) -> list[Evaluation]:
|
||||||
"""Les évaluations bonus de ce module, ou liste vide s'il n'en a pas."""
|
"""Les évaluations bonus de ce module, ou liste vide s'il n'en a pas."""
|
||||||
@ -370,6 +392,7 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
return pd.DataFrame(index=[], columns=evals_poids_df.columns)
|
return pd.DataFrame(index=[], columns=evals_poids_df.columns)
|
||||||
if nb_ues == 0:
|
if nb_ues == 0:
|
||||||
return pd.DataFrame(index=self.evals_notes.index, columns=[])
|
return pd.DataFrame(index=self.evals_notes.index, columns=[])
|
||||||
|
# coefs des évals complètes normales (pas rattr., session 2 ni bonus):
|
||||||
evals_coefs = self.get_evaluations_coefs(modimpl)
|
evals_coefs = self.get_evaluations_coefs(modimpl)
|
||||||
evals_poids = evals_poids_df.values * evals_coefs
|
evals_poids = evals_poids_df.values * evals_coefs
|
||||||
# -> evals_poids shape : (nb_evals, nb_ues)
|
# -> evals_poids shape : (nb_evals, nb_ues)
|
||||||
@ -398,26 +421,30 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
) / np.sum(evals_poids_etuds, axis=1)
|
) / np.sum(evals_poids_etuds, axis=1)
|
||||||
# etuds_moy_module shape: nb_etuds x nb_ues
|
# etuds_moy_module shape: nb_etuds x nb_ues
|
||||||
|
|
||||||
# Application des évaluations bonus:
|
|
||||||
etuds_moy_module = self.apply_bonus(
|
|
||||||
etuds_moy_module,
|
|
||||||
modimpl,
|
|
||||||
evals_poids_df,
|
|
||||||
evals_notes_stacked,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Session2 : quand elle existe, remplace la note de module
|
# Session2 : quand elle existe, remplace la note de module
|
||||||
eval_session2 = self.get_evaluation_session2(modimpl)
|
evals_session2 = self.get_evaluations_session2(modimpl)
|
||||||
if eval_session2:
|
if evals_session2:
|
||||||
notes_session2 = self.evals_notes[eval_session2.id].values
|
# Calcul moyenne notes session2 et remplace (si la note session 2 existe)
|
||||||
# n'utilise que les notes valides (pas ATT, EXC, ABS, NaN)
|
evals_coefs_s2 = self.get_evaluations_session2_coefs(modimpl)
|
||||||
etuds_use_session2 = notes_session2 > scu.NOTES_ABSENCE
|
evals_poids_s2 = evals_poids_df.values * evals_coefs_s2
|
||||||
|
poids_stacked_s2 = np.stack(
|
||||||
|
[evals_poids_s2] * nb_etuds
|
||||||
|
) # nb_etuds, nb_evals, nb_ues
|
||||||
|
evals_poids_etuds_s2 = np.where(
|
||||||
|
np.stack([self.evals_notes.values] * nb_ues, axis=2)
|
||||||
|
> scu.NOTES_NEUTRALISE,
|
||||||
|
poids_stacked_s2,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
etuds_moy_module_s2 = np.sum(
|
||||||
|
evals_poids_etuds_s2 * evals_notes_stacked, axis=1
|
||||||
|
) / np.sum(evals_poids_etuds_s2, axis=1)
|
||||||
|
# Vrai si toutes les UEs ont bien une note de session 2 calculée:
|
||||||
|
etuds_use_session2 = np.all(np.isfinite(etuds_moy_module_s2), axis=1)
|
||||||
etuds_moy_module = np.where(
|
etuds_moy_module = np.where(
|
||||||
etuds_use_session2[:, np.newaxis],
|
etuds_use_session2[:, np.newaxis],
|
||||||
np.tile(
|
etuds_moy_module_s2,
|
||||||
(notes_session2 / (eval_session2.note_max / 20.0))[:, np.newaxis],
|
|
||||||
nb_ues,
|
|
||||||
),
|
|
||||||
etuds_moy_module,
|
etuds_moy_module,
|
||||||
)
|
)
|
||||||
self.etuds_use_session2 = pd.Series(
|
self.etuds_use_session2 = pd.Series(
|
||||||
@ -435,7 +462,7 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
np.nan,
|
np.nan,
|
||||||
)
|
)
|
||||||
# "Étend" le rattrapage sur les UE: la note de rattrapage est la même
|
# "Étend" le rattrapage sur les UE: la note de rattrapage est la même
|
||||||
# pour toutes les UE mais ne remplace que là où elle est supérieure
|
# pour toutes les UE mais ne remplace que là où elle est supérieure XXX TODO
|
||||||
notes_rat_ues = np.stack([notes_rat] * nb_ues, axis=1)
|
notes_rat_ues = np.stack([notes_rat] * nb_ues, axis=1)
|
||||||
# prend le max
|
# prend le max
|
||||||
etuds_use_rattrapage = notes_rat_ues > etuds_moy_module
|
etuds_use_rattrapage = notes_rat_ues > etuds_moy_module
|
||||||
@ -446,6 +473,13 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
self.etuds_use_rattrapage = pd.Series(
|
self.etuds_use_rattrapage = pd.Series(
|
||||||
etuds_use_rattrapage.any(axis=1), index=self.evals_notes.index
|
etuds_use_rattrapage.any(axis=1), index=self.evals_notes.index
|
||||||
)
|
)
|
||||||
|
# Application des évaluations bonus:
|
||||||
|
etuds_moy_module = self.apply_bonus(
|
||||||
|
etuds_moy_module,
|
||||||
|
modimpl,
|
||||||
|
evals_poids_df,
|
||||||
|
evals_notes_stacked,
|
||||||
|
)
|
||||||
self.etuds_moy_module = pd.DataFrame(
|
self.etuds_moy_module = pd.DataFrame(
|
||||||
etuds_moy_module,
|
etuds_moy_module,
|
||||||
index=self.evals_notes.index,
|
index=self.evals_notes.index,
|
||||||
@ -525,6 +559,7 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
|
|||||||
return evals_poids, ues
|
return evals_poids, ues
|
||||||
|
|
||||||
|
|
||||||
|
# appelé par ModuleImpl.check_apc_conformity()
|
||||||
def moduleimpl_is_conforme(
|
def moduleimpl_is_conforme(
|
||||||
moduleimpl, evals_poids: pd.DataFrame, modimpl_coefs_df: pd.DataFrame
|
moduleimpl, evals_poids: pd.DataFrame, modimpl_coefs_df: pd.DataFrame
|
||||||
) -> bool:
|
) -> bool:
|
||||||
@ -546,12 +581,12 @@ def moduleimpl_is_conforme(
|
|||||||
if len(modimpl_coefs_df) != nb_ues:
|
if len(modimpl_coefs_df) != nb_ues:
|
||||||
# il arrive (#bug) que le cache ne soit pas à jour...
|
# il arrive (#bug) que le cache ne soit pas à jour...
|
||||||
sco_cache.invalidate_formsemestre()
|
sco_cache.invalidate_formsemestre()
|
||||||
raise ScoBugCatcher("moduleimpl_is_conforme: nb ue incoherent")
|
return app.critical_error("moduleimpl_is_conforme: err 1")
|
||||||
|
|
||||||
if moduleimpl.id not in modimpl_coefs_df:
|
if moduleimpl.id not in modimpl_coefs_df:
|
||||||
# soupçon de bug cache coef ?
|
# soupçon de bug cache coef ?
|
||||||
sco_cache.invalidate_formsemestre()
|
sco_cache.invalidate_formsemestre()
|
||||||
raise ScoBugCatcher("Erreur 454 - merci de ré-essayer")
|
return app.critical_error("moduleimpl_is_conforme: err 2")
|
||||||
|
|
||||||
module_evals_poids = evals_poids.transpose().sum(axis=1) != 0
|
module_evals_poids = evals_poids.transpose().sum(axis=1) != 0
|
||||||
return all((modimpl_coefs_df[moduleimpl.id] != 0).eq(module_evals_poids))
|
return all((modimpl_coefs_df[moduleimpl.id] != 0).eq(module_evals_poids))
|
||||||
@ -593,22 +628,28 @@ class ModuleImplResultsClassic(ModuleImplResults):
|
|||||||
evals_coefs_etuds * evals_notes_20, axis=1
|
evals_coefs_etuds * evals_notes_20, axis=1
|
||||||
) / np.sum(evals_coefs_etuds, axis=1)
|
) / np.sum(evals_coefs_etuds, axis=1)
|
||||||
|
|
||||||
# Application des évaluations bonus:
|
|
||||||
etuds_moy_module = self.apply_bonus(
|
|
||||||
etuds_moy_module,
|
|
||||||
modimpl,
|
|
||||||
evals_notes_20,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Session2 : quand elle existe, remplace la note de module
|
# Session2 : quand elle existe, remplace la note de module
|
||||||
eval_session2 = self.get_evaluation_session2(modimpl)
|
evals_session2 = self.get_evaluations_session2(modimpl)
|
||||||
if eval_session2:
|
if evals_session2:
|
||||||
notes_session2 = self.evals_notes[eval_session2.id].values
|
# Calculer la moyenne des évaluations de session2
|
||||||
# n'utilise que les notes valides (pas ATT, EXC, ABS, NaN)
|
# n'utilise que les notes valides et ABS (0).
|
||||||
etuds_use_session2 = notes_session2 > scu.NOTES_ABSENCE
|
# Même calcul que pour les évals normales, mais avec seulement les
|
||||||
|
# coefs des évals de session 2:
|
||||||
|
evals_coefs_s2 = self.get_evaluations_session2_coefs(modimpl).reshape(-1)
|
||||||
|
coefs_stacked_s2 = np.stack([evals_coefs_s2] * nb_etuds)
|
||||||
|
# zéro partout sauf si une note ou ABS:
|
||||||
|
evals_coefs_etuds_s2 = np.where(
|
||||||
|
self.evals_notes.values > scu.NOTES_NEUTRALISE, coefs_stacked_s2, 0
|
||||||
|
)
|
||||||
|
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
||||||
|
etuds_moy_module_s2 = np.sum(
|
||||||
|
evals_coefs_etuds_s2 * evals_notes_20, axis=1
|
||||||
|
) / np.sum(evals_coefs_etuds_s2, axis=1)
|
||||||
|
|
||||||
|
etuds_use_session2 = np.isfinite(etuds_moy_module_s2)
|
||||||
etuds_moy_module = np.where(
|
etuds_moy_module = np.where(
|
||||||
etuds_use_session2,
|
etuds_use_session2,
|
||||||
notes_session2 / (eval_session2.note_max / 20.0),
|
etuds_moy_module_s2,
|
||||||
etuds_moy_module,
|
etuds_moy_module,
|
||||||
)
|
)
|
||||||
self.etuds_use_session2 = pd.Series(
|
self.etuds_use_session2 = pd.Series(
|
||||||
@ -633,6 +674,13 @@ class ModuleImplResultsClassic(ModuleImplResults):
|
|||||||
self.etuds_use_rattrapage = pd.Series(
|
self.etuds_use_rattrapage = pd.Series(
|
||||||
etuds_use_rattrapage, index=self.evals_notes.index
|
etuds_use_rattrapage, index=self.evals_notes.index
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Application des évaluations bonus:
|
||||||
|
etuds_moy_module = self.apply_bonus(
|
||||||
|
etuds_moy_module,
|
||||||
|
modimpl,
|
||||||
|
evals_notes_20,
|
||||||
|
)
|
||||||
self.etuds_moy_module = pd.Series(
|
self.etuds_moy_module = pd.Series(
|
||||||
etuds_moy_module,
|
etuds_moy_module,
|
||||||
index=self.evals_notes.index,
|
index=self.evals_notes.index,
|
||||||
|
@ -207,7 +207,7 @@ def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple:
|
|||||||
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||||
for modimpl in formsemestre.modimpls_sorted:
|
for modimpl in formsemestre.modimpls_sorted:
|
||||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
||||||
evals_poids, _ = moy_mod.load_evaluations_poids(modimpl.id)
|
evals_poids = modimpl.get_evaluations_poids()
|
||||||
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
|
||||||
modimpls_evals_poids[modimpl.id] = evals_poids
|
modimpls_evals_poids[modimpl.id] = evals_poids
|
||||||
|
@ -6,6 +6,7 @@ from flask import abort, g
|
|||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from flask_sqlalchemy.query import Query
|
from flask_sqlalchemy.query import Query
|
||||||
|
|
||||||
|
import app
|
||||||
from app import db
|
from app import db
|
||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
from app.comp import df_cache
|
from app.comp import df_cache
|
||||||
@ -78,7 +79,9 @@ class ModuleImpl(ScoDocModel):
|
|||||||
] or self.module.get_edt_ids()
|
] or self.module.get_edt_ids()
|
||||||
|
|
||||||
def get_evaluations_poids(self) -> pd.DataFrame:
|
def get_evaluations_poids(self) -> pd.DataFrame:
|
||||||
"""Les poids des évaluations vers les UE (accès via cache)"""
|
"""Les poids des évaluations vers les UEs (accès via cache redis).
|
||||||
|
Toutes les évaluations sont considérées (normales, bonus, rattr., etc.)
|
||||||
|
"""
|
||||||
evaluations_poids = df_cache.EvaluationsPoidsCache.get(self.id)
|
evaluations_poids = df_cache.EvaluationsPoidsCache.get(self.id)
|
||||||
if evaluations_poids is None:
|
if evaluations_poids is None:
|
||||||
from app.comp import moy_mod
|
from app.comp import moy_mod
|
||||||
@ -108,20 +111,37 @@ class ModuleImpl(ScoDocModel):
|
|||||||
"""Invalide poids cachés"""
|
"""Invalide poids cachés"""
|
||||||
df_cache.EvaluationsPoidsCache.delete(self.id)
|
df_cache.EvaluationsPoidsCache.delete(self.id)
|
||||||
|
|
||||||
def check_apc_conformity(self, res: "ResultatsSemestreBUT") -> bool:
|
def check_apc_conformity(
|
||||||
"""true si les poids des évaluations du module permettent de satisfaire
|
self, res: "ResultatsSemestreBUT", evaluation_type=Evaluation.EVALUATION_NORMALE
|
||||||
les coefficients du PN.
|
) -> bool:
|
||||||
|
"""true si les poids des évaluations du type indiqué (normales par défaut)
|
||||||
|
du module permettent de satisfaire les coefficients du PN.
|
||||||
"""
|
"""
|
||||||
|
# appelé par formsemestre_status, liste notes, et moduleimpl_status
|
||||||
if not self.module.formation.get_cursus().APC_SAE or (
|
if not self.module.formation.get_cursus().APC_SAE or (
|
||||||
self.module.module_type != scu.ModuleType.RESSOURCE
|
self.module.module_type
|
||||||
and self.module.module_type != scu.ModuleType.SAE
|
not in {scu.ModuleType.RESSOURCE, scu.ModuleType.SAE}
|
||||||
):
|
):
|
||||||
return True # Non BUT, toujours conforme
|
return True # Non BUT, toujours conforme
|
||||||
from app.comp import moy_mod
|
from app.comp import moy_mod
|
||||||
|
|
||||||
|
mod_results = res.modimpls_results.get(self.id)
|
||||||
|
if mod_results is None:
|
||||||
|
app.critical_error("check_apc_conformity: err 1")
|
||||||
|
|
||||||
|
selected_evaluations_ids = [
|
||||||
|
eval_id
|
||||||
|
for eval_id, eval_type in mod_results.evals_type.items()
|
||||||
|
if eval_type == evaluation_type
|
||||||
|
]
|
||||||
|
if not selected_evaluations_ids:
|
||||||
|
return True # conforme si pas d'évaluations
|
||||||
|
selected_evaluations_poids = self.get_evaluations_poids().loc[
|
||||||
|
selected_evaluations_ids
|
||||||
|
]
|
||||||
return moy_mod.moduleimpl_is_conforme(
|
return moy_mod.moduleimpl_is_conforme(
|
||||||
self,
|
self,
|
||||||
self.get_evaluations_poids(),
|
selected_evaluations_poids,
|
||||||
res.modimpl_coefs_df,
|
res.modimpl_coefs_df,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ def moduleimpl_evaluation_menu(evaluation: Evaluation, nbnotes: int = 0) -> str:
|
|||||||
can_edit_notes_ens = modimpl.can_edit_notes(current_user)
|
can_edit_notes_ens = modimpl.can_edit_notes(current_user)
|
||||||
|
|
||||||
if can_edit_notes and nbnotes != 0:
|
if can_edit_notes and nbnotes != 0:
|
||||||
sup_label = "Supprimer évaluation impossible (il y a des notes)"
|
sup_label = "Suppression évaluation impossible (il y a des notes)"
|
||||||
else:
|
else:
|
||||||
sup_label = "Supprimer évaluation"
|
sup_label = "Supprimer évaluation"
|
||||||
|
|
||||||
@ -344,9 +344,23 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
#
|
#
|
||||||
if not modimpl.check_apc_conformity(nt):
|
if not modimpl.check_apc_conformity(nt):
|
||||||
H.append(
|
H.append(
|
||||||
"""<div class="warning conformite">Les poids des évaluations de ce module ne sont
|
"""<div class="warning conformite">Les poids des évaluations de ce
|
||||||
pas encore conformes au PN.
|
module ne permettent pas d'évaluer toutes les UEs (compétences)
|
||||||
Ses notes ne peuvent pas être prises en compte dans les moyennes d'UE.
|
prévues par les coefficients du programme.
|
||||||
|
<b>Ses notes ne peuvent pas être prises en compte dans les moyennes d'UE.</b>
|
||||||
|
Vérifiez les poids des évaluations.
|
||||||
|
</div>"""
|
||||||
|
)
|
||||||
|
if not modimpl.check_apc_conformity(
|
||||||
|
nt, evaluation_type=Evaluation.EVALUATION_SESSION2
|
||||||
|
):
|
||||||
|
H.append(
|
||||||
|
"""<div class="warning conformite">
|
||||||
|
Il y a des évaluations de <b>deuxième session</b>
|
||||||
|
mais leurs poids ne permettent pas d'évaluer toutes les UEs (compétences)
|
||||||
|
prévues par les coefficients du programme.
|
||||||
|
La deuxième session en sera donc <b>pas prise en compte</b>.
|
||||||
|
Vérifiez les poids de ces évaluations.
|
||||||
</div>"""
|
</div>"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ 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, _ = moy_mod.load_evaluations_poids(moduleimpl_id)
|
evals_poids = modimpl.get_evaluations_poids()
|
||||||
assert evals_poids.shape == (nb_evals, nb_ues)
|
assert evals_poids.shape == (nb_evals, nb_ues)
|
||||||
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
etudids, etudids_actifs = formsemestre.etudids_actifs()
|
||||||
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs)
|
||||||
|
@ -151,8 +151,9 @@ def test_notes_rattrapage(test_client):
|
|||||||
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
|
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
|
||||||
mod_res = res.modimpls_results[moduleimpl_id]
|
mod_res = res.modimpls_results[moduleimpl_id]
|
||||||
# retrouve l'éval. de session 2:
|
# retrouve l'éval. de session 2:
|
||||||
eval_session2 = mod_res.get_evaluation_session2(moduleimpl)
|
evals_session2 = mod_res.get_evaluations_session2(moduleimpl)
|
||||||
assert eval_session2.id == e_session2["id"]
|
assert len(evals_session2) == 1
|
||||||
|
assert evals_session2[0].id == e_session2["id"]
|
||||||
# Les deux évaluations sont considérées comme complètes:
|
# Les deux évaluations sont considérées comme complètes:
|
||||||
assert len(mod_res.get_evaluations_completes(moduleimpl)) == 2
|
assert len(mod_res.get_evaluations_completes(moduleimpl)) == 2
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user