Compare commits

...

7 Commits

9 changed files with 115 additions and 21 deletions

View File

@ -13,6 +13,7 @@ Les classes de Bonus fournissent deux méthodes:
"""
import datetime
import math
import numpy as np
import pandas as pd
@ -106,6 +107,8 @@ class BonusSport:
# 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)
@ -157,7 +160,8 @@ 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_non_bonus)
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
@ -236,10 +240,6 @@ class BonusSportAdditif(BonusSport):
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):
"""Bonus sport qui multiplie les moyennes d'UE par un facteur"""
@ -294,8 +294,51 @@ class BonusDirect(BonusSportAdditif):
proportion_point = 1.0
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 :
0.05 point si >=10,
0.1 point si >=12,
0.15 point si >=14,
0.2 point si >=16,
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 >= 18.0] = 0.25
bonus[note_bonus_max >= 16.0] = 0.20
bonus[note_bonus_max >= 14.0] = 0.15
bonus[note_bonus_max >= 12.0] = 0.10
bonus[note_bonus_max >= 10.0] = 0.05
# 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 BonusBethune(BonusSportMultiplicatif):
"""Calcul bonus modules optionels (sport), règle IUT de Béthune.
"""Calcul bonus modules optionnels (sport), règle IUT de Béthune.
Les points au dessus de la moyenne de 10 apportent un bonus pour le semestre.
Ce bonus est égal au nombre de points divisé par 200 et multiplié par la
@ -309,7 +352,7 @@ class BonusBethune(BonusSportMultiplicatif):
class BonusBezier(BonusSportAdditif):
"""Calcul bonus modules optionels (sport, culture), règle IUT de Bézier.
"""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
@ -330,7 +373,7 @@ class BonusBezier(BonusSportAdditif):
class BonusBordeaux1(BonusSportMultiplicatif):
"""Calcul bonus modules optionels (sport, culture), règle IUT Bordeaux 1, sur moyenne générale
"""Calcul bonus modules optionnels (sport, culture), règle IUT Bordeaux 1, sur moyenne générale
et UE.
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
@ -351,7 +394,7 @@ class BonusBordeaux1(BonusSportMultiplicatif):
class BonusColmar(BonusSportAdditif):
"""Calcul bonus modules optionels (sport, culture), règle IUT Colmar.
"""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
@ -411,7 +454,7 @@ class BonusGrenobleIUT1(BonusSportMultiplicatif):
class BonusLaRochelle(BonusSportAdditif):
"""Calcul bonus modules optionels (sport, culture), règle IUT de La Rochelle.
"""Calcul bonus modules optionnels (sport, culture), règle IUT de La Rochelle.
Si la note de sport est comprise entre 0 et 10 : pas d'ajout de point.
Si la note de sport est comprise entre 10 et 20 : ajout de 1% de cette
@ -471,7 +514,7 @@ class BonusLeMans(BonusSportAdditif):
# Bonus simple, mais avec changement de paramètres en 2010 !
class BonusLille(BonusSportAdditif):
"""Calcul bonus modules optionels (sport, culture), règle IUT Villeneuve d'Ascq
"""Calcul bonus modules optionnels (sport, culture), règle IUT Villeneuve d'Ascq
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
de l'Université Lille (sports, etc) non rattachés à une unité d'enseignement.
@ -565,7 +608,7 @@ class BonusRoanne(BonusSportAdditif):
class BonusStDenis(BonusSportAdditif):
"""Calcul bonus modules optionels (sport, culture), règle IUT Saint-Denis
"""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,
@ -611,7 +654,7 @@ class BonusTours(BonusDirect):
class BonusVilleAvray(BonusSport):
"""Bonus modules optionels (sport, culture), règle IUT Ville d'Avray.
"""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.
@ -645,7 +688,7 @@ class BonusVilleAvray(BonusSport):
class BonusIUTV(BonusSportAdditif):
"""Calcul bonus modules optionels (sport, culture), règle IUT Villetaneuse
"""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,

View File

