diff --git a/app/comp/res_but.py b/app/comp/res_but.py
index 116ec09b4..d7fec7863 100644
--- a/app/comp/res_but.py
+++ b/app/comp/res_but.py
@@ -32,7 +32,7 @@ class ResultatsSemestreBUT(NotesTableCompat):
def __init__(self, formsemestre):
super().__init__(formsemestre)
- """DataFrame, row UEs(sans bonus), cols modimplid, value coef"""
+
self.sem_cube = None
"""ndarray (etuds x modimpl x ue)"""
@@ -43,7 +43,8 @@ class ResultatsSemestreBUT(NotesTableCompat):
self.store()
t2 = time.time()
log(
- f"ResultatsSemestreBUT: cached formsemestre_id={formsemestre.id} ({(t1-t0):g}s +{(t2-t1):g}s)"
+ f"""ResultatsSemestreBUT: cached formsemestre_id={formsemestre.id
+ } ({(t1-t0):g}s +{(t2-t1):g}s)"""
)
def compute(self):
diff --git a/app/comp/res_classic.py b/app/comp/res_classic.py
index 605ba64c3..5577546b7 100644
--- a/app/comp/res_classic.py
+++ b/app/comp/res_classic.py
@@ -50,7 +50,8 @@ class ResultatsSemestreClassic(NotesTableCompat):
self.store()
t2 = time.time()
log(
- f"ResultatsSemestreClassic: cached formsemestre_id={formsemestre.id} ({(t1-t0):g}s +{(t2-t1):g}s)"
+ f"""ResultatsSemestreClassic: cached formsemestre_id={
+ formsemestre.id} ({(t1-t0):g}s +{(t2-t1):g}s)"""
)
# recalculé (aussi rapide que de les cacher)
self.moy_min = self.etud_moy_gen.min()
@@ -220,36 +221,29 @@ class ResultatsSemestreClassic(NotesTableCompat):
moyenne générale.
Coef = somme des coefs des modules de l'UE auxquels il est inscrit
"""
- c = comp_etud_sum_coef_modules_ue(self.formsemestre.id, etudid, ue["ue_id"])
- if c is not None: # inscrit à au moins un module de cette UE
- return c
+ coef = comp_etud_sum_coef_modules_ue(self.formsemestre.id, etudid, ue["ue_id"])
+ if coef is not None: # inscrit à au moins un module de cette UE
+ return coef
# arfff: aucun moyen de déterminer le coefficient de façon sûre
log(
- "* oups: calcul coef UE impossible\nformsemestre_id='%s'\netudid='%s'\nue=%s"
- % (self.formsemestre.id, etudid, ue)
+ f"""* oups: calcul coef UE impossible\nformsemestre_id='{self.formsemestre.id
+ }'\netudid='{etudid}'\nue={ue}"""
)
etud: Identite = Identite.query.get(etudid)
raise ScoValueError(
- """
Coefficient de l'UE capitalisée %s impossible à déterminer
- pour l'étudiant %s
-
Il faut saisir le coefficient de cette UE avant de continuer
+ f"""
"""
- % (
- ue.acronyme,
- url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid),
- etud.nom_disp(),
- url_for(
- "notes.formsemestre_edit_uecoefs",
- scodoc_dept=g.scodoc_dept,
- formsemestre_id=self.formsemestre.id,
- err_ue_id=ue["ue_id"],
- ),
- )
)
- return 0.0 # ?
-
def notes_sem_load_matrix(formsemestre: FormSemestre) -> tuple[np.ndarray, dict]:
"""Calcule la matrice des notes du semestre
@@ -279,7 +273,7 @@ def notes_sem_assemble_matrix(modimpls_notes: list[pd.Series]) -> np.ndarray:
(Series rendus par compute_module_moy, index: etud)
Resultat: ndarray (etud x module)
"""
- if not len(modimpls_notes):
+ if not modimpls_notes:
return np.zeros((0, 0), dtype=float)
modimpls_notes_arr = [s.values for s in modimpls_notes]
modimpls_notes = np.stack(modimpls_notes_arr)
diff --git a/app/comp/res_common.py b/app/comp/res_common.py
index 30468da3d..519e9aec3 100644
--- a/app/comp/res_common.py
+++ b/app/comp/res_common.py
@@ -4,6 +4,9 @@
# See LICENSE
##############################################################################
+"""Résultats semestre: méthodes communes aux formations classiques et APC
+"""
+
from collections import Counter
from functools import cached_property
import numpy as np
@@ -25,7 +28,6 @@ from app.scodoc import sco_groups
from app.scodoc import sco_users
from app.scodoc import sco_utils as scu
-
# Il faut bien distinguer
# - ce qui est caché de façon persistente (via redis):
# ce sont les attributs listés dans `_cached_attrs`
@@ -41,6 +43,8 @@ class ResultatsSemestre(ResultatsCache):
"""
_cached_attrs = (
+ "bonus",
+ "bonus_ues",
"etud_moy_gen_ranks",
"etud_moy_gen",
"etud_moy_ue",
@@ -55,6 +59,10 @@ class ResultatsSemestre(ResultatsCache):
# BUT ou standard ? (apc == "approche par compétences")
self.is_apc = formsemestre.formation.is_apc()
# Attributs "virtuels", définis dans les sous-classes
+ self.bonus: pd.Series = None # virtuel
+ "Bonus sur moy. gen. Series de float, index etudid"
+ self.bonus_ues: pd.DataFrame = None # virtuel
+ "DataFrame de float, index etudid, columns: ue.id"
# ResultatsSemestreBUT ou ResultatsSemestreClassic
self.etud_moy_ue = {}
"etud_moy_ue: DataFrame columns UE, rows etudid"
@@ -102,6 +110,14 @@ class ResultatsSemestre(ResultatsCache):
"dict { etudid : indice dans les inscrits }"
return {e.id: idx for idx, e in enumerate(self.etuds)}
+ def modimpl_notes(self, modimpl_id: int, ue_id: int) -> np.ndarray:
+ """Les notes moyennes des étudiants du sem. à ce modimpl dans cette ue.
+ Utile pour stats bottom tableau recap.
+ Résultat: 1d array of float
+ """
+ # différent en BUT et classique: virtuelle
+ raise NotImplementedError
+
@cached_property
def etuds_dict(self) -> dict[int, Identite]:
"""dict { etudid : Identite } inscrits au semestre,
@@ -230,6 +246,13 @@ class ResultatsSemestre(ResultatsCache):
0.0, min(self.etud_moy_gen[etudid], 20.0)
)
+ def get_etud_etat(self, etudid: int) -> str:
+ "Etat de l'etudiant: 'I', 'D', DEF ou '' (si pas connu dans ce semestre)"
+ ins = self.formsemestre.etuds_inscriptions.get(etudid, None)
+ if ins is None:
+ return ""
+ return ins.etat
+
def _get_etud_ue_cap(self, etudid: int, ue: UniteEns) -> dict:
"""Donne les informations sur la capitalisation de l'UE ue pour cet étudiant.
Résultat:
@@ -304,11 +327,11 @@ class ResultatsSemestre(ResultatsCache):
if coef_ue is None:
orig_sem = FormSemestre.query.get(ue_cap["formsemestre_id"])
raise ScoValueError(
- f"""L'UE capitalisée {ue_capitalized.acronyme}
+ f"""L'UE capitalisée {ue_capitalized.acronyme}
du semestre {orig_sem.titre_annee()}
n'a pas d'indication d'ECTS.
- Corrigez ou faite corriger le programme
-
via cette page.
"""
)
@@ -333,6 +356,11 @@ class ResultatsSemestre(ResultatsCache):
"capitalized_ue_id": ue_cap["ue_id"] if is_capitalized else None,
}
+ def compute_etud_ue_coef(self, etudid: int, ue: UniteEns) -> float:
+ "Détermine le coefficient de l'UE pour cet étudiant."
+ # calcul différent en classqiue et BUT
+ raise NotImplementedError()
+
def get_etud_ue_cap_coef(self, etudid, ue, ue_cap):
"""Calcule le coefficient d'une UE capitalisée, pour cet étudiant,
injectée dans le semestre courant.
@@ -401,7 +429,6 @@ class ResultatsSemestre(ResultatsCache):
titles = {
"rang": "Rg",
# ordre des colonnes:
- "_rang_col_order": 1,
"_civilite_str_col_order": 2,
"_nom_disp_col_order": 3,
"_prenom_col_order": 4,
@@ -544,8 +571,7 @@ class ResultatsSemestre(ResultatsCache):
# --- TABLE FOOTER: ECTS, moyennes, min, max...
footer_rows = []
- for bottom_line in bottom_infos:
- row = bottom_infos[bottom_line]
+ for (bottom_line, row) in bottom_infos.items():
# Cases vides à styler:
row["moy_gen"] = row.get("moy_gen", "")
row["_moy_gen_class"] = "col_moy_gen"
@@ -621,7 +647,7 @@ class ResultatsSemestre(ResultatsCache):
# if dec:
# codes_nb[dec["code"]] += 1
row_class = ""
- etud_etat = self.get_etud_etat(etudid) # dans NotesTableCompat, à revoir
+ etud_etat = self.get_etud_etat(etudid)
if etud_etat == DEM:
gr_name = "Dém."
row_class = "dem"
diff --git a/app/comp/res_compat.py b/app/comp/res_compat.py
index c18f549ef..8bbed0904 100644
--- a/app/comp/res_compat.py
+++ b/app/comp/res_compat.py
@@ -32,8 +32,6 @@ class NotesTableCompat(ResultatsSemestre):
"""
_cached_attrs = ResultatsSemestre._cached_attrs + (
- "bonus",
- "bonus_ues",
"malus",
"etud_moy_gen_ranks",
"etud_moy_gen_ranks_int",
@@ -44,8 +42,6 @@ class NotesTableCompat(ResultatsSemestre):
super().__init__(formsemestre)
nb_etuds = len(self.etuds)
- self.bonus = None # virtuel
- self.bonus_ues = None # virtuel
self.ue_rangs = {u.id: (None, nb_etuds) for u in self.ues}
self.mod_rangs = None # sera surchargé en Classic, mais pas en APC
"""{ modimpl_id : (rangs, effectif) }"""
@@ -251,13 +247,6 @@ class NotesTableCompat(ResultatsSemestre):
)
return self.validations.decisions_jury.get(etudid, None)
- def get_etud_etat(self, etudid: int) -> str:
- "Etat de l'etudiant: 'I', 'D', DEF ou '' (si pas connu dans ce semestre)"
- ins = self.formsemestre.etuds_inscriptions.get(etudid, None)
- if ins is None:
- return ""
- return ins.etat
-
def get_etud_mat_moy(self, matiere_id: int, etudid: int) -> str:
"""moyenne d'un étudiant dans une matière (ou NA si pas de notes)"""
if not self.moyennes_matieres:
@@ -316,6 +305,7 @@ class NotesTableCompat(ResultatsSemestre):
return self.etud_moy_gen_ranks.get(etudid, 99999)
def get_etud_rang_group(self, etudid: int, group_id: int):
+ "Le rang de l'étudiant dans ce groupe (NON IMPLEMENTE)"
return (None, 0) # XXX unimplemented TODO
def get_evals_in_mod(self, moduleimpl_id: int) -> list[dict]: