Finition choix bonus sport

This commit is contained in:
Emmanuel Viennet 2022-01-27 18:12:40 +01:00
parent e9c2c3c1f7
commit 5c17410bcb
9 changed files with 316 additions and 159 deletions

View File

@ -57,7 +57,7 @@ class BonusSport:
# Attributs virtuels:
seuil_moy_gen = None
proportion_point = None
bonus_moy_gen_limit = None
bonus_max = None
name = "virtual"
@ -217,147 +217,13 @@ class BonusSportAdditif(BonusSport):
self.bonus_moy_gen = pd.Series(
bonus_moy_gen_arr, index=self.etuds_idx, dtype=float
)
if self.bonus_moy_gen_limit is not None:
# Seuil: bonus (sur moy. gen.) limité à bonus_moy_gen_limit points
self.bonus_moy_gen = self.bonus_moy_gen.clip(upper=self.bonus_moy_gen_limit)
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)
# Laisse bonus_ues à None, en APC le bonus moy. gen. sera réparti sur les UEs.
# bonus_ue = np.stack([modimpl_coefs_spo.T] * nb_ues)
class BonusIUTV(BonusSportAdditif):
"""Calcul bonus modules optionels (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"
pass # oui, c'ets le bonus par défaut
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"
seuil_moy_gen = 0.0 # tous les points sont comptés
proportion_point = 1.0
class BonusStDenis(BonusIUTV):
"""Semblable à bonus_iutv mais sans coefficients et total limité à 0.5 points."""
name = "bonus_iut_stdenis"
bonus_moy_gen_limit = 0.5
class BonusColmar(BonusSportAdditif):
"""Calcul bonus modules optionels (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"
bonus_moy_gen_limit = 0.5
class BonusTours(BonusDirect):
"""Calcul bonus sport & culture IUT Tours.
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.
Le bonus total est limité à 1 point.
"""
name = "bonus_tours"
bonus_moy_gen_limit = 1.0 #
seuil_moy_gen = 0.0 # seuls les points au dessus du seuil sont comptés
proportion_point = 1.0 / 40.0
def bonus_iutlemans(notes_sport, coefs, infos=None):
# Calcul bonus modules optionnels (sport, culture), règle IUT Le Mans
# La moyenne de chacune des UE du semestre sera majorée à hauteur de 2% du cumul des points supérieurs à 10 obtenus en matières optionnelles,
# dans la limite de 0,5 point.
points = sum([x - 10 for x in notes_sport if x > 10]) # points au dessus de 10
bonus = points * 0.02 # ou / 20
return min(bonus, 0.5) # bonus limité à 0.5 point
class BonusLeMans(BonusSportAdditif):
"""Calcul bonus modules optionnels (sport, culture), règle IUT Le Mans
La moyenne de chacune des UE du semestre sera majorée à hauteur de
2% du cumul des points supérieurs à 10 obtenus en matières optionnelles,
dans la limite de 0,5 point.
"""
name = "bonus_iutlemans"
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
proportion_point = 0.02
bonus_moy_gen_limit = 0.5 #
# 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
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
de l'Université Lille 1 (sports, 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 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.
"""
name = "bonus_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 BonusMulhouse(BonusSportAdditif):
"""Calcul bonus modules optionnels (sport, culture), règle 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"
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
proportion_point = 0.05
bonus_moy_gen_limit = 0.5 #
class BonusSportMultiplicatif(BonusSport):
"""Bonus sport qui multiplie les moyennes d'UE par un facteur"""
@ -381,8 +247,12 @@ class BonusSportMultiplicatif(BonusSport):
factor = (notes - self.seuil_moy_gen) * self.amplitude # 5% si note=20
factor[factor <= 0] = 0.0 # note < seuil_moy_gen, pas de bonus
# S'applique qu'aux moyennes d'UE
# Ne s'applique qu'aux moyennes d'UE
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
if not self.formsemestre.formation.is_apc():
@ -390,6 +260,91 @@ class BonusSportMultiplicatif(BonusSport):
self.bonus_moy_gen = bonus
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 BonusBethune(BonusSportMultiplicatif):
"""Calcul bonus modules optionels (sport), règle IUT de Béthune.
5% des points au dessus de 10., limité à 0.5 point de bonus.
"""
name = "bonus_iutbethune"
displayed_name = "IUT de Béthune"
seuil_moy_gen = 10.0
amplitude = 0.005
bonus_max = 0.5 # plafonnement à 0.5 points
class BonusBezier(BonusSportAdditif):
"""Calcul bonus modules optionels (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 BonusBordeaux1(BonusSportMultiplicatif):
"""Calcul bonus modules optionels (sport, culture), règle IUT Bordeaux 1, sur moyenne générale et UE
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.
En cas de double activité, c'est la meilleure des 2 notes qui compte.
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.
Formule : le % = points>moyenne / 2
Par exemple : sport 13/20 : chaque UE sera multipliée par 1+0,015, ainsi que la moyenne générale.
Calcul ici du bonus sur moyenne générale et moyennes d'UE non capitalisées.
"""
pass # XXX en attente de Cédric
class BonusColmar(BonusSportAdditif):
"""Calcul bonus modules optionels (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
@ -409,6 +364,7 @@ class BonusGrenobleIUT1(BonusSportMultiplicatif):
"""
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
@ -428,6 +384,20 @@ class BonusGrenobleIUT1(BonusSportMultiplicatif):
super().compute_bonus(sem_modimpl_moys_inscrits, modimpl_coefs_etuds_no_nan)
class BonusLaRochelle(BonusSportAdditif):
"""Calcul bonus modules optionels (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
note sur la moyenne générale du semestre (ou sur les UE en BUT).
"""
name = "bonus_iutlr"
displayed_name = "IUT de La Rochelle"
seuil_moy_gen = 10.0 # tous les points sont comptés
proportion_point = 0.01
class BonusLeHavre(BonusSportMultiplicatif):
"""Bonus sport IUT du Havre sur moyenne générale et UE
@ -436,10 +406,84 @@ class BonusLeHavre(BonusSportMultiplicatif):
"""
name = "bonus_iutlh"
displayed_name = "IUT du Havre"
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
class BonusLeMans(BonusSportAdditif):
"""Calcul bonus modules optionnels (sport, culture), règle IUT Le Mans
La moyenne de chacune des UE du semestre sera majorée à hauteur de
2% du cumul des points supérieurs à 10 obtenus en matières optionnelles,
dans la limite de 0,5 point.
"""
name = "bonus_iutlemans"
displayed_name = "IUT du Mans"
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
proportion_point = 0.02
bonus_max = 0.5 #
# 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
Les étudiants de l'IUT peuvent suivre des enseignements optionnels
de l'Université Lille 1 (sports, 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 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.
"""
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 BonusLyonProvisoire(BonusSportAdditif):
"""Calcul bonus modules optionnels (sport, culture), règle IUT de Lyon (provisoire)
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, dans la limite d'1/2 point.
"""
name = "bonus_lyon_provisoire"
displayed_name = "IUT de Lyon (provisoire)"
seuil_moy_gen = 10.0 # points comptés au dessus de 10.
proportion_point = 0.018
bonus_max = 0.5
class BonusMulhouse(BonusSportAdditif):
"""Calcul bonus modules optionnels (sport, culture), règle 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)
@ -457,24 +501,60 @@ class BonusNantes(BonusSportAdditif):
"""
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_moy_gen_limit = 0.5 # plafonnement à 0.5 points
bonus_max = 0.5 # plafonnement à 0.5 points
class BonusRoanne(BonusSportAdditif):
"""IUT de Roanne.
Le bonus est compris entre 0 et 0.35 point
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_moy_gen_limit = 0.35 # plafonnement à 0.35 points
bonus_max = 0.6 # plafonnement à 0.6 points
apply_bonus_mg_to_ues = True # sur les UE, même en DUT et LP
class BonusStDenis(BonusSportAdditif):
"""Calcul bonus modules optionels (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 BonusTours(BonusDirect):
"""Calcul bonus sport & culture IUT Tours.
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.
Le bonus total est limité à 1 point.
"""
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
class BonusVilleAvray(BonusSport):
"""Bonus modules optionels (sport, culture), règle IUT Ville d'Avray.
@ -488,6 +568,7 @@ class BonusVilleAvray(BonusSport):
"""
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"""
@ -503,13 +584,29 @@ class BonusVilleAvray(BonusSport):
self.bonus_moy_gen = pd.Series(
bonus_moy_gen_arr, index=self.etuds_idx, dtype=float
)
if self.bonus_moy_gen_limit is not None:
# Seuil: bonus (sur moy. gen.) limité à bonus_moy_gen_limit points
self.bonus_moy_gen = self.bonus_moy_gen.clip(upper=self.bonus_moy_gen_limit)
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)
# Laisse bonus_ues à None, en APC le bonus moy. gen. sera réparti sur les UEs.
class BonusIUTV(BonusSportAdditif):
"""Calcul bonus modules optionels (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"
pass # oui, c'ets le bonus par défaut
def get_bonus_class_dict(start=BonusSport, d=None):
"""Dictionnaire des classes de bonus
(liste les sous-classes de BonusSport ayant un nom)

View File

@ -42,8 +42,8 @@ class ScoDocConfigurationForm(FlaskForm):
bonus_sport_func_name = SelectField(
label="Fonction de calcul des bonus sport&culture",
choices=[
(x, x if x else "Aucune")
for x in ScoDocSiteConfig.get_bonus_sport_class_names()
(name, displayed_name if name else "Aucune")
for (name, displayed_name) in ScoDocSiteConfig.get_bonus_sport_class_list()
],
)
submit = SubmitField("Valider")

View File

@ -124,7 +124,7 @@ class ScoDocSiteConfig(db.Model):
If class_name not found in module bonus_sport, returns None
and flash a warning.
"""
if class_name is None:
if not class_name: # None or ""
c = ScoDocSiteConfig.query.filter_by(name=cls.BONUS_SPORT).first()
if c is None:
return None
@ -140,12 +140,22 @@ class ScoDocSiteConfig(db.Model):
return klass
@classmethod
def get_bonus_sport_class_names(cls):
def get_bonus_sport_class_names(cls) -> list:
"""List available bonus class names
(starting with empty string to represent "no bonus function").
"""
return [""] + sorted(bonus_spo.get_bonus_class_dict().keys())
@classmethod
def get_bonus_sport_class_list(cls) -> list[tuple]:
"""List available bonus class names
(starting with empty string to represent "no bonus function").
"""
d = bonus_spo.get_bonus_class_dict()
class_list = [(name, d[name].displayed_name) for name in d.keys()]
class_list.sort(key=lambda x: x[1].replace(" du ", " de "))
return [("", "")] + class_list
@classmethod
def get_bonus_sport_func(cls):
"""Fonction bonus_sport ScoDoc 7 XXX

View File

@ -375,7 +375,7 @@ def bonus_iutBordeaux1(notes_sport, coefs, infos=None):
return bonus
def bonus_iuto(notes_sport, coefs, infos=None):
def bonus_iuto(notes_sport, coefs, infos=None): # OBSOLETE => EN ATTENTE (27/01/2022)
"""Calcul bonus modules optionels (sport, culture), règle IUT Orleans
* Avant aout 2013
Un bonus de 2,5% de la note de sport est accordé à chaque UE sauf

View File

@ -390,9 +390,9 @@ def ue_edit(ue_id=None, create=False, formation_id=None):
submitlabel=submitlabel,
)
if tf[0] == 0:
X = """<div id="ue_list_code"></div>
"""
return "\n".join(H) + tf[1] + X + html_sco_header.sco_footer()
ue_div = """<div id="ue_list_code"></div>"""
bonus_div = """<div id="bonus_description"></div>"""
return "\n".join(H) + tf[1] + bonus_div + ue_div + html_sco_header.sco_footer()
else:
if create:
if not tf[2]["ue_code"]:

View File

@ -881,6 +881,19 @@ div.sco_help {
span.wtf-field ul.errors li {
color: red;
}
#bonus_description {
color:rgb(6, 73, 6);
padding: 5px;
margin-top:5px;
border: 2px solid blue;
border-radius: 5px;
background-color: cornsilk;
}
#bonus_description div.bonus_description_head{
font-weight: bold;
}
.configuration_logo div.img {
}

View File

@ -3,8 +3,26 @@
$().ready(function () {
update_ue_list();
$("#tf_ue_code").bind("keyup", update_ue_list);
$("select#tf_type").change(function () {
update_bonus_description();
});
update_bonus_description();
});
function update_bonus_description() {
var ue_type = $("#tf_type")[0].value;
if (ue_type == "1") { /* UE SPORT */
$("#bonus_description").show();
var query = "/ScoDoc/get_bonus_description/default";
$.get(query, '', function (data) {
$("#bonus_description").html(data);
});
} else {
$("#bonus_description").html("");
$("#bonus_description").hide();
}
}
function update_ue_list() {
var ue_id = $("#tf_ue_id")[0].value;

View File

@ -30,8 +30,8 @@
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
<div class="help" id="bonus_description"></div>
</div>
<div id="bonus_description"></div>
<h1>Gestion des images: logos, signatures, ...</h1>
<div class="sco_help">Ces images peuvent être intégrées dans les documents
@ -51,14 +51,21 @@
{{ super() }}
<script>
$(function()
{
$("#configuration_form select").change(function(){
function update_bonus_description() {
var query = "/ScoDoc/get_bonus_description/" + $("#configuration_form select")[0].value;
$.get(query, '', function (data) {
$("#bonus_description").html(data);
});
}
$(function()
{
$("#configuration_form select").change(function(){
update_bonus_description();
});
update_bonus_description();
});
</script>
{% endblock %}

View File

@ -32,6 +32,7 @@ Emmanuel Viennet, 2021
"""
import datetime
import io
import re
import flask
from flask import abort, flash, url_for, redirect, render_template, send_file
@ -259,8 +260,19 @@ def configuration():
@bp.route("/ScoDoc/get_bonus_description/<bonus_name>", methods=["GET"])
def get_bonus_description(bonus_name: str):
"description text/html du bonus"
if bonus_name == "default":
bonus_name = ""
bonus_class = ScoDocSiteConfig.get_bonus_sport_class_from_name(bonus_name)
return bonus_class.__doc__
text = bonus_class.__doc__
fields = re.split(r"\n\n", text, maxsplit=1)
if len(fields) > 1:
first_line, text = fields
else:
first_line, text = "", fields[0]
return f"""<div class="bonus_description_head">{first_line}</div>
<div>{text}</div>
"""
@bp.route("/ScoDoc/configure_logos", methods=["GET", "POST"])