@ -266,6 +266,8 @@ def compute_ue_moys_apc(
)
# Annule les coefs des modules NaN
modimpl_coefs_etuds_no_nan = np.where(np.isnan(sem_cube), 0.0, modimpl_coefs_etuds)
if modimpl_coefs_etuds_no_nan.dtype == np.object: # arrive sur des tableaux vides
modimpl_coefs_etuds_no_nan = modimpl_coefs_etuds_no_nan.astype(np.float)
#
# Version vectorisée
#
@ -348,7 +350,8 @@ def compute_ue_moys_classic(
modimpl_coefs_etuds_no_nan = np.where(
np.isnan(sem_matrix), 0.0, modimpl_coefs_etuds
)
if modimpl_coefs_etuds_no_nan.dtype == np.object: # arrive sur des tableaux vides
modimpl_coefs_etuds_no_nan = modimpl_coefs_etuds_no_nan.astype(np.float)
# --------------------- Calcul des moyennes d'UE
ue_modules = np.array(
[[m.module.ue == ue for m in formsemestre.modimpls_sorted] for ue in ues]
@ -358,6 +361,8 @@ def compute_ue_moys_classic(
)
# nb_ue x nb_etuds x nb_mods : coefs prenant en compte NaN et inscriptions
coefs = (modimpl_coefs_etuds_no_nan_stacked * ue_modules).swapaxes(1, 2)
if coefs.dtype == np.object: # arrive sur des tableaux vides
coefs = coefs.astype(np.float)
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
etud_moy_ue = (
np.sum(coefs * sem_matrix_inscrits, axis=2) / np.sum(coefs, axis=2)

View File

@ -34,7 +34,7 @@ class Module(db.Model):
# id de l'element pedagogique Apogee correspondant:
code_apogee = db.Column(db.String(APO_CODE_STR_LEN))
# Type: ModuleType: DEFAULT, MALUS, RESSOURCE, MODULE_SAE (enum)
module_type = db.Column(db.Integer)
module_type = db.Column(db.Integer, nullable=False, default=0, server_default="0")
# Relations:
modimpls = db.relationship("ModuleImpl", backref="module", lazy="dynamic")
ues_apc = db.relationship("UniteEns", secondary="module_ue_coef", viewonly=True)

View File

@ -302,7 +302,12 @@ class DisplayedGroupsInfos(object):
if group_ids:
group_ids = [group_ids] # cas ou un seul parametre, pas de liste
else:
group_ids = [int(g) for g in group_ids]
try:
group_ids = [int(g) for g in group_ids]
except ValueError as exc:
raise ScoValueError(
"identifiant de groupe invalide (mettre à jour vos bookmarks ?)"
) from exc
if not formsemestre_id and moduleimpl_id:
mods = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)
if len(mods) != 1:

View File

@ -397,7 +397,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""):
)
@bp.route("/ue_infos/<ue_id>")
@bp.route("/ue_infos/<int:ue_id>")
@scodoc
@permission_required(Permission.ScoView)
def ue_infos(ue_id):

View File

@ -68,7 +68,7 @@ from app.scodoc.sco_permissions import Permission
@bp.route("/table_modules_ue_coefs/<int:formation_id>")
@bp.route("/table_modules_ue_coefs/<int:formation_id>/<semestre_idx>")
@bp.route("/table_modules_ue_coefs/<int:formation_id>/<int:semestre_idx>")
@scodoc
@permission_required(Permission.ScoView)
def table_modules_ue_coefs(formation_id, semestre_idx=None):

View File

@ -121,7 +121,7 @@ def create_dept():
)
@bp.route("/ScoDoc/toggle_dept_vis/<dept_id>", methods=["GET", "POST"])
@bp.route("/ScoDoc/toggle_dept_vis/<int:dept_id>", methods=["GET", "POST"])
@admin_required
def toggle_dept_vis(dept_id):
"""Cache ou rend visible un dept"""

View File

@ -0,0 +1,41 @@
"""module_type_non_null
Revision ID: b9aadc10227f
Revises: bd2c1c3d866e
Create Date: 2022-02-15 21:47:29.212329
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
from sqlalchemy.orm import sessionmaker # added by ev
# revision identifiers, used by Alembic.
revision = "b9aadc10227f"
down_revision = "bd2c1c3d866e"
branch_labels = None
depends_on = None
Session = sessionmaker()
def upgrade():
# Added by ev: remove duplicates
bind = op.get_bind()
session = Session(bind=bind)
session.execute(
"""UPDATE notes_modules SET module_type=0 WHERE module_type IS NULL;"""
)
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(
"notes_modules", "module_type", existing_type=sa.INTEGER(), nullable=False
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(
"notes_modules", "module_type", existing_type=sa.INTEGER(), nullable=True
)
# ### end Alembic commands ###

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.1.56"
SCOVERSION = "9.1.57"
SCONAME = "ScoDoc"