Améliore visualisation coefficients sur tableau bord module. Closes #886.

This commit is contained in:
Emmanuel Viennet 2024-05-29 11:55:28 +02:00
parent 9289535359
commit e44d3fd5dc
4 changed files with 113 additions and 67 deletions

View File

@ -340,6 +340,21 @@ class Module(models.ScoDocModel):
# Liste seulement les coefs définis: # Liste seulement les coefs définis:
return [(c.ue, c.coef) for c in self.get_ue_coefs_sorted()] return [(c.ue, c.coef) for c in self.get_ue_coefs_sorted()]
def get_ue_coefs_descr(self) -> str:
"""Description des coefficients vers les UEs (APC)"""
coefs_descr = ", ".join(
[
f"{ue.acronyme}: {co}"
for ue, co in self.ue_coefs_list()
if isinstance(co, float) and co > 0
]
)
if coefs_descr:
descr = "Coefs: " + coefs_descr
else:
descr = "(pas de coefficients) "
return descr
def get_codes_apogee(self) -> set[str]: def get_codes_apogee(self) -> set[str]:
"""Les codes Apogée (codés en base comme "VRT1,VRT2")""" """Les codes Apogée (codés en base comme "VRT1,VRT2")"""
if self.code_apogee: if self.code_apogee:

View File

