forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -104,9 +104,11 @@ class BulletinBUT:
|
|||||||
"competence": None, # XXX TODO lien avec référentiel
|
"competence": None, # XXX TODO lien avec référentiel
|
||||||
"moyenne": None,
|
"moyenne": None,
|
||||||
# Le bonus sport appliqué sur cette UE
|
# Le bonus sport appliqué sur cette UE
|
||||||
"bonus": fmt_note(res.bonus_ues[ue.id][etud.id])
|
"bonus": (
|
||||||
if res.bonus_ues is not None and ue.id in res.bonus_ues
|
fmt_note(res.bonus_ues[ue.id][etud.id])
|
||||||
else fmt_note(0.0),
|
if res.bonus_ues is not None and ue.id in res.bonus_ues
|
||||||
|
else fmt_note(0.0)
|
||||||
|
),
|
||||||
"malus": fmt_note(res.malus[ue.id][etud.id]),
|
"malus": fmt_note(res.malus[ue.id][etud.id]),
|
||||||
"capitalise": None, # "AAAA-MM-JJ" TODO #sco93
|
"capitalise": None, # "AAAA-MM-JJ" TODO #sco93
|
||||||
"ressources": self.etud_ue_mod_results(etud, ue, res.ressources),
|
"ressources": self.etud_ue_mod_results(etud, ue, res.ressources),
|
||||||
@ -181,14 +183,16 @@ class BulletinBUT:
|
|||||||
"is_external": ue_capitalisee.is_external,
|
"is_external": ue_capitalisee.is_external,
|
||||||
"date_capitalisation": ue_capitalisee.event_date,
|
"date_capitalisation": ue_capitalisee.event_date,
|
||||||
"formsemestre_id": ue_capitalisee.formsemestre_id,
|
"formsemestre_id": ue_capitalisee.formsemestre_id,
|
||||||
"bul_orig_url": url_for(
|
"bul_orig_url": (
|
||||||
"notes.formsemestre_bulletinetud",
|
url_for(
|
||||||
scodoc_dept=g.scodoc_dept,
|
"notes.formsemestre_bulletinetud",
|
||||||
etudid=etud.id,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=ue_capitalisee.formsemestre_id,
|
etudid=etud.id,
|
||||||
)
|
formsemestre_id=ue_capitalisee.formsemestre_id,
|
||||||
if ue_capitalisee.formsemestre_id
|
)
|
||||||
else None,
|
if ue_capitalisee.formsemestre_id
|
||||||
|
else None
|
||||||
|
),
|
||||||
"ressources": {}, # sans détail en BUT
|
"ressources": {}, # sans détail en BUT
|
||||||
"saes": {},
|
"saes": {},
|
||||||
}
|
}
|
||||||
@ -227,13 +231,15 @@ class BulletinBUT:
|
|||||||
"id": modimpl.id,
|
"id": modimpl.id,
|
||||||
"titre": modimpl.module.titre,
|
"titre": modimpl.module.titre,
|
||||||
"code_apogee": modimpl.module.code_apogee,
|
"code_apogee": modimpl.module.code_apogee,
|
||||||
"url": url_for(
|
"url": (
|
||||||
"notes.moduleimpl_status",
|
url_for(
|
||||||
scodoc_dept=g.scodoc_dept,
|
"notes.moduleimpl_status",
|
||||||
moduleimpl_id=modimpl.id,
|
scodoc_dept=g.scodoc_dept,
|
||||||
)
|
moduleimpl_id=modimpl.id,
|
||||||
if has_request_context()
|
)
|
||||||
else "na",
|
if has_request_context()
|
||||||
|
else "na"
|
||||||
|
),
|
||||||
"moyenne": {
|
"moyenne": {
|
||||||
# # moyenne indicative de module: moyenne des UE,
|
# # moyenne indicative de module: moyenne des UE,
|
||||||
# # ignorant celles sans notes (nan)
|
# # ignorant celles sans notes (nan)
|
||||||
@ -242,18 +248,20 @@ class BulletinBUT:
|
|||||||
# "max": fmt_note(moyennes_etuds.max()),
|
# "max": fmt_note(moyennes_etuds.max()),
|
||||||
# "moy": fmt_note(moyennes_etuds.mean()),
|
# "moy": fmt_note(moyennes_etuds.mean()),
|
||||||
},
|
},
|
||||||
"evaluations": [
|
"evaluations": (
|
||||||
self.etud_eval_results(etud, e)
|
[
|
||||||
for e in modimpl.evaluations
|
self.etud_eval_results(etud, e)
|
||||||
if (e.visibulletin or version == "long")
|
for e in modimpl.evaluations
|
||||||
and (e.id in modimpl_results.evaluations_etat)
|
if (e.visibulletin or version == "long")
|
||||||
and (
|
and (e.id in modimpl_results.evaluations_etat)
|
||||||
modimpl_results.evaluations_etat[e.id].is_complete
|
and (
|
||||||
or self.prefs["bul_show_all_evals"]
|
modimpl_results.evaluations_etat[e.id].is_complete
|
||||||
)
|
or self.prefs["bul_show_all_evals"]
|
||||||
]
|
)
|
||||||
if version != "short"
|
]
|
||||||
else [],
|
if version != "short"
|
||||||
|
else []
|
||||||
|
),
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@ -274,9 +282,11 @@ class BulletinBUT:
|
|||||||
poids = collections.defaultdict(lambda: 0.0)
|
poids = collections.defaultdict(lambda: 0.0)
|
||||||
d = {
|
d = {
|
||||||
"id": e.id,
|
"id": e.id,
|
||||||
"coef": fmt_note(e.coefficient)
|
"coef": (
|
||||||
if e.evaluation_type == scu.EVALUATION_NORMALE
|
fmt_note(e.coefficient)
|
||||||
else None,
|
if e.evaluation_type == Evaluation.EVALUATION_NORMALE
|
||||||
|
else None
|
||||||
|
),
|
||||||
"date_debut": e.date_debut.isoformat() if e.date_debut else None,
|
"date_debut": e.date_debut.isoformat() if e.date_debut else None,
|
||||||
"date_fin": e.date_fin.isoformat() if e.date_fin else None,
|
"date_fin": e.date_fin.isoformat() if e.date_fin else None,
|
||||||
"description": e.description,
|
"description": e.description,
|
||||||
@ -291,18 +301,20 @@ class BulletinBUT:
|
|||||||
"moy": fmt_note(notes_ok.mean(), note_max=e.note_max),
|
"moy": fmt_note(notes_ok.mean(), note_max=e.note_max),
|
||||||
},
|
},
|
||||||
"poids": poids,
|
"poids": poids,
|
||||||
"url": url_for(
|
"url": (
|
||||||
"notes.evaluation_listenotes",
|
url_for(
|
||||||
scodoc_dept=g.scodoc_dept,
|
"notes.evaluation_listenotes",
|
||||||
evaluation_id=e.id,
|
scodoc_dept=g.scodoc_dept,
|
||||||
)
|
evaluation_id=e.id,
|
||||||
if has_request_context()
|
)
|
||||||
else "na",
|
if has_request_context()
|
||||||
|
else "na"
|
||||||
|
),
|
||||||
# deprecated (supprimer avant #sco9.7)
|
# deprecated (supprimer avant #sco9.7)
|
||||||
"date": e.date_debut.isoformat() if e.date_debut else None,
|
"date": e.date_debut.isoformat() if e.date_debut else None,
|
||||||
"heure_debut": e.date_debut.time().isoformat("minutes")
|
"heure_debut": (
|
||||||
if e.date_debut
|
e.date_debut.time().isoformat("minutes") if e.date_debut else None
|
||||||
else None,
|
),
|
||||||
"heure_fin": e.date_fin.time().isoformat("minutes") if e.date_fin else None,
|
"heure_fin": e.date_fin.time().isoformat("minutes") if e.date_fin else None,
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
@ -524,9 +536,9 @@ class BulletinBUT:
|
|||||||
|
|
||||||
d.update(infos)
|
d.update(infos)
|
||||||
# --- Rangs
|
# --- Rangs
|
||||||
d[
|
d["rang_nt"] = (
|
||||||
"rang_nt"
|
f"{d['semestre']['rang']['value']} / {d['semestre']['rang']['total']}"
|
||||||
] = f"{d['semestre']['rang']['value']} / {d['semestre']['rang']['total']}"
|
)
|
||||||
d["rang_txt"] = "Rang " + d["rang_nt"]
|
d["rang_txt"] = "Rang " + d["rang_nt"]
|
||||||
|
|
||||||
d.update(sco_bulletins.make_context_dict(self.res.formsemestre, d["etud"]))
|
d.update(sco_bulletins.make_context_dict(self.res.formsemestre, d["etud"]))
|
||||||
|
@ -24,7 +24,7 @@ from reportlab.lib.colors import blue
|
|||||||
from reportlab.lib.units import cm, mm
|
from reportlab.lib.units import cm, mm
|
||||||
from reportlab.platypus import Paragraph, Spacer
|
from reportlab.platypus import Paragraph, Spacer
|
||||||
|
|
||||||
from app.models import ScoDocSiteConfig
|
from app.models import Evaluation, ScoDocSiteConfig
|
||||||
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
|
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
|
||||||
from app.scodoc import gen_tables
|
from app.scodoc import gen_tables
|
||||||
from app.scodoc.codes_cursus import UE_SPORT
|
from app.scodoc.codes_cursus import UE_SPORT
|
||||||
@ -422,7 +422,11 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
|||||||
def evaluations_rows(self, rows, evaluations: list[dict], ue_acros=()):
|
def evaluations_rows(self, rows, evaluations: list[dict], ue_acros=()):
|
||||||
"lignes des évaluations"
|
"lignes des évaluations"
|
||||||
for e in evaluations:
|
for e in evaluations:
|
||||||
coef = e["coef"] if e["evaluation_type"] == scu.EVALUATION_NORMALE else "*"
|
coef = (
|
||||||
|
e["coef"]
|
||||||
|
if e["evaluation_type"] == Evaluation.EVALUATION_NORMALE
|
||||||
|
else "*"
|
||||||
|
)
|
||||||
t = {
|
t = {
|
||||||
"titre": f"{e['description'] or ''}",
|
"titre": f"{e['description'] or ''}",
|
||||||
"moyenne": e["note"]["value"],
|
"moyenne": e["note"]["value"],
|
||||||
@ -431,7 +435,10 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
|||||||
),
|
),
|
||||||
"coef": coef,
|
"coef": coef,
|
||||||
"_coef_pdf": Paragraph(
|
"_coef_pdf": Paragraph(
|
||||||
f"<para align=right fontSize={self.small_fontsize}><i>{coef}</i></para>"
|
f"""<para align=right fontSize={self.small_fontsize}><i>{
|
||||||
|
coef if e["evaluation_type"] != Evaluation.EVALUATION_BONUS
|
||||||
|
else "bonus"
|
||||||
|
}</i></para>"""
|
||||||
),
|
),
|
||||||
"_pdf_style": [
|
"_pdf_style": [
|
||||||
(
|
(
|
||||||
|
@ -157,8 +157,7 @@ class ModuleImplResults:
|
|||||||
|
|
||||||
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
|
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
|
||||||
is_complete = (
|
is_complete = (
|
||||||
(evaluation.evaluation_type == scu.EVALUATION_RATTRAPAGE)
|
(evaluation.evaluation_type != Evaluation.EVALUATION_NORMALE)
|
||||||
or (evaluation.evaluation_type == scu.EVALUATION_SESSION2)
|
|
||||||
or (evaluation.publish_incomplete)
|
or (evaluation.publish_incomplete)
|
||||||
or (not etudids_sans_note)
|
or (not etudids_sans_note)
|
||||||
)
|
)
|
||||||
@ -240,19 +239,20 @@ class ModuleImplResults:
|
|||||||
).formsemestre.inscriptions
|
).formsemestre.inscriptions
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_evaluations_coefs(self, moduleimpl: ModuleImpl) -> np.array:
|
def get_evaluations_coefs(self, modimpl: ModuleImpl) -> np.array:
|
||||||
"""Coefficients des évaluations.
|
"""Coefficients des évaluations.
|
||||||
Les coefs des évals incomplètes et non "normales" (session 2, rattrapage)
|
Les coefs des évals incomplètes, rattrapage, session 2, bonus sont forcés à zéro.
|
||||||
sont zéro.
|
|
||||||
Résultat: 2d-array of floats, shape (nb_evals, 1)
|
Résultat: 2d-array of floats, shape (nb_evals, 1)
|
||||||
"""
|
"""
|
||||||
return (
|
return (
|
||||||
np.array(
|
np.array(
|
||||||
[
|
[
|
||||||
e.coefficient
|
(
|
||||||
if e.evaluation_type == scu.EVALUATION_NORMALE
|
e.coefficient
|
||||||
else 0.0
|
if e.evaluation_type == Evaluation.EVALUATION_NORMALE
|
||||||
for e in moduleimpl.evaluations
|
else 0.0
|
||||||
|
)
|
||||||
|
for e in modimpl.evaluations
|
||||||
],
|
],
|
||||||
dtype=float,
|
dtype=float,
|
||||||
)
|
)
|
||||||
@ -285,7 +285,7 @@ class ModuleImplResults:
|
|||||||
for (etudid, x) in self.evals_notes[evaluation_id].items()
|
for (etudid, x) in self.evals_notes[evaluation_id].items()
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl):
|
def get_evaluation_rattrapage(self, moduleimpl: ModuleImpl) -> Evaluation | None:
|
||||||
"""L'évaluation de rattrapage de ce module, ou None s'il n'en a pas.
|
"""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
|
Rattrapage: la moyenne du module est la meilleure note entre moyenne
|
||||||
des autres évals et la note eval rattrapage.
|
des autres évals et la note eval rattrapage.
|
||||||
@ -293,25 +293,41 @@ class ModuleImplResults:
|
|||||||
eval_list = [
|
eval_list = [
|
||||||
e
|
e
|
||||||
for e in moduleimpl.evaluations
|
for e in moduleimpl.evaluations
|
||||||
if e.evaluation_type == scu.EVALUATION_RATTRAPAGE
|
if e.evaluation_type == Evaluation.EVALUATION_RATTRAPAGE
|
||||||
]
|
]
|
||||||
if eval_list:
|
if eval_list:
|
||||||
return eval_list[0]
|
return eval_list[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_evaluation_session2(self, moduleimpl: ModuleImpl):
|
def get_evaluation_session2(self, moduleimpl: ModuleImpl) -> Evaluation | None:
|
||||||
"""L'évaluation de deuxième session de ce module, ou None s'il n'en a pas.
|
"""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.
|
Session 2: remplace la note de moyenne des autres évals.
|
||||||
"""
|
"""
|
||||||
eval_list = [
|
eval_list = [
|
||||||
e
|
e
|
||||||
for e in moduleimpl.evaluations
|
for e in moduleimpl.evaluations
|
||||||
if e.evaluation_type == scu.EVALUATION_SESSION2
|
if e.evaluation_type == Evaluation.EVALUATION_SESSION2
|
||||||
]
|
]
|
||||||
if eval_list:
|
if eval_list:
|
||||||
return eval_list[0]
|
return eval_list[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_evaluations_bonus(self, modimpl: ModuleImpl) -> list[Evaluation]:
|
||||||
|
"""Les évaluations bonus de ce module, ou liste vide s'il n'en a pas."""
|
||||||
|
return [
|
||||||
|
e
|
||||||
|
for e in modimpl.evaluations
|
||||||
|
if e.evaluation_type == Evaluation.EVALUATION_BONUS
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_evaluations_bonus_idx(self, modimpl: ModuleImpl) -> list[int]:
|
||||||
|
"""Les indices des évaluations bonus"""
|
||||||
|
return [
|
||||||
|
i
|
||||||
|
for (i, e) in enumerate(modimpl.evaluations)
|
||||||
|
if e.evaluation_type == Evaluation.EVALUATION_BONUS
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ModuleImplResultsAPC(ModuleImplResults):
|
class ModuleImplResultsAPC(ModuleImplResults):
|
||||||
"Calcul des moyennes de modules à la mode BUT"
|
"Calcul des moyennes de modules à la mode BUT"
|
||||||
@ -356,7 +372,7 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
# et dans dans evals_poids_etuds
|
# et dans dans evals_poids_etuds
|
||||||
# (rappel: la comparaison est toujours false face à un NaN)
|
# (rappel: la comparaison est toujours false face à un NaN)
|
||||||
# shape: (nb_etuds, nb_evals, nb_ues)
|
# shape: (nb_etuds, nb_evals, nb_ues)
|
||||||
poids_stacked = np.stack([evals_poids] * nb_etuds)
|
poids_stacked = np.stack([evals_poids] * nb_etuds) # nb_etuds, nb_evals, nb_ues
|
||||||
evals_poids_etuds = np.where(
|
evals_poids_etuds = np.where(
|
||||||
np.stack([self.evals_notes.values] * nb_ues, axis=2) > scu.NOTES_NEUTRALISE,
|
np.stack([self.evals_notes.values] * nb_ues, axis=2) > scu.NOTES_NEUTRALISE,
|
||||||
poids_stacked,
|
poids_stacked,
|
||||||
@ -364,10 +380,20 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
)
|
)
|
||||||
# Calcule la moyenne pondérée sur les notes disponibles:
|
# Calcule la moyenne pondérée sur les notes disponibles:
|
||||||
evals_notes_stacked = np.stack([evals_notes_20] * nb_ues, axis=2)
|
evals_notes_stacked = np.stack([evals_notes_20] * nb_ues, axis=2)
|
||||||
|
# evals_notes_stacked shape: nb_etuds, nb_evals, nb_ues
|
||||||
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
||||||
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)
|
||||||
|
# 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)
|
eval_session2 = self.get_evaluation_session2(modimpl)
|
||||||
@ -416,6 +442,30 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
|||||||
)
|
)
|
||||||
return self.etuds_moy_module
|
return self.etuds_moy_module
|
||||||
|
|
||||||
|
def apply_bonus(
|
||||||
|
self,
|
||||||
|
etuds_moy_module: pd.DataFrame,
|
||||||
|
modimpl: ModuleImpl,
|
||||||
|
evals_poids_df: pd.DataFrame,
|
||||||
|
evals_notes_stacked: np.ndarray,
|
||||||
|
):
|
||||||
|
"""Ajoute les points des évaluations bonus.
|
||||||
|
Il peut y avoir un nb quelconque d'évaluations bonus.
|
||||||
|
Les points sont directement ajoutés (ils peuvent être négatifs).
|
||||||
|
"""
|
||||||
|
evals_bonus = self.get_evaluations_bonus(modimpl)
|
||||||
|
if not evals_bonus:
|
||||||
|
return etuds_moy_module
|
||||||
|
poids_stacked = np.stack([evals_poids_df.values] * len(etuds_moy_module))
|
||||||
|
for evaluation in evals_bonus:
|
||||||
|
eval_idx = evals_poids_df.index.get_loc(evaluation.id)
|
||||||
|
etuds_moy_module += (
|
||||||
|
evals_notes_stacked[:, eval_idx, :] * poids_stacked[:, eval_idx, :]
|
||||||
|
)
|
||||||
|
# Clip dans [0,20]
|
||||||
|
etuds_moy_module.clip(0, 20, out=etuds_moy_module)
|
||||||
|
return etuds_moy_module
|
||||||
|
|
||||||
|
|
||||||
def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
|
def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
|
||||||
"""Charge poids des évaluations d'un module et retourne un dataframe
|
"""Charge poids des évaluations d'un module et retourne un dataframe
|
||||||
@ -532,6 +582,13 @@ 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)
|
eval_session2 = self.get_evaluation_session2(modimpl)
|
||||||
if eval_session2:
|
if eval_session2:
|
||||||
@ -571,3 +628,22 @@ class ModuleImplResultsClassic(ModuleImplResults):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return self.etuds_moy_module
|
return self.etuds_moy_module
|
||||||
|
|
||||||
|
def apply_bonus(
|
||||||
|
self,
|
||||||
|
etuds_moy_module: np.ndarray,
|
||||||
|
modimpl: ModuleImpl,
|
||||||
|
evals_notes_20: np.ndarray,
|
||||||
|
):
|
||||||
|
"""Ajoute les points des évaluations bonus.
|
||||||
|
Il peut y avoir un nb quelconque d'évaluations bonus.
|
||||||
|
Les points sont directement ajoutés (ils peuvent être négatifs).
|
||||||
|
"""
|
||||||
|
evals_bonus_idx = self.get_evaluations_bonus_idx(modimpl)
|
||||||
|
if not evals_bonus_idx:
|
||||||
|
return etuds_moy_module
|
||||||
|
for eval_idx in evals_bonus_idx:
|
||||||
|
etuds_moy_module += evals_notes_20[:, eval_idx]
|
||||||
|
# Clip dans [0,20]
|
||||||
|
etuds_moy_module.clip(0, 20, out=etuds_moy_module)
|
||||||
|
return etuds_moy_module
|
||||||
|
@ -23,8 +23,6 @@ MAX_EVALUATION_DURATION = datetime.timedelta(days=365)
|
|||||||
NOON = datetime.time(12, 00)
|
NOON = datetime.time(12, 00)
|
||||||
DEFAULT_EVALUATION_TIME = datetime.time(8, 0)
|
DEFAULT_EVALUATION_TIME = datetime.time(8, 0)
|
||||||
|
|
||||||
VALID_EVALUATION_TYPES = {0, 1, 2}
|
|
||||||
|
|
||||||
|
|
||||||
class Evaluation(db.Model):
|
class Evaluation(db.Model):
|
||||||
"""Evaluation (contrôle, examen, ...)"""
|
"""Evaluation (contrôle, examen, ...)"""
|
||||||
@ -57,6 +55,17 @@ class Evaluation(db.Model):
|
|||||||
numero = db.Column(db.Integer, nullable=False, default=0)
|
numero = db.Column(db.Integer, nullable=False, default=0)
|
||||||
ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
|
ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
|
||||||
|
|
||||||
|
EVALUATION_NORMALE = 0 # valeurs stockées en base, ne pas changer !
|
||||||
|
EVALUATION_RATTRAPAGE = 1
|
||||||
|
EVALUATION_SESSION2 = 2
|
||||||
|
EVALUATION_BONUS = 3
|
||||||
|
VALID_EVALUATION_TYPES = {
|
||||||
|
EVALUATION_NORMALE,
|
||||||
|
EVALUATION_RATTRAPAGE,
|
||||||
|
EVALUATION_SESSION2,
|
||||||
|
EVALUATION_BONUS,
|
||||||
|
}
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"""<Evaluation {self.id} {
|
return f"""<Evaluation {self.id} {
|
||||||
self.date_debut.isoformat() if self.date_debut else ''} "{
|
self.date_debut.isoformat() if self.date_debut else ''} "{
|
||||||
@ -546,7 +555,7 @@ def check_convert_evaluation_args(moduleimpl: "ModuleImpl", data: dict):
|
|||||||
# --- evaluation_type
|
# --- evaluation_type
|
||||||
try:
|
try:
|
||||||
data["evaluation_type"] = int(data.get("evaluation_type", 0) or 0)
|
data["evaluation_type"] = int(data.get("evaluation_type", 0) or 0)
|
||||||
if not data["evaluation_type"] in VALID_EVALUATION_TYPES:
|
if not data["evaluation_type"] in Evaluation.VALID_EVALUATION_TYPES:
|
||||||
raise ScoValueError("invalid evaluation_type value")
|
raise ScoValueError("invalid evaluation_type value")
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
raise ScoValueError("invalid evaluation_type value") from exc
|
raise ScoValueError("invalid evaluation_type value") from exc
|
||||||
|
@ -610,16 +610,19 @@ def _ue_mod_bulletin(
|
|||||||
e_dict["coef_txt"] = ""
|
e_dict["coef_txt"] = ""
|
||||||
else:
|
else:
|
||||||
e_dict["coef_txt"] = scu.fmt_coef(e.coefficient)
|
e_dict["coef_txt"] = scu.fmt_coef(e.coefficient)
|
||||||
if e.evaluation_type == scu.EVALUATION_RATTRAPAGE:
|
if e.evaluation_type == Evaluation.EVALUATION_RATTRAPAGE:
|
||||||
e_dict["coef_txt"] = "rat."
|
e_dict["coef_txt"] = "rat."
|
||||||
elif e.evaluation_type == scu.EVALUATION_SESSION2:
|
elif e.evaluation_type == Evaluation.EVALUATION_SESSION2:
|
||||||
e_dict["coef_txt"] = "Ses. 2"
|
e_dict["coef_txt"] = "Ses. 2"
|
||||||
|
|
||||||
if modimpl_results.evaluations_etat[e.id].nb_attente:
|
if modimpl_results.evaluations_etat[e.id].nb_attente:
|
||||||
mod_attente = True # une eval en attente dans ce module
|
mod_attente = True # une eval en attente dans ce module
|
||||||
|
|
||||||
if ((not is_malus) or (val != "NP")) and (
|
if ((not is_malus) or (val != "NP")) and (
|
||||||
(e.evaluation_type == scu.EVALUATION_NORMALE or not np.isnan(val))
|
(
|
||||||
|
e.evaluation_type == Evaluation.EVALUATION_NORMALE
|
||||||
|
or not np.isnan(val)
|
||||||
|
)
|
||||||
):
|
):
|
||||||
# ne liste pas les eval malus sans notes
|
# ne liste pas les eval malus sans notes
|
||||||
# ni les rattrapages et sessions 2 si pas de note
|
# ni les rattrapages et sessions 2 si pas de note
|
||||||
|
@ -51,7 +51,7 @@ from reportlab.lib.colors import Color, blue
|
|||||||
from reportlab.lib.units import cm, mm
|
from reportlab.lib.units import cm, mm
|
||||||
from reportlab.platypus import KeepTogether, Paragraph, Spacer, Table
|
from reportlab.platypus import KeepTogether, Paragraph, Spacer, Table
|
||||||
|
|
||||||
from app.models import BulAppreciations
|
from app.models import BulAppreciations, Evaluation
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import (
|
from app.scodoc import (
|
||||||
gen_tables,
|
gen_tables,
|
||||||
@ -715,9 +715,15 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
|||||||
eval_style = ""
|
eval_style = ""
|
||||||
t = {
|
t = {
|
||||||
"module": '<bullet indent="2mm">•</bullet> ' + e["name"],
|
"module": '<bullet indent="2mm">•</bullet> ' + e["name"],
|
||||||
"coef": ("<i>" + e["coef_txt"] + "</i>")
|
"coef": (
|
||||||
if prefs["bul_show_coef"]
|
(
|
||||||
else "",
|
f"<i>{e['coef_txt']}</i>"
|
||||||
|
if e["evaluation_type"] != Evaluation.EVALUATION_BONUS
|
||||||
|
else "bonus"
|
||||||
|
)
|
||||||
|
if prefs["bul_show_coef"]
|
||||||
|
else ""
|
||||||
|
),
|
||||||
"_hidden": hidden,
|
"_hidden": hidden,
|
||||||
"_module_target": e["target_html"],
|
"_module_target": e["target_html"],
|
||||||
# '_module_help' : ,
|
# '_module_help' : ,
|
||||||
|
@ -183,7 +183,8 @@ def evaluation_create_form(
|
|||||||
{
|
{
|
||||||
"size": 6,
|
"size": 6,
|
||||||
"type": "float", # peut être négatif (!)
|
"type": "float", # peut être négatif (!)
|
||||||
"explanation": "coef. dans le module (choisi librement par l'enseignant, non utilisé pour rattrapage et 2ème session)",
|
"explanation": """coef. dans le module (choisi librement par
|
||||||
|
l'enseignant, non utilisé pour rattrapage, 2ème session et bonus)""",
|
||||||
"allow_null": False,
|
"allow_null": False,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -195,7 +196,7 @@ def evaluation_create_form(
|
|||||||
"size": 4,
|
"size": 4,
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"title": "Notes de 0 à",
|
"title": "Notes de 0 à",
|
||||||
"explanation": f"barème (note max actuelle: {min_note_max_str})",
|
"explanation": f"""barème (note max actuelle: {min_note_max_str}).""",
|
||||||
"allow_null": False,
|
"allow_null": False,
|
||||||
"max_value": scu.NOTES_MAX,
|
"max_value": scu.NOTES_MAX,
|
||||||
"min_value": min_note_max,
|
"min_value": min_note_max,
|
||||||
@ -206,7 +207,8 @@ def evaluation_create_form(
|
|||||||
{
|
{
|
||||||
"size": 36,
|
"size": 36,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"explanation": """type d'évaluation, apparait sur le bulletins longs. Exemples: "contrôle court", "examen de TP", "examen final".""",
|
"explanation": """type d'évaluation, apparait sur le bulletins longs.
|
||||||
|
Exemples: "contrôle court", "examen de TP", "examen final".""",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -230,16 +232,20 @@ def evaluation_create_form(
|
|||||||
{
|
{
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"title": "Modalité",
|
"title": "Modalité",
|
||||||
"allowed_values": (
|
"allowed_values": Evaluation.VALID_EVALUATION_TYPES,
|
||||||
scu.EVALUATION_NORMALE,
|
|
||||||
scu.EVALUATION_RATTRAPAGE,
|
|
||||||
scu.EVALUATION_SESSION2,
|
|
||||||
),
|
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"labels": (
|
"labels": (
|
||||||
"Normale",
|
"Normale",
|
||||||
"Rattrapage (remplace si meilleure note)",
|
"Rattrapage (remplace si meilleure note)",
|
||||||
"Deuxième session (remplace toujours)",
|
"Deuxième session (remplace toujours)",
|
||||||
|
(
|
||||||
|
"Bonus "
|
||||||
|
+ (
|
||||||
|
"(pondéré par poids et ajouté aux moyennes de ce module)"
|
||||||
|
if is_apc
|
||||||
|
else "(ajouté à la moyenne de ce module)"
|
||||||
|
)
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -251,7 +257,8 @@ def evaluation_create_form(
|
|||||||
{
|
{
|
||||||
"size": 6,
|
"size": 6,
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"explanation": "importance de l'évaluation (multiplie les poids ci-dessous)",
|
"explanation": """importance de l'évaluation (multiplie les poids ci-dessous).
|
||||||
|
Non utilisé pour les bonus.""",
|
||||||
"allow_null": False,
|
"allow_null": False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -217,19 +217,9 @@ def do_evaluation_etat(
|
|||||||
|
|
||||||
gr_incomplets = list(group_nb_missing.keys())
|
gr_incomplets = list(group_nb_missing.keys())
|
||||||
gr_incomplets.sort()
|
gr_incomplets.sort()
|
||||||
if (
|
|
||||||
(total_nb_missing > 0)
|
|
||||||
and (E["evaluation_type"] != scu.EVALUATION_RATTRAPAGE)
|
|
||||||
and (E["evaluation_type"] != scu.EVALUATION_SESSION2)
|
|
||||||
):
|
|
||||||
complete = False
|
|
||||||
else:
|
|
||||||
complete = True
|
|
||||||
|
|
||||||
complete = (
|
complete = (total_nb_missing == 0) or (
|
||||||
(total_nb_missing == 0)
|
E["evaluation_type"] != Evaluation.EVALUATION_NORMALE
|
||||||
or (E["evaluation_type"] == scu.EVALUATION_RATTRAPAGE)
|
|
||||||
or (E["evaluation_type"] == scu.EVALUATION_SESSION2)
|
|
||||||
)
|
)
|
||||||
evalattente = (total_nb_missing > 0) and (
|
evalattente = (total_nb_missing > 0) and (
|
||||||
(total_nb_missing == total_nb_att) or E["publish_incomplete"]
|
(total_nb_missing == total_nb_att) or E["publish_incomplete"]
|
||||||
@ -498,13 +488,14 @@ def formsemestre_evaluations_delai_correction(formsemestre_id, fmt="html"):
|
|||||||
"""Experimental: un tableau indiquant pour chaque évaluation
|
"""Experimental: un tableau indiquant pour chaque évaluation
|
||||||
le nombre de jours avant la publication des notes.
|
le nombre de jours avant la publication des notes.
|
||||||
|
|
||||||
N'indique pas les évaluations de rattrapage ni celles des modules de bonus/malus.
|
N'indique que les évaluations "normales" (pas rattrapage, ni bonus, ni session2,
|
||||||
|
ni celles des modules de bonus/malus).
|
||||||
"""
|
"""
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
evaluations = formsemestre.get_evaluations()
|
evaluations = formsemestre.get_evaluations()
|
||||||
rows = []
|
rows = []
|
||||||
for e in evaluations:
|
for e in evaluations:
|
||||||
if (e.evaluation_type != scu.EVALUATION_NORMALE) or (
|
if (e.evaluation_type != Evaluation.EVALUATION_NORMALE) or (
|
||||||
e.moduleimpl.module.module_type == ModuleType.MALUS
|
e.moduleimpl.module.module_type == ModuleType.MALUS
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
@ -610,13 +601,17 @@ def evaluation_describe(evaluation_id="", edit_in_place=True, link_saisie=True)
|
|||||||
# Indique l'UE
|
# Indique l'UE
|
||||||
ue = modimpl.module.ue
|
ue = modimpl.module.ue
|
||||||
H.append(f"<p><b>UE : {ue.acronyme}</b></p>")
|
H.append(f"<p><b>UE : {ue.acronyme}</b></p>")
|
||||||
|
if (
|
||||||
|
modimpl.module.module_type == ModuleType.MALUS
|
||||||
|
or evaluation.evaluation_type == Evaluation.EVALUATION_BONUS
|
||||||
|
):
|
||||||
# store min/max values used by JS client-side checks:
|
# store min/max values used by JS client-side checks:
|
||||||
H.append(
|
H.append(
|
||||||
"""<span id="eval_note_min" class="sco-hidden">-20.</span>
|
"""<span id="eval_note_min" class="sco-hidden">-20.</span>
|
||||||
<span id="eval_note_max" class="sco-hidden">20.</span>"""
|
<span id="eval_note_max" class="sco-hidden">20.</span>"""
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# date et absences (pas pour evals de malus)
|
# date et absences (pas pour evals bonus ni des modules de malus)
|
||||||
if evaluation.date_debut is not None:
|
if evaluation.date_debut is not None:
|
||||||
H.append(f"<p>Réalisée le <b>{evaluation.descr_date()}</b> ")
|
H.append(f"<p>Réalisée le <b>{evaluation.descr_date()}</b> ")
|
||||||
group_id = sco_groups.get_default_group(modimpl.formsemestre_id)
|
group_id = sco_groups.get_default_group(modimpl.formsemestre_id)
|
||||||
|
@ -490,9 +490,9 @@ def _make_table_notes(
|
|||||||
rlinks = {"_table_part": "head"}
|
rlinks = {"_table_part": "head"}
|
||||||
for e in evaluations:
|
for e in evaluations:
|
||||||
rlinks[e.id] = "afficher"
|
rlinks[e.id] = "afficher"
|
||||||
rlinks[
|
rlinks["_" + str(e.id) + "_help"] = (
|
||||||
"_" + str(e.id) + "_help"
|
"afficher seulement les notes de cette évaluation"
|
||||||
] = "afficher seulement les notes de cette évaluation"
|
)
|
||||||
rlinks["_" + str(e.id) + "_target"] = url_for(
|
rlinks["_" + str(e.id) + "_target"] = url_for(
|
||||||
"notes.evaluation_listenotes",
|
"notes.evaluation_listenotes",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
@ -709,9 +709,9 @@ def _add_eval_columns(
|
|||||||
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:
|
||||||
titles[
|
titles[evaluation.id] = (
|
||||||
evaluation.id
|
f"{evaluation.description} ({evaluation.date_debut.strftime('%d/%m/%Y')})"
|
||||||
] = f"{evaluation.description} ({evaluation.date_debut.strftime('%d/%m/%Y')})"
|
)
|
||||||
else:
|
else:
|
||||||
titles[evaluation.id] = f"{evaluation.description} "
|
titles[evaluation.id] = f"{evaluation.description} "
|
||||||
|
|
||||||
@ -820,14 +820,17 @@ def _add_eval_columns(
|
|||||||
row_moys[evaluation.id] = scu.fmt_note(
|
row_moys[evaluation.id] = scu.fmt_note(
|
||||||
sum_notes / nb_notes, keep_numeric=keep_numeric
|
sum_notes / nb_notes, keep_numeric=keep_numeric
|
||||||
)
|
)
|
||||||
row_moys[
|
row_moys["_" + str(evaluation.id) + "_help"] = (
|
||||||
"_" + str(evaluation.id) + "_help"
|
"moyenne sur %d notes (%s le %s)"
|
||||||
] = "moyenne sur %d notes (%s le %s)" % (
|
% (
|
||||||
nb_notes,
|
nb_notes,
|
||||||
evaluation.description,
|
evaluation.description,
|
||||||
evaluation.date_debut.strftime("%d/%m/%Y")
|
(
|
||||||
if evaluation.date_debut
|
evaluation.date_debut.strftime("%d/%m/%Y")
|
||||||
else "",
|
if evaluation.date_debut
|
||||||
|
else ""
|
||||||
|
),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
row_moys[evaluation.id] = ""
|
row_moys[evaluation.id] = ""
|
||||||
@ -884,8 +887,9 @@ def _add_moymod_column(
|
|||||||
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 inscrits and not isinstance(val, str):
|
||||||
notes.append(val)
|
notes.append(val)
|
||||||
nb_notes = nb_notes + 1
|
if not np.isnan(val):
|
||||||
sum_notes += val
|
nb_notes = nb_notes + 1
|
||||||
|
sum_notes += val
|
||||||
row_coefs[col_id] = "(avec abs)"
|
row_coefs[col_id] = "(avec abs)"
|
||||||
if is_apc:
|
if is_apc:
|
||||||
row_poids[col_id] = "à titre indicatif"
|
row_poids[col_id] = "à titre indicatif"
|
||||||
|
@ -519,13 +519,15 @@ def _ligne_evaluation(
|
|||||||
partition_id=partition_id,
|
partition_id=partition_id,
|
||||||
select_first_partition=True,
|
select_first_partition=True,
|
||||||
)
|
)
|
||||||
if evaluation.evaluation_type in (
|
if evaluation.evaluation_type == Evaluation.EVALUATION_RATTRAPAGE:
|
||||||
scu.EVALUATION_RATTRAPAGE,
|
|
||||||
scu.EVALUATION_SESSION2,
|
|
||||||
):
|
|
||||||
tr_class = "mievr mievr_rattr"
|
tr_class = "mievr mievr_rattr"
|
||||||
|
elif evaluation.evaluation_type == Evaluation.EVALUATION_SESSION2:
|
||||||
|
tr_class = "mievr mievr_session2"
|
||||||
|
elif evaluation.evaluation_type == Evaluation.EVALUATION_BONUS:
|
||||||
|
tr_class = "mievr mievr_bonus"
|
||||||
else:
|
else:
|
||||||
tr_class = "mievr"
|
tr_class = "mievr"
|
||||||
|
|
||||||
if not evaluation.visibulletin:
|
if not evaluation.visibulletin:
|
||||||
tr_class += " non_visible_inter"
|
tr_class += " non_visible_inter"
|
||||||
tr_class_1 = "mievr"
|
tr_class_1 = "mievr"
|
||||||
@ -563,13 +565,17 @@ def _ligne_evaluation(
|
|||||||
}" class="mievr_evalnodate">Évaluation sans date</a>"""
|
}" class="mievr_evalnodate">Évaluation sans date</a>"""
|
||||||
)
|
)
|
||||||
H.append(f" <em>{evaluation.description or ''}</em>")
|
H.append(f" <em>{evaluation.description or ''}</em>")
|
||||||
if evaluation.evaluation_type == scu.EVALUATION_RATTRAPAGE:
|
if evaluation.evaluation_type == Evaluation.EVALUATION_RATTRAPAGE:
|
||||||
H.append(
|
H.append(
|
||||||
"""<span class="mievr_rattr" title="remplace si meilleure note">rattrapage</span>"""
|
"""<span class="mievr_rattr" title="remplace si meilleure note">rattrapage</span>"""
|
||||||
)
|
)
|
||||||
elif evaluation.evaluation_type == scu.EVALUATION_SESSION2:
|
elif evaluation.evaluation_type == Evaluation.EVALUATION_SESSION2:
|
||||||
H.append(
|
H.append(
|
||||||
"""<span class="mievr_rattr" title="remplace autres notes">session 2</span>"""
|
"""<span class="mievr_session2" title="remplace autres notes">session 2</span>"""
|
||||||
|
)
|
||||||
|
elif evaluation.evaluation_type == Evaluation.EVALUATION_BONUS:
|
||||||
|
H.append(
|
||||||
|
"""<span class="mievr_bonus" title="s'ajoute aux moyennes de ce module">bonus</span>"""
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
if etat["last_modif"]:
|
if etat["last_modif"]:
|
||||||
|
@ -134,12 +134,12 @@ def _displayNote(val):
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
def _check_notes(notes: list[(int, float)], evaluation: Evaluation):
|
def _check_notes(notes: list[(int, float | str)], evaluation: Evaluation):
|
||||||
# XXX typehint : float or str
|
|
||||||
"""notes is a list of tuples (etudid, value)
|
"""notes is a list of tuples (etudid, value)
|
||||||
mod is the module (used to ckeck type, for malus)
|
mod is the module (used to ckeck type, for malus)
|
||||||
returns list of valid notes (etudid, float value)
|
returns list of valid notes (etudid, float value)
|
||||||
and 4 lists of etudid: etudids_invalids, etudids_without_notes, etudids_absents, etudid_to_suppress
|
and 4 lists of etudid:
|
||||||
|
etudids_invalids, etudids_without_notes, etudids_absents, etudid_to_suppress
|
||||||
"""
|
"""
|
||||||
note_max = evaluation.note_max or 0.0
|
note_max = evaluation.note_max or 0.0
|
||||||
module: Module = evaluation.moduleimpl.module
|
module: Module = evaluation.moduleimpl.module
|
||||||
@ -148,7 +148,10 @@ def _check_notes(notes: list[(int, float)], evaluation: Evaluation):
|
|||||||
scu.ModuleType.RESSOURCE,
|
scu.ModuleType.RESSOURCE,
|
||||||
scu.ModuleType.SAE,
|
scu.ModuleType.SAE,
|
||||||
):
|
):
|
||||||
note_min = scu.NOTES_MIN
|
if evaluation.evaluation_type == Evaluation.EVALUATION_BONUS:
|
||||||
|
note_min, note_max = -20, 20
|
||||||
|
else:
|
||||||
|
note_min = scu.NOTES_MIN
|
||||||
elif module.module_type == ModuleType.MALUS:
|
elif module.module_type == ModuleType.MALUS:
|
||||||
note_min = -20.0
|
note_min = -20.0
|
||||||
else:
|
else:
|
||||||
|
@ -175,7 +175,7 @@ def external_ue_inscrit_et_note(
|
|||||||
note_max=20.0,
|
note_max=20.0,
|
||||||
coefficient=1.0,
|
coefficient=1.0,
|
||||||
publish_incomplete=True,
|
publish_incomplete=True,
|
||||||
evaluation_type=scu.EVALUATION_NORMALE,
|
evaluation_type=Evaluation.EVALUATION_NORMALE,
|
||||||
visibulletin=False,
|
visibulletin=False,
|
||||||
description="note externe",
|
description="note externe",
|
||||||
)
|
)
|
||||||
|
@ -454,10 +454,6 @@ NOTES_MENTIONS_LABS = (
|
|||||||
"Excellent",
|
"Excellent",
|
||||||
)
|
)
|
||||||
|
|
||||||
EVALUATION_NORMALE = 0
|
|
||||||
EVALUATION_RATTRAPAGE = 1
|
|
||||||
EVALUATION_SESSION2 = 2
|
|
||||||
|
|
||||||
# Dates et années scolaires
|
# Dates et années scolaires
|
||||||
# Ces dates "pivot" sont paramétrables dans les préférences générales
|
# Ces dates "pivot" sont paramétrables dans les préférences générales
|
||||||
# on donne ici les valeurs par défaut.
|
# on donne ici les valeurs par défaut.
|
||||||
|
@ -273,6 +273,10 @@ section>div:nth-child(1) {
|
|||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
div.eval-bonus {
|
||||||
|
color: #197614;
|
||||||
|
background-color: pink;
|
||||||
|
}
|
||||||
|
|
||||||
.ueBonus,
|
.ueBonus,
|
||||||
.ueBonus h3 {
|
.ueBonus h3 {
|
||||||
@ -280,7 +284,7 @@ section>div:nth-child(1) {
|
|||||||
color: #000 !important;
|
color: #000 !important;
|
||||||
}
|
}
|
||||||
/* UE Capitalisée */
|
/* UE Capitalisée */
|
||||||
.synthese .ue.capitalisee,
|
.synthese .ue.capitalisee,
|
||||||
.ue.capitalisee>h3{
|
.ue.capitalisee>h3{
|
||||||
background: var(--couleurFondTitresUECapitalisee);;
|
background: var(--couleurFondTitresUECapitalisee);;
|
||||||
}
|
}
|
||||||
|
@ -2103,11 +2103,11 @@ tr.mievr {
|
|||||||
background-color: #eeeeee;
|
background-color: #eeeeee;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.mievr_rattr {
|
tr.mievr_rattr, tr.mievr_session2, tr.mievr_bonus {
|
||||||
background-color: #dddddd;
|
background-color: #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.mievr_rattr {
|
span.mievr_rattr, span.mievr_session2, span.mievr_bonus {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
@ -4743,6 +4743,10 @@ table.table_recap th.col_malus {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: rgb(165, 0, 0);
|
color: rgb(165, 0, 0);
|
||||||
}
|
}
|
||||||
|
table.table_recap td.col_eval_bonus,
|
||||||
|
table.table_recap th.col_eval_bonus {
|
||||||
|
color: #90c;
|
||||||
|
}
|
||||||
|
|
||||||
table.table_recap tr.ects td {
|
table.table_recap tr.ects td {
|
||||||
color: rgb(160, 86, 3);
|
color: rgb(160, 86, 3);
|
||||||
|
@ -491,14 +491,15 @@ class releveBUT extends HTMLElement {
|
|||||||
let output = "";
|
let output = "";
|
||||||
evaluations.forEach((evaluation) => {
|
evaluations.forEach((evaluation) => {
|
||||||
output += `
|
output += `
|
||||||
<div class=eval>
|
<div class="eval ${evaluation.evaluation_type == 3 ? "eval-bonus" : ""}">
|
||||||
<div>${this.URL(evaluation.url, evaluation.description || "Évaluation")}</div>
|
<div>${this.URL(evaluation.url, evaluation.description || "Évaluation")}</div>
|
||||||
<div>
|
<div>
|
||||||
${evaluation.note.value}
|
${evaluation.note.value}
|
||||||
<em>Coef. ${evaluation.coef ?? "*"}</em>
|
<em>${evaluation.evaluation_type == 0 ? "Coef." : evaluation.evaluation_type == 3 ? "Bonus" : ""
|
||||||
|
} ${evaluation.coef ?? ""}</em>
|
||||||
</div>
|
</div>
|
||||||
<div class=complement>
|
<div class=complement>
|
||||||
<div>Coef</div><div>${evaluation.coef}</div>
|
<div>${evaluation.evaluation_type == 0 ? "Coef." : ""}</div><div>${evaluation.coef ?? ""}</div>
|
||||||
<div>Max. promo.</div><div>${evaluation.note.max}</div>
|
<div>Max. promo.</div><div>${evaluation.note.max}</div>
|
||||||
<div>Moy. promo.</div><div>${evaluation.note.moy}</div>
|
<div>Moy. promo.</div><div>${evaluation.note.moy}</div>
|
||||||
<div>Min. promo.</div><div>${evaluation.note.min}</div>
|
<div>Min. promo.</div><div>${evaluation.note.min}</div>
|
||||||
|
@ -13,7 +13,7 @@ import numpy as np
|
|||||||
from app import db
|
from app import db
|
||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
from app.comp.res_common import ResultatsSemestre
|
from app.comp.res_common import ResultatsSemestre
|
||||||
from app.models import Identite, FormSemestre, UniteEns
|
from app.models import Identite, Evaluation, FormSemestre, UniteEns
|
||||||
from app.scodoc.codes_cursus import UE_SPORT, DEF
|
from app.scodoc.codes_cursus import UE_SPORT, DEF
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
@ -405,15 +405,22 @@ class TableRecap(tb.Table):
|
|||||||
val = notes_db[etudid]["value"]
|
val = notes_db[etudid]["value"]
|
||||||
else:
|
else:
|
||||||
# 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
|
||||||
|
if e.evaluation_type != Evaluation.EVALUATION_BONUS
|
||||||
|
else ""
|
||||||
|
)
|
||||||
content = self.fmt_note(val)
|
content = self.fmt_note(val)
|
||||||
classes = col_classes + [
|
if e.evaluation_type != Evaluation.EVALUATION_BONUS:
|
||||||
{
|
classes = col_classes + [
|
||||||
"ABS": "abs",
|
{
|
||||||
"ATT": "att",
|
"ABS": "abs",
|
||||||
"EXC": "exc",
|
"ATT": "att",
|
||||||
}.get(content, "")
|
"EXC": "exc",
|
||||||
]
|
}.get(content, "")
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
classes = col_classes + ["col_eval_bonus"]
|
||||||
row.add_cell(
|
row.add_cell(
|
||||||
col_id, title, content, group="eval", classes=classes
|
col_id, title, content, group="eval", classes=classes
|
||||||
)
|
)
|
||||||
|
@ -8,13 +8,15 @@
|
|||||||
</p>
|
</p>
|
||||||
{%if is_apc%}
|
{%if is_apc%}
|
||||||
<p class="help help_but">
|
<p class="help help_but">
|
||||||
Dans le BUT, une évaluation peut évaluer différents apprentissages critiques... (à compléter)
|
Dans le BUT, une évaluation peut évaluer différents apprentissages critiques,
|
||||||
Le coefficient est multiplié par les poids vers chaque UE.
|
et les poids permettent de moduler l'importance de l'évaluation pour
|
||||||
|
chaque compétence (UE).
|
||||||
|
Le coefficient de l'évaluation est multiplié par les poids vers chaque UE.
|
||||||
</p>
|
</p>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
<p class="help">
|
<p class="help">
|
||||||
Ne pas confondre ce coefficient avec le coefficient du module, qui est
|
Ne pas confondre ce coefficient avec le coefficient du module, qui est
|
||||||
lui fixé par le programme pédagogique (le PPN pour les DUT) et pondère
|
lui fixé par le programme pédagogique (le PN pour les BUT) et pondère
|
||||||
les moyennes de chaque module pour obtenir les moyennes d'UE et la
|
les moyennes de chaque module pour obtenir les moyennes d'UE et la
|
||||||
moyenne générale.
|
moyenne générale.
|
||||||
</p>
|
</p>
|
||||||
@ -22,17 +24,31 @@
|
|||||||
L'option <em>Visible sur bulletins</em> indique que la note sera
|
L'option <em>Visible sur bulletins</em> indique que la note sera
|
||||||
reportée sur les bulletins en version dite "intermédiaire" (dans cette
|
reportée sur les bulletins en version dite "intermédiaire" (dans cette
|
||||||
version, on peut ne faire apparaitre que certaines notes, en sus des
|
version, on peut ne faire apparaitre que certaines notes, en sus des
|
||||||
moyennes de modules. Attention, cette option n'empêche pas la
|
moyennes de modules). Attention, cette option n'empêche pas la
|
||||||
publication sur les bulletins en version "longue" (la note est donc
|
publication sur les bulletins en version "longue" (la note est donc
|
||||||
visible par les étudiants sur le portail).
|
visible par les étudiants sur le portail).
|
||||||
</p>
|
</p>
|
||||||
|
<p class="help">
|
||||||
|
Les évaluations bonus sont particulières:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>la valeur est ajoutée à la moyenne du module;</li>
|
||||||
|
<li>le bonus peut être négatif (malus);
|
||||||
|
</li>
|
||||||
|
<li>le bonus ne s'applique pas aux notes de rattrapage et deuxième session;
|
||||||
|
</li>
|
||||||
|
<li>le coefficient est ignoré, mais en BUT le bonus vers une UE est multiplié
|
||||||
|
par le poids correspondant (par défaut égal à 1);
|
||||||
|
</li>
|
||||||
|
<li>les notes de bonus sont prises en compte même si incomplètes.</li>
|
||||||
|
</ul>
|
||||||
<p class="help">
|
<p class="help">
|
||||||
Les modalités "rattrapage" et "deuxième session" définissent des
|
Les modalités "rattrapage" et "deuxième session" définissent des
|
||||||
évaluations prises en compte de façon spéciale:
|
évaluations prises en compte de façon spéciale:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>les notes d'une évaluation de "rattrapage" remplaceront les moyennes
|
<li>les notes d'une évaluation de "rattrapage" remplaceront les moyennes
|
||||||
du module <em>si elles sont meilleures que celles calculées</em>.
|
du module <em>si elles sont meilleures que celles calculées;</em>.
|
||||||
</li>
|
</li>
|
||||||
<li>les notes de "deuxième session" remplacent, lorsqu'elles sont
|
<li>les notes de "deuxième session" remplacent, lorsqu'elles sont
|
||||||
saisies, la moyenne de l'étudiant à ce module, même si la note de
|
saisies, la moyenne de l'étudiant à ce module, même si la note de
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.6.944"
|
SCOVERSION = "9.6.945"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
SCONEWS = """
|
SCONEWS = """
|
||||||
<h4>Année 2023</h4>
|
<h4>Année 2023-2024</h4>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li>ScoDoc 9.6 (juillet 2023)</li>
|
<li>ScoDoc 9.6 (2023-2024)</li>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Nouveaux bulletins BUT compacts</li>
|
<li>Nouveaux bulletins BUT compacts</li>
|
||||||
<li>Nouvelle gestion des absences et assiduité</li>
|
<li>Nouvelle gestion des absences et assiduité</li>
|
||||||
<li>Mise à jour logiciels: Debian 12, Python 3.11, ...</li>
|
<li>Mise à jour logiciels: Debian 12, Python 3.11, ...</li>
|
||||||
|
<li>Evaluations bonus</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<li>ScoDoc 9.5 (juillet 2023)</li>
|
<li>ScoDoc 9.5 (juillet 2023)</li>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Test calculs rattrapages
|
"""Test calculs rattrapages
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import app
|
import app
|
||||||
@ -68,7 +69,7 @@ def test_notes_rattrapage(test_client):
|
|||||||
date_debut=datetime.datetime(2020, 1, 2),
|
date_debut=datetime.datetime(2020, 1, 2),
|
||||||
description="evaluation rattrapage",
|
description="evaluation rattrapage",
|
||||||
coefficient=1.0,
|
coefficient=1.0,
|
||||||
evaluation_type=scu.EVALUATION_RATTRAPAGE,
|
evaluation_type=Evaluation.EVALUATION_RATTRAPAGE,
|
||||||
)
|
)
|
||||||
etud = etuds[0]
|
etud = etuds[0]
|
||||||
_, _, _ = G.create_note(evaluation_id=e["id"], etudid=etud["etudid"], note=12.0)
|
_, _, _ = G.create_note(evaluation_id=e["id"], etudid=etud["etudid"], note=12.0)
|
||||||
@ -144,7 +145,7 @@ def test_notes_rattrapage(test_client):
|
|||||||
date_debut=datetime.datetime(2020, 1, 2),
|
date_debut=datetime.datetime(2020, 1, 2),
|
||||||
description="evaluation session 2",
|
description="evaluation session 2",
|
||||||
coefficient=1.0,
|
coefficient=1.0,
|
||||||
evaluation_type=scu.EVALUATION_SESSION2,
|
evaluation_type=Evaluation.EVALUATION_SESSION2,
|
||||||
)
|
)
|
||||||
|
|
||||||
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
|
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
Loading…
Reference in New Issue
Block a user