1
0
forked from ScoDoc/ScoDoc

calcul et affiche les rangs / moy gen BUT

This commit is contained in:
Emmanuel Viennet 2021-12-12 10:17:02 +01:00
parent 80b8956af5
commit 711ca9c220
4 changed files with 61 additions and 23 deletions

View File

@ -34,6 +34,7 @@ class ResultatsSemestreBUT:
"modimpls_evals_poids", "modimpls_evals_poids",
"modimpls_evals_notes", "modimpls_evals_notes",
"etud_moy_gen", "etud_moy_gen",
"etud_moy_gen_ranks",
) )
def __init__(self, formsemestre): def __init__(self, formsemestre):
@ -94,6 +95,7 @@ class ResultatsSemestreBUT:
self.etud_moy_gen = moy_sem.compute_sem_moys( self.etud_moy_gen = moy_sem.compute_sem_moys(
self.etud_moy_ue, self.modimpl_coefs_df self.etud_moy_ue, self.modimpl_coefs_df
) )
self.etud_moy_gen_ranks = moy_sem.comp_ranks_series(self.etud_moy_gen)
def etud_ue_mod_results(self, etud, ue, modimpls) -> dict: def etud_ue_mod_results(self, etud, ue, modimpls) -> dict:
"dict synthèse résultats dans l'UE pour les modules indiqués" "dict synthèse résultats dans l'UE pour les modules indiqués"
@ -227,8 +229,8 @@ class ResultatsSemestreBUT:
"max": fmt_note(self.etud_moy_gen.max()), "max": fmt_note(self.etud_moy_gen.max()),
}, },
"rang": { # classement wrt moyenne général, indicatif "rang": { # classement wrt moyenne général, indicatif
"value": None, # XXX TODO "value": self.etud_moy_gen_ranks[etud.id],
"total": None, "total": len(self.etuds),
}, },
"absences": { # XXX TODO "absences": { # XXX TODO
"injustifie": 1, "injustifie": 1,

View File

@ -44,3 +44,36 @@ def compute_sem_moys(etud_moy_ue_df, modimpl_coefs_df):
axis=1 axis=1
) / modimpl_coefs_df.values.sum() ) / modimpl_coefs_df.values.sum()
return moy_gen return moy_gen
def comp_ranks_series(notes: pd.Series):
"""Calcul rangs à partir d'une séries ("vecteur") de notes (index etudid, valeur numérique)
en tenant compte des ex-aequos
Le resultat est: { etudid : rang } rang est une chaine decrivant le rang
"""
notes = notes.sort_values(ascending=False) # Serie, tri par ordre décroissant
rangs = pd.Series(index=notes.index, dtype=str) # le rang est une chaîne
N = len(notes)
nb_ex = 0 # nb d'ex-aequo consécutifs en cours
notes_i = notes.iat
for i, etudid in enumerate(notes.index):
# test ex-aequo
if i < (N - 1):
next = notes_i[i + 1]
else:
next = None
val = notes_i[i]
if nb_ex:
srang = "%d ex" % (i + 1 - nb_ex)
if val == next:
nb_ex += 1
else:
nb_ex = 0
else:
if val == next:
srang = "%d ex" % (i + 1 - nb_ex)
nb_ex = 1
else:
srang = "%d" % (i + 1)
rangs[etudid] = srang
return rangs

View File

