forked from ScoDoc/ScoDoc
Notes rattrapage et 2eme session en BUT et DUT (pas affichées sur buls)
This commit is contained in:
parent
7a4e0206a3
commit
e3c9f187dd
@ -41,7 +41,6 @@ from app import db
|
|||||||
from app.models import ModuleImpl, Evaluation, EvaluationUEPoids
|
from app.models import ModuleImpl, Evaluation, EvaluationUEPoids
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
|
||||||
|
|
||||||
from app.scodoc.sco_utils import ModuleType
|
from app.scodoc.sco_utils import ModuleType
|
||||||
|
|
||||||
@ -92,6 +91,10 @@ class ModuleImplResults:
|
|||||||
ne donnent pas de coef vers cette UE.
|
ne donnent pas de coef vers cette UE.
|
||||||
"""
|
"""
|
||||||
self.load_notes()
|
self.load_notes()
|
||||||
|
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): # 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.
|
||||||
@ -135,8 +138,11 @@ class ModuleImplResults:
|
|||||||
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
|
||||||
# ou évaluation déclarée "à prise en compte immédiate"
|
# ou évaluation déclarée "à prise en compte immédiate"
|
||||||
is_complete = evaluation.publish_incomplete or (
|
# Les évaluations de rattrapage et 2eme session sont toujours incomplètes
|
||||||
not (inscrits_module - set(eval_df.index))
|
# car on calcule leur moyenne à part.
|
||||||
|
is_complete = (evaluation.evaluation_type == scu.EVALUATION_NORMALE) and (
|
||||||
|
evaluation.publish_incomplete
|
||||||
|
or (not (inscrits_module - set(eval_df.index)))
|
||||||
)
|
)
|
||||||
self.evaluations_completes.append(is_complete)
|
self.evaluations_completes.append(is_complete)
|
||||||
self.evaluations_completes_dict[evaluation.id] = is_complete
|
self.evaluations_completes_dict[evaluation.id] = is_complete
|
||||||
@ -212,6 +218,33 @@ class ModuleImplResults:
|
|||||||
self.evals_notes.values > scu.NOTES_ABSENCE, self.evals_notes.values, 0.0
|
self.evals_notes.values > scu.NOTES_ABSENCE, self.evals_notes.values, 0.0
|
||||||
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
||||||
|
|
||||||
|
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl):
|
||||||
|
"""L'évaluation de rattrapage de ce module, ou None s'il n'en a pas.
|
||||||
|
Rattrapage: la moyenne du module est la meilleure note entre moyenne
|
||||||
|
des autres évals et la note eval rattrapage.
|
||||||
|
"""
|
||||||
|
eval_list = [
|
||||||
|
e
|
||||||
|
for e in moduleimpl.evaluations
|
||||||
|
if e.evaluation_type == scu.EVALUATION_RATTRAPAGE
|
||||||
|
]
|
||||||
|
if eval_list:
|
||||||
|
return eval_list[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_evaluation_session2(self, moduleimpl: ModuleImpl):
|
||||||
|
"""L'évaluation 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.
|
||||||
|
"""
|
||||||
|
eval_list = [
|
||||||
|
e
|
||||||
|
for e in moduleimpl.evaluations
|
||||||
|
if e.evaluation_type == scu.EVALUATION_SESSION2
|
||||||
|
]
|
||||||
|
if eval_list:
|
||||||
|
return eval_list[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ModuleImplResultsAPC(ModuleImplResults):
|
class ModuleImplResultsAPC(ModuleImplResults):
|
||||||
"Calcul des moyennes de modules à la mode BUT"
|
"Calcul des moyennes de modules à la mode BUT"
|
||||||
@ -229,7 +262,7 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
ou NaN si les évaluations (dans lesquelles l'étudiant a des notes)
|
ou NaN si les évaluations (dans lesquelles l'étudiant a des notes)
|
||||||
ne donnent pas de coef vers cette UE.
|
ne donnent pas de coef vers cette UE.
|
||||||
"""
|
"""
|
||||||
moduleimpl = ModuleImpl.query.get(self.moduleimpl_id)
|
modimpl = ModuleImpl.query.get(self.moduleimpl_id)
|
||||||
nb_etuds, nb_evals = self.evals_notes.shape
|
nb_etuds, nb_evals = self.evals_notes.shape
|
||||||
nb_ues = evals_poids_df.shape[1]
|
nb_ues = evals_poids_df.shape[1]
|
||||||
assert evals_poids_df.shape[0] == nb_evals # compat notes/poids
|
assert evals_poids_df.shape[0] == nb_evals # compat notes/poids
|
||||||
@ -237,11 +270,11 @@ 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=[])
|
||||||
evals_coefs = self.get_evaluations_coefs(moduleimpl)
|
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)
|
||||||
assert evals_poids.shape == (nb_evals, nb_ues)
|
assert evals_poids.shape == (nb_evals, nb_ues)
|
||||||
evals_notes_20 = self.get_eval_notes_sur_20(moduleimpl)
|
evals_notes_20 = self.get_eval_notes_sur_20(modimpl)
|
||||||
|
|
||||||
# Les poids des évals pour chaque étudiant: là où il a des notes
|
# Les poids des évals pour chaque étudiant: là où il a des notes
|
||||||
# non neutralisées
|
# non neutralisées
|
||||||
@ -262,6 +295,45 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
etuds_moy_module = np.sum(
|
etuds_moy_module = np.sum(
|
||||||
evals_poids_etuds * evals_notes_stacked, axis=1
|
evals_poids_etuds * evals_notes_stacked, axis=1
|
||||||
) / np.sum(evals_poids_etuds, axis=1)
|
) / np.sum(evals_poids_etuds, axis=1)
|
||||||
|
|
||||||
|
# Session2 : quand elle existe, remplace la note de module
|
||||||
|
eval_session2 = self.get_evaluation_session2(modimpl)
|
||||||
|
if eval_session2:
|
||||||
|
notes_session2 = self.evals_notes[eval_session2.id].values
|
||||||
|
# n'utilise que les notes valides (pas ATT, EXC, ABS, NaN)
|
||||||
|
etuds_use_session2 = notes_session2 > scu.NOTES_ABSENCE
|
||||||
|
etuds_moy_module = np.where(
|
||||||
|
etuds_use_session2[:, np.newaxis],
|
||||||
|
np.tile(
|
||||||
|
(notes_session2 / (eval_session2.note_max / 20.0))[:, np.newaxis],
|
||||||
|
nb_ues,
|
||||||
|
),
|
||||||
|
etuds_moy_module,
|
||||||
|
)
|
||||||
|
self.etuds_use_session2 = pd.Series(
|
||||||
|
etuds_use_session2, index=self.evals_notes.index
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Rattrapage: remplace la note de module ssi elle est supérieure
|
||||||
|
eval_rat = self.get_evaluation_rattrapage(modimpl)
|
||||||
|
if eval_rat:
|
||||||
|
notes_rat = self.evals_notes[eval_rat.id].values
|
||||||
|
# remplace les notes invalides (ATT, EXC...) par des NaN
|
||||||
|
notes_rat = np.where(
|
||||||
|
notes_rat > scu.NOTES_ABSENCE,
|
||||||
|
notes_rat / (eval_rat.note_max / 20.0),
|
||||||
|
np.nan,
|
||||||
|
)
|
||||||
|
# prend le max
|
||||||
|
etuds_use_rattrapage = notes_rat > etuds_moy_module
|
||||||
|
etuds_moy_module = np.where(
|
||||||
|
etuds_use_rattrapage[:, np.newaxis],
|
||||||
|
np.tile(notes_rat[:, np.newaxis], nb_ues),
|
||||||
|
etuds_moy_module,
|
||||||
|
)
|
||||||
|
self.etuds_use_rattrapage = pd.Series(
|
||||||
|
etuds_use_rattrapage, index=self.evals_notes.index
|
||||||
|
)
|
||||||
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,
|
||||||
@ -371,8 +443,42 @@ 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)
|
||||||
|
|
||||||
|
# Session2 : quand elle existe, remplace la note de module
|
||||||
|
eval_session2 = self.get_evaluation_session2(modimpl)
|
||||||
|
if eval_session2:
|
||||||
|
notes_session2 = self.evals_notes[eval_session2.id].values
|
||||||
|
# n'utilise que les notes valides (pas ATT, EXC, ABS, NaN)
|
||||||
|
etuds_use_session2 = notes_session2 > scu.NOTES_ABSENCE
|
||||||
|
etuds_moy_module = np.where(
|
||||||
|
etuds_use_session2,
|
||||||
|
notes_session2 / (eval_session2.note_max / 20.0),
|
||||||
|
etuds_moy_module,
|
||||||
|
)
|
||||||
|
self.etuds_use_session2 = pd.Series(
|
||||||
|
etuds_use_session2, index=self.evals_notes.index
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Rattrapage: remplace la note de module ssi elle est supérieure
|
||||||
|
eval_rat = self.get_evaluation_rattrapage(modimpl)
|
||||||
|
if eval_rat:
|
||||||
|
notes_rat = self.evals_notes[eval_rat.id].values
|
||||||
|
# remplace les notes invalides (ATT, EXC...) par des NaN
|
||||||
|
notes_rat = np.where(
|
||||||
|
notes_rat > scu.NOTES_ABSENCE,
|
||||||
|
notes_rat / (eval_rat.note_max / 20.0),
|
||||||
|
np.nan,
|
||||||
|
)
|
||||||
|
# prend le max
|
||||||
|
etuds_use_rattrapage = notes_rat > etuds_moy_module
|
||||||
|
etuds_moy_module = np.where(
|
||||||
|
etuds_use_rattrapage, notes_rat, etuds_moy_module
|
||||||
|
)
|
||||||
|
self.etuds_use_rattrapage = pd.Series(
|
||||||
|
etuds_use_rattrapage, index=self.evals_notes.index
|
||||||
|
)
|
||||||
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,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.etuds_moy_module
|
return self.etuds_moy_module
|
||||||
|
@ -619,7 +619,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
|||||||
prefs=prefs,
|
prefs=prefs,
|
||||||
)
|
)
|
||||||
|
|
||||||
if nbeval: # boite autour des evaluations (en pdf)
|
if nbeval: # boite autour des évaluations (en pdf)
|
||||||
P[-1]["_pdf_style"].append(
|
P[-1]["_pdf_style"].append(
|
||||||
("BOX", (1, 1 - nbeval), (-1, 0), 0.2, self.PDF_LIGHT_GRAY)
|
("BOX", (1, 1 - nbeval), (-1, 0), 0.2, self.PDF_LIGHT_GRAY)
|
||||||
)
|
)
|
||||||
|
@ -207,7 +207,7 @@ def evaluation_create_form(
|
|||||||
{
|
{
|
||||||
"size": 6,
|
"size": 6,
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"explanation": "coef. dans le module (choisi librement par l'enseignant)",
|
"explanation": "coef. dans le module (choisi librement par l'enseignant, non utilisé pour rattrapage et 2ème session)",
|
||||||
"allow_null": False,
|
"allow_null": False,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user