Tableau jury BUT: col. RCUEs avec tri sur moy. gen. S_pair

This commit is contained in:
Emmanuel Viennet 2022-06-24 08:59:09 +02:00
parent 145f69aee2
commit dcee2a441f
4 changed files with 74 additions and 17 deletions

View File

@ -207,6 +207,19 @@ class DecisionsProposeesAnnee(DecisionsProposees):
self.code_valide = self.validation.code self.code_valide = self.validation.code
self.parcour = None self.parcour = None
"Le parcours considéré (celui du semestre pair, ou à défaut impair)" "Le parcours considéré (celui du semestre pair, ou à défaut impair)"
if self.formsemestre_pair is not None:
self.res_pair: ResultatsSemestreBUT = res_sem.load_formsemestre_results(
self.formsemestre_pair
)
else:
self.res_pair = None
if self.formsemestre_impair is not None:
self.res_impair: ResultatsSemestreBUT = res_sem.load_formsemestre_results(
self.formsemestre_impair
)
else:
self.res_impair = None
self.ues_impair, self.ues_pair = self.compute_ues_annee() # pylint: disable=all self.ues_impair, self.ues_pair = self.compute_ues_annee() # pylint: disable=all
self.decisions_ues = { self.decisions_ues = {
ue.id: DecisionsProposeesUE(etud, formsemestre_impair, ue) ue.id: DecisionsProposeesUE(etud, formsemestre_impair, ue)
@ -332,14 +345,14 @@ class DecisionsProposeesAnnee(DecisionsProposees):
""" """
etudid = self.etud.id etudid = self.etud.id
ues_sems = [] ues_sems = []
for formsemestre in self.formsemestre_impair, self.formsemestre_pair: for (formsemestre, res) in (
(self.formsemestre_impair, self.res_impair),
(self.formsemestre_pair, self.res_pair),
):
if formsemestre is None: if formsemestre is None:
ues = [] ues = []
else: else:
formation: Formation = formsemestre.formation formation: Formation = formsemestre.formation
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(
formsemestre
)
# Parcour dans lequel l'étudiant est inscrit, et liste des UEs # Parcour dans lequel l'étudiant est inscrit, et liste des UEs
if res.etuds_parcour_id[etudid] is None: if res.etuds_parcour_id[etudid] is None:
# pas de parcour: prend toutes les UEs (non bonus) # pas de parcour: prend toutes les UEs (non bonus)

View File

@ -11,6 +11,7 @@ import time
from flask import g, url_for from flask import g, url_for
from app.but import jury_but from app.but import jury_but
from app.but.jury_but import DecisionsProposeesAnnee
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
from app.comp import res_sem from app.comp import res_sem
from app.models.but_validations import RegroupementCoherentUE from app.models.but_validations import RegroupementCoherentUE
@ -65,7 +66,7 @@ def formsemestre_saisie_jury_but(
) )
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title=f"{formsemestre2.sem_modalite()}: moyennes", page_title=f"{formsemestre2.sem_modalite()}: jury BUT annuel",
no_side_bar=True, no_side_bar=True,
init_qtip=True, init_qtip=True,
javascripts=["js/etud_info.js", "js/table_recap.js"], javascripts=["js/etud_info.js", "js/table_recap.js"],
@ -123,6 +124,7 @@ class RowCollector:
self.titles = titles self.titles = titles
self.row = cells or {} # col_id : str self.row = cells or {} # col_id : str
self.idx = 0 self.idx = 0
self.last_etud_cell_idx = 0
if convert_values: if convert_values:
self.fmt_note = scu.fmt_note self.fmt_note = scu.fmt_note
else: else:
@ -175,6 +177,7 @@ class RowCollector:
self["_nom_short_target_attrs"] = f'class="etudinfo" id="{etud.id}"' self["_nom_short_target_attrs"] = f'class="etudinfo" id="{etud.id}"'
self["_nom_disp_target"] = self["_nom_short_target"] self["_nom_disp_target"] = self["_nom_short_target"]
self["_nom_disp_target_attrs"] = self["_nom_short_target_attrs"] self["_nom_disp_target_attrs"] = self["_nom_short_target_attrs"]
self.last_etud_cell_idx = self.idx
def add_ue_cell(self, ue: UniteEns, val): def add_ue_cell(self, ue: UniteEns, val):
"cell de moyenne d'UE" "cell de moyenne d'UE"
@ -196,18 +199,48 @@ class RowCollector:
val = rcue.moy_rcue val = rcue.moy_rcue
if isinstance(val, float): if isinstance(val, float):
if val < BUT_BARRE_RCUE: if val < BUT_BARRE_RCUE:
note_class = " moy_inf" note_class = " moy_ue_inf"
elif val >= BUT_BARRE_RCUE: elif val >= BUT_BARRE_RCUE:
note_class = " moy_ue_valid" note_class = " moy_ue_valid"
if val < BUT_RCUE_SUFFISANT: if val < BUT_RCUE_SUFFISANT:
note_class = " moy_ue_warning" # notes très basses note_class = " moy_ue_warning" # notes très basses
self.add_cell( self.add_cell(
col_id, col_id,
f"{rcue.ue_1.acronyme}-{rcue.ue_2.acronyme}", f"<div>{rcue.ue_1.acronyme}</div><div>{rcue.ue_2.acronyme}</div>",
self.fmt_note(val), self.fmt_note(val),
"col_ue" + note_class, "col_rcue" + note_class,
) )
def add_nb_rcues_cell(self, deca: DecisionsProposeesAnnee):
"cell avec nb niveaux validables / total"
klass = " "
if deca.nb_rcues_under_8 > 0:
klass += "moy_ue_warning"
elif deca.nb_validables < deca.nb_competences:
klass += "moy_ue_inf"
else:
klass += "moy_ue_valid"
self.add_cell(
"rcues_validables",
"RCUEs",
f"""{deca.nb_validables}/{deca.nb_competences}"""
+ ((" " + scu.EMO_WARNING) if deca.nb_rcues_under_8 > 0 else ""),
"col_rcue col_rcues_validables" + klass,
)
if len(deca.rcues_annee) > 0:
# permet un tri par nb de niveaux validables + moyenne gen indicative S_pair
if deca.res_pair and deca.etud.id in deca.res_pair.etud_moy_gen:
moy_gen_d = f"{int(deca.res_pair.etud_moy_gen[deca.etud.id]*1000):05}"
else:
moy_gen_d = "x"
self["_rcues_validables_order"] = f"{deca.nb_validables:04d}-{moy_gen_d}"
else:
# etudiants sans RCUE: pas de semestre impair, ...
# les classe à la fin
self[
"_rcues_validables_order"
] = f"{deca.nb_validables:04d}-00000-{deca.etud.sort_key}"
def get_table_jury_but( def get_table_jury_but(
formsemestre2: FormSemestre, readonly: bool = False formsemestre2: FormSemestre, readonly: bool = False
@ -221,7 +254,9 @@ def get_table_jury_but(
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre2) deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre2)
row = RowCollector(titles=titles) row = RowCollector(titles=titles)
row.add_etud_cells(etud, formsemestre2) row.add_etud_cells(etud, formsemestre2)
row.idx = 100 # laisse place pour les colonnes de groupes
# --- Nombre de niveaux
row.add_nb_rcues_cell(deca)
# --- Les RCUEs # --- Les RCUEs
for rcue in deca.rcues_annee: for rcue in deca.rcues_annee:
row.add_ue_cell(rcue.ue_1, rcue.moy_ue_1) row.add_ue_cell(rcue.ue_1, rcue.moy_ue_1)
@ -251,7 +286,8 @@ def get_table_jury_but(
""", """,
) )
rows.append(row.row) rows.append(row.row)
res2.recap_add_partitions(rows, titles) if len(rows) > 0:
res2.recap_add_partitions(rows, titles, col_idx=row.last_etud_cell_idx + 1)
column_ids = [title for title in titles if not title.startswith("_")] column_ids = [title for title in titles if not title.startswith("_")]
column_ids.sort(key=lambda col_id: titles.get("_" + col_id + "_col_order", 1000)) column_ids.sort(key=lambda col_id: titles.get("_" + col_id + "_col_order", 1000))
rows.sort(key=lambda row: row["_nom_disp_order"]) rows.sort(key=lambda row: row["_nom_disp_order"])

View File

@ -829,7 +829,7 @@ class ResultatsSemestre(ResultatsCache):
else: else:
row[f"_{cid}_class"] = "admission" row[f"_{cid}_class"] = "admission"
def recap_add_partitions(self, rows: list[dict], titles: dict): def recap_add_partitions(self, rows: list[dict], titles: dict, col_idx: int = None):
"""Ajoute les colonnes indiquant les groupes """Ajoute les colonnes indiquant les groupes
rows est une liste de dict avec une clé "etudid" rows est une liste de dict avec une clé "etudid"
Les colonnes ont la classe css "partition" Les colonnes ont la classe css "partition"
@ -838,7 +838,7 @@ class ResultatsSemestre(ResultatsCache):
self.formsemestre.id self.formsemestre.id
) )
first_partition = True first_partition = True
col_order = 10 col_order = 10 if col_idx is None else col_idx
for partition in partitions: for partition in partitions:
cid = f"part_{partition['partition_id']}" cid = f"part_{partition['partition_id']}"
rg_cid = cid + "_rg" # rang dans la partition rg_cid = cid + "_rg" # rang dans la partition

