From b6af7d45c9e2082889a9565f3cc626b0102b1185 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Wed, 18 May 2022 20:40:50 +0200
Subject: [PATCH] Bonus Rennes 1 (Lannion, St Malo)

---
 app/comp/bonus_spo.py | 45 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/app/comp/bonus_spo.py b/app/comp/bonus_spo.py
index 8d426b682..06a7bde76 100644
--- a/app/comp/bonus_spo.py
+++ b/app/comp/bonus_spo.py
@@ -703,6 +703,51 @@ class BonusGrenobleIUT1(BonusSportMultiplicatif):
         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, St Malo).
+
+    <ul>
+    <li>Les étudiants peuvent 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 vingtième des points au dessus de 10 est ajouté à la moyenne des UE.
+    </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, St Malo)"
+    seuil_moy_gen = 10.0
+    proportion_point = 1 / 20.0
+    classic_use_bonus_ues = True
+    # Adapté de BonusTarbes, mais s'applique aussi en classic
+    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)
+
+
 class BonusLaRochelle(BonusSportAdditif):
     """Calcul bonus modules optionnels (sport, culture), règle IUT de La Rochelle.