From 45a950ad79f6bcc7bc202e0c5f16d2fd24a7cc05 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Fri, 12 May 2023 12:50:26 +0200
Subject: [PATCH] Bareme notes moy/min/max promo. Fix #633

---
 app/but/bulletin_but.py              |  6 +--
 app/scodoc/sco_bulletins.py          |  2 +-
 app/scodoc/sco_bulletins_json.py     |  6 +--
 app/scodoc/sco_bulletins_standard.py |  7 +--
 app/scodoc/sco_evaluations.py        | 76 ++++++++++++++--------------
 tools/etc/scodoc9.service            |  1 -
 6 files changed, 50 insertions(+), 48 deletions(-)

diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py
index eb71373f1..fc680dbc7 100644
--- a/app/but/bulletin_but.py
+++ b/app/but/bulletin_but.py
@@ -285,9 +285,9 @@ class BulletinBUT:
                     eval_notes[etud.id],
                     note_max=e.note_max,
                 ),
-                "min": fmt_note(notes_ok.min()),
-                "max": fmt_note(notes_ok.max()),
-                "moy": fmt_note(notes_ok.mean()),
+                "min": fmt_note(notes_ok.min(), note_max=e.note_max),
+                "max": fmt_note(notes_ok.max(), note_max=e.note_max),
+                "moy": fmt_note(notes_ok.mean(), note_max=e.note_max),
             },
             "poids": poids,
             "url": url_for(
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index fce11e1c1..2f9624698 100644
--- a/app/scodoc/sco_bulletins.py
+++ b/app/scodoc/sco_bulletins.py
@@ -144,7 +144,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
     """
     from app.scodoc import sco_abs
 
-    if not version in scu.BULLETINS_VERSIONS:
+    if version not in scu.BULLETINS_VERSIONS:
         raise ValueError("invalid version code !")
 
     prefs = sco_preferences.SemPreferences(formsemestre_id)
diff --git a/app/scodoc/sco_bulletins_json.py b/app/scodoc/sco_bulletins_json.py
index 20ca1f410..a93f4392e 100644
--- a/app/scodoc/sco_bulletins_json.py
+++ b/app/scodoc/sco_bulletins_json.py
@@ -388,10 +388,10 @@ def _list_modimpls(
                     if prefs["bul_show_minmax_eval"] or prefs["bul_show_moypromo"]:
                         etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
                         if prefs["bul_show_minmax_eval"]:
-                            eval_dict["min"] = scu.fmt_note(etat["mini"])
-                            eval_dict["max"] = scu.fmt_note(etat["maxi"])
+                            eval_dict["min"] = etat["mini"]  # chaine, sur 20
+                            eval_dict["max"] = etat["maxi"]
                         if prefs["bul_show_moypromo"]:
-                            eval_dict["moy"] = scu.fmt_note(etat["moy"])
+                            eval_dict["moy"] = etat["moy"]
 
                     mod_dict["evaluation"].append(eval_dict)
 
diff --git a/app/scodoc/sco_bulletins_standard.py b/app/scodoc/sco_bulletins_standard.py
index c7c51135c..4a6bb2772 100644
--- a/app/scodoc/sco_bulletins_standard.py
+++ b/app/scodoc/sco_bulletins_standard.py
@@ -69,6 +69,7 @@ from app.scodoc import sco_groups
 from app.scodoc import sco_evaluations
 from app.scodoc import gen_tables
 
+
 # Important: Le nom de la classe ne doit pas changer (bien le choisir),
 # car il sera stocké en base de données (dans les préférences)
 class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
@@ -685,10 +686,10 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
                 if prefs["bul_show_minmax_eval"] or prefs["bul_show_moypromo"]:
                     etat = sco_evaluations.do_evaluation_etat(e["evaluation_id"])
                 if prefs["bul_show_minmax_eval"]:
-                    t["min"] = scu.fmt_note(etat["mini"])
-                    t["max"] = scu.fmt_note(etat["maxi"])
+                    t["min"] = etat["mini"]
+                    t["max"] = etat["maxi"]
                 if prefs["bul_show_moypromo"]:
-                    t["moy"] = scu.fmt_note(etat["moy"])
+                    t["moy"] = etat["moy"]
                 P.append(t)
                 nbeval += 1
         return nbeval
diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py
index 4626509f4..ed34842ab 100644
--- a/app/scodoc/sco_evaluations.py
+++ b/app/scodoc/sco_evaluations.py
@@ -97,11 +97,22 @@ def ListMedian(L):
 # --------------------------------------------------------------------
 
 
-def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=False):
-    """donne infos sur l'état de l'évaluation
-    { nb_inscrits, nb_notes, nb_abs, nb_neutre, nb_att,
-    moyenne, mediane, mini, maxi,
-    date_last_modif, gr_complets, gr_incomplets, evalcomplete }
+def do_evaluation_etat(
+    evaluation_id: int, partition_id: int = None, select_first_partition=False
+) -> dict:
+    """Donne infos sur l'état de l'évaluation.
+    Ancienne fonction, lente: préférer ModuleImplResults pour tout calcul.
+    {
+        nb_inscrits : inscrits au module
+        nb_notes
+        nb_abs,
+        nb_neutre,
+        nb_att,
+        moy, median, mini, maxi : # notes, en chaine, sur 20
+        last_modif: datetime,
+        gr_complets, gr_incomplets,
+        evalcomplete
+    }
     evalcomplete est vrai si l'eval est complete (tous les inscrits
     à ce module ont des notes)
     evalattente est vrai s'il ne manque que des notes en attente
@@ -137,7 +148,7 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
     insmod = sco_moduleimpl.do_moduleimpl_inscription_list(
         moduleimpl_id=E["moduleimpl_id"]
     )
-    insmodset = set([x["etudid"] for x in insmod])
+    insmodset = {x["etudid"] for x in insmod}
     # retire de insem ceux qui ne sont pas inscrits au module
     ins = [i for i in insem if i["etudid"] in insmodset]
 
@@ -155,14 +166,13 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
     moy_num, median_num, mini_num, maxi_num = notes_moyenne_median_mini_maxi(notes)
     if moy_num is None:
         median, moy = "", ""
-        median_num, moy_num = None, None
         mini, maxi = "", ""
-        mini_num, maxi_num = None, None
+        maxi_num = None
     else:
         median = scu.fmt_note(median_num)
-        moy = scu.fmt_note(moy_num)
-        mini = scu.fmt_note(mini_num)
-        maxi = scu.fmt_note(maxi_num)
+        moy = scu.fmt_note(moy_num, E["note_max"])
+        mini = scu.fmt_note(mini_num, E["note_max"])
+        maxi = scu.fmt_note(maxi_num, E["note_max"])
     # cherche date derniere modif note
     if len(etuds_notes_dict):
         t = [x["date"] for x in etuds_notes_dict.values()]
@@ -226,28 +236,22 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
 
     # Calcul moyenne dans chaque groupe de TD
     gr_moyennes = []  # group : {moy,median, nb_notes}
-    for group_id in GrNotes.keys():
-        notes = GrNotes[group_id]
+    for group_id, notes in GrNotes.items():
         gr_moy, gr_median, gr_mini, gr_maxi = notes_moyenne_median_mini_maxi(notes)
         gr_moyennes.append(
             {
                 "group_id": group_id,
                 "group_name": groups[group_id]["group_name"],
-                "gr_moy_num": gr_moy,
-                "gr_moy": scu.fmt_note(gr_moy),
-                "gr_median_num": gr_median,
-                "gr_median": scu.fmt_note(gr_median),
-                "gr_mini": scu.fmt_note(gr_mini),
-                "gr_maxi": scu.fmt_note(gr_maxi),
-                "gr_mini_num": gr_mini,
-                "gr_maxi_num": gr_maxi,
+                "gr_moy": scu.fmt_note(gr_moy, E["note_max"]),
+                "gr_median": scu.fmt_note(gr_median, E["note_max"]),
+                "gr_mini": scu.fmt_note(gr_mini, E["note_max"]),
+                "gr_maxi": scu.fmt_note(gr_maxi, E["note_max"]),
                 "gr_nb_notes": len(notes),
                 "gr_nb_att": len([x for x in notes if x == scu.NOTES_ATTENTE]),
             }
         )
     gr_moyennes.sort(key=operator.itemgetter("group_name"))
 
-    # retourne mapping
     return {
         "evaluation_id": evaluation_id,
         "nb_inscrits": nb_inscrits,
@@ -256,14 +260,11 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
         "nb_abs": nb_abs,
         "nb_neutre": nb_neutre,
         "nb_att": nb_att,
-        "moy": moy,
-        "moy_num": moy_num,
+        "moy": moy,  # chaine formattée, sur 20
         "median": median,
         "mini": mini,
-        "mini_num": mini_num,
         "maxi": maxi,
-        "maxi_num": maxi_num,
-        "median_num": median_num,
+        "maxi_num": maxi_num,  # note maximale, en nombre
         "last_modif": last_modif,
         "gr_incomplets": gr_incomplets,
         "gr_moyennes": gr_moyennes,
@@ -283,18 +284,19 @@ def do_evaluation_list_in_sem(formsemestre_id, with_etat=True):
        [ {
        'coefficient': 1.0,
        'description': 'QCM et cas pratiques',
-       'etat': {'evalattente': False,
+       'etat': {
+             'evalattente': False,
              'evalcomplete': True,
              'evaluation_id': 'GEAEVAL82883',
              'gr_incomplets': [],
-             'gr_moyennes': [{'gr_median': '12.00',
-                              'gr_median_num' : 12.,
-                              'gr_moy': '11.88',
-                              'gr_moy_num' : 11.88,
-                              'gr_nb_att': 0,
-                              'gr_nb_notes': 166,
-                              'group_id': 'GEAG266762',
-                              'group_name': None}],
+             'gr_moyennes': [{
+                'gr_median': '12.00', # sur 20
+                'gr_moy': '11.88',
+                'gr_nb_att': 0,
+                'gr_nb_notes': 166,
+                'group_id': 'GEAG266762',
+                'group_name': None
+             }],
              'groups': {'GEAG266762': {'etudid': 'GEAEID80603',
                                        'group_id': 'GEAG266762',
                                        'group_name': None,
@@ -362,7 +364,7 @@ def _eval_etat(evals):
         if last_modif is not None:
             dates.append(e["etat"]["last_modif"])
 
-    if len(dates):
+    if dates:
         dates = scu.sort_dates(dates)
         last_modif = dates[-1]  # date de derniere modif d'une note dans un module
     else:
diff --git a/tools/etc/scodoc9.service b/tools/etc/scodoc9.service
index 8028442cd..5745ade30 100644
--- a/tools/etc/scodoc9.service
+++ b/tools/etc/scodoc9.service
@@ -19,7 +19,6 @@ After=network.target
 User=scodoc
 Group=scodoc
 WorkingDirectory=/opt/scodoc
-#Environment=FLASK_ENV=production
 ExecStart=/opt/scodoc/venv/bin/gunicorn -b localhost:8000 -w 4 --timeout 600 scodoc:app
 Restart=always
 
-- 
GitLab