From 267dbb6460d59643098758b3bf9d6d0045a8ac99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9o=20BARAS=20=28IUT1=20Grenoble=29?= Date: Wed, 14 Feb 2024 17:00:05 +0100 Subject: [PATCH] Ajoute les moy par ue et par tag au semtag --- app/pe/pe_affichage.py | 13 ++++--- app/pe/pe_semtag.py | 46 +++++++++++++++-------- app/pe/pe_tabletags.py | 84 ++++++++++++++++++++++++++---------------- 3 files changed, 89 insertions(+), 54 deletions(-) diff --git a/app/pe/pe_affichage.py b/app/pe/pe_affichage.py index 50f2e2ab..f1ee72a7 100644 --- a/app/pe/pe_affichage.py +++ b/app/pe/pe_affichage.py @@ -9,7 +9,7 @@ from flask import g from app import log -PE_DEBUG = False +PE_DEBUG = True # On stocke les logs PE dans g.scodoc_pe_log @@ -22,14 +22,15 @@ def pe_start_log() -> list[str]: def pe_print(*a): "Log (or print in PE_DEBUG mode) and store in g" - lines = getattr(g, "scodoc_pe_log") - if lines is None: - lines = pe_start_log() - msg = " ".join(a) - lines.append(msg) if PE_DEBUG: + msg = " ".join(a) print(msg) else: + lines = getattr(g, "scodoc_pe_log") + if lines is None: + lines = pe_start_log() + msg = " ".join(a) + lines.append(msg) log(msg) diff --git a/app/pe/pe_semtag.py b/app/pe/pe_semtag.py index 9ed2418b..8e602531 100644 --- a/app/pe/pe_semtag.py +++ b/app/pe/pe_semtag.py @@ -76,6 +76,7 @@ class SemestreTag(TableTag): # Les étudiants self.etuds = self.nt.etuds self.etudiants = {etud.etudid: etud.etat_civil for etud in self.etuds} + self.etudids = list(self.etudiants.keys()) # Les notes, les modules implémentés triés, les étudiants, les coeffs, # récupérés notamment de py:mod:`res_but` @@ -94,12 +95,12 @@ class SemestreTag(TableTag): tags_personnalises = get_synthese_tags_personnalises_semestre( self.nt.formsemestre ) - noms_tags_perso = list(set(tags_personnalises.keys())) + noms_tags_perso = sorted(list(set(tags_personnalises.keys()))) ## Déduit des compétences - dict_ues_competences = get_noms_competences_from_ues(self.nt.formsemestre) - noms_tags_comp = list(set(dict_ues_competences.values())) - noms_tags_auto = ["but"] + noms_tags_comp + # dict_ues_competences = get_noms_competences_from_ues(self.nt.formsemestre) + # noms_tags_comp = list(set(dict_ues_competences.values())) + noms_tags_auto = ["but"] # + noms_tags_comp self.tags = noms_tags_perso + noms_tags_auto """Tags du semestre taggué""" @@ -122,23 +123,31 @@ class SemestreTag(TableTag): """ raise ScoValueError(message) + ues_hors_sport = [ue for ue in self.ues if ue.type != UE_SPORT] + # Calcul des moyennes & les classements de chaque étudiant à chaque tag self.moyennes_tags = {} for tag in tags_personnalises: # pe_affichage.pe_print(f" -> Traitement du tag {tag}") - moy_gen_tag = self.compute_moyenne_tag(tag, tags_personnalises) - self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_tag) + moy_ues_tag = self.compute_moy_ues_tag(tag, tags_personnalises) + moy_gen_tag = self.compute_moy_gen_tag(moy_ues_tag) - # Ajoute les moyennes générales de BUT pour le semestre considéré + self.moyennes_tags[tag] = MoyenneTag( + tag, ues_hors_sport, moy_ues_tag, moy_gen_tag + ) + + # Ajoute les d'UE moyennes générales de BUT pour le semestre considéré + # moy_gen_but = self.nt.etud_moy_gen + # self.moyennes_tags["but"] = MoyenneTag("but", [], None, moy_gen_but, ) + + # Ajoute les moyennes par UEs (et donc par compétence) + la moyenne générale (but) + df_ues = pd.DataFrame({ue.id: self.nt.etud_moy_ue[ue.id] for ue in ues_hors_sport}, + index = self.etudids) + # moy_ues = self.nt.etud_moy_ue[ue_id] moy_gen_but = self.nt.etud_moy_gen - self.moyennes_tags["but"] = MoyenneTag("but", moy_gen_but) + self.moyennes_tags["but"] = MoyenneTag("but", ues_hors_sport, df_ues, moy_gen_but) - # Ajoute les moyennes par compétence - for ue_id, competence in dict_ues_competences.items(): - if competence not in self.moyennes_tags: - moy_ue = self.nt.etud_moy_ue[ue_id] - self.moyennes_tags[competence] = MoyenneTag(competence, moy_ue) self.tags_sorted = self.get_all_tags() """Tags (personnalisés+compétences) par ordre alphabétique""" @@ -156,8 +165,8 @@ class SemestreTag(TableTag): """Nom affiché pour le semestre taggué""" return app.pe.pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True) - def compute_moyenne_tag(self, tag: str, tags_infos: dict) -> pd.Series: - """Calcule la moyenne des étudiants pour le tag indiqué, + def compute_moy_ues_tag(self, tag: str, tags_infos: dict) -> pd.Series: + """Calcule la moyenne par UE des étudiants pour le tag indiqué, pour ce SemestreTag, en ayant connaissance des informations sur les tags (dictionnaire donnant les coeff de repondération) @@ -199,7 +208,12 @@ class SemestreTag(TableTag): self.dispense_ues, block=self.formsemestre.block_moyennes, ) + return moyennes_ues_tag + def compute_moy_gen_tag(self, moy_ues_tag: pd.DataFrame) -> pd.Series: + """Calcule la moyenne générale (toutes UE confondus) + pour le tag considéré, en les pondérant par les crédits ECTS. + """ # Les ects ects = self.ues_inscr_parcours_df.fillna(0.0) * [ ue.ects for ue in self.ues if ue.type != UE_SPORT @@ -207,7 +221,7 @@ class SemestreTag(TableTag): # Calcule la moyenne générale dans le semestre (pondérée par le ECTS) moy_gen_tag = comp.moy_sem.compute_sem_moys_apc_using_ects( - moyennes_ues_tag, + moy_ues_tag, ects, formation_id=self.formsemestre.formation_id, skip_empty_ues=True, diff --git a/app/pe/pe_tabletags.py b/app/pe/pe_tabletags.py index 68be8772..a761fa0b 100644 --- a/app/pe/pe_tabletags.py +++ b/app/pe/pe_tabletags.py @@ -42,19 +42,27 @@ import numpy as np from app import ScoValueError from app.comp.moy_sem import comp_ranks_series +from app.models import UniteEns from app.pe import pe_affichage from app.pe.pe_affichage import SANS_NOTE from app.scodoc import sco_utils as scu import pandas as pd +from app.scodoc.codes_cursus import UE_SPORT TAGS_RESERVES = ["but"] class MoyenneTag: - def __init__(self, tag: str, notes: pd.Series): + def __init__( + self, + tag: str, + ues: list[UniteEns], + notes_ues: pd.DataFrame, + notes_gen: pd.Series, + ): """Classe centralisant la synthèse des moyennes/classements d'une série - d'étudiants à un tag donné, en stockant un dictionnaire : + d'étudiants à un tag donné, en stockant : `` { @@ -69,16 +77,26 @@ class MoyenneTag: Args: tag: Un tag - note: Une série de notes (moyenne) sous forme d'un pd.Series() + ues: La liste des UEs ayant servie au calcul de la moyenne + notes_ues: Les moyennes (etudid x ues) aux différentes UEs et pour le tag + notes_gen: Une série de notes (moyenne) sous forme d'un pd.Series() (toutes UEs confondues) """ self.tag = tag """Le tag associé à la moyenne""" - self.etudids = list(notes.index) # calcul à venir + self.etudids = list(notes_gen.index) # calcul à venir """Les id des étudiants""" - self.inscrits_ids = notes[notes.notnull()].index.to_list() - """Les id des étudiants dont la moyenne est non nulle""" - self.df: pd.DataFrame = self.comp_moy_et_stat(notes) - """Le dataframe retraçant les moyennes/classements/statistiques""" + self.ues: list[UniteEns] = ues + """Les UEs sur lesquelles sont calculées les moyennes""" + self.df_ues: dict[int, pd.DataFrame] = {} + """Les dataframes retraçant les moyennes/classements/statistiques des étudiants aux UEs""" + for ue in self.ues: # if ue.type != UE_SPORT: + notes = notes_ues[ue.id] + self.df_ues[ue.id] = self.comp_moy_et_stat(notes) + + self.inscrits_ids = notes_gen[notes_gen.notnull()].index.to_list() + """Les id des étudiants dont la moyenne générale est non nulle""" + self.df_gen: pd.DataFrame = self.comp_moy_et_stat(notes_gen) + """Le dataframe retraçant les moyennes/classements/statistiques général""" self.synthese = self.to_dict() """La synthèse (dictionnaire) des notes/classements/statistiques""" @@ -88,7 +106,8 @@ class MoyenneTag: def comp_moy_et_stat(self, notes: pd.Series) -> dict: """Calcule et structure les données nécessaires au PE pour une série - de notes (souvent une moyenne par tag) dans un dictionnaire spécifique. + de notes (pouvant être une moyenne d'un tag à une UE ou une moyenne générale + d'un tag) dans un dictionnaire spécifique. Partant des notes, sont calculés les classements (en ne tenant compte que des notes non nulles). @@ -121,64 +140,65 @@ class MoyenneTag: # Les nb d'étudiants & nb d'inscrits df["nb_etuds"] = len(self.etudids) - df.loc[self.inscrits_ids, "nb_inscrits"] = len(self.inscrits_ids) + # Les étudiants dont la note n'est pas nulle + inscrits_ids = notes[notes.notnull()].index.to_list() + df.loc[inscrits_ids, "nb_inscrits"] = len(inscrits_ids) # Le classement des inscrits - notes_non_nulles = notes[self.inscrits_ids] + notes_non_nulles = notes[inscrits_ids] (class_str, class_int) = comp_ranks_series(notes_non_nulles) - df.loc[self.inscrits_ids, "classement"] = class_int + df.loc[inscrits_ids, "classement"] = class_int # Le rang (classement/nb_inscrit) df["rang"] = df["rang"].astype(str) - df.loc[self.inscrits_ids, "rang"] = ( - df.loc[self.inscrits_ids, "classement"].astype(int).astype(str) + df.loc[inscrits_ids, "rang"] = ( + df.loc[inscrits_ids, "classement"].astype(int).astype(str) + "/" - + df.loc[self.inscrits_ids, "nb_inscrits"].astype(int).astype(str) + + df.loc[inscrits_ids, "nb_inscrits"].astype(int).astype(str) ) # Les stat (des inscrits) - df.loc[self.inscrits_ids, "min"] = notes.min() - df.loc[self.inscrits_ids, "max"] = notes.max() - df.loc[self.inscrits_ids, "moy"] = notes.mean() + df.loc[inscrits_ids, "min"] = notes.min() + df.loc[inscrits_ids, "max"] = notes.max() + df.loc[inscrits_ids, "moy"] = notes.mean() return df def to_dict(self) -> dict: """Renvoie un dictionnaire de synthèse des moyennes/classements/statistiques""" synthese = { - "notes": self.df["note"], - "classements": self.df["classement"], - "min": self.df["min"].mean(), - "max": self.df["max"].mean(), - "moy": self.df["moy"].mean(), - "nb_inscrits": self.df["nb_inscrits"].mean(), + "notes": self.df_gen["note"], + "classements": self.df_gen["classement"], + "min": self.df_gen["min"].mean(), + "max": self.df_gen["max"].mean(), + "moy": self.df_gen["moy"].mean(), + "nb_inscrits": self.df_gen["nb_inscrits"].mean(), } return synthese def get_notes(self): """Série des notes, arrondies à 2 chiffres après la virgule""" - return self.df["note"].round(2) + return self.df_gen["note"].round(2) def get_rangs_inscrits(self) -> pd.Series: """Série des rangs classement/nbre_inscrit""" - return self.df["rang"] + return self.df_gen["rang"] def get_min(self) -> pd.Series: """Série des min""" - return self.df["min"].round(2) + return self.df_gen["min"].round(2) def get_max(self) -> pd.Series: """Série des max""" - return self.df["max"].round(2) + return self.df_gen["max"].round(2) def get_moy(self) -> pd.Series: """Série des moy""" - return self.df["moy"].round(2) - + return self.df_gen["moy"].round(2) def get_note_for_df(self, etudid: int): """Note d'un étudiant donné par son etudid""" - return round(self.df["note"].loc[etudid], 2) + return round(self.df_gen["note"].loc[etudid], 2) def get_min_for_df(self) -> float: """Min renseigné pour affichage dans un df""" @@ -195,7 +215,7 @@ class MoyenneTag: def get_class_for_df(self, etudid: int) -> str: """Classement ramené au nombre d'inscrits, pour un étudiant donné par son etudid""" - classement = self.df["rang"].loc[etudid] + classement = self.df_gen["rang"].loc[etudid] if not pd.isna(classement): return classement else: