Bonus sport multiplicatifs ou additifs sur bulletins DUT et BUT
This commit is contained in:
parent
7e4459a15e
commit
23672bebde
@ -28,21 +28,29 @@ class BulletinBUT(ResultatsSemestreBUT):
|
||||
"dict synthèse résultats dans l'UE pour les modules indiqués"
|
||||
d = {}
|
||||
etud_idx = self.etud_index[etud.id]
|
||||
ue_idx = self.modimpl_coefs_df.index.get_loc(ue.id)
|
||||
if ue.type != UE_SPORT:
|
||||
ue_idx = self.modimpl_coefs_df.index.get_loc(ue.id)
|
||||
etud_moy_module = self.sem_cube[etud_idx] # module x UE
|
||||
for modimpl in modimpls:
|
||||
if self.modimpl_inscr_df[str(modimpl.id)][etud.id]: # si inscrit
|
||||
coef = self.modimpl_coefs_df[modimpl.id][ue.id]
|
||||
if coef > 0:
|
||||
d[modimpl.module.code] = {
|
||||
"id": modimpl.id,
|
||||
"coef": coef,
|
||||
"moyenne": fmt_note(
|
||||
etud_moy_module[
|
||||
self.modimpl_coefs_df.columns.get_loc(modimpl.id)
|
||||
][ue_idx]
|
||||
),
|
||||
}
|
||||
if ue.type != UE_SPORT:
|
||||
coef = self.modimpl_coefs_df[modimpl.id][ue.id]
|
||||
if coef > 0:
|
||||
d[modimpl.module.code] = {
|
||||
"id": modimpl.id,
|
||||
"coef": coef,
|
||||
"moyenne": fmt_note(
|
||||
etud_moy_module[
|
||||
self.modimpl_coefs_df.columns.get_loc(modimpl.id)
|
||||
][ue_idx]
|
||||
),
|
||||
}
|
||||
# else: # modules dans UE bonus sport
|
||||
# d[modimpl.module.code] = {
|
||||
# "id": modimpl.id,
|
||||
# "coef": "",
|
||||
# "moyenne": "?x?",
|
||||
# }
|
||||
return d
|
||||
|
||||
def etud_ue_results(self, etud, ue):
|
||||
|
@ -38,7 +38,7 @@ class BonusSport:
|
||||
notes moyennes aux modules (tous les étuds x tous les modimpls)
|
||||
floats avec des NaN.
|
||||
En classique: sem_matrix, ndarray (etuds x modimpls)
|
||||
En APC: sem_cube, ndarray (etuds x modimpls x UEs)
|
||||
En APC: sem_cube, ndarray (etuds x modimpls x UEs non bonus)
|
||||
- ues: les ues du semestre (incluant le bonus sport)
|
||||
- modimpl_inscr_df: matrice d'inscription aux modules du semestre (etud x modimpl)
|
||||
- modimpl_coefs: les coefs des modules
|
||||
@ -50,10 +50,9 @@ class BonusSport:
|
||||
etud_moy_gen et etud_moy_ue ne sont PAS modifiés (mais utilisés par certains bonus non additifs).
|
||||
"""
|
||||
|
||||
# Si vrai, en APC, si le bonus UE est None, reporte le bonus moy gen:
|
||||
apc_apply_bonus_mg_to_ues = True
|
||||
# Si True, reporte toujours le bonus moy gen sur les UE (même en formations classiques)
|
||||
apply_bonus_mg_to_ues = False
|
||||
# En classique, active un bonus sur les UEs: (dans ce cas bonus_moy_gen reste None)
|
||||
classic_use_bonus_ues = False
|
||||
|
||||
# Attributs virtuels:
|
||||
seuil_moy_gen = None
|
||||
proportion_point = None
|
||||
@ -77,7 +76,7 @@ class BonusSport:
|
||||
self.etud_moy_ue = etud_moy_ue
|
||||
self.etuds_idx = modimpl_inscr_df.index # les étudiants inscrits au semestre
|
||||
self.bonus_ues: pd.DataFrame = None # virtual
|
||||
self.bonus_moy_gen: pd.Series = None # virtual
|
||||
self.bonus_moy_gen: pd.Series = None # virtual (pour formations non apc slt)
|
||||
# Restreint aux modules standards des UE de type "sport":
|
||||
modimpl_mask = np.array(
|
||||
[
|
||||
@ -94,13 +93,14 @@ class BonusSport:
|
||||
"liste des modimpls sport"
|
||||
|
||||
# Les moyennes des modules "sport": (une par UE en APC)
|
||||
# donc (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
||||
sem_modimpl_moys_spo = sem_modimpl_moys[:, modimpl_mask]
|
||||
# Les inscriptions aux modules sport:
|
||||
modimpl_inscr_spo = modimpl_inscr_df.values[:, modimpl_mask]
|
||||
# Les coefficients des modules sport (en apc: nb_mod_sport x nb_ue)
|
||||
# Les coefficients des modules sport (en apc: nb_mod_sport x nb_ue) (toutes ues)
|
||||
modimpl_coefs_spo = modimpl_coefs[modimpl_mask]
|
||||
# sem_modimpl_moys_spo est (nb_etuds, nb_mod_sport)
|
||||
# ou (nb_etuds, nb_mod_sport, nb_ues)
|
||||
# ou (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
||||
nb_etuds, nb_mod_sport = sem_modimpl_moys_spo.shape[:2]
|
||||
nb_ues = len(ues)
|
||||
# Enlève les NaN du numérateur:
|
||||
@ -115,7 +115,7 @@ class BonusSport:
|
||||
[modimpl_inscr_spo] * nb_ues_no_bonus, axis=2
|
||||
)
|
||||
# Ne prend pas en compte les notes des étudiants non inscrits au module:
|
||||
# Annule les notes:
|
||||
# Annule les notes: (nb_etuds, nb_mod_bonus, nb_ues_non_bonus)
|
||||
sem_modimpl_moys_inscrits = np.where(
|
||||
modimpl_inscr_spo_stacked, sem_modimpl_moys_no_nan, 0.0
|
||||
)
|
||||
@ -151,7 +151,7 @@ class BonusSport:
|
||||
"""Calcul des bonus: méthode virtuelle à écraser.
|
||||
Arguments:
|
||||
- sem_modimpl_moys_inscrits:
|
||||
ndarray (nb_etuds, mod_sport) ou en APC (nb_etuds, mods_sport, nb_ue)
|
||||
ndarray (nb_etuds, mod_sport) ou en APC (nb_etuds, mods_sport, nb_ue_non_bonus)
|
||||
les notes aux modules sports auxquel l'étudiant est inscrit, 0 sinon. Pas de nans.
|
||||
- modimpl_coefs_etuds_no_nan:
|
||||
les coefficients: float ndarray
|
||||
@ -164,24 +164,16 @@ class BonusSport:
|
||||
"""Les bonus à appliquer aux UE
|
||||
Résultat: DataFrame de float, index etudid, columns: ue.id
|
||||
"""
|
||||
if self.bonus_ues is None and (
|
||||
(self.apc_apply_bonus_mg_to_ues and self.formsemestre.formation.is_apc())
|
||||
or self.apply_bonus_mg_to_ues
|
||||
):
|
||||
# reporte uniformément le bonus moyenne générale sur les UEs
|
||||
# (assure la compatibilité de la plupart des anciens bonus avec le BUT)
|
||||
# ues = self.formsemestre.query_ues(with_sport=False)
|
||||
ues_idx = [ue.id for ue in self.formsemestre.query_ues(with_sport=False)]
|
||||
bonus_moy_gen = self.get_bonus_moy_gen()
|
||||
bonus_ues = np.stack([bonus_moy_gen.values] * len(ues_idx), axis=1)
|
||||
return pd.DataFrame(bonus_ues, index=self.etuds_idx, columns=ues_idx)
|
||||
|
||||
return self.bonus_ues
|
||||
if self.classic_use_bonus_ues or self.formsemestre.formation.is_apc():
|
||||
return self.bonus_ues
|
||||
return None
|
||||
|
||||
def get_bonus_moy_gen(self):
|
||||
"""Le bonus à appliquer à la moyenne générale.
|
||||
Résultat: Series de float, index etudid
|
||||
"""
|
||||
if self.formsemestre.formation.is_apc():
|
||||
return None # garde-fou
|
||||
return self.bonus_moy_gen
|
||||
|
||||
|
||||
@ -200,8 +192,12 @@ class BonusSportAdditif(BonusSport):
|
||||
proportion_point = 0.05 # multiplie les points au dessus du seuil
|
||||
|
||||
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
||||
"""calcul du bonus"""
|
||||
bonus_moy_gen_arr = np.sum(
|
||||
"""calcul du bonus
|
||||
sem_modimpl_moys_inscrits: les notes de sport
|
||||
En APC: ndarray (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
||||
modimpl_coefs_etuds_no_nan:
|
||||
"""
|
||||
bonus_moy_arr = np.sum(
|
||||
np.where(
|
||||
sem_modimpl_moys_inscrits > self.seuil_moy_gen,
|
||||
(sem_modimpl_moys_inscrits - self.seuil_moy_gen)
|
||||
@ -210,18 +206,28 @@ class BonusSportAdditif(BonusSport):
|
||||
),
|
||||
axis=1,
|
||||
)
|
||||
# en APC, applati la moyenne gen. XXX pourrait être fait en amont
|
||||
if len(bonus_moy_gen_arr.shape) > 1:
|
||||
bonus_moy_gen_arr = bonus_moy_gen_arr.sum(axis=1)
|
||||
# Bonus moyenne générale, et 0 sur les UE
|
||||
self.bonus_moy_gen = pd.Series(
|
||||
bonus_moy_gen_arr, index=self.etuds_idx, dtype=float
|
||||
)
|
||||
if self.bonus_max is not None:
|
||||
# Seuil: bonus (sur moy. gen.) limité à bonus_max points
|
||||
self.bonus_moy_gen = self.bonus_moy_gen.clip(upper=self.bonus_max)
|
||||
# Seuil: bonus limité à bonus_max points (et >= 0)
|
||||
bonus_moy_arr = np.clip(
|
||||
bonus_moy_arr, 0.0, self.bonus_max, out=bonus_moy_arr
|
||||
)
|
||||
|
||||
# Laisse bonus_ues à None, en APC le bonus moy. gen. sera réparti sur les UEs.
|
||||
# en APC, bonus_moy_arr est (nb_etuds, nb_ues_non_bonus)
|
||||
if self.formsemestre.formation.is_apc() or self.classic_use_bonus_ues:
|
||||
# Bonus sur les UE et None sur moyenne générale
|
||||
ues_idx = [ue.id for ue in self.formsemestre.query_ues(with_sport=False)]
|
||||
self.bonus_ues = pd.DataFrame(
|
||||
bonus_moy_arr, index=self.etuds_idx, columns=ues_idx, dtype=float
|
||||
)
|
||||
else:
|
||||
# Bonus sur la moyenne générale seulement
|
||||
self.bonus_moy_gen = pd.Series(
|
||||
bonus_moy_arr, index=self.etuds_idx, dtype=float
|
||||
)
|
||||
|
||||
# if len(bonus_moy_arr.shape) > 1:
|
||||
# bonus_moy_arr = bonus_moy_arr.sum(axis=1)
|
||||
# Laisse bonus_moy_gen à None, en APC le bonus moy. gen. sera réparti sur les UEs.
|
||||
|
||||
|
||||
class BonusSportMultiplicatif(BonusSport):
|
||||
@ -229,6 +235,8 @@ class BonusSportMultiplicatif(BonusSport):
|
||||
|
||||
seuil_moy_gen = 10.0 # seuls les points au dessus du seuil sont comptés
|
||||
amplitude = 0.005 # multiplie les points au dessus du seuil
|
||||
# En classique, les bonus multiplicatifs agissent par défaut sur les UE:
|
||||
classic_use_bonus_ues = True
|
||||
|
||||
# C'est un bonus "multiplicatif": on l'exprime en additif,
|
||||
# sur chaque moyenne d'UE m_0
|
||||
@ -243,11 +251,12 @@ class BonusSportMultiplicatif(BonusSport):
|
||||
sem_modimpl_moys_inscrits * modimpl_coefs_etuds_no_nan, axis=1
|
||||
) / np.sum(modimpl_coefs_etuds_no_nan, axis=1)
|
||||
notes = np.nan_to_num(notes, copy=False)
|
||||
|
||||
factor = (notes - self.seuil_moy_gen) * self.amplitude # 5% si note=20
|
||||
factor[factor <= 0] = 0.0 # note < seuil_moy_gen, pas de bonus
|
||||
|
||||
# Ne s'applique qu'aux moyennes d'UE
|
||||
if len(factor.shape) == 1: # classic
|
||||
factor = factor[:, np.newaxis]
|
||||
bonus = self.etud_moy_ue * factor
|
||||
if self.bonus_max is not None:
|
||||
# Seuil: bonus limité à bonus_max points
|
||||
@ -255,9 +264,8 @@ class BonusSportMultiplicatif(BonusSport):
|
||||
|
||||
self.bonus_ues = bonus # DataFrame
|
||||
|
||||
if not self.formsemestre.formation.is_apc():
|
||||
# s'applique à la moyenne générale
|
||||
self.bonus_moy_gen = bonus
|
||||
# Les bonus multiplicatifs ne s'appliquent pas à la moyenne générale
|
||||
self.bonus_moy_gen = None
|
||||
|
||||
|
||||
class BonusDirect(BonusSportAdditif):
|
||||
@ -323,6 +331,7 @@ class BonusBordeaux1(BonusSportMultiplicatif):
|
||||
|
||||
name = "bonus_iutBordeaux1"
|
||||
displayed_name = "IUT de Bordeaux 1"
|
||||
classic_use_bonus_ues = True # s'applique aux UEs en DUT et LP
|
||||
seuil_moy_gen = 10.0
|
||||
amplitude = 0.005
|
||||
|
||||
@ -576,17 +585,15 @@ class BonusVilleAvray(BonusSport):
|
||||
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
||||
"""calcul du bonus"""
|
||||
# Calcule moyenne pondérée des notes de sport:
|
||||
bonus_moy_gen_arr = np.sum(
|
||||
bonus_moy_arr = np.sum(
|
||||
sem_modimpl_moys_inscrits * modimpl_coefs_etuds_no_nan, axis=1
|
||||
) / np.sum(modimpl_coefs_etuds_no_nan, axis=1)
|
||||
bonus_moy_gen_arr[bonus_moy_gen_arr >= 10.0] = 0.1
|
||||
bonus_moy_gen_arr[bonus_moy_gen_arr >= 12.0] = 0.2
|
||||
bonus_moy_gen_arr[bonus_moy_gen_arr >= 16.0] = 0.3
|
||||
bonus_moy_arr[bonus_moy_arr >= 10.0] = 0.1
|
||||
bonus_moy_arr[bonus_moy_arr >= 12.0] = 0.2
|
||||
bonus_moy_arr[bonus_moy_arr >= 16.0] = 0.3
|
||||
|
||||
# Bonus moyenne générale, et 0 sur les UE
|
||||
self.bonus_moy_gen = pd.Series(
|
||||
bonus_moy_gen_arr, index=self.etuds_idx, dtype=float
|
||||
)
|
||||
self.bonus_moy_gen = pd.Series(bonus_moy_arr, index=self.etuds_idx, dtype=float)
|
||||
if self.bonus_max is not None:
|
||||
# Seuil: bonus (sur moy. gen.) limité à bonus_max points
|
||||
self.bonus_moy_gen = self.bonus_moy_gen.clip(upper=self.bonus_max)
|
||||
|
@ -40,6 +40,7 @@ import pandas as pd
|
||||
from app import db
|
||||
from app.models import ModuleImpl, Evaluation, EvaluationUEPoids
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
|
||||
|
||||
@ -269,7 +270,8 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
|
||||
"""Charge poids des évaluations d'un module et retourne un dataframe
|
||||
rows = evaluations, columns = UE, value = poids (float).
|
||||
Les valeurs manquantes (évaluations sans coef vers des UE) sont
|
||||
remplies: 1 si le coef de ce module dans l'UE est non nul, zéro sinon.
|
||||
remplies: 1 si le coef de ce module dans l'UE est non nul, zéro sinon
|
||||
(sauf pour module bonus, defaut à 1)
|
||||
Résultat: (evals_poids, liste de UEs du semestre sauf le sport)
|
||||
"""
|
||||
modimpl: ModuleImpl = ModuleImpl.query.get(moduleimpl_id)
|
||||
@ -287,11 +289,13 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
|
||||
pass # poids vers des UE qui n'existent plus ou sont dans un autre semestre...
|
||||
|
||||
# Initialise poids non enregistrés:
|
||||
default_poids = 1.0 if modimpl.module.ue.type == UE_SPORT else 0.0
|
||||
|
||||
if np.isnan(evals_poids.values.flat).any():
|
||||
ue_coefs = modimpl.module.get_ue_coef_dict()
|
||||
for ue in ues:
|
||||
evals_poids[ue.id][evals_poids[ue.id].isna()] = (
|
||||
1 if ue_coefs.get(ue.id, 0.0) > 0 else 0
|
||||
1 if ue_coefs.get(ue.id, default_poids) > 0 else 0
|
||||
)
|
||||
|
||||
return evals_poids, ues
|
||||
|
@ -36,6 +36,7 @@ from app.models import UniteEns, Module, ModuleImpl, ModuleUECoef
|
||||
from app.comp import moy_mod
|
||||
from app.models.formsemestre import FormSemestre
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
|
||||
|
||||
@ -44,10 +45,10 @@ def df_load_module_coefs(formation_id: int, semestre_idx: int = None) -> pd.Data
|
||||
|
||||
En APC, ces coefs lient les modules à chaque UE.
|
||||
|
||||
Résultat: (module_coefs_df, ues, modules)
|
||||
Résultat: (module_coefs_df, ues_no_bonus, modules)
|
||||
DataFrame rows = UEs, columns = modules, value = coef.
|
||||
|
||||
Considère toutes les UE (sauf sport) et modules du semestre.
|
||||
Considère toutes les UE sauf bonus et tous les modules du semestre.
|
||||
Les coefs non définis (pas en base) sont mis à zéro.
|
||||
|
||||
Si semestre_idx None, prend toutes les UE de la formation.
|
||||
@ -92,7 +93,17 @@ def df_load_module_coefs(formation_id: int, semestre_idx: int = None) -> pd.Data
|
||||
module_coefs_df[mod_coef.module_id][mod_coef.ue_id] = mod_coef.coef
|
||||
# silently ignore coefs associated to other modules (ie when module_type is changed)
|
||||
|
||||
module_coefs_df.fillna(value=0, inplace=True)
|
||||
# Initialisation des poids non fixés:
|
||||
# 0 pour modules normaux, 1. pour bonus (car par défaut, on veut qu'un bonus agisse
|
||||
# sur toutes les UE)
|
||||
default_poids = {
|
||||
mod.id: 1.0
|
||||
if (mod.module_type == ModuleType.STANDARD) and (mod.ue.type == UE_SPORT)
|
||||
else 0.0
|
||||
for mod in modules
|
||||
}
|
||||
|
||||
module_coefs_df.fillna(value=default_poids, inplace=True)
|
||||
|
||||
return module_coefs_df, ues, modules
|
||||
|
||||
@ -104,9 +115,9 @@ def df_load_modimpl_coefs(
|
||||
|
||||
Comme df_load_module_coefs mais prend seulement les UE
|
||||
et modules du formsemestre.
|
||||
Si ues et modimpls sont None, prend tous ceux du formsemestre.
|
||||
Si ues et modimpls sont None, prend tous ceux du formsemestre (sauf ue bonus).
|
||||
Résultat: (module_coefs_df, ues, modules)
|
||||
DataFrame rows = UEs (avec bonus), columns = modimpl, value = coef.
|
||||
DataFrame rows = UEs (sans bonus), columns = modimpl, value = coef.
|
||||
"""
|
||||
if ues is None:
|
||||
ues = formsemestre.query_ues().all()
|
||||
@ -124,7 +135,19 @@ def df_load_modimpl_coefs(
|
||||
|
||||
for mod_coef in mod_coefs:
|
||||
modimpl_coefs_df[mod2impl[mod_coef.module_id]][mod_coef.ue_id] = mod_coef.coef
|
||||
modimpl_coefs_df.fillna(value=0, inplace=True)
|
||||
|
||||
# Initialisation des poids non fixés:
|
||||
# 0 pour modules normaux, 1. pour bonus (car par défaut, on veut qu'un bonus agisse
|
||||
# sur toutes les UE)
|
||||
default_poids = {
|
||||
modimpl.id: 1.0
|
||||
if (modimpl.module.module_type == ModuleType.STANDARD)
|
||||
and (modimpl.module.ue.type == UE_SPORT)
|
||||
else 0.0
|
||||
for modimpl in formsemestre.modimpls_sorted
|
||||
}
|
||||
|
||||
modimpl_coefs_df.fillna(value=default_poids, inplace=True)
|
||||
return modimpl_coefs_df, ues, modimpls
|
||||
|
||||
|
||||
|
@ -40,22 +40,22 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
||||
) = moy_ue.notes_sem_load_cube(self.formsemestre)
|
||||
self.modimpl_inscr_df = inscr_mod.df_load_modimpl_inscr(self.formsemestre)
|
||||
self.modimpl_coefs_df, _, _ = moy_ue.df_load_modimpl_coefs(
|
||||
self.formsemestre, ues=self.ues, modimpls=self.formsemestre.modimpls_sorted
|
||||
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)
|
||||
|
||||
# Elimine les coefs des UE bonus sports
|
||||
no_bonus = [ue.type != UE_SPORT for ue in self.ues]
|
||||
modimpl_coefs_no_bonus_df = self.modimpl_coefs_df[no_bonus]
|
||||
# Elimine les coefs des UE bonus sports XXX inutile car df_load_modimpl_coefs sans bonus
|
||||
# no_bonus = [ue.type != UE_SPORT for ue in self.ues]
|
||||
# modimpl_coefs_no_bonus_df = self.modimpl_coefs_df[no_bonus]
|
||||
self.etud_moy_ue = moy_ue.compute_ue_moys_apc(
|
||||
self.sem_cube,
|
||||
self.etuds,
|
||||
self.formsemestre.modimpls_sorted,
|
||||
self.ues,
|
||||
self.modimpl_inscr_df,
|
||||
modimpl_coefs_no_bonus_df,
|
||||
self.modimpl_coefs_df,
|
||||
)
|
||||
# Les coefficients d'UE ne sont pas utilisés en APC
|
||||
self.etud_coef_ue_df = pd.DataFrame(
|
||||
@ -63,25 +63,33 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
||||
)
|
||||
|
||||
# --- Bonus Sport & Culture
|
||||
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
||||
if bonus_class is not None:
|
||||
bonus: BonusSport = bonus_class(
|
||||
self.formsemestre,
|
||||
self.sem_cube,
|
||||
self.ues,
|
||||
self.modimpl_inscr_df,
|
||||
self.modimpl_coefs_df.transpose(),
|
||||
self.etud_moy_gen,
|
||||
self.etud_moy_ue,
|
||||
)
|
||||
self.bonus_ues = bonus.get_bonus_ues()
|
||||
if self.bonus_ues is not None:
|
||||
self.etud_moy_ue += self.bonus_ues # somme les dataframes
|
||||
self.etud_moy_ue.clip(lower=0.0, upper=20.0, inplace=True)
|
||||
modimpl_sport = [
|
||||
modimpl
|
||||
for modimpl in self.formsemestre.modimpls_sorted
|
||||
if modimpl.module.ue.type == UE_SPORT
|
||||
]
|
||||
if len(modimpl_sport) > 0:
|
||||
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
||||
if bonus_class is not None:
|
||||
bonus: BonusSport = bonus_class(
|
||||
self.formsemestre,
|
||||
self.sem_cube,
|
||||
self.ues,
|
||||
self.modimpl_inscr_df,
|
||||
self.modimpl_coefs_df.transpose(),
|
||||
self.etud_moy_gen,
|
||||
self.etud_moy_ue,
|
||||
)
|
||||
self.bonus_ues = bonus.get_bonus_ues()
|
||||
if self.bonus_ues is not None:
|
||||
self.etud_moy_ue += self.bonus_ues # somme les dataframes
|
||||
self.etud_moy_ue.clip(lower=0.0, upper=20.0, inplace=True)
|
||||
|
||||
# Moyenne générale indicative:
|
||||
# (note: le bonus sport a déjà été appliqué aux moyenens d'UE, et impacte
|
||||
# donc la moyenne indicative)
|
||||
self.etud_moy_gen = moy_sem.compute_sem_moys_apc(
|
||||
self.etud_moy_ue, modimpl_coefs_no_bonus_df
|
||||
self.etud_moy_ue, self.modimpl_coefs_df
|
||||
)
|
||||
self.etud_moy_gen_ranks = moy_sem.comp_ranks_series(self.etud_moy_gen)
|
||||
|
||||
|
@ -219,18 +219,18 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
ues.append(d)
|
||||
return ues
|
||||
|
||||
def get_modimpls_dict(self, ue_id=None):
|
||||
def get_modimpls_dict(self, ue_id=None) -> list[dict]:
|
||||
"""Liste des modules pour une UE (ou toutes si ue_id==None),
|
||||
triés par numéros (selon le type de formation)
|
||||
"""
|
||||
if ue_id is None:
|
||||
return [m.to_dict() for m in self.formsemestre.modimpls_sorted]
|
||||
else:
|
||||
return [
|
||||
m.to_dict()
|
||||
for m in self.formsemestre.modimpls_sorted
|
||||
if m.module.ue.id == ue_id
|
||||
]
|
||||
modimpls_dict = []
|
||||
for modimpl in self.formsemestre.modimpls_sorted:
|
||||
if ue_id == None or modimpl.module.ue.id == ue_id:
|
||||
d = modimpl.to_dict()
|
||||
# compat ScoDoc < 9.2: ajoute matières
|
||||
d["mat"] = modimpl.module.matiere.to_dict()
|
||||
modimpls_dict.append(d)
|
||||
return modimpls_dict
|
||||
|
||||
def get_etud_decision_sem(self, etudid: int) -> dict:
|
||||
"""Decision du jury prise pour cet etudiant, ou None s'il n'y en pas eu.
|
||||
@ -259,13 +259,10 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
return ""
|
||||
return ins.etat
|
||||
|
||||
def get_etud_moy_gen(self, etudid): # -> float | str
|
||||
"""Moyenne générale de cet etudiant dans ce semestre.
|
||||
Prend(ra) en compte les UE capitalisées. (TODO) XXX
|
||||
Si apc, moyenne indicative.
|
||||
Si pas de notes: 'NA'
|
||||
"""
|
||||
return self.etud_moy_gen[etudid]
|
||||
def get_etud_mat_moy(self, matiere_id, etudid):
|
||||
"""moyenne d'un étudiant dans une matière (ou NA si pas de notes)"""
|
||||
# non supporté en 9.2
|
||||
return "na"
|
||||
|
||||
def get_etud_mod_moy(self, moduleimpl_id: int, etudid: int) -> float:
|
||||
"""La moyenne de l'étudiant dans le moduleimpl
|
||||
@ -274,6 +271,14 @@ class NotesTableCompat(ResultatsSemestre):
|
||||
"""
|
||||
raise NotImplementedError() # virtual method
|
||||
|
||||
def get_etud_moy_gen(self, etudid): # -> float | str
|
||||
"""Moyenne générale de cet etudiant dans ce semestre.
|
||||
Prend(ra) en compte les UE capitalisées. (TODO) XXX
|
||||
Si apc, moyenne indicative.
|
||||
Si pas de notes: 'NA'
|
||||
"""
|
||||
return self.etud_moy_gen[etudid]
|
||||
|
||||
def get_etud_ue_status(self, etudid: int, ue_id: int):
|
||||
coef_ue = self.etud_coef_ue_df[ue_id][etudid]
|
||||
return {
|
||||
|
@ -161,3 +161,16 @@ class Matiere(db.Model):
|
||||
numero = db.Column(db.Integer) # ordre de présentation
|
||||
|
||||
modules = db.relationship("Module", lazy="dynamic", backref="matiere")
|
||||
|
||||
def __repr__(self):
|
||||
return f"""<{self.__class__.__name__}(id={self.id}, ue_id={
|
||||
self.ue_id}, titre='{self.titre}')>"""
|
||||
|
||||
def to_dict(self):
|
||||
"""as a dict, with the same conversions as in ScoDoc7"""
|
||||
e = dict(self.__dict__)
|
||||
e.pop("_sa_instance_state", None)
|
||||
# ScoDoc7 output_formators
|
||||
e["ue_id"] = self.id
|
||||
e["numero"] = e["numero"] if e["numero"] else 0
|
||||
return e
|
||||
|
@ -310,7 +310,10 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
else:
|
||||
x = ""
|
||||
if isinstance(x, str):
|
||||
u["cur_moy_ue_txt"] = "pas de bonus"
|
||||
if nt.bonus_ues is None:
|
||||
u["cur_moy_ue_txt"] = "pas de bonus"
|
||||
else:
|
||||
u["cur_moy_ue_txt"] = "bonus appliqué sur les UEs"
|
||||
else:
|
||||
u["cur_moy_ue_txt"] = "bonus de %.3g points" % x
|
||||
u["moy_ue_txt"] = scu.fmt_note(ue_status["moy"])
|
||||
@ -380,7 +383,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
||||
)
|
||||
else:
|
||||
if prefs["bul_show_ue_rangs"] and ue["type"] != sco_codes_parcours.UE_SPORT:
|
||||
if ue_attente: # nt.get_moduleimpls_attente():
|
||||
if ue_attente or nt.ue_rangs[ue["ue_id"]][0] is None:
|
||||
u["ue_descr_txt"] = "%s/%s" % (
|
||||
scu.RANG_ATTENTE_STR,
|
||||
nt.ue_rangs[ue["ue_id"]][1],
|
||||
@ -398,8 +401,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
|
||||
# voir si on supporte encore cela en #sco92 XXX
|
||||
# I["matieres_modules"].update(_sort_mod_by_matiere(modules, nt, etudid))
|
||||
# En #sco92, pas d'information
|
||||
I["matieres_modules"].update(_sort_mod_by_matiere(modules, nt, etudid))
|
||||
|
||||
#
|
||||
C = make_context_dict(I["sem"], I["etud"])
|
||||
@ -616,12 +619,15 @@ def _ue_mod_bulletin(etudid, formsemestre_id, ue_id, modimpls, nt, version):
|
||||
# Classement
|
||||
if bul_show_mod_rangs and mod["mod_moy_txt"] != "-" and not is_malus:
|
||||
rg = nt.mod_rangs[modimpl["moduleimpl_id"]]
|
||||
if mod_attente: # nt.get_moduleimpls_attente():
|
||||
mod["mod_rang"] = scu.RANG_ATTENTE_STR
|
||||
if rg[0] is None:
|
||||
mod["mod_rang_txt"] = ""
|
||||
else:
|
||||
mod["mod_rang"] = rg[0][etudid]
|
||||
mod["mod_eff"] = rg[1] # effectif dans ce module
|
||||
mod["mod_rang_txt"] = "%s/%s" % (mod["mod_rang"], mod["mod_eff"])
|
||||
if mod_attente: # nt.get_moduleimpls_attente():
|
||||
mod["mod_rang"] = scu.RANG_ATTENTE_STR
|
||||
else:
|
||||
mod["mod_rang"] = rg[0][etudid]
|
||||
mod["mod_eff"] = rg[1] # effectif dans ce module
|
||||
mod["mod_rang_txt"] = "%s/%s" % (mod["mod_rang"], mod["mod_eff"])
|
||||
else:
|
||||
mod["mod_rang_txt"] = ""
|
||||
if mod_attente:
|
||||
|
Loading…
Reference in New Issue
Block a user