# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Emmanuel Viennet emmanuel.viennet@viennet.net # ############################################################################## ############################################################################## # Module "Avis de poursuite d'étude" # conçu et développé par Cléo Baras (IUT de Grenoble) ############################################################################## """ Created on Thu Sep 8 09:36:33 2016 @author: barasc """ import datetime import numpy as np from app.comp.moy_sem import comp_ranks_series from app.pe import pe_affichage from app.scodoc import sco_utils as scu import pandas as pd TAGS_RESERVES = ["but"] class TableTag(object): def __init__(self): """Classe centralisant différentes méthodes communes aux SemestreTag, TrajectoireTag, AggregatInterclassTag """ pass # ----------------------------------------------------------------------------------------------------------- def get_all_tags(self): """Liste des tags de la table, triée par ordre alphabétique Returns: Liste de tags triés par ordre alphabétique """ return sorted(self.moyennes_tags.keys()) def df_moyennes_et_classements(self): """Renvoie un dataframe listant toutes les moyennes, et les classements des étudiants pour tous les tags """ etudiants = self.etudiants df = pd.DataFrame.from_dict(etudiants, orient="index", columns=["nom"]) for tag in self.get_all_tags(): df = df.join(self.moyennes_tags[tag]["notes"].rename(f"Moy {tag}")) df = df.join(self.moyennes_tags[tag]["classements"].rename(f"Class {tag}")) return df def df_notes(self): """Renvoie un dataframe (etudid x tag) listant toutes les moyennes par tags Returns: Un dataframe etudids x tag (avec tag par ordre alphabétique) """ tags = self.get_all_tags() if tags: dict_series = {tag: self.moyennes_tags[tag]["notes"] for tag in tags} df = pd.DataFrame(dict_series) return df else: return None def str_tagtable(self): """Renvoie une chaine de caractère listant toutes les moyennes, les rangs des étudiants pour tous les tags.""" etudiants = self.etudiants df = pd.DataFrame.from_dict(etudiants, orient="index", columns=["nom"]) for tag in self.get_all_tags(): df = df.join(self.moyennes_tags[tag]["notes"].rename(f"moy {tag}")) df = df.join(self.moyennes_tags[tag]["classements"].rename(f"class {tag}")) return df.to_csv(sep=";") 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. Partant des notes, sont calculés les classements (en ne tenant compte que des notes non nulles). Args: notes: Une série de notes (avec des éventuels NaN) Returns: Un dictionnaire stockant les notes, les classements, le min, le max, la moyenne, le nb de notes (donc d'inscrits) """ # Supprime d'éventuels chaines de caractères dans les notes notes = pd.to_numeric(notes, errors="coerce") # Les indices des ... et les notes non nulles/pertinentes indices = notes.notnull() notes_non_nulles = notes[indices] # Les classements sur les notes non nulles (_, class_gen_ue_non_nul) = comp_ranks_series(notes_non_nulles) # Les classements (toutes notes confondues, avec NaN si pas de notes) class_gen_ue = pd.Series(np.nan, index=notes.index, dtype="Int64") class_gen_ue[indices] = class_gen_ue_non_nul[indices] synthese = { "notes": notes, "classements": class_gen_ue, "min": notes.min(), "max": notes.max(), "moy": notes.mean(), "nb_inscrits": len(indices), } return synthese @classmethod def get_min_for_df(cls, bilan: dict) -> float: """Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné, revoie le min renseigné pour affichage dans un df""" return round(bilan["min"], 2) @classmethod def get_max_for_df(cls, bilan: dict) -> float: """Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné, renvoie le max renseigné pour affichage dans un df""" return round(bilan["max"], 2) @classmethod def get_moy_for_df(cls, bilan: dict) -> float: """Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné, renvoie la moyenne renseignée pour affichage dans un df""" return round(bilan["moy"], 2) @classmethod def get_class_for_df(cls, bilan: dict, etudid: int) -> str: """Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné, renvoie le classement ramené au nombre d'inscrits, pour un étudiant donné par son etudid""" classement = bilan['classements'].loc[etudid] if not pd.isna(classement): return f"{classement}/{bilan['nb_inscrits']}" else: return pe_affichage.SANS_NOTE @classmethod def get_note_for_df(cls, bilan: dict, etudid: int): """Partant d'un dictionnaire `bilan` généralement une moyennes_tags pour un tag donné, renvoie la note (moyenne) pour un étudiant donné par son etudid""" return round(bilan["notes"].loc[etudid], 2)