@ -822,7 +822,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
</div> </div>
</div> </div>
<div class="sem-groups-assi"> <div class="sem-groups-assi">
""" """
) )
if can_edit_abs: if can_edit_abs:
@ -875,7 +875,7 @@ def _make_listes_sem(formsemestre: FormSemestre) -> str:
group_ids=group.id, group_ids=group.id,
)}" title="Page en cours de fusion et sera prochainement supprimée. Veuillez utiliser la page `Saisir l'assiduité`"> )}" title="Page en cours de fusion et sera prochainement supprimée. Veuillez utiliser la page `Saisir l'assiduité`">
(Saisie différée)</a> (Saisie différée)</a>
</div> </div>
""" """
) )
@ -1188,17 +1188,7 @@ def formsemestre_tableau_modules(
mod_descr = "Module " + (mod.titre or "") mod_descr = "Module " + (mod.titre or "")
is_apc = mod.is_apc() # SAE ou ressource is_apc = mod.is_apc() # SAE ou ressource
if is_apc: if is_apc:
coef_descr = ", ".join( mod_descr += " " + mod.get_ue_coefs_descr()
[
f"{ue.acronyme}: {co}"
for ue, co in mod.ue_coefs_list()
if isinstance(co, float) and co > 0
]
)
if coef_descr:
mod_descr += " Coefs: " + coef_descr
else:
mod_descr += " (pas de coefficients) "
else: else:
mod_descr += ", coef. " + str(mod.coefficient) mod_descr += ", coef. " + str(mod.coefficient)
mod_ens = sco_users.user_info(modimpl.responsable_id)["nomcomplet"] mod_ens = sco_users.user_info(modimpl.responsable_id)["nomcomplet"]

View File

@ -146,29 +146,48 @@ def moduleimpl_evaluation_menu(evaluation: Evaluation, nbnotes: int = 0) -> str:
return htmlutils.make_menu("actions", menu_eval, alone=True) return htmlutils.make_menu("actions", menu_eval, alone=True)
def _ue_coefs_html(coefs_lst) -> str: def _ue_coefs_html(modimpl: ModuleImpl) -> str:
""" """ """ """
max_coef = max([x[1] for x in coefs_lst]) if coefs_lst else 1.0 coefs_lst = modimpl.module.ue_coefs_list()
H = """ max_coef = max(x[1] for x in coefs_lst) if coefs_lst else 1.0
H = f"""
<div id="modimpl_coefs"> <div id="modimpl_coefs">
<div>Coefficients vers les UE</div> <div>Coefficients vers les UEs
""" <span><a class="stdlink" href="{
if coefs_lst: url_for(
H += ( "notes.edit_modules_ue_coefs",
f""" scodoc_dept=g.scodoc_dept,
<div class="coefs_histo" style="--max:{max_coef}"> formation_id=modimpl.module.formation.id,
""" semestre_idx=modimpl.formsemestre.semestre_id,
+ "\n".join(
[
f"""<div style="--coef:{coef};
{'background-color: ' + ue.color + ';' if ue.color else ''}
"><div>{coef}</div>{ue.acronyme}</div>"""
for ue, coef in coefs_lst
if coef > 0
]
) )
+ "</div>" }">détail</a>
</span>
</div>
"""
if coefs_lst:
H += _html_hinton_map(
colors=(uc[0].color for uc in coefs_lst),
max_val=max_coef,
size=36,
title=modimpl.module.get_ue_coefs_descr(),
values=(uc[1] for uc in coefs_lst),
) )
# (
# f"""
# <div class="coefs_histo" style="--max:{max_coef}">
# """
# + "\n".join(
# [
# f"""<div style="--coef:{coef};
# {'background-color: ' + ue.color + ';' if ue.color else ''}
# "><div>{coef}</div>{ue.acronyme}</div>"""
# for ue, coef in coefs_lst
# if coef > 0
# ]
# )
# + "</div>"
# )
else: else:
H += """<div class="missing_value">non définis</div>""" H += """<div class="missing_value">non définis</div>"""
H += "</div>" H += "</div>"
@ -265,7 +284,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
H.append(scu.icontag("lock32_img", title="verrouillé")) H.append(scu.icontag("lock32_img", title="verrouillé"))
H.append("""</td><td class="fichetitre2">""") H.append("""</td><td class="fichetitre2">""")
if modimpl.module.is_apc(): if modimpl.module.is_apc():
H.append(_ue_coefs_html(modimpl.module.ue_coefs_list())) H.append(_ue_coefs_html(modimpl))
else: else:
H.append( H.append(
f"""Coef. dans le semestre: { f"""Coef. dans le semestre: {
@ -781,27 +800,27 @@ def _ligne_evaluation(
# #
if etat["nb_notes"] == 0: if etat["nb_notes"] == 0:
H.append(f"""<tr class="{tr_class}"><td></td>""") H.append(f"""<tr class="{tr_class}"><td></td>""")
if modimpl.module.is_apc(): # if modimpl.module.is_apc():
H.append( # H.append(
f"""<td colspan="8" class="eval_poids">{ # f"""<td colspan="8" class="eval_poids">{
evaluation.get_ue_poids_str()}</td>""" # evaluation.get_ue_poids_str()}</td>"""
) # )
else: # else:
H.append('<td colspan="8"></td>') # H.append('<td colspan="8"></td>')
H.append("""</tr>""") H.append("""</tr>""")
else: # il y a deja des notes saisies else: # il y a deja des notes saisies
gr_moyennes = etat["gr_moyennes"] gr_moyennes = etat["gr_moyennes"]
first_group = True # first_group = True
for gr_moyenne in gr_moyennes: for gr_moyenne in gr_moyennes:
H.append(f"""<tr class="{tr_class}"><td>&nbsp;</td>""") H.append(f"""<tr class="{tr_class}"><td>&nbsp;</td>""")
if first_group and modimpl.module.is_apc(): # if first_group and modimpl.module.is_apc():
H.append( # H.append(
f"""<td class="eval_poids" colspan="4">{ # f"""<td class="eval_poids" colspan="4">{
evaluation.get_ue_poids_str()}</td>""" # evaluation.get_ue_poids_str()}</td>"""
) # )
else: # else:
H.append("""<td colspan="4"></td>""") H.append("""<td colspan="4"></td>""")
first_group = False # first_group = False
if gr_moyenne["group_name"] is None: if gr_moyenne["group_name"] is None:
name = "Tous" # tous name = "Tous" # tous
else: else:
@ -857,26 +876,47 @@ def _evaluation_poids_html(evaluation: Evaluation, max_poids: float = 0.0) -> st
ue_poids = evaluation.get_ue_poids_dict(sort=True) # { ue_id : poids } ue_poids = evaluation.get_ue_poids_dict(sort=True) # { ue_id : poids }
if not ue_poids: if not ue_poids:
return "" return ""
if max_poids < scu.NOTES_PRECISION: values = [poids * (evaluation.coefficient) for poids in ue_poids.values()]
colors = [db.session.get(UniteEns, ue_id).color for ue_id in ue_poids]
return _html_hinton_map(
classes=("evaluation_poids",),
colors=colors,
max_val=max_poids,
title=f"Poids de l'évaluation vers les UEs: {evaluation.get_ue_poids_str()}",
values=values,
)
def _html_hinton_map(
classes=(),
colors=(),
max_val: float | None = None,
size=12,
title: str = "",
values=(),
) -> str:
"""Représente une liste de nombres sous forme de carrés"""
if max_val is None:
max_val = max(values)
if max_val < scu.NOTES_PRECISION:
return "" return ""
H = ( return (
"""<div class="evaluation_poids">""" f"""<div class="hinton_map {" ".join(classes)}"
style="--size:{size}px;"
title="{title}"
data-tooltip>"""
+ "\n".join( + "\n".join(
[ [
f"""<div title="poids vers {ue.acronyme}: {poids:g}"> f"""<div>
<div style="--size:{math.sqrt(poids*(evaluation.coefficient)/max_poids*144)}px; <div style="--boxsize:{size*math.sqrt(value/max_val)}px;
{'background-color: ' + ue.color + ';' if ue.color else ''} {'background-color: ' + color + ';' if color else ''}
"></div> "></div>
</div>""" </div>"""
for ue, poids in ( for value, color in zip(values, colors)
(db.session.get(UniteEns, ue_id), poids)
for ue_id, poids in ue_poids.items()
)
] ]
) )
+ "</div>" + "</div>"
) )
return H
def _html_modimpl_etuds_attente(res: ResultatsSemestre, modimpl: ModuleImpl) -> str: def _html_modimpl_etuds_attente(res: ResultatsSemestre, modimpl: ModuleImpl) -> str:

View File

@ -2096,8 +2096,9 @@ div.evaluation_titre {
vertical-align: super; vertical-align: super;
} }
/* visualisation poids évaluations */ /* visualisation poids évaluations */
.evaluation_poids { .hinton_map {
height: 12px; height: 12px;
display: inline-flex; display: inline-flex;
text-align: center; text-align: center;
@ -2105,10 +2106,10 @@ div.evaluation_titre {
margin-left: 4px; margin-left: 4px;
} }
.evaluation_poids>div { .hinton_map>div {
display: inline-flex; display: inline-flex;
height: 12px; height: var(--size);
width: 12px; width: var(--size);
margin-left: 2px; margin-left: 2px;
margin-right: 2px; margin-right: 2px;
border: 1px solid rgb(180, 180, 180); border: 1px solid rgb(180, 180, 180);
@ -2116,9 +2117,9 @@ div.evaluation_titre {
justify-content: center; justify-content: center;
} }
.evaluation_poids>div>div { .hinton_map>div>div {
height: var(--size); height: var(--boxsize);
width: var(--size); width: var(--boxsize);
background: #09c; background: #09c;
} }