View File

@ -2371,7 +2371,6 @@ td.recap_col_ue_inf {
padding-right: 1.2em; padding-right: 1.2em;
padding-left: 4px; padding-left: 4px;
text-align: left; text-align: left;
font-weight: bold;
color: rgb(255, 0, 0); color: rgb(255, 0, 0);
border-left: 1px solid blue; border-left: 1px solid blue;
} }
@ -2380,7 +2379,6 @@ td.recap_col_ue_val {
padding-right: 1.2em; padding-right: 1.2em;
padding-left: 4px; padding-left: 4px;
text-align: left; text-align: left;
font-weight: bold;
color: rgb(0, 140, 0); color: rgb(0, 140, 0);
border-left: 1px solid blue; border-left: 1px solid blue;
} }
@ -3773,6 +3771,19 @@ table.table_recap .group {
border-left: 1px solid blue; border-left: 1px solid blue;
} }
table.table_recap .col_ue {
font-weight: bold;
}
table.table_recap.jury .col_ue {
font-weight: normal;
}
table.table_recap.jury .col_rcue {
font-weight: bold;
}
table.table_recap .group { table.table_recap .group {
border-left: 1px dashed rgb(160, 160, 160); border-left: 1px dashed rgb(160, 160, 160);
white-space: nowrap; white-space: nowrap;
@ -3817,18 +3828,15 @@ table.table_recap td.moy_inf {
} }
table.table_recap td.moy_ue_valid { table.table_recap td.moy_ue_valid {
font-weight: bold;
color: rgb(0, 140, 0); color: rgb(0, 140, 0);
} }
table.table_recap td.moy_ue_warning { table.table_recap td.moy_ue_warning {
font-weight: bold;
color: rgb(255, 0, 0); color: rgb(255, 0, 0);
} }
table.table_recap td.col_ues_validables { table.table_recap td.col_ues_validables {
white-space: nowrap; white-space: nowrap;
font-weight: bold;
font-style: normal !important; font-style: normal !important;
} }