@ -200,9 +200,7 @@ class NotesTable(object):
self.inscrlist.sort(key=itemgetter("nomp")) self.inscrlist.sort(key=itemgetter("nomp"))
# { etudid : rang dans l'ordre alphabetique } # { etudid : rang dans l'ordre alphabetique }
rangalpha = {} self.rang_alpha = {e["etudid"]: i for i, e in enumerate(self.inscrlist)}
for i in range(len(self.inscrlist)):
rangalpha[self.inscrlist[i]["etudid"]] = i
self.bonus = scu.DictDefault(defaultvalue=0) self.bonus = scu.DictDefault(defaultvalue=0)
# Notes dans les modules { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } } # Notes dans les modules { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
@ -264,7 +262,7 @@ class NotesTable(object):
self._ues.sort(key=lambda u: u["numero"]) self._ues.sort(key=lambda u: u["numero"])
T = [] T = []
# XXX self.comp_ue_coefs(cnx)
self.moy_gen = {} # etudid : moy gen (avec UE capitalisées) self.moy_gen = {} # etudid : moy gen (avec UE capitalisées)
self.moy_ue = {} # ue_id : { etudid : moy ue } (valeur numerique) self.moy_ue = {} # ue_id : { etudid : moy ue } (valeur numerique)
self.etud_moy_infos = {} # etudid : resultats de comp_etud_moy_gen() self.etud_moy_infos = {} # etudid : resultats de comp_etud_moy_gen()
@ -305,21 +303,11 @@ class NotesTable(object):
# #
t.append(etudid) t.append(etudid)
T.append(t) T.append(t)
self.T = T
# tri par moyennes décroissantes, # tri par moyennes décroissantes,
# en laissant les demissionnaires a la fin, par ordre alphabetique # en laissant les demissionnaires a la fin, par ordre alphabetique
def row_key(x): self.T.sort(key=self._row_key)
"""clé de tri par moyennes décroissantes,
en laissant les demissionnaires a la fin, par ordre alphabetique.
(moy_gen, rang_alpha)
"""
try:
moy = -float(x[0])
except (ValueError, TypeError):
moy = 1000.0
return (moy, rangalpha[x[-1]])
T.sort(key=row_key)
self.T = T
if len(valid_moy): if len(valid_moy):
self.moy_min = min(valid_moy) self.moy_min = min(valid_moy)
@ -349,7 +337,7 @@ class NotesTable(object):
ue_eff = len( ue_eff = len(
[x for x in val_ids if isinstance(x[0], float)] [x for x in val_ids if isinstance(x[0], float)]
) # nombre d'étudiants avec une note dans l'UE ) # nombre d'étudiants avec une note dans l'UE
val_ids.sort(key=row_key) val_ids.sort(key=self._row_key)
ue_rangs[ue_id] = ( ue_rangs[ue_id] = (
comp_ranks(val_ids), comp_ranks(val_ids),
ue_eff, ue_eff,
@ -360,13 +348,24 @@ class NotesTable(object):
for modimpl in self._modimpls: for modimpl in self._modimpls:
vals = self._modmoys[modimpl["moduleimpl_id"]] vals = self._modmoys[modimpl["moduleimpl_id"]]
val_ids = [(vals[etudid], etudid) for etudid in vals.keys()] val_ids = [(vals[etudid], etudid) for etudid in vals.keys()]
val_ids.sort(key=row_key) val_ids.sort(key=self._row_key)
self.mod_rangs[modimpl["moduleimpl_id"]] = (comp_ranks(val_ids), len(vals)) self.mod_rangs[modimpl["moduleimpl_id"]] = (comp_ranks(val_ids), len(vals))
# #
self.compute_moy_moy() self.compute_moy_moy()
# #
log(f"NotesTable( formsemestre_id={formsemestre_id} ) done.") log(f"NotesTable( formsemestre_id={formsemestre_id} ) done.")
def _row_key(self, x):
"""clé de tri par moyennes décroissantes,
en laissant les demissionnaires a la fin, par ordre alphabetique.
(moy_gen, rang_alpha)
"""
try:
moy = -float(x[0])
except (ValueError, TypeError):
moy = 1000.0
return (moy, self.rang_alpha[x[-1]])
def get_etudids(self, sorted=False): def get_etudids(self, sorted=False):
if sorted: if sorted:
# Tri par moy. generale décroissante # Tri par moy. generale décroissante
@ -1338,7 +1337,7 @@ class NotesTable(object):
] ]
def apc_recompute_moyennes(self): def apc_recompute_moyennes(self):
"""recalule les moyennes en APC (BUT) """recalcule les moyennes en APC (BUT)
et modifie en place le tableau T. et modifie en place le tableau T.
XXX Raccord provisoire avant refonte de cette classe. XXX Raccord provisoire avant refonte de cette classe.
""" """
@ -1355,3 +1354,7 @@ class NotesTable(object):
for i, ue in enumerate(ues, start=1): for i, ue in enumerate(ues, start=1):
if ue["type"] != UE_SPORT: if ue["type"] != UE_SPORT:
t[i] = results.etud_moy_ue[ue["id"]][etudid] t[i] = results.etud_moy_ue[ue["id"]][etudid]
# re-trie selon la nouvelle moyenne générale:
self.T.sort(key=self._row_key)
# Remplace aussi le rang:
self.rangs = results.etud_moy_gen_ranks

View File

@ -1121,7 +1121,7 @@ def formsemestre_tableau_modules(
[f"{ue_acro}: {co}" for ue_acro, co in mod.ue_coefs_descr()] [f"{ue_acro}: {co}" for ue_acro, co in mod.ue_coefs_descr()]
) )
if coef_descr: if coef_descr:
mod_descr += "coefs: " + coef_descr mod_descr += " Coefs: " + coef_descr
else: else:
mod_descr += " (pas de coefficients) " mod_descr += " (pas de coefficients) "
else: else: