WIP: reorganisation des calculs
This commit is contained in:
parent
a7324ac634
commit
02989e6c88
@ -147,6 +147,7 @@ class BulletinBUT(ResultatsSemestreBUT):
|
||||
def bulletin_etud(self, etud, formsemestre) -> dict:
|
||||
"""Le bulletin de l'étudiant dans ce semestre"""
|
||||
etat_inscription = etud.etat_inscription(formsemestre.id)
|
||||
nb_inscrits = self.get_inscriptions_counts()[scu.INSCRIT]
|
||||
d = {
|
||||
"version": "0",
|
||||
"type": "BUT",
|
||||
@ -189,7 +190,7 @@ class BulletinBUT(ResultatsSemestreBUT):
|
||||
},
|
||||
"rang": { # classement wrt moyenne général, indicatif
|
||||
"value": self.etud_moy_gen_ranks[etud.id],
|
||||
"total": len(self.etuds),
|
||||
"total": nb_inscrits,
|
||||
},
|
||||
},
|
||||
)
|
||||
@ -212,7 +213,7 @@ class BulletinBUT(ResultatsSemestreBUT):
|
||||
"moy": "",
|
||||
"max": "",
|
||||
},
|
||||
"rang": {"value": "DEM", "total": len(self.etuds)},
|
||||
"rang": {"value": "DEM", "total": nb_inscrits},
|
||||
}
|
||||
)
|
||||
d.update(
|
||||
|
@ -69,10 +69,11 @@ def bulletin_but_xml_compat(
|
||||
% (formsemestre_id, etudid)
|
||||
)
|
||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
etud = Identite.query.get_or_404(etudid)
|
||||
etud: Identite = Identite.query.get_or_404(etudid)
|
||||
results = bulletin_but.ResultatsSemestreBUT(formsemestre)
|
||||
nb_inscrits = len(results.etuds)
|
||||
etat_inscription = etud.etat_inscription(formsemestre.id)
|
||||
nb_inscrits = results.get_inscriptions_counts()[scu.INSCRIT]
|
||||
# etat_inscription = etud.etat_inscription(formsemestre.id)
|
||||
etat_inscription = results.formsemestre.etuds_inscriptions[etudid].etat
|
||||
if (not formsemestre.bul_hide_xml) or force_publishing:
|
||||
published = 1
|
||||
else:
|
||||
|
@ -16,13 +16,13 @@ from app import models
|
||||
#
|
||||
def df_load_modimpl_inscr(formsemestre) -> pd.DataFrame:
|
||||
"""Charge la matrice des inscriptions aux modules du semestre
|
||||
rows: etudid
|
||||
rows: etudid (inscrits au semestre, avec DEM et DEF)
|
||||
columns: moduleimpl_id (en chaîne)
|
||||
value: bool (0/1 inscrit ou pas)
|
||||
"""
|
||||
# méthode la moins lente: une requete par module, merge les dataframes
|
||||
moduleimpl_ids = [m.id for m in formsemestre.modimpls]
|
||||
etudids = [i.etudid for i in formsemestre.get_inscrits(include_dem=False)]
|
||||
etudids = [inscr.etudid for inscr in formsemestre.inscriptions]
|
||||
df = pd.DataFrame(index=etudids, dtype=int)
|
||||
for moduleimpl_id in moduleimpl_ids:
|
||||
ins_df = pd.read_sql_query(
|
||||
|
@ -75,7 +75,7 @@ class ModuleImplResults:
|
||||
"{ evaluation_id: EvaluationEtat }"
|
||||
#
|
||||
self.evals_notes = None
|
||||
"""DataFrame, colonnes: EVALS, Lignes: etudid
|
||||
"""DataFrame, colonnes: EVALS, Lignes: etudid (inscrits au SEMESTRE)
|
||||
valeur: notes brutes, float ou NOTES_ATTENTE, NOTES_NEUTRALISE,
|
||||
NOTES_ABSENCE.
|
||||
Les NaN désignent les notes manquantes (non saisies).
|
||||
@ -105,7 +105,7 @@ class ModuleImplResults:
|
||||
|
||||
Évaluation "complete" (prise en compte dans les calculs) si:
|
||||
- soit tous les étudiants inscrits au module ont des notes
|
||||
- soit elle a été déclarée "à prise ne compte immédiate" (publish_incomplete)
|
||||
- soit elle a été déclarée "à prise en compte immédiate" (publish_incomplete)
|
||||
|
||||
Évaluation "attente" (prise en compte dans les calculs, mais il y
|
||||
manque des notes) ssi il y a des étudiants inscrits au semestre et au module
|
||||
@ -178,14 +178,12 @@ class ModuleImplResults:
|
||||
return eval_df
|
||||
|
||||
def _etudids(self):
|
||||
"""L'index du dataframe est la liste des étudiants inscrits au semestre,
|
||||
sans les démissionnaires.
|
||||
"""
|
||||
"""L'index du dataframe est la liste de tous les étudiants inscrits au semestre"""
|
||||
return [
|
||||
e.etudid
|
||||
for e in ModuleImpl.query.get(self.moduleimpl_id).formsemestre.get_inscrits(
|
||||
include_dem=False
|
||||
)
|
||||
inscr.etudid
|
||||
for inscr in ModuleImpl.query.get(
|
||||
self.moduleimpl_id
|
||||
).formsemestre.inscriptions
|
||||
]
|
||||
|
||||
def get_evaluations_coefs(self, moduleimpl: ModuleImpl) -> np.array:
|
||||
|
@ -31,8 +31,10 @@ import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def compute_sem_moys_apc(etud_moy_ue_df, modimpl_coefs_df):
|
||||
"""Calcule la moyenne générale indicative
|
||||
def compute_sem_moys_apc(
|
||||
etud_moy_ue_df: pd.DataFrame, modimpl_coefs_df: pd.DataFrame
|
||||
) -> pd.Series:
|
||||
"""Calcule les moyennes générales indicatives de tous les étudiants
|
||||
= moyenne des moyennes d'UE, pondérée par la somme de leurs coefs
|
||||
|
||||
etud_moy_ue_df: DataFrame, colonnes ue_id, lignes etudid
|
||||
@ -46,10 +48,11 @@ def compute_sem_moys_apc(etud_moy_ue_df, modimpl_coefs_df):
|
||||
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 } où rang est une chaine decrivant le rang
|
||||
def comp_ranks_series(notes: pd.Series) -> dict[int, str]:
|
||||
"""Calcul rangs à partir d'une séries ("vecteur") de notes (index etudid, valeur
|
||||
numérique) en tenant compte des ex-aequos.
|
||||
|
||||
Result: { etudid : rang:str } où 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
|
||||
|
@ -140,9 +140,14 @@ def notes_sem_assemble_cube(modimpls_notes: list[pd.DataFrame]) -> np.ndarray:
|
||||
|
||||
|
||||
def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple:
|
||||
"""Calcule le cube des notes du semestre
|
||||
(charge toutes les notes, calcule les moyenne des modules
|
||||
et assemble le cube)
|
||||
"""Construit le "cube" (tenseur) des notes du semestre.
|
||||
Charge toutes les notes (sql), calcule les moyennes des modules
|
||||
et assemble le cube.
|
||||
|
||||
etuds: tous les inscrits au semestre (avec dem. et def.)
|
||||
modimpls: _tous_ les modimpls de ce semestre
|
||||
UEs: X?X voir quelles sont les UE considérées ici
|
||||
|
||||
Resultat:
|
||||
sem_cube : ndarray (etuds x modimpls x UEs)
|
||||
modimpls_evals_poids dict { modimpl.id : evals_poids }
|
||||
@ -174,14 +179,14 @@ def compute_ue_moys_apc(
|
||||
) -> pd.DataFrame:
|
||||
"""Calcul de la moyenne d'UE en mode APC (BUT).
|
||||
La moyenne d'UE est un nombre (note/20), ou NI ou NA ou ERR
|
||||
NI non inscrit à (au moins un) module de cette UE
|
||||
NA pas de notes disponibles
|
||||
ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
|
||||
NI non inscrit à (au moins un) module de cette UE
|
||||
NA pas de notes disponibles
|
||||
ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
|
||||
|
||||
sem_cube: notes moyennes aux modules
|
||||
ndarray (etuds x modimpls x UEs)
|
||||
(floats avec des NaN)
|
||||
etuds : listes des étudiants (dim. 0 du cube)
|
||||
etuds : liste des étudiants (dim. 0 du cube)
|
||||
modimpls : liste des modules à considérer (dim. 1 du cube)
|
||||
ues : liste des UE (dim. 2 du cube)
|
||||
modimpl_inscr_df: matrice d'inscription du semestre (etud x modimpl)
|
||||
@ -235,12 +240,12 @@ def compute_ue_moys_classic(
|
||||
ues: list,
|
||||
modimpl_inscr_df: pd.DataFrame,
|
||||
modimpl_coefs: np.array,
|
||||
) -> tuple:
|
||||
) -> tuple[pd.Series, pd.DataFrame, pd.DataFrame]:
|
||||
"""Calcul de la moyenne d'UE en mode classique.
|
||||
La moyenne d'UE est un nombre (note/20), ou NI ou NA ou ERR
|
||||
NI non inscrit à (au moins un) module de cette UE
|
||||
NA pas de notes disponibles
|
||||
ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
|
||||
NI non inscrit à (au moins un) module de cette UE
|
||||
NA pas de notes disponibles
|
||||
ERR erreur dans une formule utilisateur. [XXX pas encore gérées ici]
|
||||
|
||||
sem_matrix: notes moyennes aux modules
|
||||
ndarray (etuds x modimpls)
|
||||
@ -253,6 +258,9 @@ def compute_ue_moys_classic(
|
||||
Résultat:
|
||||
- moyennes générales: pd.Series, index etudid
|
||||
- moyennes d'UE: DataFrame columns UE, rows etudid
|
||||
- coefficients d'UE: DataFrame, columns UE, rows etudid
|
||||
les coefficients effectifs de chaque UE pour chaque étudiant
|
||||
(sommes de coefs de modules pris en compte)
|
||||
"""
|
||||
nb_etuds, nb_modules = sem_matrix.shape
|
||||
assert len(modimpl_coefs) == nb_modules
|
||||
@ -293,4 +301,9 @@ def compute_ue_moys_classic(
|
||||
etud_moy_ue_df = pd.DataFrame(
|
||||
etud_moy_ue, index=modimpl_inscr_df.index, columns=[ue.id for ue in ues]
|
||||
)
|
||||
return etud_moy_gen_s, etud_moy_ue_df
|
||||
etud_coef_ue_df = pd.DataFrame(
|
||||
coefs.sum(axis=2).T,
|
||||
index=modimpl_inscr_df.index, # etudids
|
||||
columns=[ue.id for ue in ues],
|
||||
)
|
||||
return etud_moy_gen_s, etud_moy_ue_df, etud_coef_ue_df
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
"""Résultats semestres BUT
|
||||
"""
|
||||
import pandas as pd
|
||||
|
||||
from app.comp import moy_ue, moy_sem, inscr_mod
|
||||
from app.comp.res_common import NotesTableCompat
|
||||
@ -49,6 +50,10 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
||||
self.modimpl_inscr_df,
|
||||
self.modimpl_coefs_df,
|
||||
)
|
||||
# Les coefficients d'UE ne sont pas utilisés en APC
|
||||
self.etud_coef_ue_df = pd.DataFrame(
|
||||
1.0, index=self.etud_moy_ue.index, columns=self.etud_moy_ue.columns
|
||||
)
|
||||
self.etud_moy_gen = moy_sem.compute_sem_moys_apc(
|
||||
self.etud_moy_ue, self.modimpl_coefs_df
|
||||
)
|
||||
|
@ -8,6 +8,7 @@
|
||||
"""
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from app.comp import moy_mod, moy_ue, moy_sem, inscr_mod
|
||||
from app.comp.res_common import NotesTableCompat
|
||||
from app.models.formsemestre import FormSemestre
|
||||
@ -45,7 +46,11 @@ class ResultatsSemestreClassic(NotesTableCompat):
|
||||
self.modimpl_idx = {m.id: i for i, m in enumerate(self.formsemestre.modimpls)}
|
||||
"l'idx de la colonne du mod modimpl.id est modimpl_idx[modimpl.id]"
|
||||
|
||||
self.etud_moy_gen, self.etud_moy_ue = moy_ue.compute_ue_moys_classic(
|
||||
(
|
||||
self.etud_moy_gen,
|
||||
self.etud_moy_ue,
|
||||
self.etud_coef_ue_df,
|
||||
) = moy_ue.compute_ue_moys_classic(
|
||||
self.formsemestre,
|
||||
self.sem_matrix,
|
||||
self.ues,
|
||||
|
@ -4,13 +4,13 @@
|
||||
# See LICENSE
|
||||
##############################################################################
|
||||
|
||||
from collections import defaultdict
|
||||
from collections import defaultdict, Counter
|
||||
from functools import cached_property
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from app.comp.aux import StatsMoyenne
|
||||
from app.comp.moy_mod import ModuleImplResults
|
||||
from app.models import FormSemestre, ModuleImpl
|
||||
from app.models import FormSemestre, Identite, ModuleImpl
|
||||
from app.models.ues import UniteEns
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.sco_cache import ResultatsSemestreCache
|
||||
@ -32,6 +32,7 @@ class ResultatsSemestre:
|
||||
"etud_moy_ue",
|
||||
"modimpl_inscr_df",
|
||||
"modimpls_results",
|
||||
"etud_coef_ue_df",
|
||||
)
|
||||
|
||||
def __init__(self, formsemestre: FormSemestre):
|
||||
@ -45,7 +46,10 @@ class ResultatsSemestre:
|
||||
self.etud_moy_gen = {}
|
||||
self.etud_moy_gen_ranks = {}
|
||||
self.modimpls_results: ModuleImplResults = None
|
||||
# TODO
|
||||
self.etud_coef_ue_df = None
|
||||
"""coefs d'UE effectifs pour chaque etudiant (pour form. classiques)"""
|
||||
|
||||
# TODO ?
|
||||
|
||||
def load_cached(self) -> bool:
|
||||
"Load cached dataframes, returns False si pas en cache"
|
||||
@ -68,24 +72,34 @@ class ResultatsSemestre:
|
||||
# voir ce qui est chargé / calculé ici et dans les sous-classes
|
||||
raise NotImplementedError()
|
||||
|
||||
@cached_property
|
||||
def etuds(self):
|
||||
"Liste des inscrits au semestre, sans les démissionnaires"
|
||||
# nb: si la liste des inscrits change, ResultatsSemestre devient invalide
|
||||
return self.formsemestre.get_inscrits(include_dem=False)
|
||||
def get_inscriptions_counts(self) -> Counter:
|
||||
"""Nombre d'inscrits, défaillants, démissionnaires.
|
||||
|
||||
Exemple: res.get_inscriptions_counts()[scu.INSCRIT]
|
||||
|
||||
Result: a collections.Counter instance
|
||||
"""
|
||||
return Counter(ins.etat for ins in self.formsemestre.inscriptions)
|
||||
|
||||
@cached_property
|
||||
def etud_index(self):
|
||||
def etuds(self) -> list[Identite]:
|
||||
"Liste des inscrits au semestre, avec les démissionnaires et les défaillants"
|
||||
# nb: si la liste des inscrits change, ResultatsSemestre devient invalide
|
||||
return self.formsemestre.get_inscrits(include_demdef=True)
|
||||
|
||||
@cached_property
|
||||
def etud_index(self) -> dict[int, int]:
|
||||
"dict { etudid : indice dans les inscrits }"
|
||||
return {e.id: idx for idx, e in enumerate(self.etuds)}
|
||||
|
||||
@cached_property
|
||||
def etuds_dict(self):
|
||||
"dict { etudid : Identite } inscrits au semestre, sans les démissionnaires"
|
||||
def etuds_dict(self) -> dict[int, Identite]:
|
||||
"""dict { etudid : Identite } inscrits au semestre,
|
||||
avec les démissionnaires et defs."""
|
||||
return {etud.id: etud for etud in self.etuds}
|
||||
|
||||
@cached_property
|
||||
def ues(self) -> list:
|
||||
def ues(self) -> list[UniteEns]:
|
||||
"""Liste des UEs du semestre
|
||||
(indices des DataFrames)
|
||||
"""
|
||||
@ -153,6 +167,7 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
|
||||
def __init__(self, formsemestre: FormSemestre):
|
||||
super().__init__(formsemestre)
|
||||
|
||||
nb_etuds = len(self.etuds)
|
||||
self.bonus = defaultdict(lambda: 0.0) # XXX TODO
|
||||
self.ue_rangs = {u.id: (defaultdict(lambda: 0.0), nb_etuds) for u in self.ues}
|
||||
@ -178,12 +193,18 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
|
||||
return [x["etudid"] for x in self.inscrlist]
|
||||
|
||||
@cached_property
|
||||
def sem(self) -> dict:
|
||||
"""le formsemestre, comme un dict (nt.sem)"""
|
||||
return self.formsemestre.to_dict()
|
||||
|
||||
@cached_property
|
||||
def inscrlist(self) -> list[dict]: # utilisé par PE seulement
|
||||
"""Liste de dict etud, avec démissionnaires
|
||||
"""Liste des inscrits au semestre (avec DEM et DEF),
|
||||
sous forme de dict etud,
|
||||
classée dans l'ordre alphabétique de noms.
|
||||
"""
|
||||
etuds = self.formsemestre.get_inscrits(include_dem=True)
|
||||
etuds = self.formsemestre.get_inscrits(include_demdef=True)
|
||||
etuds.sort(key=lambda e: e.sort_key)
|
||||
return [e.to_dict_scodoc7() for e in etuds]
|
||||
|
||||
@ -256,9 +277,12 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
raise NotImplementedError() # virtual method
|
||||
|
||||
def get_etud_ue_status(self, etudid: int, ue_id: int):
|
||||
coef_ue = self.etud_coef_ue_df[ue_id][etudid]
|
||||
return {
|
||||
"cur_moy_ue": self.etud_moy_ue[ue_id][etudid],
|
||||
"moy": self.etud_moy_ue[ue_id][etudid],
|
||||
"is_capitalized": False, # XXX TODO
|
||||
"coef_ue": coef_ue, # XXX TODO
|
||||
}
|
||||
|
||||
def get_etud_rang(self, etudid: int):
|
||||
@ -277,18 +301,20 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
for e in modimpl.evaluations:
|
||||
if self.modimpls_results[moduleimpl_id].evaluations_completes_dict[e.id]:
|
||||
d = e.to_dict()
|
||||
moduleimpl_results = self.modimpls_results[e.moduleimpl_id]
|
||||
d["heure_debut"] = e.heure_debut # datetime.time
|
||||
d["heure_fin"] = e.heure_fin
|
||||
d["jour"] = e.jour # datetime
|
||||
d["notes"] = {
|
||||
etud.id: {
|
||||
"etudid": etud.id,
|
||||
"value": self.modimpls_evals_notes[e.moduleimpl_id][e.id][
|
||||
etud.id
|
||||
],
|
||||
"value": moduleimpl_results.evals_notes[e.id][etud.id],
|
||||
}
|
||||
for etud in self.etuds
|
||||
}
|
||||
d["etat"] = {
|
||||
"evalattente": moduleimpl_results.evaluations_etat[e.id].nb_attente,
|
||||
}
|
||||
evals_results.append(d)
|
||||
return evals_results
|
||||
|
||||
|
@ -117,11 +117,18 @@ class FormSemestre(db.Model):
|
||||
d.pop("_sa_instance_state", None)
|
||||
# ScoDoc7 output_formators: (backward compat)
|
||||
d["formsemestre_id"] = self.id
|
||||
d["date_debut"] = (
|
||||
self.date_debut.strftime("%d/%m/%Y") if self.date_debut else ""
|
||||
)
|
||||
d["date_fin"] = self.date_fin.strftime("%d/%m/%Y") if self.date_fin else ""
|
||||
if self.date_debut:
|
||||
d["date_debut"] = self.date_debut.strftime("%d/%m/%Y")
|
||||
d["date_debut_iso"] = self.date_debut.isoformat()
|
||||
else:
|
||||
d["date_debut"] = d["date_debut_iso"] = ""
|
||||
if self.date_fin:
|
||||
d["date_fin"] = self.date_fin.strftime("%d/%m/%Y")
|
||||
d["date_fin_iso"] = self.date_fin.isoformat()
|
||||
else:
|
||||
d["date_fin"] = d["date_fin_iso"] = ""
|
||||
d["responsables"] = [u.id for u in self.responsables]
|
||||
|
||||
return d
|
||||
|
||||
def query_ues(self, with_sport=False) -> flask_sqlalchemy.BaseQuery:
|
||||
@ -271,18 +278,19 @@ class FormSemestre(db.Model):
|
||||
etudid, self.date_debut.isoformat(), self.date_fin.isoformat()
|
||||
)
|
||||
|
||||
def get_inscrits(self, include_dem=False) -> list[Identite]:
|
||||
def get_inscrits(self, include_demdef=False) -> list[Identite]:
|
||||
"""Liste des étudiants inscrits à ce semestre
|
||||
Si all, tous les étudiants, avec les démissionnaires.
|
||||
Si include_demdef, tous les étudiants, avec les démissionnaires
|
||||
et défaillants.
|
||||
"""
|
||||
if include_dem:
|
||||
if include_demdef:
|
||||
return [ins.etud for ins in self.inscriptions]
|
||||
else:
|
||||
return [ins.etud for ins in self.inscriptions if ins.etat == scu.INSCRIT]
|
||||
|
||||
@cached_property
|
||||
def etuds_inscriptions(self) -> dict:
|
||||
"""Map { etudid : inscription }"""
|
||||
"""Map { etudid : inscription } (incluant DEM et DEF)"""
|
||||
return {ins.etud.id: ins for ins in self.inscriptions}
|
||||
|
||||
|
||||
|
@ -62,7 +62,7 @@ Pour modifier les moyennes d'UE:
|
||||
|
||||
La valeur retournée est:
|
||||
- formations classiques: ajoutée à la moyenne générale
|
||||
- BUT: ajoutée à chaque UE si le coef XXX
|
||||
- BUT: valeur multipliée par la somme des coefs modules sport ajoutée à chaque UE.
|
||||
|
||||
"""
|
||||
|
||||
|
@ -171,6 +171,7 @@ class NotesTable:
|
||||
|
||||
def __init__(self, formsemestre_id):
|
||||
log(f"NotesTable( formsemestre_id={formsemestre_id} )")
|
||||
# raise NotImplementedError() # XXX
|
||||
if not formsemestre_id:
|
||||
raise ValueError("invalid formsemestre_id (%s)" % formsemestre_id)
|
||||
self.formsemestre_id = formsemestre_id
|
||||
@ -409,7 +410,7 @@ class NotesTable:
|
||||
return ""
|
||||
|
||||
def get_etud_etat_html(self, etudid):
|
||||
etat = self.inscrdict[etudid]["etat"]
|
||||
|
||||
if etat == "I":
|
||||
return ""
|
||||
elif etat == "D":
|
||||
|
@ -48,6 +48,9 @@ import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app import log
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_common import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||
from app.scodoc import html_sco_header
|
||||
@ -136,7 +139,9 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
raise ValueError("invalid version code !")
|
||||
|
||||
prefs = sco_preferences.SemPreferences(formsemestre_id)
|
||||
nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes
|
||||
# nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes
|
||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_result(formsemestre)
|
||||
if not nt.get_etud_etat(etudid):
|
||||
raise ScoValueError("Etudiant non inscrit à ce semestre")
|
||||
I = scu.DictDefault(defaultvalue="")
|
||||
@ -191,7 +196,9 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
I["decision_sem"] = ""
|
||||
I.update(infos)
|
||||
|
||||
I["etud_etat_html"] = nt.get_etud_etat_html(etudid)
|
||||
I["etud_etat_html"] = _get_etud_etat_html(
|
||||
formsemestre.etuds_inscriptions[etudid].etat
|
||||
)
|
||||
I["etud_etat"] = nt.get_etud_etat(etudid)
|
||||
I["filigranne"] = ""
|
||||
I["demission"] = ""
|
||||
@ -261,17 +268,18 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
# notes en attente dans ce semestre
|
||||
rang = scu.RANG_ATTENTE_STR
|
||||
rang_gr = scu.DictDefault(defaultvalue=scu.RANG_ATTENTE_STR)
|
||||
inscriptions_counts = nt.get_inscriptions_counts()
|
||||
I["rang"] = rang
|
||||
I["rang_gr"] = rang_gr
|
||||
I["gr_name"] = gr_name
|
||||
I["ninscrits_gr"] = ninscrits_gr
|
||||
I["nbetuds"] = len(nt.etud_moy_gen_ranks)
|
||||
I["nb_demissions"] = nt.nb_demissions
|
||||
I["nb_defaillants"] = nt.nb_defaillants
|
||||
I["nb_demissions"] = inscriptions_counts[scu.DEMISSION]
|
||||
I["nb_defaillants"] = inscriptions_counts[scu.DEF]
|
||||
if prefs["bul_show_rangs"]:
|
||||
I["rang_nt"] = "%s / %d" % (
|
||||
rang,
|
||||
I["nbetuds"] - nt.nb_demissions - nt.nb_defaillants,
|
||||
inscriptions_counts[scu.INSCRIT],
|
||||
)
|
||||
I["rang_txt"] = "Rang " + I["rang_nt"]
|
||||
else:
|
||||
@ -379,7 +387,8 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
I["ues"].append(u) # ne montre pas les UE si non inscrit
|
||||
|
||||
# Accès par matieres
|
||||
I["matieres_modules"].update(_sort_mod_by_matiere(modules, nt, etudid))
|
||||
# voir si on supporte encore cela en #sco92 XXX
|
||||
# I["matieres_modules"].update(_sort_mod_by_matiere(modules, nt, etudid))
|
||||
|
||||
#
|
||||
C = make_context_dict(I["sem"], I["etud"])
|
||||
@ -389,6 +398,18 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
return C
|
||||
|
||||
|
||||
def _get_etud_etat_html(etat: str) -> str:
|
||||
"""chaine html représentant l'état (backward compat sco7)"""
|
||||
if etat == scu.INSCRIT: # "I"
|
||||
return ""
|
||||
elif etat == scu.DEMISSION: # "D"
|
||||
return ' <font color="red">(DEMISSIONNAIRE)</font> '
|
||||
elif etat == scu.DEF: # "DEF"
|
||||
return ' <font color="red">(DEFAILLANT)</font> '
|
||||
else:
|
||||
return ' <font color="red">(%s)</font> ' % etat
|
||||
|
||||
|
||||
def _sort_mod_by_matiere(modlist, nt, etudid):
|
||||
matmod = {} # { matiere_id : [] }
|
||||
for mod in modlist:
|
||||
|
@ -1433,18 +1433,19 @@ def create_etapes_partition(formsemestre_id, partition_name="apo_etapes"):
|
||||
|
||||
|
||||
def do_evaluation_listeetuds_groups(
|
||||
evaluation_id, groups=None, getallstudents=False, include_dems=False
|
||||
evaluation_id, groups=None, getallstudents=False, include_demdef=False
|
||||
):
|
||||
"""Donne la liste des etudids inscrits a cette evaluation dans les
|
||||
groupes indiqués.
|
||||
Si getallstudents==True, donne tous les etudiants inscrits a cette
|
||||
evaluation.
|
||||
Si include_dems, compte aussi les etudiants démissionnaires
|
||||
Si include_demdef, compte aussi les etudiants démissionnaires et défaillants
|
||||
(sinon, par défaut, seulement les 'I')
|
||||
|
||||
Résultat: [ (etudid, etat) ], où etat='I', 'D', 'DEF'
|
||||
"""
|
||||
# nb: pour notes_table / do_evaluation_etat, getallstudents est vrai et include_dems faux
|
||||
# nb: pour notes_table / do_evaluation_etat, getallstudents est vrai et
|
||||
# include_demdef faux
|
||||
fromtables = [
|
||||
"notes_moduleimpl_inscription Im",
|
||||
"notes_formsemestre_inscription Isem",
|
||||
@ -1476,7 +1477,7 @@ def do_evaluation_listeetuds_groups(
|
||||
and E.id = %(evaluation_id)s
|
||||
"""
|
||||
)
|
||||
if not include_dems:
|
||||
if not include_demdef:
|
||||
req += " and Isem.etat='I'"
|
||||
req += r
|
||||
cnx = ndb.GetDBConnexion()
|
||||
|
@ -309,7 +309,7 @@ def _make_table_notes(
|
||||
anonymous_lst_key = "etudid"
|
||||
|
||||
etudid_etats = sco_groups.do_evaluation_listeetuds_groups(
|
||||
E["evaluation_id"], groups, include_dems=True
|
||||
E["evaluation_id"], groups, include_demdef=True
|
||||
)
|
||||
for etudid, etat in etudid_etats:
|
||||
css_row_class = None
|
||||
|
@ -307,7 +307,7 @@ class PlacementRunner:
|
||||
self.evaluation_id,
|
||||
self.groups,
|
||||
getallstudents=get_all_students,
|
||||
include_dems=True,
|
||||
include_demdef=True,
|
||||
)
|
||||
listetud = [] # liste de couples (nom,prenom)
|
||||
for etudid, etat in etudid_etats:
|
||||
|
@ -306,8 +306,8 @@ def make_formsemestre_recapcomplet(
|
||||
)[0]
|
||||
parcours = formsemestre.formation.get_parcours()
|
||||
|
||||
# nt = sco_cache.NotesTableCache.get(formsemestre_id)
|
||||
# XXX EXPERIMENTAL
|
||||
# nt = sco_cache.NotesTableCache.get(formsemestre_id) # sco91
|
||||
# sco92 :
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_result(formsemestre)
|
||||
modimpls = nt.get_modimpls_dict()
|
||||
ues = nt.get_ues_stat_dict() # incluant le(s) UE de sport
|
||||
@ -434,13 +434,12 @@ def make_formsemestre_recapcomplet(
|
||||
|
||||
e["admission"] = {}
|
||||
if not hidebac:
|
||||
if etud_etat == scu.INSCRIT:
|
||||
e["admission"] = nt.etuds_dict[etudid].admission.first()
|
||||
if e["admission"]:
|
||||
bac = nt.etuds_dict[etudid].admission[0].get_bac()
|
||||
l.append(bac.abbrev())
|
||||
else:
|
||||
l.append("")
|
||||
e["admission"] = nt.etuds_dict[etudid].admission.first()
|
||||
if e["admission"]:
|
||||
bac = nt.etuds_dict[etudid].admission[0].get_bac()
|
||||
l.append(bac.abbrev())
|
||||
else:
|
||||
l.append("")
|
||||
|
||||
if format[:3] == "xls" or format == "csv": # tous les groupes
|
||||
for partition in partitions:
|
||||
|
@ -310,7 +310,7 @@ def do_evaluation_set_missing(evaluation_id, value, dialog_confirmed=False):
|
||||
#
|
||||
NotesDB = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
|
||||
etudid_etats = sco_groups.do_evaluation_listeetuds_groups(
|
||||
evaluation_id, getallstudents=True, include_dems=False
|
||||
evaluation_id, getallstudents=True, include_demdef=False
|
||||
)
|
||||
notes = []
|
||||
for etudid, _ in etudid_etats: # pour tous les inscrits
|
||||
@ -482,7 +482,7 @@ def notes_add(
|
||||
inscrits = {
|
||||
x[0]
|
||||
for x in sco_groups.do_evaluation_listeetuds_groups(
|
||||
evaluation_id, getallstudents=True, include_dems=True
|
||||
evaluation_id, getallstudents=True, include_demdef=True
|
||||
)
|
||||
}
|
||||
for (etudid, value) in notes:
|
||||
@ -833,7 +833,7 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
||||
etudids = [
|
||||
x[0]
|
||||
for x in sco_groups.do_evaluation_listeetuds_groups(
|
||||
evaluation_id, groups, getallstudents=getallstudents, include_dems=True
|
||||
evaluation_id, groups, getallstudents=getallstudents, include_demdef=True
|
||||
)
|
||||
]
|
||||
|
||||
@ -1079,7 +1079,7 @@ def _form_saisie_notes(E, M, group_ids, destination=""):
|
||||
etudids = [
|
||||
x[0]
|
||||
for x in sco_groups.do_evaluation_listeetuds_groups(
|
||||
evaluation_id, getallstudents=True, include_dems=True
|
||||
evaluation_id, getallstudents=True, include_demdef=True
|
||||
)
|
||||
]
|
||||
if not etudids:
|
||||
|
Loading…
Reference in New Issue
Block a user