1463 lines
56 KiB
Python
1463 lines
56 KiB
Python
##############################################################################
|
|
# ScoDoc
|
|
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
|
# See LICENSE
|
|
##############################################################################
|
|
|
|
"""Classes spécifiques de calcul du bonus sport, culture ou autres activités
|
|
|
|
Les classes de Bonus fournissent deux méthodes:
|
|
- get_bonus_ues()
|
|
- get_bonus_moy_gen()
|
|
|
|
|
|
"""
|
|
import datetime
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
from flask import g
|
|
|
|
from app.scodoc.codes_cursus import UE_SPORT
|
|
from app.scodoc.codes_cursus import CursusDUT, CursusDUTMono
|
|
from app.scodoc.sco_utils import ModuleType
|
|
|
|
|
|
class BonusSport:
|
|
"""Calcul du bonus sport.
|
|
|
|
Arguments:
|
|
- sem_modimpl_moys :
|
|
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 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
|
|
En classique: 1d ndarray de float (modimpl)
|
|
En APC: 2d ndarray de float, (modimpl x UE) <= attention à transposer
|
|
- etud_moy_gen: Series, index etudid, valeur float (moyenne générale avant bonus)
|
|
- etud_moy_ue: DataFrame columns UE (sans sport), rows etudid (moyennes avant bonus)
|
|
|
|
etud_moy_gen et etud_moy_ue ne sont PAS modifiés (mais utilisés par certains bonus non additifs).
|
|
"""
|
|
|
|
# En classique, active un bonus sur les UEs: (dans ce cas bonus_moy_gen est ajusté pour le prendre en compte)
|
|
classic_use_bonus_ues = False
|
|
|
|
# Attributs virtuels:
|
|
seuil_moy_gen = None
|
|
proportion_point = None
|
|
bonus_max = None
|
|
|
|
name = "virtual"
|
|
|
|
def __init__(
|
|
self,
|
|
formsemestre: "FormSemestre",
|
|
sem_modimpl_moys: np.array,
|
|
ues: list,
|
|
modimpl_inscr_df: pd.DataFrame,
|
|
modimpl_coefs: np.array,
|
|
etud_moy_gen,
|
|
etud_moy_ue,
|
|
):
|
|
self.formsemestre = formsemestre
|
|
self.ues = ues
|
|
self.etud_moy_gen = etud_moy_gen
|
|
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 (pour formations non apc slt)
|
|
# Restreint aux modules standards des UE de type "sport":
|
|
modimpl_mask = np.array(
|
|
[
|
|
(m.module.module_type == ModuleType.STANDARD)
|
|
and (m.module.ue.type == UE_SPORT)
|
|
for m in formsemestre.modimpls_sorted
|
|
]
|
|
)
|
|
if len(modimpl_mask) == 0:
|
|
modimpl_mask = np.s_[:] # il n'y a rien, on prend tout donc rien
|
|
self.modimpls_spo = [
|
|
modimpl
|
|
for i, modimpl in enumerate(formsemestre.modimpls_sorted)
|
|
if modimpl_mask[i]
|
|
]
|
|
"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) (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_non_bonus)
|
|
nb_etuds, nb_mod_sport = sem_modimpl_moys_spo.shape[:2]
|
|
if nb_etuds == 0 or nb_mod_sport == 0:
|
|
return # no bonus at all
|
|
# Enlève les NaN du numérateur:
|
|
sem_modimpl_moys_no_nan = np.nan_to_num(sem_modimpl_moys_spo, nan=0.0)
|
|
|
|
# Annule les coefs des modules où l'étudiant n'est pas inscrit:
|
|
if formsemestre.formation.is_apc():
|
|
# BUT
|
|
nb_ues_no_bonus = sem_modimpl_moys.shape[2]
|
|
# Duplique les inscriptions sur les UEs non bonus:
|
|
modimpl_inscr_spo_stacked = np.stack(
|
|
[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: (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
|
|
)
|
|
# Annule les coefs des modules où l'étudiant n'est pas inscrit:
|
|
modimpl_coefs_etuds = np.where(
|
|
modimpl_inscr_spo_stacked,
|
|
np.stack([modimpl_coefs_spo] * nb_etuds),
|
|
0.0,
|
|
)
|
|
else:
|
|
# Formations classiques
|
|
# Ne prend pas en compte les notes des étudiants non inscrits au module:
|
|
# Annule les notes:
|
|
sem_modimpl_moys_inscrits = np.where(
|
|
modimpl_inscr_spo, sem_modimpl_moys_no_nan, 0.0
|
|
)
|
|
modimpl_coefs_spo = modimpl_coefs_spo.T
|
|
if nb_etuds == 0:
|
|
modimpl_coefs_etuds = modimpl_inscr_spo # vide
|
|
else:
|
|
modimpl_coefs_etuds = np.where(
|
|
modimpl_inscr_spo, np.stack([modimpl_coefs_spo] * nb_etuds), 0.0
|
|
)
|
|
# Annule les coefs des modules NaN (nb_etuds x nb_mod_sport)
|
|
modimpl_coefs_etuds_no_nan = np.where(
|
|
np.isnan(sem_modimpl_moys_spo), 0.0, modimpl_coefs_etuds
|
|
)
|
|
#
|
|
self.compute_bonus(sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan)
|
|
|
|
def compute_bonus(
|
|
self,
|
|
sem_modimpl_moys_inscrits: np.ndarray,
|
|
modimpl_coefs_etuds_no_nan: np.ndarray,
|
|
):
|
|
"""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_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
|
|
|
|
Résultat: None
|
|
"""
|
|
raise NotImplementedError("méthode virtuelle")
|
|
|
|
def get_bonus_ues(self) -> pd.DataFrame:
|
|
"""Les bonus à appliquer aux UE
|
|
Résultat: DataFrame de float, index etudid, columns: ue.id
|
|
"""
|
|
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
|
|
|
|
|
|
class BonusSportAdditif(BonusSport):
|
|
"""Bonus sport simples calcule un bonus à partir des notes moyennes de modules
|
|
de l'UE sport, et ce bonus est soit ajouté à la moyenne générale (formations classiques),
|
|
soit ajouté à chaque UE (formations APC).
|
|
|
|
Le bonus est par défaut calculé comme:
|
|
Les points au-dessus du seuil (par défaut) 10 sur 20 obtenus dans chacun des
|
|
modules optionnels sont cumulés et une fraction de ces points cumulés s'ajoute
|
|
à la moyenne générale du semestre déjà obtenue par l'étudiant.
|
|
"""
|
|
|
|
seuil_moy_gen = 10.0 # seuls les bonus au dessus du seuil sont pris en compte
|
|
# les points au dessus du seuil sont comptés (defaut: seuil_moy_gen):
|
|
seuil_comptage = None
|
|
proportion_point = 0.05 # multiplie les points au dessus du seuil
|
|
bonux_max = 20.0 # le bonus ne peut dépasser 20 points
|
|
bonus_min = 0.0 # et ne peut pas être négatif
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus
|
|
sem_modimpl_moys_inscrits: les notes de sport
|
|
En APC: ndarray (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
|
En classic: ndarray (nb_etuds, nb_mod_sport)
|
|
modimpl_coefs_etuds_no_nan: même shape, les coefs.
|
|
"""
|
|
if 0 in sem_modimpl_moys_inscrits.shape:
|
|
# pas d'étudiants ou pas d'UE ou pas de module...
|
|
return
|
|
seuil_comptage = (
|
|
self.seuil_moy_gen if self.seuil_comptage is None else self.seuil_comptage
|
|
)
|
|
bonus_moy_arr = np.sum(
|
|
np.where(
|
|
(sem_modimpl_moys_inscrits >= self.seuil_moy_gen)
|
|
& (modimpl_coefs_etuds_no_nan > 0),
|
|
(sem_modimpl_moys_inscrits - seuil_comptage) * self.proportion_point,
|
|
0.0,
|
|
),
|
|
axis=1,
|
|
)
|
|
# Seuil: bonus dans [min, max] (défaut [0,20])
|
|
bonus_max = self.bonus_max or 20.0
|
|
np.clip(bonus_moy_arr, self.bonus_min, bonus_max, out=bonus_moy_arr)
|
|
|
|
self.bonus_additif(bonus_moy_arr)
|
|
|
|
def bonus_additif(self, bonus_moy_arr: np.array):
|
|
"Set bonus_ues et bonus_moy_gen"
|
|
# en APC, bonus_moy_arr est (nb_etuds, nb_ues_non_bonus)
|
|
if self.formsemestre.formation.is_apc():
|
|
# 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
|
|
)
|
|
elif self.classic_use_bonus_ues:
|
|
# Formations classiques apppliquant le bonus sur les UEs
|
|
# ici bonus_moy_arr = ndarray 1d nb_etuds
|
|
ues_idx = [ue.id for ue in self.formsemestre.query_ues(with_sport=False)]
|
|
self.bonus_ues = pd.DataFrame(
|
|
np.stack([bonus_moy_arr] * len(ues_idx)).T,
|
|
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
|
|
)
|
|
|
|
|
|
class BonusSportMultiplicatif(BonusSport):
|
|
"""Bonus sport qui multiplie les moyennes d'UE par un facteur"""
|
|
|
|
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
|
|
# Facteur multiplicatif max: (bonus = moy_ue*factor)
|
|
factor_max = 1000.0 # infini
|
|
|
|
# C'est un bonus "multiplicatif": on l'exprime en additif,
|
|
# sur chaque moyenne d'UE m_0
|
|
# Augmenter de 5% correspond à multiplier par a=1.05
|
|
# m_1 = a . m_0
|
|
# m_1 = m_0 + bonus
|
|
# bonus = m_0 (a - 1)
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
if 0 in sem_modimpl_moys_inscrits.shape:
|
|
# pas d'étudiants ou pas d'UE ou pas de module...
|
|
return
|
|
# Calcule moyenne pondérée des notes de sport:
|
|
notes = np.sum(
|
|
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
|
|
# note < seuil_moy_gen, pas de bonus: pas de facteur négatif, ni
|
|
factor.clip(0.0, self.factor_max, out=factor)
|
|
|
|
# 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
|
|
bonus.clip(upper=self.bonus_max, inplace=True)
|
|
|
|
self.bonus_ues = bonus # DataFrame
|
|
|
|
# Les bonus multiplicatifs ne s'appliquent pas à la moyenne générale
|
|
self.bonus_moy_gen = None
|
|
|
|
|
|
class BonusDirect(BonusSportAdditif):
|
|
"""Bonus direct: les points sont directement ajoutés à la moyenne générale.
|
|
|
|
Les coefficients sont ignorés: tous les points de bonus sont sommés.
|
|
(rappel: la note est ramenée sur 20 avant application).
|
|
"""
|
|
|
|
name = "bonus_direct"
|
|
displayed_name = 'Bonus "direct"'
|
|
seuil_moy_gen = 0.0 # tous les points sont comptés
|
|
proportion_point = 1.0
|
|
|
|
|
|
class BonusAisneStQuentin(BonusSportAdditif):
|
|
"""Calcul bonus modules optionels (sport, culture), règle IUT Aisne St Quentin
|
|
|
|
<p>Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université de St Quentin non rattachés à une unité d'enseignement.
|
|
</p>
|
|
<ul>
|
|
<li>Si la note est >= 10 et < 12.1, bonus de 0.1 point</li>
|
|
<li>Si la note est >= 12.1 et < 14.1, bonus de 0.2 point</li>
|
|
<li>Si la note est >= 14.1 et < 16.1, bonus de 0.3 point</li>
|
|
<li>Si la note est >= 16.1 et < 18.1, bonus de 0.4 point</li>
|
|
<li>Si la note est >= 18.1, bonus de 0.5 point</li>
|
|
</ul>
|
|
<p>
|
|
Ce bonus s'ajoute à la moyenne générale du semestre déjà obtenue par
|
|
l'étudiant (en BUT, s'ajoute à la moyenne de chaque UE).
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iutstq"
|
|
displayed_name = "IUT de Saint-Quentin"
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
if 0 in sem_modimpl_moys_inscrits.shape:
|
|
# pas d'étudiants ou pas d'UE ou pas de module...
|
|
return
|
|
# Calcule moyenne pondérée des notes de sport:
|
|
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
|
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)
|
|
np.nan_to_num(bonus_moy_arr, nan=0.0, copy=False)
|
|
|
|
bonus_moy_arr[bonus_moy_arr < 10.0] = 0.0
|
|
bonus_moy_arr[bonus_moy_arr >= 18.1] = 0.5
|
|
bonus_moy_arr[bonus_moy_arr >= 16.1] = 0.4
|
|
bonus_moy_arr[bonus_moy_arr >= 14.1] = 0.3
|
|
bonus_moy_arr[bonus_moy_arr >= 12.1] = 0.2
|
|
bonus_moy_arr[bonus_moy_arr >= 10] = 0.1
|
|
|
|
self.bonus_additif(bonus_moy_arr)
|
|
|
|
|
|
class BonusAmiens(BonusSportAdditif):
|
|
"""Bonus IUT Amiens pour les modules optionnels (sport, culture, ...)
|
|
|
|
<p><b>À partir d'août 2022:</b></p>
|
|
<p>
|
|
Deux activités optionnelles sont possibles chaque semestre, et peuvent donner lieu à une bonification de 0,1 chacune sur la moyenne de chaque UE.
|
|
</p><p>
|
|
La note saisie peut valoir 0 (pas de bonus), 1 (bonus de 0,1 points) ou 2 (bonus de 0,2 points).
|
|
</p>
|
|
|
|
<p><b>Avant juillet 2022:</b></p>
|
|
<p>Toute note non nulle, peu importe sa valeur, entraine un bonus de 0,1 point
|
|
sur toutes les moyennes d'UE.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_amiens"
|
|
displayed_name = "IUT d'Amiens"
|
|
classic_use_bonus_ues = True # s'applique aux UEs en DUT et LP
|
|
seuil_moy_gen = 0.0 # tous les points sont comptés
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus, avec réglage différent suivant la date"""
|
|
|
|
if self.formsemestre.date_debut > datetime.date(2022, 8, 1):
|
|
self.proportion_point = 0.1
|
|
self.bonus_max = 0.2
|
|
else: # anciens semestres
|
|
self.proportion_point = 1e10
|
|
self.bonus_max = 0.1
|
|
|
|
super().compute_bonus(sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan)
|
|
|
|
|
|
# Finalement ils n'en veulent pas.
|
|
# class BonusAnnecy(BonusSport):
|
|
# """Calcul bonus modules optionnels (sport), règle IUT d'Annecy.
|
|
|
|
# Il peut y avoir plusieurs modules de bonus.
|
|
# Prend pour chaque étudiant la meilleure de ses notes bonus et
|
|
# ajoute à chaque UE :<br>
|
|
# 0.05 point si >=10,<br>
|
|
# 0.1 point si >=12,<br>
|
|
# 0.15 point si >=14,<br>
|
|
# 0.2 point si >=16,<br>
|
|
# 0.25 point si >=18.
|
|
# """
|
|
|
|
# name = "bonus_iut_annecy"
|
|
# displayed_name = "IUT d'Annecy"
|
|
|
|
# def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
# """calcul du bonus"""
|
|
# # if math.prod(sem_modimpl_moys_inscrits.shape) == 0:
|
|
# # return # no etuds or no mod sport
|
|
# # Prend la note de chaque modimpl, sans considération d'UE
|
|
# if len(sem_modimpl_moys_inscrits.shape) > 2: # apc
|
|
# sem_modimpl_moys_inscrits = sem_modimpl_moys_inscrits[:, :, 0]
|
|
# # ici sem_modimpl_moys_inscrits est nb_etuds x nb_mods_bonus, en APC et en classic
|
|
# note_bonus_max = np.max(sem_modimpl_moys_inscrits, axis=1) # 1d, nb_etuds
|
|
# bonus = np.zeros(note_bonus_max.shape)
|
|
# bonus[note_bonus_max >= 10.0] = 0.05
|
|
# bonus[note_bonus_max >= 12.0] = 0.10
|
|
# bonus[note_bonus_max >= 14.0] = 0.15
|
|
# bonus[note_bonus_max >= 16.0] = 0.20
|
|
# bonus[note_bonus_max >= 18.0] = 0.25
|
|
|
|
# # Bonus moyenne générale et sur les UE
|
|
# self.bonus_moy_gen = pd.Series(bonus, index=self.etuds_idx, dtype=float)
|
|
# ues_idx = [ue.id for ue in self.formsemestre.query_ues(with_sport=False)]
|
|
# nb_ues_no_bonus = len(ues_idx)
|
|
# self.bonus_ues = pd.DataFrame(
|
|
# np.stack([bonus] * nb_ues_no_bonus, axis=1),
|
|
# columns=ues_idx,
|
|
# index=self.etuds_idx,
|
|
# dtype=float,
|
|
# )
|
|
|
|
|
|
class BonusBesanconVesoul(BonusSportAdditif):
|
|
"""Bonus IUT Besançon - Vesoul pour les UE libres
|
|
|
|
<p>Toute note non nulle, peu importe sa valeur, entraine un bonus de 0,2 point
|
|
sur toutes les moyennes d'UE.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_besancon_vesoul"
|
|
displayed_name = "IUT de Besançon - Vesoul"
|
|
classic_use_bonus_ues = True # s'applique aux UEs en DUT et LP
|
|
seuil_moy_gen = 0.0 # tous les points sont comptés
|
|
proportion_point = 1e10 # infini
|
|
bonus_max = 0.2
|
|
|
|
|
|
class BonusBethune(BonusSportMultiplicatif):
|
|
"""
|
|
Calcul bonus modules optionnels (sport, culture), règle IUT de Béthune.
|
|
<p>
|
|
<b>Pour le BUT :</b>
|
|
La note de sport est sur 20, et on calcule une bonification (en %)
|
|
qui va s'appliquer à <b>la moyenne de chaque UE</b> du semestre en appliquant
|
|
la formule : bonification (en %) = max(note-10, 0)*(1/<b>500</b>).
|
|
</p><p>
|
|
<em>La bonification ne s'applique que si la note est supérieure à 10.</em>
|
|
</p><p>
|
|
(Une note de 10 donne donc 0% de bonif,
|
|
1 point au dessus de 10 augmente la moyenne des UE de 0.2%)
|
|
</p>
|
|
<p>
|
|
<b>Pour le DUT/LP :</b>
|
|
La note de sport est sur 20, et on calcule une bonification (en %)
|
|
qui va s'appliquer à <b>la moyenne générale</b> du semestre en appliquant
|
|
la formule : bonification (en %) = max(note-10, 0)*(1/<b>200</b>).
|
|
</p><p>
|
|
<em>La bonification ne s'applique que si la note est supérieure à 10.</em>
|
|
</p><p>
|
|
(Une note de 10 donne donc 0% de bonif,
|
|
1 point au dessus de 10 augmente la moyenne des UE de 0.5%)
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iutbethune"
|
|
displayed_name = "IUT de Béthune"
|
|
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
if self.formsemestre.formation.is_apc():
|
|
self.amplitude = 0.002
|
|
else:
|
|
self.amplitude = 0.005
|
|
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
class BonusBezier(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT de Bézier.
|
|
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
sport , etc) non rattachés à une unité d'enseignement. Les points
|
|
au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés et 3% de ces points cumulés s'ajoutent à
|
|
la moyenne générale du semestre déjà obtenue par l'étudiant, dans
|
|
la limite de 0,3 points.
|
|
"""
|
|
|
|
# note: cela revient à dire que l'on ajoute 5% des points au dessus de 10,
|
|
# et qu'on limite à 5% de 10, soit 0.5 points
|
|
# ce bonus est donc strictement identique à celui de St Denis (BonusIUTStDenis)
|
|
name = "bonus_iutbeziers"
|
|
displayed_name = "IUT de Bézier"
|
|
bonus_max = 0.3
|
|
seuil_moy_gen = 10.0 # tous les points sont comptés
|
|
proportion_point = 0.03
|
|
|
|
|
|
class BonusBlagnac(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT de Blagnac.
|
|
|
|
Le bonus est égal à 5% des points au dessus de 10 à appliquer sur toutes
|
|
les UE du semestre, applicable dans toutes les formations (DUT, BUT, ...).
|
|
"""
|
|
|
|
name = "bonus_iutblagnac"
|
|
displayed_name = "IUT de Blagnac"
|
|
proportion_point = 0.05
|
|
classic_use_bonus_ues = True # toujours sur les UE
|
|
|
|
|
|
class BonusBordeaux1(BonusSportMultiplicatif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Bordeaux 1,
|
|
sur moyenne générale et UEs.
|
|
<p>
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université Bordeaux 1 (sport, théâtre) non rattachés à une unité d'enseignement.
|
|
</p><p>
|
|
Chaque point au-dessus de 10 sur 20 obtenus dans cet enseignement correspond à un %
|
|
qui augmente la moyenne de chaque UE et la moyenne générale.<br>
|
|
Formule : pourcentage = (points au dessus de 10) / 2
|
|
</p><p>
|
|
Par exemple : sport 13/20 : chaque UE sera multipliée par 1+0,015, ainsi que la moyenne générale.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iutBordeaux1"
|
|
displayed_name = "IUT de Bordeaux"
|
|
classic_use_bonus_ues = True # s'applique aux UEs en DUT et LP
|
|
seuil_moy_gen = 10.0
|
|
amplitude = 0.005
|
|
|
|
|
|
# Exactement le même que Bordeaux:
|
|
class BonusBrest(BonusSportMultiplicatif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT de Brest,
|
|
sur moyenne générale et UEs.
|
|
<p>
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université (sport, théâtre) non rattachés à une unité d'enseignement.
|
|
</p><p>
|
|
Chaque point au-dessus de 10 sur 20 obtenus dans cet enseignement correspond à un %
|
|
qui augmente la moyenne de chaque UE et la moyenne générale.<br>
|
|
Formule : pourcentage = (points au dessus de 10) / 2
|
|
</p><p>
|
|
Par exemple : sport 13/20 : chaque UE sera multipliée par 1+0,015, ainsi que la moyenne générale.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iut_brest"
|
|
displayed_name = "IUT de Brest"
|
|
classic_use_bonus_ues = True # s'applique aux UEs en DUT et LP
|
|
seuil_moy_gen = 10.0
|
|
amplitude = 0.005
|
|
|
|
|
|
class BonusCachan1(BonusSportAdditif):
|
|
"""Calcul bonus optionnels (sport, culture), règle IUT de Cachan 1.
|
|
|
|
<ul>
|
|
<li> DUT/LP : la meilleure note d'option, si elle est supérieure à 10,
|
|
bonifie les moyennes d'UE (uniquement UE13_E pour le semestre 1, UE23_E
|
|
pour le semestre 2, UE33_E pour le semestre 3 et UE43_E pour le semestre
|
|
4) à raison
|
|
de <em>bonus = (option - 10)/10</em>.
|
|
</li>
|
|
<li> BUT : la meilleure note d'option, si elle est supérieure à 10, bonifie
|
|
les moyennes d'UE à raison de <em>bonus = (option - 10) * 3%</em>.</li>
|
|
</ul>
|
|
"""
|
|
|
|
name = "bonus_cachan1"
|
|
displayed_name = "IUT de Cachan 1"
|
|
seuil_moy_gen = 10.0 # tous les points sont comptés
|
|
proportion_point = 0.03
|
|
classic_use_bonus_ues = True
|
|
ues_bonifiables_cachan = {"UE13_E", "UE23_E", "UE33_E", "UE43_E"}
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus, avec réglage différent suivant le type de formation"""
|
|
# Prend la note de chaque modimpl, sans considération d'UE
|
|
if len(sem_modimpl_moys_inscrits.shape) > 2: # apc
|
|
sem_modimpl_moys_inscrits = sem_modimpl_moys_inscrits[:, :, 0]
|
|
# ici sem_modimpl_moys_inscrits est nb_etuds x nb_mods_bonus, en APC et en classic
|
|
note_bonus_max = np.max(sem_modimpl_moys_inscrits, axis=1) # 1d, nb_etuds
|
|
ues = self.formsemestre.query_ues(with_sport=False).all()
|
|
ues_idx = [ue.id for ue in ues]
|
|
|
|
if self.formsemestre.formation.is_apc(): # --- BUT
|
|
bonus_moy_arr = np.where(
|
|
note_bonus_max > self.seuil_moy_gen,
|
|
(note_bonus_max - self.seuil_moy_gen) * self.proportion_point,
|
|
0.0,
|
|
)
|
|
self.bonus_ues = pd.DataFrame(
|
|
np.stack([bonus_moy_arr] * len(ues)).T,
|
|
index=self.etuds_idx,
|
|
columns=ues_idx,
|
|
dtype=float,
|
|
)
|
|
else: # --- DUT
|
|
# pareil mais proportion différente et application à certaines UEs
|
|
proportion_point = 0.1
|
|
bonus_moy_arr = np.where(
|
|
note_bonus_max > self.seuil_moy_gen,
|
|
(note_bonus_max - self.seuil_moy_gen) * proportion_point,
|
|
0.0,
|
|
)
|
|
self.bonus_ues = pd.DataFrame(
|
|
np.stack([bonus_moy_arr] * len(ues)).T,
|
|
index=self.etuds_idx,
|
|
columns=ues_idx,
|
|
dtype=float,
|
|
)
|
|
# Applique bonus seulement sur certaines UE de code connu:
|
|
for ue in ues:
|
|
if ue.ue_code not in self.ues_bonifiables_cachan:
|
|
self.bonus_ues[ue.id] = 0.0 # annule
|
|
|
|
|
|
class BonusCaen(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT de Caen Normandie.
|
|
|
|
Les étudiants de l'IUT de Caen Normandie peuvent suivre des enseignements
|
|
optionnels non rattachés à une unité d'enseignement:
|
|
<ul>
|
|
<li><b>Sport</b>.
|
|
<li><b>Engagement étudiant</b>
|
|
</ul>
|
|
Les points au-dessus de 10 sur 20 obtenus dans chacune de ces matières
|
|
optionnelles sont cumulés et donnent lieu à un bonus sur chaque UE de 5%
|
|
des points au dessus de 10 (soit +0,1 point pour chaque tranche de 2 points au
|
|
dessus de 10).
|
|
"""
|
|
|
|
name = "bonus_caen"
|
|
displayed_name = "IUT de Caen Normandie"
|
|
bonus_max = 1.0
|
|
seuil_moy_gen = 10.0 # au dessus de 10
|
|
proportion_point = 0.05 # 5%
|
|
|
|
|
|
class BonusCalais(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT LCO.
|
|
|
|
Les étudiants de l'IUT LCO peuvent suivre des enseignements optionnels non
|
|
rattachés à une unité d'enseignement. Les points au-dessus de 10
|
|
sur 20 obtenus dans chacune des matières optionnelles sont cumulés
|
|
dans la limite de 10 points. 6% de ces points cumulés s'ajoutent :
|
|
<ul>
|
|
<li><b>en DUT</b> à la moyenne générale du semestre déjà obtenue par l'étudiant.
|
|
</li>
|
|
<li><b>en BUT et LP</b> à la moyenne des UE dont l'acronyme fini par <b>BS</b>
|
|
(ex : UE2.1BS, UE32BS)
|
|
</li>
|
|
</ul>
|
|
"""
|
|
|
|
name = "bonus_calais"
|
|
displayed_name = "IUT du Littoral"
|
|
bonus_max = 0.6
|
|
seuil_moy_gen = 10.0 # au dessus de 10
|
|
proportion_point = 0.06 # 6%
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
parcours = self.formsemestre.formation.get_cursus()
|
|
# Variantes de DUT ?
|
|
if (
|
|
isinstance(parcours, CursusDUT)
|
|
or parcours.TYPE_CURSUS == CursusDUTMono.TYPE_CURSUS
|
|
): # DUT
|
|
super().compute_bonus(sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan)
|
|
else:
|
|
self.classic_use_bonus_ues = True # pour les LP
|
|
super().compute_bonus(sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan)
|
|
ues = self.formsemestre.query_ues(with_sport=False).all()
|
|
ues_sans_bs = [
|
|
ue for ue in ues if ue.acronyme[-2:].upper() != "BS"
|
|
] # les 2 derniers cars forcés en majus
|
|
for ue in ues_sans_bs:
|
|
self.bonus_ues[ue.id] = 0.0
|
|
|
|
|
|
class BonusColmar(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Colmar.
|
|
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'U.H.A. (sports, musique, deuxième langue, culture, etc) non
|
|
rattachés à une unité d'enseignement. Les points au-dessus de 10
|
|
sur 20 obtenus dans chacune des matières optionnelles sont cumulés
|
|
dans la limite de 10 points. 5% de ces points cumulés s'ajoutent à
|
|
la moyenne générale du semestre déjà obtenue par l'étudiant.
|
|
"""
|
|
|
|
# note: cela revient à dire que l'on ajoute 5% des points au dessus de 10,
|
|
# et qu'on limite à 5% de 10, soit 0.5 points
|
|
# ce bonus est donc strictement identique à celui de St Denis (BonusIUTStDenis)
|
|
name = "bonus_colmar"
|
|
displayed_name = "IUT de Colmar"
|
|
bonus_max = 0.5
|
|
seuil_moy_gen = 10.0 # tous les points sont comptés
|
|
proportion_point = 0.05
|
|
|
|
|
|
class BonusGrenobleIUT1(BonusSportMultiplicatif):
|
|
"""Bonus IUT1 de Grenoble
|
|
|
|
<p>
|
|
À compter de sept. 2021:
|
|
La note de sport est sur 20, et on calcule une bonification (en %)
|
|
qui va s'appliquer à la moyenne de chaque UE du semestre en appliquant
|
|
la formule : bonification (en %) = (note-10)*0,5.
|
|
</p><p>
|
|
<em>La bonification ne s'applique que si la note est supérieure à 10.</em>
|
|
</p><p>
|
|
(Une note de 10 donne donc 0% de bonif, et une note de 20 : 5% de bonif)
|
|
</p><p>
|
|
Avant sept. 2021, la note de sport allait de 0 à 5 points (sur 20).
|
|
Chaque point correspondait à 0.25% d'augmentation de la moyenne
|
|
générale.
|
|
Par exemple : note de sport 2/5 : la moyenne générale était augmentée de 0.5%.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iut1grenoble_2017"
|
|
displayed_name = "IUT de Grenoble 1"
|
|
# C'est un bonus "multiplicatif": on l'exprime en additif,
|
|
# sur chaque moyenne d'UE m_0
|
|
# Augmenter de 5% correspond à multiplier par a=1.05
|
|
# m_1 = a . m_0
|
|
# m_1 = m_0 + bonus
|
|
# bonus = m_0 (a - 1)
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus, avec réglage différent suivant la date"""
|
|
|
|
if self.formsemestre.date_debut > datetime.date(2021, 7, 15):
|
|
self.seuil_moy_gen = 10.0
|
|
self.amplitude = 0.005
|
|
else: # anciens semestres
|
|
self.seuil_moy_gen = 0.0
|
|
self.amplitude = 1 / 400.0
|
|
|
|
super().compute_bonus(sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan)
|
|
|
|
|
|
class BonusIUTRennes1(BonusSportAdditif):
|
|
"""Calcul bonus optionnels (sport, langue vivante, engagement étudiant),
|
|
règle IUT de l'Université de Rennes 1 (Lannion, Rennes, St Brieuc, St Malo).
|
|
|
|
<ul>
|
|
<li>Les étudiants peuvent suivre un ou plusieurs activités optionnelles notées
|
|
dans les semestres pairs.<br>
|
|
La meilleure des notes obtenue est prise en compte, si elle est supérieure à 10/20.
|
|
</li>
|
|
<li>Le vingtième des points au dessus de 10 est ajouté à la moyenne de chaque UE
|
|
en BUT, ou à la moyenne générale pour les autres formations.
|
|
</li>
|
|
<li> Exemple: un étudiant ayant 16/20 bénéficiera d'un bonus de (16-10)/20 = 0,3 points
|
|
sur chaque UE.
|
|
</li>
|
|
</ul>
|
|
"""
|
|
|
|
name = "bonus_iut_rennes1"
|
|
displayed_name = "IUTs de Rennes 1 (Lannion, Rennes, St Brieuc, St Malo)"
|
|
seuil_moy_gen = 10.0
|
|
proportion_point = 1 / 20.0
|
|
classic_use_bonus_ues = False
|
|
# S'applique aussi en classic, sur la moy. gen.
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
# Prend la note de chaque modimpl, sans considération d'UE
|
|
if len(sem_modimpl_moys_inscrits.shape) > 2: # apc
|
|
sem_modimpl_moys_inscrits = sem_modimpl_moys_inscrits[:, :, 0]
|
|
# ici sem_modimpl_moys_inscrits est nb_etuds x nb_mods_bonus, en APC et en classic
|
|
note_bonus_max = np.max(sem_modimpl_moys_inscrits, axis=1) # 1d, nb_etuds
|
|
nb_ues = self.formsemestre.query_ues(with_sport=False).count()
|
|
|
|
bonus_moy_arr = np.where(
|
|
note_bonus_max > self.seuil_moy_gen,
|
|
(note_bonus_max - self.seuil_moy_gen) * self.proportion_point,
|
|
0.0,
|
|
)
|
|
# Seuil: bonus dans [min, max] (défaut [0,20])
|
|
bonus_max = self.bonus_max or 20.0
|
|
np.clip(bonus_moy_arr, self.bonus_min, bonus_max, out=bonus_moy_arr)
|
|
if self.formsemestre.formation.is_apc():
|
|
bonus_moy_arr = np.stack([bonus_moy_arr] * nb_ues).T
|
|
|
|
self.bonus_additif(bonus_moy_arr)
|
|
|
|
|
|
# juste pour compatibilité (nom bonus en base):
|
|
class BonusStBrieuc(BonusIUTRennes1):
|
|
name = "bonus_iut_stbrieuc"
|
|
displayed_name = "IUTs de Rennes 1/St-Brieuc"
|
|
__doc__ = BonusIUTRennes1.__doc__
|
|
|
|
|
|
class BonusStMalo(BonusIUTRennes1):
|
|
name = "bonus_iut_stmalo"
|
|
displayed_name = "IUTs de Rennes 1/St-Malo"
|
|
__doc__ = BonusIUTRennes1.__doc__
|
|
|
|
|
|
class BonusLaRocheSurYon(BonusSportAdditif):
|
|
"""Bonus IUT de La Roche-sur-Yon
|
|
|
|
Si une note de bonus est saisie, l'étudiant est gratifié de 0,2 points
|
|
sur sa moyenne générale ou, en BUT, sur la moyenne de chaque UE.
|
|
"""
|
|
|
|
name = "bonus_larochesuryon"
|
|
displayed_name = "IUT de La Roche-sur-Yon"
|
|
seuil_moy_gen = 0.0
|
|
seuil_comptage = 0.0
|
|
proportion_point = 1e10 # le moindre point sature le bonus
|
|
bonus_max = 0.2 # à 0.2
|
|
|
|
|
|
class BonusLaRochelle(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT de La Rochelle.
|
|
|
|
<ul>
|
|
<li>Si la note de sport est comprise entre 0 et 10 : pas d'ajout de point.</li>
|
|
<li>Si la note de sport est comprise entre 10 et 20 :
|
|
<ul>
|
|
<li>Pour le BUT, application pour chaque UE du semestre :
|
|
<ul>
|
|
<li>pour une note entre 18 et 20 => + 0,10 points</li>
|
|
<li>pour une note entre 16 et 17,99 => + 0,08 points</li>
|
|
<li>pour une note entre 14 et 15,99 => + 0,06 points</li>
|
|
<li>pour une note entre 12 et 13,99 => + 0,04 points</li>
|
|
<li>pour une note entre 10 et 11,99 => + 0,02 points</li>
|
|
</ul>
|
|
</li>
|
|
<li>Pour les DUT/LP :
|
|
ajout de 1% de la note sur la moyenne générale du semestre
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
"""
|
|
|
|
name = "bonus_iutlr"
|
|
displayed_name = "IUT de La Rochelle"
|
|
|
|
seuil_moy_gen = 10.0 # si bonus > 10,
|
|
seuil_comptage = 0.0 # tous les points sont comptés
|
|
proportion_point = 0.01 # 1%
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
# La date du semestre ?
|
|
if self.formsemestre.formation.is_apc():
|
|
if 0 in sem_modimpl_moys_inscrits.shape:
|
|
# pas d'étudiants ou pas d'UE ou pas de module...
|
|
return
|
|
# Calcule moyenne pondérée des notes de sport:
|
|
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
|
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)
|
|
np.nan_to_num(bonus_moy_arr, nan=0.0, copy=False)
|
|
bonus_moy_arr[bonus_moy_arr < 10.0] = 0.0
|
|
bonus_moy_arr[bonus_moy_arr >= 18.0] = 0.10
|
|
bonus_moy_arr[bonus_moy_arr >= 16.0] = 0.08
|
|
bonus_moy_arr[bonus_moy_arr >= 14.0] = 0.06
|
|
bonus_moy_arr[bonus_moy_arr >= 12.0] = 0.04
|
|
bonus_moy_arr[bonus_moy_arr >= 10.0] = 0.02
|
|
self.bonus_additif(bonus_moy_arr)
|
|
else:
|
|
# DUT et LP:
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
class BonusLeHavre(BonusSportAdditif):
|
|
"""Bonus sport IUT du Havre sur les moyennes d'UE
|
|
|
|
<p>
|
|
Les enseignements optionnels de langue, préprofessionnalisation,
|
|
PIX (compétences numériques), l'entrepreneuriat étudiant, l'engagement
|
|
bénévole au sein d'association dès lors qu'une grille d'évaluation des
|
|
compétences existe ainsi que les activités sportives et culturelles
|
|
seront traités au niveau semestriel.
|
|
</p><p>
|
|
Le maximum de bonification qu'un étudiant peut obtenir sur sa moyenne
|
|
est plafonné à 0.5 point.
|
|
</p><p>
|
|
Lorsqu'un étudiant suit plus de deux matières qui donnent droit à
|
|
bonification, l'étudiant choisit les deux notes à retenir.
|
|
</p><p>
|
|
Les points bonus ne sont acquis que pour une note supérieure à 10/20.
|
|
</p><p>
|
|
La bonification est calculée de la manière suivante :<br>
|
|
|
|
Pour chaque matière (max. 2) donnant lieu à bonification :<br>
|
|
|
|
Bonification = (N-10) x 0,05,
|
|
N étant la note de l'activité sur 20.
|
|
</p>
|
|
"""
|
|
|
|
# note: ScoDoc ne vérifie pas que le nombre de modules avec inscription n'excède pas 2
|
|
name = "bonus_iutlh"
|
|
displayed_name = "IUT du Havre"
|
|
classic_use_bonus_ues = True # sur les UE, même en DUT et LP
|
|
seuil_moy_gen = 10.0 # seuls les points au dessus du seuil sont comptés
|
|
proportion_point = 0.05
|
|
bonus_max = 0.5 #
|
|
|
|
|
|
class BonusLeMans(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Le Mans.
|
|
|
|
<p>Les points au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés.
|
|
</p>
|
|
<ul>
|
|
<li>En BUT: la moyenne de chacune des UE du semestre est augmentée de
|
|
2% du cumul des points de bonus;</li>
|
|
|
|
<li>En DUT/LP: la moyenne générale est augmentée de 5% du cumul des points bonus.
|
|
</li>
|
|
</ul>
|
|
<p>Dans tous les cas, le bonus est dans la limite de 0,5 point.</p>
|
|
"""
|
|
|
|
name = "bonus_iutlemans"
|
|
displayed_name = "IUT du Mans"
|
|
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
|
|
bonus_max = 0.5 #
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
# La date du semestre ?
|
|
if self.formsemestre.formation.is_apc():
|
|
self.proportion_point = 0.02
|
|
else:
|
|
self.proportion_point = 0.05
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
# Bonus simple, mais avec changement de paramètres en 2010 !
|
|
class BonusLille(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Villeneuve d'Ascq
|
|
|
|
<p>Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université Lille (sports, etc) non rattachés à une unité d'enseignement.
|
|
</p><p>
|
|
Les points au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés et 4% (2% avant août 2010) de ces points cumulés
|
|
s'ajoutent à la moyenne générale du semestre déjà obtenue par l'étudiant.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_lille"
|
|
displayed_name = "IUT de Lille"
|
|
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
# La date du semestre ?
|
|
if self.formsemestre.date_debut > datetime.date(2010, 8, 1):
|
|
self.proportion_point = 0.04
|
|
else:
|
|
self.proportion_point = 0.02
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
class BonusLimousin(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture) à l'IUT du Limousin
|
|
|
|
Les points au-dessus de 10 sur 20 obtenus dans chacune des matières optionnelles
|
|
sont cumulés.
|
|
|
|
La moyenne de chacune des UE du semestre pair est augmentée de 5% du
|
|
cumul des points de bonus.
|
|
Le maximum de points bonus est de 0,5.
|
|
"""
|
|
|
|
name = "bonus_limousin"
|
|
displayed_name = "IUT du Limousin"
|
|
proportion_point = 0.05
|
|
bonus_max = 0.5
|
|
|
|
|
|
class BonusLyon(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture) à l'IUT de Lyon (2022)
|
|
|
|
<p><b>À partir de 2022-2023 :</b>
|
|
des points de bonification seront ajoutés aux moyennes de toutes les UE
|
|
du semestre concerné (3/100e de point par point au-dessus de 10).<br>
|
|
Cette bonification ne pourra excéder 1/2 point sur chacune des UE
|
|
</p>
|
|
<ul>
|
|
<li>Exemple 1 :<br>
|
|
<tt>
|
|
Sport 12/20 => +0.06<br>
|
|
LV2 13/20 => +0.09<br>
|
|
Bonus total = +0.15 appliqué à toutes les UE du semestre
|
|
</tt>
|
|
</li>
|
|
<li>Exemple 2 :<br>
|
|
<tt>
|
|
Sport 20/20 => +0.30<br>
|
|
LV2 18/20 => +0.24<br>
|
|
Bonus total = +0.50 appliqué à toutes les UE du semestre
|
|
</tt></li>
|
|
</ul>
|
|
|
|
<p><b>Jusqu'en 2021-2022 :</b>
|
|
Les points au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés et 1,8% de ces points cumulés
|
|
s'ajoutent aux moyennes générales, dans la limite d'1/2 point.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_lyon_provisoire"
|
|
displayed_name = "IUT de Lyon"
|
|
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
|
|
bonus_max = 0.5
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
if self.formsemestre.date_debut > datetime.date(2022, 8, 1):
|
|
self.classic_use_bonus_ues = True # pour les LP
|
|
self.proportion_point = 0.03
|
|
else:
|
|
self.classic_use_bonus_ues = False
|
|
self.proportion_point = 0.018
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
class BonusMantes(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (investissement, ...), IUT de Mantes en Yvelines.
|
|
|
|
<p>
|
|
Soit N la note attribuée, le bonus (ou malus) correspond à :
|
|
(N-10) x 0,05
|
|
appliqué sur chaque UE du semestre sélectionné pour le BUT
|
|
ou appliqué sur la moyenne générale du semestre sélectionné pour le DUT.
|
|
</p>
|
|
<p>Exemples :</p>
|
|
<ul>
|
|
<li> pour une note de 20 : bonus de + 0,5</li>
|
|
<li> pour une note de 15 : bonus de + 0,25</li>
|
|
<li> note de 10 : Ni bonus, ni malus (+0)</li>
|
|
<li> note de 5, malus : - 0,25</li>
|
|
<li> note de 0,malus : - 0,5</li>
|
|
</ul>
|
|
"""
|
|
|
|
name = "bonus_mantes"
|
|
displayed_name = "IUT de Mantes en Yvelines"
|
|
bonus_min = -0.5 # peut être NEGATIF !
|
|
bonus_max = 0.5
|
|
seuil_moy_gen = 0.0 # tous les points comptent
|
|
seuil_comptage = 10.0 # pivot à 10.
|
|
proportion_point = 0.05
|
|
|
|
|
|
class BonusMulhouse(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture) à l'IUT de Mulhouse
|
|
|
|
La moyenne de chacune des UE du semestre sera majorée à hauteur de
|
|
5% du cumul des points supérieurs à 10 obtenus en matières optionnelles,
|
|
dans la limite de 0,5 point.
|
|
"""
|
|
|
|
name = "bonus_iutmulhouse"
|
|
displayed_name = "IUT de Mulhouse"
|
|
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
|
|
proportion_point = 0.05
|
|
bonus_max = 0.5 #
|
|
|
|
|
|
class BonusNantes(BonusSportAdditif):
|
|
"""IUT de Nantes (Septembre 2018)
|
|
|
|
<p>Nous avons différents types de bonification
|
|
(sport, culture, engagement citoyen).
|
|
</p><p>
|
|
Nous ajoutons aux moyennes une bonification de 0,2 pour chaque item
|
|
la bonification totale ne doit pas excéder les 0,5 point.
|
|
Sur le bulletin nous ne mettons pas une note sur 20 mais directement les bonifications.
|
|
</p><p>
|
|
Dans ScoDoc: on a déclarera une UE "sport&culture" dans laquelle on aura
|
|
des modules pour chaque activité (Sport, Associations, ...)
|
|
avec à chaque fois une note (ScoDoc l'affichera comme une note sur 20,
|
|
mais en fait ce sera la valeur de la bonification: entrer 0,1/20 signifiera
|
|
un bonus de 0,1 point la moyenne générale).
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_nantes"
|
|
displayed_name = "IUT de Nantes"
|
|
seuil_moy_gen = 0.0 # seuls les points au dessus du seuil sont comptés
|
|
proportion_point = 1 # multiplie les points au dessus du seuil
|
|
bonus_max = 0.5 # plafonnement à 0.5 points
|
|
|
|
|
|
class BonusOrleans(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT d'Orléans
|
|
<p><b>Cadre général :</b>
|
|
En reconnaissance de l'engagement des étudiants dans la vie associative,
|
|
sociale ou professionnelle, l'IUT d'Orléans accorde, sous conditions,
|
|
une bonification aux étudiants inscrits qui en font la demande en début
|
|
d'année universitaire.
|
|
</p>
|
|
<p>Cet engagement doit être régulier et correspondre à une activité réelle
|
|
et sérieuse qui bénéficie à toute la communauté étudiante de l'IUT,
|
|
de l'Université ou à l'ensemble de la collectivité.</p>
|
|
<p><b>Bonification :</b>
|
|
Pour les DUT et LP, cette bonification interviendra sur la moyenne générale
|
|
des semestres pairs :
|
|
<ul><li> du 2ème semestre pour les étudiants de 1ère année de DUT</li>
|
|
<li> du 4ème semestre pour les étudiants de 2nde année de DUT</li>
|
|
<li> du 6ème semestre pour les étudiants en LP</li>
|
|
</ul>
|
|
Pour le BUT, cette bonification interviendra sur la moyenne de chacune
|
|
des UE des semestre pairs :
|
|
<ul><li> du 2ème semestre pour les étudiants de 1ère année de BUT</li>
|
|
<li> du 4ème semestre pour les étudiants de 2ème année de BUT</li>
|
|
<li> du 6ème semestre pour les étudiants de 3ème année de BUT</li>
|
|
</ul>
|
|
<em>La bonification ne peut dépasser +0,5 points par année universitaire.</em>
|
|
</p>
|
|
<p><b> Avant février 2020 :</b>
|
|
Un bonus de 2,5% de la note de sport est accordé à la moyenne générale.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iutorleans"
|
|
displayed_name = "IUT d'Orléans"
|
|
bonus_max = 0.5
|
|
seuil_moy_gen = 0.0 # seuls les points au dessus du seuil sont comptés
|
|
proportion_point = 1
|
|
classic_use_bonus_ues = False
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
if self.formsemestre.date_debut > datetime.date(2020, 2, 1):
|
|
self.proportion_point = 1.0
|
|
else:
|
|
self.proportion_point = 2.5 / 100.0
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
class BonusPoitiers(BonusSportAdditif):
|
|
"""Calcul bonus optionnels (sport, culture), règle IUT de Poitiers.
|
|
|
|
Les deux notes d'option supérieure à 10, bonifient les moyennes de chaque UE.
|
|
|
|
bonus = (option1 - 10)*5% + (option2 - 10)*5%
|
|
"""
|
|
|
|
name = "bonus_poitiers"
|
|
displayed_name = "IUT de Poitiers"
|
|
proportion_point = 0.05
|
|
|
|
|
|
class BonusRoanne(BonusSportAdditif):
|
|
"""IUT de Roanne.
|
|
|
|
Le bonus est compris entre 0 et 0.6 points
|
|
et est toujours appliqué aux UEs.
|
|
"""
|
|
|
|
name = "bonus_iutr"
|
|
displayed_name = "IUT de Roanne"
|
|
seuil_moy_gen = 0.0
|
|
bonus_max = 0.6 # plafonnement à 0.6 points
|
|
classic_use_bonus_ues = True # sur les UE, même en DUT et LP
|
|
proportion_point = 1
|
|
|
|
|
|
class BonusStEtienne(BonusSportAdditif):
|
|
"""IUT de Saint-Etienne.
|
|
|
|
Le bonus est compris entre 0 et 0.6 points.
|
|
"""
|
|
|
|
name = "bonus_iutse"
|
|
displayed_name = "IUT de Saint-Etienne"
|
|
seuil_moy_gen = 0.0
|
|
bonus_max = 0.6 # plafonnement à 0.6 points
|
|
proportion_point = 1
|
|
|
|
|
|
class BonusStDenis(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Saint-Denis
|
|
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université Paris 13 (sports, musique, deuxième langue,
|
|
culture, etc) non rattachés à une unité d'enseignement. Les points
|
|
au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés et 5% de ces points cumulés s'ajoutent à
|
|
la moyenne générale du semestre déjà obtenue par l'étudiant, dans la limite
|
|
d'1/2 point.
|
|
"""
|
|
|
|
name = "bonus_iut_stdenis"
|
|
displayed_name = "IUT de Saint-Denis"
|
|
bonus_max = 0.5
|
|
|
|
|
|
class BonusStNazaire(BonusSport):
|
|
"""IUT de Saint-Nazaire
|
|
|
|
Trois bonifications sont possibles : sport, culture et engagement citoyen
|
|
(qui seront déclarées comme des modules séparés de l'UE bonus).
|
|
<ul>
|
|
<li>Chaque bonus est compris entre 0 et 20 points -> 4pt = 1%<br>
|
|
(note 4/20: 1%, 8/20: 2%, 12/20: 3%, 16/20: 4%, 20/20: 5%)
|
|
</li>
|
|
<li>Le total des 3 bonus ne peut excéder 10%</li>
|
|
<li>La somme des bonus s'applique à la moyenne de chaque UE</li>
|
|
</ul>
|
|
<p>Exemple: une moyenne d'UE de 10/20 avec un total des bonus de 6% donne
|
|
une moyenne de 10,6.</p>
|
|
<p>Les bonifications s'appliquent aussi au classement général du semestre
|
|
et de l'année.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iutSN"
|
|
displayed_name = "IUT de Saint-Nazaire"
|
|
classic_use_bonus_ues = True # s'applique aux UEs en DUT et LP
|
|
amplitude = 0.01 / 4 # 4pt => 1%
|
|
factor_max = 0.1 # 10% max
|
|
# Modifié 2022-11-29: calculer chaque bonus
|
|
# (de 1 à 3 modules) séparément.
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""Calcul du bonus St Nazaire 2022
|
|
sem_modimpl_moys_inscrits: les notes de sport
|
|
En APC: ndarray (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
|
En classic: ndarray (nb_etuds, nb_mod_sport)
|
|
"""
|
|
if 0 in sem_modimpl_moys_inscrits.shape:
|
|
# pas d'étudiants ou pas d'UE ou pas de module...
|
|
return
|
|
# Prend les 3 premiers bonus trouvés
|
|
# ignore les coefficients
|
|
bonus_mod_moys = sem_modimpl_moys_inscrits[:, :3]
|
|
bonus_mod_moys = np.nan_to_num(bonus_mod_moys, copy=False)
|
|
factor = bonus_mod_moys * self.amplitude
|
|
# somme les bonus:
|
|
factor = factor.sum(axis=1)
|
|
# et limite à 10%:
|
|
factor.clip(0.0, self.factor_max, out=factor)
|
|
|
|
# Applique aux moyennes d'UE
|
|
if len(factor.shape) == 1: # classic
|
|
factor = factor[:, np.newaxis]
|
|
bonus = self.etud_moy_ue * factor
|
|
self.bonus_ues = bonus # DataFrame
|
|
|
|
# Les bonus multiplicatifs ne s'appliquent pas à la moyenne générale
|
|
self.bonus_moy_gen = None
|
|
|
|
|
|
class BonusTarbes(BonusIUTRennes1):
|
|
"""Calcul bonus optionnels (sport, culture), règle IUT de Tarbes.
|
|
|
|
<ul>
|
|
<li>Les étudiants opeuvent suivre un ou plusieurs activités optionnelles notées.
|
|
La meilleure des notes obtenue est prise en compte, si elle est supérieure à 10/20.
|
|
</li>
|
|
<li>Le trentième des points au dessus de 10 est ajouté à la moyenne des UE en BUT,
|
|
ou à la moyenne générale en DUT et LP.
|
|
</li>
|
|
<li> Exemple: un étudiant ayant 16/20 bénéficiera d'un bonus de (16-10)/30 = 0,2 points
|
|
sur chaque UE.
|
|
</li>
|
|
</ul>
|
|
"""
|
|
|
|
name = "bonus_tarbes"
|
|
displayed_name = "IUT de Tarbes"
|
|
seuil_moy_gen = 10.0
|
|
proportion_point = 1 / 30.0
|
|
classic_use_bonus_ues = True
|
|
|
|
|
|
class BonusTours(BonusDirect):
|
|
"""Calcul bonus sport & culture IUT Tours.
|
|
|
|
<p>Les notes des UE bonus (ramenées sur 20) sont sommées
|
|
et 1/40 (2,5%) est ajouté aux moyennes: soit à la moyenne générale,
|
|
soit pour le BUT à chaque moyenne d'UE.
|
|
</p><p>
|
|
<em>Attention: en GEII, facteur 1/40, ailleurs facteur 1.</em>
|
|
</p><p>
|
|
Le bonus total est limité à 1 point.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_tours"
|
|
displayed_name = "IUT de Tours"
|
|
bonus_max = 1.0 #
|
|
seuil_moy_gen = 0.0 # seuls les points au dessus du seuil sont comptés
|
|
proportion_point = 1.0 / 40.0
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul différencié selon le département !"""
|
|
if g.scodoc_dept == "GEII":
|
|
self.proportion_point = 1.0 / 40.0
|
|
else:
|
|
self.proportion_point = 1.0
|
|
return super().compute_bonus(
|
|
sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan
|
|
)
|
|
|
|
|
|
class BonusIUTvannes(BonusSportAdditif):
|
|
"""Calcul bonus modules optionels (sport, culture), règle IUT Vannes
|
|
|
|
<p><b>Ne concerne actuellement que les DUT et LP</b></p>
|
|
<p>Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'U.B.S. (sports, musique, deuxième langue, culture, etc) non
|
|
rattachés à une unité d'enseignement.
|
|
</p><p>
|
|
Les points au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés.
|
|
</p><p>
|
|
3% de ces points cumulés s'ajoutent à la moyenne générale du semestre
|
|
déjà obtenue par l'étudiant.
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_iutvannes"
|
|
displayed_name = "IUT de Vannes"
|
|
seuil_moy_gen = 10.0
|
|
proportion_point = 0.03 # 3%
|
|
classic_use_bonus_ues = False # seulement sur moy gen.
|
|
|
|
|
|
class BonusValenciennes(BonusDirect):
|
|
"""Article 7 des RCC de l'IUT de Valenciennes
|
|
|
|
<p>
|
|
Une bonification maximale de 0.25 point (1/4 de point) peut être ajoutée
|
|
à la moyenne de chaque Unité d'Enseignement pour :
|
|
</p>
|
|
<ul>
|
|
<li>l'engagement citoyen ;</li>
|
|
<li>la participation à un module de sport.</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Une bonification accordée par la commission des sports de l'UPHF peut être attribuée
|
|
aux sportifs de haut niveau. Cette bonification est appliquée à l'ensemble des
|
|
Unités d'Enseignement. Ce bonus est :
|
|
</p>
|
|
<ul>
|
|
<li> 0.5 pour la catégorie <em>or</em> (sportif inscrit sur liste ministérielle
|
|
jeunesse et sport) ;
|
|
</li>
|
|
<li> 0.45 pour la catégorie <em>argent</em> (sportif en club professionnel) ;
|
|
</li>
|
|
<li> 0.40 pour le <em>bronze</em> (sportif de niveau départemental, régional ou national).
|
|
</li>
|
|
</ul>
|
|
<p>Le cumul de bonifications est possible mais ne peut excéder 0.5 point (un demi-point).
|
|
</p>
|
|
<p><em>Dans ScoDoc, saisir directement la valeur désirée du bonus
|
|
dans une évaluation notée sur 20.</em>
|
|
</p>
|
|
"""
|
|
|
|
name = "bonus_valenciennes"
|
|
displayed_name = "IUT de Valenciennes"
|
|
bonus_max = 0.5
|
|
|
|
|
|
class BonusVilleAvray(BonusSportAdditif):
|
|
"""Bonus modules optionnels (sport, culture), règle IUT Ville d'Avray.
|
|
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université Paris 10 (C2I) non rattachés à une unité d'enseignement.
|
|
<ul>
|
|
<li>Si la note est >= 10 et < 12, bonus de 0.1 point</li>
|
|
<li>Si la note est >= 12 et < 16, bonus de 0.2 point</li>
|
|
<li>Si la note est >= 16, bonus de 0.3 point</li>
|
|
</ul>
|
|
<p>Ce bonus s'ajoute à la moyenne générale du semestre déjà obtenue par
|
|
l'étudiant.</p>
|
|
"""
|
|
|
|
name = "bonus_iutva"
|
|
displayed_name = "IUT de Ville d'Avray"
|
|
|
|
def compute_bonus(self, sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan):
|
|
"""calcul du bonus"""
|
|
if 0 in sem_modimpl_moys_inscrits.shape:
|
|
# pas d'étudiants ou pas d'UE ou pas de module...
|
|
return
|
|
# Calcule moyenne pondérée des notes de sport:
|
|
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
|
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)
|
|
np.nan_to_num(bonus_moy_arr, nan=0.0, copy=False)
|
|
bonus_moy_arr[bonus_moy_arr < 10.0] = 0.0
|
|
bonus_moy_arr[bonus_moy_arr >= 16.0] = 0.3
|
|
bonus_moy_arr[bonus_moy_arr >= 12.0] = 0.2
|
|
bonus_moy_arr[bonus_moy_arr >= 10.0] = 0.1
|
|
|
|
self.bonus_additif(bonus_moy_arr)
|
|
|
|
|
|
class BonusIUTV(BonusSportAdditif):
|
|
"""Calcul bonus modules optionnels (sport, culture), règle IUT Villetaneuse
|
|
|
|
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
|
|
de l'Université Paris 13 (sports, musique, deuxième langue,
|
|
culture, etc) non rattachés à une unité d'enseignement. Les points
|
|
au-dessus de 10 sur 20 obtenus dans chacune des matières
|
|
optionnelles sont cumulés et 5% de ces points cumulés s'ajoutent à
|
|
la moyenne générale du semestre déjà obtenue par l'étudiant.
|
|
"""
|
|
|
|
name = "bonus_iutv"
|
|
displayed_name = "IUT de Villetaneuse"
|
|
# c'est le bonus par défaut: aucune méthode à surcharger
|
|
|
|
|
|
def get_bonus_class_dict(start=BonusSport, d=None):
|
|
"""Dictionnaire des classes de bonus
|
|
(liste les sous-classes de BonusSport ayant un nom)
|
|
Resultat: { name : class }
|
|
"""
|
|
if d is None:
|
|
d = {}
|
|
if start.name != "virtual":
|
|
d[start.name] = start
|
|
for subclass in start.__subclasses__():
|
|
get_bonus_class_dict(subclass, d=d)
|
|
return d
|