Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
6 changed files with 71 additions and 54 deletions
Showing only changes of commit dece9a82d1 - Show all commits

View File

@ -148,6 +148,7 @@ class ModuleImplResults:
evals_notes = pd.DataFrame(index=self.etudids, dtype=float)
self.evaluations_completes = []
self.evaluations_completes_dict = {}
self.etudids_attente = set() # empty
for evaluation in moduleimpl.evaluations:
eval_df = self._load_evaluation_notes(evaluation)
# is_complete ssi
@ -155,13 +156,13 @@ class ModuleImplResults:
# ou évaluation déclarée "à prise en compte immédiate"
# ou rattrapage, 2eme session, bonus
# ET pas bloquée par date (is_blocked)
is_blocked = evaluation.is_blocked()
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
is_complete = (
(evaluation.evaluation_type != Evaluation.EVALUATION_NORMALE)
or (evaluation.publish_incomplete)
or (not etudids_sans_note)
) and not evaluation.is_blocked()
) and not is_blocked
self.evaluations_completes.append(is_complete)
self.evaluations_completes_dict[evaluation.id] = is_complete
self.evals_etudids_sans_note[evaluation.id] = etudids_sans_note
@ -178,16 +179,21 @@ class ModuleImplResults:
eval_notes_inscr = evals_notes[str(evaluation.id)][list(inscrits_module)]
# Nombre de notes (non vides, incluant ATT etc) des inscrits:
nb_notes = eval_notes_inscr.notna().sum()
# Etudiants avec notes en attente:
# = ceux avec note ATT
eval_etudids_attente = set(
eval_notes_inscr.iloc[
(eval_notes_inscr == scu.NOTES_ATTENTE).to_numpy()
].index
)
if evaluation.publish_incomplete:
# et en "immédiat", tous ceux sans note
eval_etudids_attente |= etudids_sans_note
if is_blocked:
eval_etudids_attente = set()
else:
# Etudiants avec notes en attente:
# = ceux avec note ATT
eval_etudids_attente = set(
eval_notes_inscr.iloc[
(eval_notes_inscr == scu.NOTES_ATTENTE).to_numpy()
].index
)
if evaluation.publish_incomplete:
# et en "immédiat", tous ceux sans note
eval_etudids_attente |= etudids_sans_note
# Synthèse pour état du module:
self.etudids_attente |= eval_etudids_attente
self.evaluations_etat[evaluation.id] = EvaluationEtat(

View File

@ -209,6 +209,7 @@ class ResultatsSemestre(ResultatsCache):
"evalcomplete" : bool,
"last_modif" : datetime.datetime | None, # saisie de note la plus récente
"nb_notes" : int, # nb notes d'étudiants inscrits
"nb_attente" : int, # nb de notes en ATTente (même si bloquée)
},
"evaluation_id" : int,
"jour" : datetime.datetime, # e.date_debut or datetime.datetime(1900, 1, 1)
@ -236,6 +237,7 @@ class ResultatsSemestre(ResultatsCache):
"etat": {
"blocked": evaluation.is_blocked(),
"evalcomplete": etat.is_complete,
"nb_attente": etat.nb_attente,
"nb_notes": etat.nb_notes,
"last_modif": last_modif,
},

View File

