ScoDoc/app/pe/moys/pe_tabletags.py

204 lines
6.4 KiB
Python

# -*- pole: 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 pandas as pd
from app.models import Identite
from app.pe.moys import pe_moytag
TAGS_RESERVES = ["but"]
CHAMPS_ADMINISTRATIFS = ["Civilité", "Nom", "Prénom"]
class TableTag(object):
def __init__(self):
"""Classe centralisant différentes méthodes communes aux
SemestreTag, TrajectoireTag, AggregatInterclassTag
"""
# Les étudiants
# self.etuds: list[Identite] = None # A venir
"""Les étudiants"""
# self.etudids: list[int] = {}
"""Les etudids"""
def add_etuds(self, etuds: list[Identite]):
"""Mémorise les informations sur les étudiants
Args:
etuds: la liste des identités de l'étudiant
"""
# self.etuds = etuds
self.etudids = list({etud.etudid for etud in etuds})
def get_all_significant_tags(self):
"""Liste des tags de la table, triée par ordre alphabétique,
extraite des clés du dictionnaire ``moyennes_tags``, en ne
considérant que les moyennes ayant des notes.
Returns:
Liste de tags triés par ordre alphabétique
"""
tags = []
tag: str = ""
moytag: pe_moytag.MoyennesTag = None
for tag, moytag in self.moyennes_tags.items():
if moytag.has_notes():
tags.append(tag)
return sorted(tags)
def to_df(
self,
administratif=True,
aggregat=None,
tags_cibles=None,
cohorte=None,
options={"min_max_moy": True},
) -> pd.DataFrame:
"""Renvoie un dataframe listant toutes les données
des moyennes/classements/nb_inscrits/min/max/moy
des étudiants aux différents tags.
tags_cibles limitent le dataframe aux tags indiqués
type_colonnes indiquent si les colonnes doivent être passées en multiindex
Args:
administratif: Indique si les données administratives sont incluses
aggregat: l'aggrégat représenté
tags_cibles: la liste des tags ciblés
cohorte: la cohorte représentée
Returns:
Le dataframe complet de synthèse
"""
# Les tags visés
tags_tries = self.get_all_significant_tags()
if not tags_cibles:
tags_cibles = tags_tries
tags_cibles = sorted(tags_cibles)
# Les tags visés avec des notes
# Les étudiants visés
if administratif:
df = df_administratif(self.etuds, aggregat=aggregat, cohorte=cohorte)
else:
df = pd.DataFrame(index=self.etudids)
if not self.is_significatif():
return df
# Ajout des données par tags
for tag in tags_cibles:
if tag in self.moyennes_tags:
moy_tag_df = self.moyennes_tags[tag].to_df(
aggregat=aggregat, cohorte=cohorte, options=options
)
df = df.join(moy_tag_df)
# Tri par nom, prénom
if administratif:
colonnes_tries = [
_get_champ_administratif(champ, aggregat=aggregat, cohorte=cohorte)
for champ in CHAMPS_ADMINISTRATIFS[1:]
] # Nom + Prénom
df = df.sort_values(by=colonnes_tries)
return df
def has_etuds(self):
"""Indique si un tabletag contient des étudiants"""
return len(self.etuds) > 0
def is_significatif(self):
"""Indique si une tabletag a des données"""
# A des étudiants
if not self.etuds:
return False
# A des tags avec des notes
tags_tries = self.get_all_significant_tags()
if not tags_tries:
return False
return True
def _get_champ_administratif(champ, aggregat=None, cohorte=None):
"""Pour un champ donné, renvoie l'index (ou le multindex)
à intégrer au dataframe"""
liste = []
if aggregat != None:
liste += [aggregat]
liste += ["Administratif", "Identité"]
if cohorte != None:
liste += [champ]
liste += [champ]
return "|".join(liste)
def df_administratif(
etuds: list[Identite], aggregat=None, cohorte=None
) -> pd.DataFrame:
"""Renvoie un dataframe donnant les données administratives
des étudiants du TableTag
Args:
etuds: Identité des étudiants générant les données administratives
"""
identites = {etud.etudid: etud for etud in etuds}
donnees = {}
etud: Identite = None
for etudid, etud in identites.items():
data = {
CHAMPS_ADMINISTRATIFS[0]: etud.civilite_str,
CHAMPS_ADMINISTRATIFS[1]: etud.nom,
CHAMPS_ADMINISTRATIFS[2]: etud.prenom_str,
}
donnees[etudid] = {
_get_champ_administratif(champ, aggregat, cohorte): data[champ]
for champ in CHAMPS_ADMINISTRATIFS
}
colonnes = [
_get_champ_administratif(champ, aggregat, cohorte)
for champ in CHAMPS_ADMINISTRATIFS
]
df = pd.DataFrame.from_dict(donnees, orient="index", columns=colonnes)
df = df.sort_values(by=colonnes[1:])
return df