Module PE pour 9.1.50 - ok (à peu près) mais totalement inefficace/inutilisable.

This commit is contained in:
Emmanuel Viennet 2022-02-11 23:12:40 +01:00
parent e5b212a6e6
commit 7923921777
7 changed files with 89 additions and 81 deletions

View File

@ -6,9 +6,11 @@
"""Résultats semestres BUT """Résultats semestres BUT
""" """
import time
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from app import log
from app.comp import moy_ue, moy_sem, inscr_mod from app.comp import moy_ue, moy_sem, inscr_mod
from app.comp.res_common import NotesTableCompat from app.comp.res_common import NotesTableCompat
from app.comp.bonus_spo import BonusSport from app.comp.bonus_spo import BonusSport
@ -30,8 +32,14 @@ class ResultatsSemestreBUT(NotesTableCompat):
super().__init__(formsemestre) super().__init__(formsemestre)
if not self.load_cached(): if not self.load_cached():
t0 = time.time()
self.compute() self.compute()
t1 = time.time()
self.store() self.store()
t2 = time.time()
log(
f"ResultatsSemestreBUT: cached formsemestre_id={formsemestre.id} ({(t1-t0):g}s +{(t2-t1):g}s)"
)
def compute(self): def compute(self):
"Charge les notes et inscriptions et calcule les moyennes d'UE et gen." "Charge les notes et inscriptions et calcule les moyennes d'UE et gen."

View File

@ -6,7 +6,7 @@
"""Résultats semestres classiques (non APC) """Résultats semestres classiques (non APC)
""" """
import time
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from sqlalchemy.sql import text from sqlalchemy.sql import text
@ -40,8 +40,14 @@ class ResultatsSemestreClassic(NotesTableCompat):
super().__init__(formsemestre) super().__init__(formsemestre)
if not self.load_cached(): if not self.load_cached():
t0 = time.time()
self.compute() self.compute()
t1 = time.time()
self.store() self.store()
t2 = time.time()
log(
f"ResultatsSemestreClassic: cached formsemestre_id={formsemestre.id} ({(t1-t0):g}s +{(t2-t1):g}s)"
)
# recalculé (aussi rapide que de les cacher) # recalculé (aussi rapide que de les cacher)
self.moy_min = self.etud_moy_gen.min() self.moy_min = self.etud_moy_gen.min()
self.moy_max = self.etud_moy_gen.max() self.moy_max = self.etud_moy_gen.max()

View File

@ -213,9 +213,10 @@ class ResultatsSemestre(ResultatsCache):
def get_etud_ue_status(self, etudid: int, ue_id: int) -> dict: def get_etud_ue_status(self, etudid: int, ue_id: int) -> dict:
"""L'état de l'UE pour cet étudiant. """L'état de l'UE pour cet étudiant.
L'UE doit être du semestre. Result: dict, ou None si l'UE n'est pas dans ce semestre.
Result: dict.
""" """
if not ue_id in self.etud_moy_ue:
return None
if not self.validations: if not self.validations:
self.validations = res_sem.load_formsemestre_validations(self.formsemestre) self.validations = res_sem.load_formsemestre_validations(self.formsemestre)
ue = UniteEns.query.get(ue_id) # TODO cacher nos UEs ? ue = UniteEns.query.get(ue_id) # TODO cacher nos UEs ?
@ -333,8 +334,8 @@ class NotesTableCompat(ResultatsSemestre):
@cached_property @cached_property
def sem(self) -> dict: def sem(self) -> dict:
"""le formsemestre, comme un dict (nt.sem)""" """le formsemestre, comme un gros et gras dict (nt.sem)"""
return self.formsemestre.to_dict() return self.formsemestre.get_infos_dict()
@cached_property @cached_property
def inscrlist(self) -> list[dict]: # utilisé par PE seulement def inscrlist(self) -> list[dict]: # utilisé par PE seulement

View File

@ -25,7 +25,7 @@ def load_formsemestre_results(formsemestre: FormSemestre) -> ResultatsSemestre:
""" """
# --- Try local cache (within the same request context) # --- Try local cache (within the same request context)
if not hasattr(g, "formsemestre_results_cache"): if not hasattr(g, "formsemestre_results_cache"):
g.formsemestre_results_cache = {} # pylint: disable=C0237 g.formsemestre_results_cache = {}
else: else:
if formsemestre.id in g.formsemestre_results_cache: if formsemestre.id in g.formsemestre_results_cache:
return g.formsemestre_results_cache[formsemestre.id] return g.formsemestre_results_cache[formsemestre.id]

View File