@ -873,7 +873,7 @@ class FormSemestre(db.Model):
descr_sem += " " + self.modalite
return descr_sem
def get_abs_count(self, etudid):
def get_abs_count(self, etudid) -> tuple[int, int, int]:
"""Les comptes d'absences de cet étudiant dans ce semestre:
tuple (nb abs non just, nb abs justifiées, nb abs total)
Utilise un cache.

View File

@ -30,17 +30,18 @@
(coût théorique en heures équivalent TD)
"""
from flask import request
from flask import request, Response
from app.models import FormSemestre
from app.scodoc.gen_tables import GenTable
from app.scodoc import sco_preferences
from app.scodoc.gen_tables import GenTable
from app.scodoc.sco_exceptions import ScoValueError
import app.scodoc.sco_utils as scu
import sco_version
def formsemestre_table_estim_cost(
formsemestre_id,
formsemestre: FormSemestre,
n_group_td=1,
n_group_tp=1,
coef_tp=1,
@ -55,8 +56,6 @@ def formsemestre_table_estim_cost(
peut conduire à une sur-estimation du coût s'il y a des modules optionnels
(dans ce cas, retoucher le tableau excel exporté).
"""
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
rows = []
for modimpl in formsemestre.modimpls:
rows.append(
@ -76,14 +75,14 @@ def formsemestre_table_estim_cost(
+ coef_cours * row["heures_cours"]
+ coef_tp * row["heures_tp"]
)
sum_cours = sum([t["heures_cours"] for t in rows])
sum_td = sum([t["heures_td"] for t in rows])
sum_tp = sum([t["heures_tp"] for t in rows])
sum_cours = sum(t["heures_cours"] for t in rows)
sum_td = sum(t["heures_td"] for t in rows)
sum_tp = sum(t["heures_tp"] for t in rows)
sum_heqtd = sum_td + coef_cours * sum_cours + coef_tp * sum_tp
assert abs(sum([t["HeqTD"] for t in rows]) - sum_heqtd) < 0.01, "%s != %s" % (
sum([t["HeqTD"] for t in rows]),
sum_heqtd,
)
# assert abs(sum(t["HeqTD"] for t in rows) - sum_heqtd) < 0.01, "%s != %s" % (
# sum(t["HeqTD"] for t in rows),
# sum_heqtd,
# )
rows.append(
{
@ -117,7 +116,7 @@ def formsemestre_table_estim_cost(
),
rows=rows,
html_sortable=True,
preferences=sco_preferences.SemPreferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(formsemestre.id),
html_class="table_leftalign table_listegroupe",
xls_before_table=[
[formsemestre.titre_annee()],
@ -146,47 +145,45 @@ def formsemestre_table_estim_cost(
return tab
# view
def formsemestre_estim_cost(
formsemestre_id,
n_group_td=1,
n_group_tp=1,
coef_tp=1,
coef_cours=1.5,
formsemestre_id: int,
n_group_td: int | str = 1,
n_group_tp: int | str = 1,
coef_tp: float | str = 1.0,
coef_cours: float | str = 1.5,
fmt="html",
):
) -> str | Response:
"""Page (formulaire) estimation coûts"""
try:
n_group_td = int(n_group_td)
n_group_tp = int(n_group_tp)
coef_tp = float(coef_tp)
coef_cours = float(coef_cours)
except ValueError as exc:
raise ScoValueError("paramètre invalide: utiliser des nombres") from exc
n_group_td = int(n_group_td)
n_group_tp = int(n_group_tp)
coef_tp = float(coef_tp)
coef_cours = float(coef_cours)
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
tab = formsemestre_table_estim_cost(
formsemestre_id,
formsemestre,
n_group_td=n_group_td,
n_group_tp=n_group_tp,
coef_tp=coef_tp,
coef_cours=coef_cours,
)
h = """
<form name="f" method="get" action="%s">
<input type="hidden" name="formsemestre_id" value="%s"></input>
Nombre de groupes de TD: <input type="text" name="n_group_td" value="%s" onchange="document.f.submit()"/><br>
Nombre de groupes de TP: <input type="text" name="n_group_tp" value="%s" onchange="document.f.submit()"/>
&nbsp;Coefficient heures TP: <input type="text" name="coef_tp" value="%s" onchange="document.f.submit()"/>
tab.html_before_table = f"""
<form name="f" method="get" action="{request.base_url}">
<input type="hidden" name="formsemestre_id" value="{formsemestre.id}"></input>
Nombre de groupes de TD: <input type="text" name="n_group_td" value="{n_group_td}" onchange="document.f.submit()"/><br>
Nombre de groupes de TP: <input type="text" name="n_group_tp" value="{n_group_tp}" onchange="document.f.submit()"/>
&nbsp;Coefficient heures TP: <input type="text" name="coef_tp" value="{coef_tp}" onchange="document.f.submit()"/>
<br>
</form>
""" % (
request.base_url,
formsemestre_id,
n_group_td,
n_group_tp,
coef_tp,
)
tab.html_before_table = h
"""
tab.base_url = "%s?formsemestre_id=%s&n_group_td=%s&n_group_tp=%s&coef_tp=%s" % (
request.base_url,
formsemestre_id,
formsemestre.id,
n_group_td,
n_group_tp,
coef_tp,

View File

@ -279,11 +279,18 @@ def _summarize_evals_etats(etat_evals: list[dict]) -> dict:
nb_eval_completes (= prises en compte)
nb_evals_en_cours (= avec des notes, mais pas complete)
nb_evals_vides (= sans aucune note)
nb_evals_attente (= avec des notes en ATTente et pas bloquée)
date derniere modif
Une eval est "complete" ssi tous les etudiants *inscrits* ont une note.
"""
nb_evals_completes, nb_evals_en_cours, nb_evals_vides, nb_evals_blocked = 0, 0, 0, 0
(
nb_evals_completes,
nb_evals_en_cours,
nb_evals_vides,
nb_evals_blocked,
nb_evals_attente,
) = (0, 0, 0, 0, 0)
dates = []
for e in etat_evals:
if e["etat"]["blocked"]:
@ -294,6 +301,8 @@ def _summarize_evals_etats(etat_evals: list[dict]) -> dict:
nb_evals_vides += 1
elif not e["etat"]["blocked"]:
nb_evals_en_cours += 1
if e["etat"]["nb_attente"] and not e["etat"]["blocked"]:
nb_evals_attente += 1
last_modif = e["etat"]["last_modif"]
if last_modif is not None:
dates.append(e["etat"]["last_modif"])
@ -303,6 +312,7 @@ def _summarize_evals_etats(etat_evals: list[dict]) -> dict:
return {
"nb_evals": len(etat_evals),
"nb_evals_attente": nb_evals_attente,
"nb_evals_blocked": nb_evals_blocked,
"nb_evals_completes": nb_evals_completes,
"nb_evals_en_cours": nb_evals_en_cours,

View File

@ -1312,7 +1312,9 @@ def formsemestre_tableau_modules(
if etat["attente"]:
H.append(
f""" <span><a class="redlink" href="{moduleimpl_status_url}"
title="Il y a des notes en attente"><span class="evals_attente">en attente</span></a></span>"""
title="Il y a des notes en attente"><span class="evals_attente">{
etat["nb_evals_attente"]
} en attente</span></a></span>"""
)
if not mod_is_conforme:
H.append(