From 6749ca70d6b244773ca0b0a647902532d8e833db Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Tue, 28 May 2024 13:51:27 +0200 Subject: [PATCH 1/2] Fix prise en compte evals session 2 avec poids ne couvrant pas toutes les UEs (#811) --- app/comp/moy_mod.py | 14 +++++++++----- app/comp/moy_ue.py | 6 ++++-- app/comp/res_but.py | 9 +++++---- sco_version.py | 2 +- tests/unit/test_but_modules.py | 6 ++++-- tests/unit/test_but_ues.py | 11 +++++++++-- 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/app/comp/moy_mod.py b/app/comp/moy_mod.py index 3ed27ffad..aa315ffd3 100644 --- a/app/comp/moy_mod.py +++ b/app/comp/moy_mod.py @@ -360,12 +360,13 @@ class ModuleImplResultsAPC(ModuleImplResults): "Calcul des moyennes de modules à la mode BUT" def compute_module_moy( - self, - evals_poids_df: pd.DataFrame, + self, evals_poids_df: pd.DataFrame, modimpl_coefs_df: pd.DataFrame ) -> pd.DataFrame: """Calcule les moyennes des étudiants dans ce module - Argument: evals_poids: DataFrame, colonnes: UEs, Lignes: EVALs + Argument: + evals_poids: DataFrame, colonnes: UEs, lignes: EVALs + modimpl_coefs_df: DataFrame, colonnes: modimpl_id, lignes: ue_id Résultat: DataFrame, colonnes UE, lignes etud = la note de l'étudiant dans chaque UE pour ce module. @@ -427,8 +428,11 @@ class ModuleImplResultsAPC(ModuleImplResults): Evaluation.EVALUATION_SESSION2, ) - # 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) + # Vrai si toutes les UEs avec coef non nul ont bien une note de session 2 calculée: + mod_coefs = modimpl_coefs_df[modimpl.id] + etuds_use_session2 = np.all( + np.isfinite(etuds_moy_module_s2[:, mod_coefs != 0]), axis=1 + ) etuds_moy_module = np.where( etuds_use_session2[:, np.newaxis], etuds_moy_module_s2, diff --git a/app/comp/moy_ue.py b/app/comp/moy_ue.py index d247301fd..24fdbd468 100644 --- a/app/comp/moy_ue.py +++ b/app/comp/moy_ue.py @@ -183,7 +183,9 @@ def notes_sem_assemble_cube(modimpls_notes: list[pd.DataFrame]) -> np.ndarray: return modimpls_notes.swapaxes(0, 1) -def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple: +def notes_sem_load_cube( + formsemestre: FormSemestre, modimpl_coefs_df: pd.DataFrame +) -> tuple: """Construit le "cube" (tenseur) des notes du semestre. Charge toutes les notes (sql), calcule les moyennes des modules et assemble le cube. @@ -208,7 +210,7 @@ def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple: for modimpl in formsemestre.modimpls_sorted: mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs) 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, modimpl_coefs_df) modimpls_results[modimpl.id] = mod_results modimpls_evals_poids[modimpl.id] = evals_poids modimpls_notes.append(etuds_moy_module) diff --git a/app/comp/res_but.py b/app/comp/res_but.py index c6d99fb95..a92c99506 100644 --- a/app/comp/res_but.py +++ b/app/comp/res_but.py @@ -59,16 +59,17 @@ class ResultatsSemestreBUT(NotesTableCompat): def compute(self): "Charge les notes et inscriptions et calcule les moyennes d'UE et gen." + self.modimpl_coefs_df, _, _ = moy_ue.df_load_modimpl_coefs( + self.formsemestre, modimpls=self.formsemestre.modimpls_sorted + ) ( self.sem_cube, self.modimpls_evals_poids, self.modimpls_results, - ) = moy_ue.notes_sem_load_cube(self.formsemestre) + ) = moy_ue.notes_sem_load_cube(self.formsemestre, self.modimpl_coefs_df) self.modimpl_inscr_df = inscr_mod.df_load_modimpl_inscr(self.formsemestre) self.ues_inscr_parcours_df = self.load_ues_inscr_parcours() - self.modimpl_coefs_df, _, _ = moy_ue.df_load_modimpl_coefs( - self.formsemestre, modimpls=self.formsemestre.modimpls_sorted - ) + # l'idx de la colonne du mod modimpl.id est # modimpl_coefs_df.columns.get_loc(modimpl.id) # idx de l'UE: modimpl_coefs_df.index.get_loc(ue.id) diff --git a/sco_version.py b/sco_version.py index 4675621d2..16534d3d1 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.6.967" +SCOVERSION = "9.6.968" SCONAME = "ScoDoc" diff --git a/tests/unit/test_but_modules.py b/tests/unit/test_but_modules.py index 684248e62..515e156e1 100644 --- a/tests/unit/test_but_modules.py +++ b/tests/unit/test_but_modules.py @@ -253,8 +253,10 @@ def test_module_moy(test_client): mod_results = moy_mod.ModuleImplResultsAPC(modimpl, etudids, etudids_actifs) evals_notes = mod_results.evals_notes assert evals_notes[evaluation1.id].dtype == np.float64 - - etuds_moy_module = mod_results.compute_module_moy(evals_poids) + modimpl_coefs_df, _, _ = moy_ue.df_load_modimpl_coefs( + formsemestre, modimpls=formsemestre.modimpls_sorted + ) + etuds_moy_module = mod_results.compute_module_moy(evals_poids, modimpl_coefs_df) return etuds_moy_module # --- Notes ordinaires: diff --git a/tests/unit/test_but_ues.py b/tests/unit/test_but_ues.py index ee66bcde7..1c0e33aef 100644 --- a/tests/unit/test_but_ues.py +++ b/tests/unit/test_but_ues.py @@ -1,6 +1,7 @@ """ Test calcul moyennes UE """ + import numpy as np from tests.unit import setup @@ -63,7 +64,10 @@ def test_ue_moy(test_client): _ = sco_saisie_notes.notes_add(G.default_user, evaluation1.id, [(etudid, n1)]) _ = sco_saisie_notes.notes_add(G.default_user, evaluation2.id, [(etudid, n2)]) # Recalcul des moyennes - sem_cube, _, _ = moy_ue.notes_sem_load_cube(formsemestre) + modimpl_coefs_df, _, _ = moy_ue.df_load_modimpl_coefs( + formsemestre, modimpls=formsemestre.modimpls_sorted + ) + sem_cube, _, _ = moy_ue.notes_sem_load_cube(formsemestre, modimpl_coefs_df) # Masque de tous les modules _sauf_ les bonus (sport) modimpl_mask = [ modimpl.module.ue.type != UE_SPORT @@ -117,7 +121,10 @@ def test_ue_moy(test_client): exception_raised = True assert exception_raised # Recalcule les notes: - sem_cube, _, _ = moy_ue.notes_sem_load_cube(formsemestre) + modimpl_coefs_df, _, _ = moy_ue.df_load_modimpl_coefs( + formsemestre, modimpls=formsemestre.modimpls_sorted + ) + sem_cube, _, _ = moy_ue.notes_sem_load_cube(formsemestre, modimpl_coefs_df) etuds = formsemestre.etuds.all() modimpl_mask = [ modimpl.module.ue.type != UE_SPORT for modimpl in formsemestre.modimpls_sorted From 9289535359083ed3270e2b4a3a22e8ac7dce1c98 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Wed, 29 May 2024 10:48:34 +0200 Subject: [PATCH 2/2] Ajout Identite.nom_prenom() --- app/models/etudiants.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/models/etudiants.py b/app/models/etudiants.py index 7ee87d418..a81ac73d5 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -299,9 +299,10 @@ class Identite(models.ScoDocModel): @property def nomprenom(self, reverse=False) -> str: - """Civilité/nom/prenom pour affichages: "M. Pierre Dupont" + """DEPRECATED + Civilité/prénom/nom pour affichages: "M. Pierre Dupont" Si reverse, "Dupont Pierre", sans civilité. - Prend l'identité courant et non celle de l'état civile si elles diffèrent. + Prend l'identité courante et non celle de l'état civil si elles diffèrent. """ nom = self.nom_usuel or self.nom prenom = self.prenom_str @@ -309,6 +310,12 @@ class Identite(models.ScoDocModel): return f"{nom} {prenom}".strip() return f"{self.civilite_str} {prenom} {nom}".strip() + def nom_prenom(self) -> str: + """Civilite NOM Prénom + Prend l'identité courante et non celle de l'état civil si elles diffèrent. + """ + return f"{self.civilite_str} {(self.nom_usuel or self.nom).upper()} {self.prenom_str}" + @property def prenom_str(self): """Prénom à afficher. Par exemple: "Jean-Christophe" """