@ -1133,7 +1133,7 @@ class JuryPE(object):
def get_cache_notes_d_un_semestre(self, formsemestre_id: int) -> NotesTableCompat: def get_cache_notes_d_un_semestre(self, formsemestre_id: int) -> NotesTableCompat:
"""Charge la table des notes d'un formsemestre""" """Charge la table des notes d'un formsemestre"""
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) return res_sem.load_formsemestre_results(formsemestre)
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------

View File

@ -40,6 +40,7 @@ from app import log
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_common import NotesTableCompat from app.comp.res_common import NotesTableCompat
from app.models import FormSemestre from app.models import FormSemestre
from app.models.moduleimpls import ModuleImpl
from app.models.ues import UniteEns from app.models.ues import UniteEns
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
@ -55,7 +56,7 @@ class SemestreTag(pe_tagtable.TableTag):
- nt: le tableau de notes du semestre considéré - nt: le tableau de notes du semestre considéré
- nt.inscrlist: étudiants inscrits à ce semestre, par ordre alphabétique (avec demissions) - nt.inscrlist: étudiants inscrits à ce semestre, par ordre alphabétique (avec demissions)
- nt.identdict: { etudid : ident } - nt.identdict: { etudid : ident }
- nt._modimpls : liste des moduleimpl { ... 'module_id', ...} - liste des moduleimpl { ... 'module_id', ...}
Attributs supplémentaires : Attributs supplémentaires :
- inscrlist/identdict: étudiants inscrits hors démissionnaires ou défaillants - inscrlist/identdict: étudiants inscrits hors démissionnaires ou défaillants
@ -100,7 +101,11 @@ class SemestreTag(pe_tagtable.TableTag):
self.nt = notetable self.nt = notetable
# Les attributs hérités : la liste des étudiants # Les attributs hérités : la liste des étudiants
self.inscrlist = [etud for etud in self.nt.inscrlist if etud["etat"] == "I"] self.inscrlist = [
etud
for etud in self.nt.inscrlist
if self.nt.get_etud_etat(etud["etudid"]) == "I"
]
self.identdict = { self.identdict = {
etudid: ident etudid: ident
for (etudid, ident) in self.nt.identdict.items() for (etudid, ident) in self.nt.identdict.items()
@ -110,12 +115,15 @@ class SemestreTag(pe_tagtable.TableTag):
# Les modules pris en compte dans le calcul des moyennes par tag => ceux des UE standards # Les modules pris en compte dans le calcul des moyennes par tag => ceux des UE standards
self.modimpls = [ self.modimpls = [
modimpl modimpl
for modimpl in self.nt._modimpls for modimpl in self.nt.formsemestre.modimpls_sorted
if modimpl["ue"]["type"] == sco_codes_parcours.UE_STANDARD if modimpl.module.ue.type == sco_codes_parcours.UE_STANDARD
] # la liste des modules (objet modimpl) ] # la liste des modules (objet modimpl)
# self._modimpl_ids = [modimpl['moduleimpl_id'] for modimpl in self._modimpls] # la liste de id des modules (modimpl_id)
self.somme_coeffs = sum( self.somme_coeffs = sum(
[modimpl["module"]["coefficient"] for modimpl in self.modimpls] [
modimpl.module.coefficient
for modimpl in self.modimpls
if modimpl.module.coefficient is not None
]
) )
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@ -159,9 +167,9 @@ class SemestreTag(pe_tagtable.TableTag):
tagdict = {} tagdict = {}
for modimpl in self.modimpls: for modimpl in self.modimpls:
modimpl_id = modimpl["moduleimpl_id"] modimpl_id = modimpl.id
# liste des tags pour le modimpl concerné: # liste des tags pour le modimpl concerné:
tags = sco_tag_module.module_tag_list(modimpl["module_id"]) tags = sco_tag_module.module_tag_list(modimpl.module.id)
for ( for (
tag tag
@ -175,17 +183,13 @@ class SemestreTag(pe_tagtable.TableTag):
# Ajout du modimpl au tagname considéré # Ajout du modimpl au tagname considéré
tagdict[tagname][modimpl_id] = { tagdict[tagname][modimpl_id] = {
"module_id": modimpl["module_id"], # les données sur le module "module_id": modimpl.module.id, # les données sur le module
"coeff": modimpl["module"][ "coeff": modimpl.module.coefficient, # le coeff du module dans le semestre
"coefficient"
], # le coeff du module dans le semestre
"ponderation": ponderation, # la pondération demandée pour le tag sur le module "ponderation": ponderation, # la pondération demandée pour le tag sur le module
"module_code": modimpl["module"][ "module_code": modimpl.module.code, # le code qui doit se retrouver à l'identique dans des ue capitalisee
"code" "ue_id": modimpl.module.ue.id, # les données sur l'ue
], # le code qui doit se retrouver à l'identique dans des ue capitalisee "ue_code": modimpl.module.ue.ue_code,
"ue_id": modimpl["ue"]["ue_id"], # les données sur l'ue "ue_acronyme": modimpl.module.ue.acronyme,
"ue_code": modimpl["ue"]["ue_code"],
"ue_acronyme": modimpl["ue"]["acronyme"],
} }
return tagdict return tagdict
@ -221,7 +225,9 @@ class SemestreTag(pe_tagtable.TableTag):
def get_moyennes_DUT(self): def get_moyennes_DUT(self):
"""Lit les moyennes DUT du semestre pour tous les étudiants """Lit les moyennes DUT du semestre pour tous les étudiants
et les renvoie au même format que comp_MoyennesTag""" et les renvoie au même format que comp_MoyennesTag"""
return [(self.nt.moy_gen[etudid], 1.0, etudid) for etudid in self.get_etudids()] return [
(self.nt.etud_moy_gen[etudid], 1.0, etudid) for etudid in self.get_etudids()
]
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_noteEtCoeff_modimpl(self, modimpl_id, etudid, profondeur=2): def get_noteEtCoeff_modimpl(self, modimpl_id, etudid, profondeur=2):
@ -233,7 +239,7 @@ class SemestreTag(pe_tagtable.TableTag):
""" """
(note, coeff_norm) = (None, None) (note, coeff_norm) = (None, None)
modimpl = get_moduleimpl(self.nt, modimpl_id) # Le module considéré modimpl = get_moduleimpl(modimpl_id) # Le module considéré
if modimpl == None or profondeur < 0: if modimpl == None or profondeur < 0:
return (None, None) return (None, None)
@ -241,14 +247,14 @@ class SemestreTag(pe_tagtable.TableTag):
ue_capitalisees = self.get_ue_capitalisees( ue_capitalisees = self.get_ue_capitalisees(
etudid etudid
) # les ue capitalisées des étudiants ) # les ue capitalisées des étudiants
ue_capitalisees_id = [ ue_capitalisees_id = {
ue.id for ue in ue_capitalisees ue_cap["ue_id"] for ue_cap in ue_capitalisees
] # les id des ue capitalisées } # les id des ue capitalisées
# Si le module ne fait pas partie des UE capitalisées # Si le module ne fait pas partie des UE capitalisées
if modimpl["module"]["ue_id"] not in ue_capitalisees_id: if modimpl.module.ue.id not in ue_capitalisees_id:
note = self.nt.get_etud_mod_moy(modimpl_id, etudid) # lecture de la note note = self.nt.get_etud_mod_moy(modimpl_id, etudid) # lecture de la note
coeff = modimpl["module"]["coefficient"] # le coeff coeff = modimpl.module.coefficient # le coeff
coeff_norm = ( coeff_norm = (
coeff / self.somme_coeffs if self.somme_coeffs != 0 else 0 coeff / self.somme_coeffs if self.somme_coeffs != 0 else 0
) # le coeff normalisé ) # le coeff normalisé
@ -259,12 +265,10 @@ class SemestreTag(pe_tagtable.TableTag):
self.nt, etudid, modimpl_id self.nt, etudid, modimpl_id
) # la moyenne actuelle ) # la moyenne actuelle
# A quel semestre correspond l'ue capitalisée et quelles sont ses notes ? # A quel semestre correspond l'ue capitalisée et quelles sont ses notes ?
# fid_prec = [ ue['formsemestre_id'] for ue in ue_capitalisees if ue['ue_id'] == modimpl['module']['ue_id'] ][0]
# semestre_id = modimpl['module']['semestre_id']
fids_prec = [ fids_prec = [
ue["formsemestre_id"] ue_cap["formsemestre_id"]
for ue in ue_capitalisees for ue_cap in ue_capitalisees
if ue.ue_code == modimpl["ue"]["ue_code"] if ue_cap["ue_code"] == modimpl.module.ue.ue_code
] # and ue['semestre_id'] == semestre_id] ] # and ue['semestre_id'] == semestre_id]
if len(fids_prec) > 0: if len(fids_prec) > 0:
# => le formsemestre_id du semestre dont vient la capitalisation # => le formsemestre_id du semestre dont vient la capitalisation
@ -277,13 +281,14 @@ class SemestreTag(pe_tagtable.TableTag):
) )
# Y-a-t-il un module équivalent c'est à dire correspondant au même code (le module_id n'étant pas significatif en cas de changement de PPN) # Y-a-t-il un module équivalent c'est à dire correspondant au même code (le module_id n'étant pas significatif en cas de changement de PPN)
modimpl_prec = [ modimpl_prec = [
module modi
for module in nt_prec._modimpls for modi in nt_prec.formsemestre.modimpls_sorted
if module["module"]["code"] == modimpl["module"]["code"] if modi.module.code == modimpl.module.code
] ]
if len(modimpl_prec) > 0: # si une correspondance est trouvée if len(modimpl_prec) > 0: # si une correspondance est trouvée
modprec_id = modimpl_prec[0]["moduleimpl_id"] modprec_id = modimpl_prec[0].id
moy_ue_capitalisee = get_moy_ue_from_nt(nt_prec, etudid, modprec_id) moy_ue_capitalisee = get_moy_ue_from_nt(nt_prec, etudid, modprec_id)
if ( if (
moy_ue_capitalisee is None moy_ue_capitalisee is None
@ -291,7 +296,7 @@ class SemestreTag(pe_tagtable.TableTag):
note = self.nt.get_etud_mod_moy( note = self.nt.get_etud_mod_moy(
modimpl_id, etudid modimpl_id, etudid
) # lecture de la note ) # lecture de la note
coeff = modimpl["module"]["coefficient"] # le coeff coeff = modimpl.module.coefficient # le coeff
coeff_norm = ( coeff_norm = (
coeff / self.somme_coeffs if self.somme_coeffs != 0 else 0 coeff / self.somme_coeffs if self.somme_coeffs != 0 else 0
) # le coeff normalisé ) # le coeff normalisé
@ -305,13 +310,11 @@ class SemestreTag(pe_tagtable.TableTag):
return (note, coeff_norm) return (note, coeff_norm)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_ue_capitalisees(self, etudid) -> list[UniteEns]: def get_ue_capitalisees(self, etudid) -> list[dict]:
"""Renvoie la liste des ue_id effectivement capitalisées par un étudiant""" """Renvoie la liste des capitalisation effectivement capitalisées par un étudiant"""
ue_ids = [ if etudid in self.nt.validations.ue_capitalisees.index:
ue_id return self.nt.validations.ue_capitalisees.loc[[etudid]].to_dict("records")
for ue_id in self.nt.validations.ue_capitalisees.loc[[etudid]]["ue_id"] return []
]
return [UniteEns.query.get(ue_id) for ue_id in ue_ids]
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_listesNotesEtCoeffsTagEtudiant(self, tag, etudid): def get_listesNotesEtCoeffsTagEtudiant(self, tag, etudid):
@ -477,37 +480,27 @@ def comp_coeff_pond(coeffs, ponderations):
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_moduleimpl(nt, modimpl_id): def get_moduleimpl(modimpl_id) -> dict:
"""Renvoie l'objet modimpl dont l'id est modimpl_id fourni dans la note table nt, """Renvoie l'objet modimpl dont l'id est modimpl_id"""
en utilisant l'attribut nt._modimpls""" modimpl = ModuleImpl.query.get(modimpl_id)
modimplids = [ if modimpl:
modimpl["moduleimpl_id"] for modimpl in nt._modimpls return modimpl
] # la liste de id des modules (modimpl_id)
if modimpl_id not in modimplids:
if SemestreTag.DEBUG: if SemestreTag.DEBUG:
log( log(
"SemestreTag.get_moduleimpl( %s ) : le modimpl recherche n'existe pas" "SemestreTag.get_moduleimpl( %s ) : le modimpl recherche n'existe pas"
% (modimpl_id) % (modimpl_id)
) )
return None return None
return nt._modimpls[modimplids.index(modimpl_id)]
# ********************************************** # **********************************************
def get_moy_ue_from_nt(nt, etudid, modimpl_id): def get_moy_ue_from_nt(nt, etudid, modimpl_id) -> float:
"""Renvoie la moyenne de l'UE d'un etudid dans laquelle se trouve le module de modimpl_id """Renvoie la moyenne de l'UE d'un etudid dans laquelle se trouve
en partant du note table nt""" le module de modimpl_id
mod = get_moduleimpl(nt, modimpl_id) # le module """
indice = 0 # ré-écrit
while indice < len(nt._ues): modimpl = get_moduleimpl(modimpl_id) # le module
if ( ue_status = nt.get_etud_ue_status(etudid, modimpl.module.ue.id)
nt._ues[indice]["ue_id"] == mod["module"]["ue_id"] if ue_status is None:
): # si les ue_id correspond return None
data = [ return ue_status["moy"]
ligne for ligne in nt.T if ligne[-1] == etudid
] # les notes de l'étudiant
if data:
return data[0][indice + 1] # la moyenne à l'ue
else:
indice += 1
return None # si non trouvé

View File

@ -68,7 +68,7 @@ class TableTag(object):
self.taglist = [] self.taglist = []
self.resultats = {} self.resultats = {}
self.etud_moy_gen_ranks = {} self.rangs = {}
self.statistiques = {} self.statistiques = {}
# ***************************************************************************************************************** # *****************************************************************************************************************