# -*- 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 Fri Sep  9 09:15:05 2016

@author: barasc
"""

# ----------------------------------------------------------
# Ensemble des fonctions et des classes
# permettant les calculs preliminaires (hors affichage)
# a l'edition d'un jury de poursuites d'etudes
# ----------------------------------------------------------

import io
import os
from zipfile import ZipFile

import numpy as np

from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE

from app.pe.pe_etudiant import *
from app.pe.pe_rcs import *
import app.pe.pe_comp as pe_comp
from app.pe.pe_semtag import SemestreTag
from app.pe.pe_interclasstag import RCSInterclasseTag
from app.pe.pe_rcstag import RCSTag
import app.pe.pe_affichage as pe_affichage

import pandas as pd


class JuryPE(object):
    def __init__(self, diplome):
        """
        Classe mémorisant toutes les informations nécessaires pour établir un jury de PE, sur la base
        d'une année de diplôme. De ce semestre est déduit :
        1. l'année d'obtention du DUT,
        2. tous les étudiants susceptibles à ce stade (au regard de leur parcours) d'être diplomés.

        Args:
            diplome : l'année d'obtention du diplome BUT et du jury de PE (généralement février XXXX)
        """
        self.diplome = diplome
        "L'année du diplome"

        self.nom_export_zip = f"Jury_PE_{self.diplome}"
        "Nom du zip où ranger les fichiers générés"

        # Chargement des étudiants à prendre en compte Sydans le jury
        pe_affichage.pe_print(
            f"""*** Recherche et chargement des étudiants diplômés en {
                self.diplome}"""
        )
        self.etudiants = EtudiantsJuryPE(self.diplome)  # Les infos sur les étudiants
        self.etudiants.find_etudiants()
        self.diplomes_ids = self.etudiants.diplomes_ids

        self.zipdata = io.BytesIO()
        with ZipFile(self.zipdata, "w") as zipfile:
            if not self.diplomes_ids:
                pe_affichage.pe_print("*** Aucun étudiant diplômé")
            else:
                self._gen_xls_diplomes(zipfile)
                self._gen_xls_semestre_taggues(zipfile)
                self._gen_xls_rcss_tags(zipfile)
                self._gen_xls_interclassements_rcss(zipfile)
                self._gen_xls_synthese_jury_par_tag(zipfile)
                self._gen_xls_synthese_par_etudiant(zipfile)

        # Fin !!!! Tada :)

    def _gen_xls_diplomes(self, zipfile: ZipFile):
        "Intègre le bilan des semestres taggués au zip"
        output = io.BytesIO()
        with pd.ExcelWriter(  # pylint: disable=abstract-class-instantiated
            output, engine="openpyxl"
        ) as writer:
            if self.diplomes_ids:
                onglet = "diplômés"
                df_diplome = self.etudiants.df_administratif(self.diplomes_ids)
                df_diplome.to_excel(writer, onglet, index=True, header=True)
            if self.etudiants.abandons_ids:
                onglet = "redoublants-réorientés"
                df_abandon = self.etudiants.df_administratif(
                    self.etudiants.abandons_ids
                )
                df_abandon.to_excel(writer, onglet, index=True, header=True)
        output.seek(0)

        self.add_file_to_zip(
            zipfile,
            f"etudiants_{self.diplome}.xlsx",
            output.read(),
            path="details",
        )

    def _gen_xls_semestre_taggues(self, zipfile: ZipFile):
        "Génère les semestres taggués (avec le calcul des moyennes) pour le jury PE"
        pe_affichage.pe_print("*** Génère les semestres taggués")
        self.sems_tags = compute_semestres_tag(self.etudiants)

        # Intègre le bilan des semestres taggués au zip final
        output = io.BytesIO()
        with pd.ExcelWriter(  # pylint: disable=abstract-class-instantiated
            output, engine="openpyxl"
        ) as writer:
            for formsemestretag in self.sems_tags.values():
                onglet = formsemestretag.nom
                df = formsemestretag.df_moyennes_et_classements()
                # écriture dans l'onglet
                df.to_excel(writer, onglet, index=True, header=True)
        output.seek(0)

        self.add_file_to_zip(
            zipfile,
            f"semestres_taggues_{self.diplome}.xlsx",
            output.read(),
            path="details",
        )

    def _gen_xls_rcss_tags(self, zipfile: ZipFile):
        """Génère les RCS (combinaisons de semestres suivis
        par un étudiant)
        """
        pe_affichage.pe_print(
            "*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
        )
        self.rcss = RCSsJuryPE(self.diplome)
        self.rcss.cree_rcss(self.etudiants)

        # Génère les moyennes par tags des trajectoires
        pe_affichage.pe_print(
            "*** Calcule les moyennes par tag des RCS possibles"
        )
        self.rcss_tags = compute_trajectoires_tag(
            self.rcss, self.etudiants, self.sems_tags
        )

        # Intègre le bilan des trajectoires tagguées au zip final
        output = io.BytesIO()
        with pd.ExcelWriter(  # pylint: disable=abstract-class-instantiated
            output, engine="openpyxl"
        ) as writer:
            for rcs_tag in self.rcss_tags.values():
                onglet = rcs_tag.get_repr()
                df = rcs_tag.df_moyennes_et_classements()
                # écriture dans l'onglet
                df.to_excel(writer, onglet, index=True, header=True)
        output.seek(0)

        self.add_file_to_zip(
            zipfile,
            f"RCS_taggues_{self.diplome}.xlsx",
            output.read(),
            path="details",
        )

    def _gen_xls_interclassements_rcss(self, zipfile: ZipFile):
        """Intègre le bilan des RCS (interclassé par promo) au zip"""
        # Génère les interclassements (par promo et) par (nom d') aggrégat
        pe_affichage.pe_print("*** Génère les interclassements par aggrégat")
        self.interclassements_taggues = compute_interclassements(
            self.etudiants, self.rcss, self.rcss_tags
        )

        # Intègre le bilan des aggrégats (interclassé par promo) au zip final
        output = io.BytesIO()
        with pd.ExcelWriter(  # pylint: disable=abstract-class-instantiated
            output, engine="openpyxl"
        ) as writer:
            for interclass_tag in self.interclassements_taggues.values():
                if interclass_tag.significatif:  # Avec des notes
                    onglet = interclass_tag.get_repr()
                    df = interclass_tag.df_moyennes_et_classements()
                    # écriture dans l'onglet
                    df.to_excel(writer, onglet, index=True, header=True)
        output.seek(0)

        self.add_file_to_zip(
            zipfile,
            f"interclassements_taggues_{self.diplome}.xlsx",
            output.read(),
            path="details",
        )

    def _gen_xls_synthese_jury_par_tag(self, zipfile: ZipFile):
        """Synthèse des éléments du jury PE tag par tag"""
        # Synthèse des éléments du jury PE
        self.synthese = self.synthetise_jury_par_tags()

        # Export des données => mode 1 seule feuille -> supprimé
        pe_affichage.pe_print("*** Export du jury de synthese par tags")
        output = io.BytesIO()
        with pd.ExcelWriter(  # pylint: disable=abstract-class-instantiated
            output, engine="openpyxl"
        ) as writer:
            for onglet, df in self.synthese.items():
                # écriture dans l'onglet:
                df.to_excel(writer, onglet, index=True, header=True)
        output.seek(0)

        self.add_file_to_zip(
            zipfile, f"synthese_jury_{self.diplome}_par_tag.xlsx", output.read()
        )

    def _gen_xls_synthese_par_etudiant(self, zipfile: ZipFile):
        """Synthèse des éléments du jury PE, étudiant par étudiant"""
        # Synthèse des éléments du jury PE
        synthese = self.synthetise_jury_par_etudiants()

        # Export des données => mode 1 seule feuille -> supprimé
        pe_affichage.pe_print("*** Export du jury de synthese par étudiants")
        output = io.BytesIO()
        with pd.ExcelWriter(  # pylint: disable=abstract-class-instantiated
            output, engine="openpyxl"
        ) as writer:
            for onglet, df in synthese.items():
                # écriture dans l'onglet:
                df.to_excel(writer, onglet, index=True, header=True)
        output.seek(0)

        self.add_file_to_zip(
            zipfile, f"synthese_jury_{self.diplome}_par_etudiant.xlsx", output.read()
        )

    def add_file_to_zip(self, zipfile: ZipFile, filename: str, data, path=""):
        """Add a file to given zip
        All files under NOM_EXPORT_ZIP/
        path may specify a subdirectory

        Args:
             zipfile: ZipFile
             filename: Le nom du fichier à intégrer au zip
             data: Les données du fichier
             path: Un dossier dans l'arborescence du zip
        """
        path_in_zip = os.path.join(path, filename)  # self.nom_export_zip,
        zipfile.writestr(path_in_zip, data)

    def get_zipped_data(self) -> io.BytesIO | None:
        """returns file-like data with a zip of all generated (CSV) files.
        Warning: reset stream to the begining.
        """
        self.zipdata.seek(0)
        return self.zipdata

    def do_tags_list(self, interclassements: dict[str, RCSInterclasseTag]):
        """La liste des tags extraites des interclassements"""
        tags = []
        for aggregat in interclassements:
            interclass = interclassements[aggregat]
            if interclass.tags_sorted:
                tags.extend(interclass.tags_sorted)
        tags = sorted(set(tags))
        return tags

    # **************************************************************************************************************** #
    # Méthodes pour la synthèse du juryPE
    # *****************************************************************************************************************

    def synthetise_jury_par_tags(self) -> dict[pd.DataFrame]:
        """Synthétise tous les résultats du jury PE dans des dataframes,
        dont les onglets sont les tags"""

        pe_affichage.pe_print("*** Synthèse finale des moyennes par tag***")

        synthese = {}
        pe_affichage.pe_print("  -> Synthèse des données administratives")
        synthese["administratif"] = self.etudiants.df_administratif(self.diplomes_ids)

        tags = self.do_tags_list(self.interclassements_taggues)
        for tag in tags:
            pe_affichage.pe_print(f"  -> Synthèse du tag {tag}")
            synthese[tag] = self.df_tag(tag)
        return synthese

    def df_tag(self, tag):
        """Génère le DataFrame synthétisant les moyennes/classements (groupe,
        interclassement promo) pour tous les aggrégats prévus,
        tels que fourni dans l'excel final.

        Args:
            tag: Un des tags (a minima `but`)

        Returns:
        """

        etudids = list(self.diplomes_ids)

        # Les données des étudiants
        donnees_etudiants = {}
        for etudid in etudids:
            etudiant = self.etudiants.identites[etudid]
            donnees_etudiants[etudid] = {
                ("Identité", "", "Civilite"): etudiant.civilite_str,
                ("Identité", "", "Nom"): etudiant.nom,
                ("Identité", "", "Prenom"): etudiant.prenom,
            }
        df_synthese = pd.DataFrame.from_dict(donnees_etudiants, orient="index")

        # Ajout des aggrégats
        for aggregat in TOUS_LES_RCS:
            descr = TYPES_RCS[aggregat]["descr"]

            # Les trajectoires (tagguées) suivies par les étudiants pour l'aggrégat et le tag
            # considéré
            trajectoires_tagguees = []
            for etudid in etudids:
                trajectoire = self.rcss.suivi[etudid][aggregat]
                if trajectoire:
                    tid = trajectoire.rcs_id
                    trajectoire_tagguee = self.rcss_tags[tid]
                    if (
                        tag in trajectoire_tagguee.moyennes_tags
                        and trajectoire_tagguee not in trajectoires_tagguees
                    ):
                        trajectoires_tagguees.append(trajectoire_tagguee)

            # Combien de notes vont être injectées ?
            nbre_notes_injectees = 0
            for traj in trajectoires_tagguees:
                moy_traj = traj.moyennes_tags[tag]
                inscrits_traj = moy_traj.inscrits_ids
                etudids_communs = set(etudids) & set(inscrits_traj)
                nbre_notes_injectees += len(etudids_communs)

            # Si l'aggrégat est significatif (aka il y a des notes)
            if nbre_notes_injectees > 0:
                # Ajout des données classements & statistiques
                nom_stat_promo = f"{NOM_STAT_PROMO} {self.diplome}"
                donnees = pd.DataFrame(
                    index=etudids,
                    columns=[
                        [descr] * (1 + 4 * 2),
                        [""] + [NOM_STAT_GROUPE] * 4 + [nom_stat_promo] * 4,
                        ["note"] + ["class.", "min", "moy", "max"] * 2,
                    ],
                )

                for traj in trajectoires_tagguees:
                    # Les données des trajectoires_tagguees
                    moy_traj = traj.moyennes_tags[tag]

                    # Les étudiants communs entre tableur de synthèse et trajectoires
                    inscrits_traj = moy_traj.inscrits_ids
                    etudids_communs = list(set(etudids) & set(inscrits_traj))

                    # Les notes
                    champ = (descr, "", "note")
                    notes_traj = moy_traj.get_notes()
                    donnees.loc[etudids_communs, champ] = notes_traj.loc[
                        etudids_communs]

                    # Les rangs
                    champ = (descr, NOM_STAT_GROUPE, "class.")
                    rangs = moy_traj.get_rangs_inscrits()
                    donnees.loc[etudids_communs, champ] = rangs.loc[
                        etudids_communs
                    ]

                    # Les mins
                    champ = (descr, NOM_STAT_GROUPE, "min")
                    mins = moy_traj.get_min()
                    donnees.loc[etudids_communs, champ] = mins.loc[etudids_communs]

                    # Les max
                    champ = (descr, NOM_STAT_GROUPE, "max")
                    maxs = moy_traj.get_max()
                    donnees.loc[etudids_communs, champ] = maxs.loc[etudids_communs]

                    # Les moys
                    champ = (descr, NOM_STAT_GROUPE, "moy")
                    moys = moy_traj.get_max()
                    donnees.loc[etudids_communs, champ] = moys.loc[etudids_communs]

                # Ajoute les données d'interclassement
                interclass = self.interclassements_taggues[aggregat]
                moy_interclass = interclass.moyennes_tags[tag]

                # Les étudiants communs entre tableur de synthèse et l'interclassement
                inscrits_interclass = moy_interclass.inscrits_ids
                etudids_communs = list(set(etudids) & set(inscrits_interclass))

                # Les classements d'interclassement
                champ = (descr, nom_stat_promo, "class.")
                rangs = moy_interclass.get_rangs_inscrits()
                donnees.loc[etudids_communs, champ] = rangs.loc[etudids_communs]

                # Les mins
                champ = (descr, nom_stat_promo, "min")
                mins = moy_interclass.get_min()
                donnees.loc[etudids_communs, champ] = mins.loc[etudids_communs]

                # Les max
                champ = (descr, nom_stat_promo, "max")
                maxs = moy_interclass.get_max()
                donnees.loc[etudids_communs, champ] = maxs.loc[etudids_communs]

                # Les moys
                champ = (descr, nom_stat_promo, "moy")
                moys = moy_interclass.get_max()
                donnees.loc[etudids_communs, champ] = moys.loc[etudids_communs]

                df_synthese = df_synthese.join(donnees)
            # Fin de l'aggrégat

        # Tri par nom/prénom
        df_synthese.sort_values(
            by=[("Identité", "", "Nom"), ("Identité", "", "Prenom")], inplace=True
        )
        return df_synthese

    def synthetise_jury_par_etudiants(self) -> dict[pd.DataFrame]:
        """Synthétise tous les résultats du jury PE dans des dataframes,
        dont les onglets sont les étudiants"""
        pe_affichage.pe_print("*** Synthèse finale des moyennes par étudiants***")

        synthese = {}
        pe_affichage.pe_print("  -> Synthèse des données administratives")
        synthese["administratif"] = self.etudiants.df_administratif(self.diplomes_ids)

        etudids = list(self.diplomes_ids)

        for etudid in etudids:
            etudiant = self.etudiants.identites[etudid]
            nom = etudiant.nom
            prenom = etudiant.prenom[0]  # initial du prénom

            onglet = f"{nom} {prenom}. ({etudid})"
            if len(onglet) > 32:  # limite sur la taille des onglets
                fin_onglet = f"{prenom}. ({etudid})"
                onglet = f"{nom[:32-len(fin_onglet)-2]}." + fin_onglet

            pe_affichage.pe_print(f"  -> Synthèse de l'étudiant {etudid}")
            synthese[onglet] = self.df_synthese_etudiant(etudid)
        return synthese

    def df_synthese_etudiant(self, etudid: int) -> pd.DataFrame:
        """Créé un DataFrame pour un étudiant donné par son etudid, retraçant
        toutes ses moyennes aux différents tag et aggrégats"""
        tags = self.do_tags_list(self.interclassements_taggues)

        donnees = {}

        for tag in tags:
            # Une ligne pour le tag
            donnees[tag] = {("", "", "tag"): tag}

            for aggregat in TOUS_LES_RCS:
                # Le dictionnaire par défaut des moyennes
                donnees[tag] |= get_defaut_dict_synthese_aggregat(
                    aggregat, self.diplome
                )

                # La trajectoire de l'étudiant sur l'aggrégat
                trajectoire = self.rcss.suivi[etudid][aggregat]
                if trajectoire:
                    trajectoire_tagguee = self.rcss_tags[
                        trajectoire.rcs_id
                    ]
                    if tag in trajectoire_tagguee.moyennes_tags:
                        # L'interclassement
                        interclass = self.interclassements_taggues[aggregat]

                        # Injection des données dans un dictionnaire
                        donnees[tag] |= get_dict_synthese_aggregat(
                            aggregat,
                            trajectoire_tagguee,
                            interclass,
                            etudid,
                            tag,
                            self.diplome,
                        )

            # Fin de l'aggrégat
        # Construction du dataFrame
        df = pd.DataFrame.from_dict(donnees, orient="index")

        # Tri par nom/prénom
        df.sort_values(by=[("", "", "tag")], inplace=True)
        return df

def get_formsemestres_etudiants(etudiants: EtudiantsJuryPE) -> dict:
    """Ayant connaissance des étudiants dont il faut calculer les moyennes pour
    le jury PE (attribut `self.etudiant_ids) et de leur cursus (semestres
    parcourus),
    renvoie un dictionnaire ``{fid: FormSemestre(fid)}``
    contenant l'ensemble des formsemestres de leurs cursus, dont il faudra calculer
    la moyenne.

    Args:
        etudiants: Les étudiants du jury PE

    Returns:
        Un dictionnaire de la forme `{fid: FormSemestre(fid)}`

    """
    semestres = {}
    for etudid in etudiants.etudiants_ids:
        for cle in etudiants.cursus[etudid]:
            if cle.startswith("S"):
                semestres = semestres | etudiants.cursus[etudid][cle]
    return semestres

def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
    """Créé les semestres taggués, de type 'S1', 'S2', ..., pour un groupe d'étudiants donnés.
    Chaque semestre taggué est rattaché à l'un des FormSemestre faisant partie du cursus scolaire
    des étudiants (cf. attribut etudiants.cursus).
    En crééant le semestre taggué, sont calculées les moyennes/classements par tag associé.
        .

    Args:
        etudiants: Un groupe d'étudiants participant au jury

    Returns:
        Un dictionnaire {fid: SemestreTag(fid)}
    """

    """Création des semestres taggués, de type 'S1', 'S2', ..."""
    pe_affichage.pe_print("*** Création des semestres taggués")

    formsemestres = get_formsemestres_etudiants(etudiants)

    semestres_tags = {}
    for frmsem_id, formsemestre in formsemestres.items():
        # Crée le semestre_tag et exécute les calculs de moyennes
        formsemestretag = SemestreTag(frmsem_id)
        pe_affichage.pe_print(
            f"  --> Semestre taggué {formsemestretag.nom} sur la base de {formsemestre}"
        )
        # Stocke le semestre taggué
        semestres_tags[frmsem_id] = formsemestretag

    return semestres_tags


def compute_trajectoires_tag(
    trajectoires: RCSsJuryPE,
    etudiants: EtudiantsJuryPE,
    semestres_taggues: dict[int, SemestreTag],
):
    """Créée les trajectoires tagguées (combinaison aggrégeant plusieurs semestres au sens
    d'un aggrégat (par ex: '3S')),
    en calculant les moyennes et les classements par tag pour chacune.

    Pour rappel : Chaque trajectoire est identifiée un nom d'aggrégat et par un formsemestre terminal.

    Par exemple :

    * combinaisons '3S' : S1+S2+S3 en prenant en compte tous les S3 qu'ont fréquenté les
      étudiants du jury PE. Ces S3 marquent les formsemestre terminal de chaque combinaison.

    * combinaisons 'S2' : 1 seul S2 pour des étudiants n'ayant pas redoublé, 2 pour des redoublants (dont les
      notes seront moyennées sur leur 2 semestres S2). Ces combinaisons ont pour formsemestre le dernier S2 en
      date (le S2 redoublé par les redoublants est forcément antérieur)


    Args:
        etudiants: Les données des étudiants
        semestres_tag: Les semestres tag (pour lesquels des moyennes par tag ont été calculés)

    Return:
        Un dictionnaire de la forme ``{nom_aggregat: {fid_terminal: SetTag(fid_terminal)} }``
    """
    trajectoires_tagguees = {}

    for trajectoire_id, trajectoire in trajectoires.rcss.items():
        nom = trajectoire.get_repr()
        pe_affichage.pe_print(f"  --> Aggrégat {nom}")
        # Trajectoire_tagguee associée
        trajectoire_tagguee = RCSTag(trajectoire, semestres_taggues)
        # Mémorise le résultat
        trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee

    return trajectoires_tagguees


def compute_interclassements(
    etudiants: EtudiantsJuryPE,
    trajectoires_jury_pe: RCSsJuryPE,
    trajectoires_tagguees: dict[tuple, RCS],
):
    """Interclasse les étudiants, (nom d') aggrégat par aggrégat,
    pour fournir un classement sur la promo. Le classement est établi au regard du nombre
    d'étudiants ayant participé au même aggrégat.
    """
    aggregats_interclasses_taggues = {}
    for nom_aggregat in TOUS_LES_RCS:
        pe_affichage.pe_print(f"   --> Interclassement {nom_aggregat}")
        interclass = RCSInterclasseTag(
            nom_aggregat, etudiants, trajectoires_jury_pe, trajectoires_tagguees
        )
        aggregats_interclasses_taggues[nom_aggregat] = interclass
    return aggregats_interclasses_taggues


def get_defaut_dict_synthese_aggregat(nom_rcs: str, diplome: int) -> dict:
    """Renvoie le dictionnaire de synthèse (à intégrer dans
    un tableur excel) pour décrire les résultats d'un aggrégat

    Args:
        nom_rcs : Le nom du RCS visé
        diplôme : l'année du diplôme
    """
    # L'affichage de l'aggrégat dans le tableur excel
    descr = get_descr_rcs(nom_rcs)

    nom_stat_promo = f"{NOM_STAT_PROMO} {diplome}"
    donnees = {
        (descr, "", "note"): SANS_NOTE,
        # Les stat du groupe
        (descr, NOM_STAT_GROUPE, "class."): SANS_NOTE,
        (descr, NOM_STAT_GROUPE, "min"): SANS_NOTE,
        (descr, NOM_STAT_GROUPE, "moy"): SANS_NOTE,
        (descr, NOM_STAT_GROUPE, "max"): SANS_NOTE,
        # Les stats de l'interclassement dans la promo
        (descr, nom_stat_promo, "class."): SANS_NOTE,
        (
            descr,
            nom_stat_promo,
            "min",
        ): SANS_NOTE,
        (
            descr,
            nom_stat_promo,
            "moy",
        ): SANS_NOTE,
        (
            descr,
            nom_stat_promo,
            "max",
        ): SANS_NOTE,
    }
    return donnees


def get_dict_synthese_aggregat(
    aggregat: str,
    trajectoire_tagguee: RCSTag,
    interclassement_taggue: RCSInterclasseTag,
    etudid: int,
    tag: str,
    diplome: int,
):
    """Renvoie le dictionnaire (à intégrer au tableur excel de synthese)
    traduisant les résultats (moy/class) d'un étudiant à une trajectoire tagguée associée
    à l'aggrégat donné et pour un tag donné"""
    donnees = {}
    # L'affichage de l'aggrégat dans le tableur excel
    descr = get_descr_rcs(aggregat)

    # La note de l'étudiant (chargement à venir)
    note = np.nan

    # Les données de la trajectoire tagguée pour le tag considéré
    moy_tag = trajectoire_tagguee.moyennes_tags[tag]

    # Les données de l'étudiant
    note = moy_tag.get_note_for_df(etudid)

    classement = moy_tag.get_class_for_df(etudid)
    nmin = moy_tag.get_min_for_df()
    nmax = moy_tag.get_max_for_df()
    nmoy = moy_tag.get_moy_for_df()

    # Statistiques sur le groupe
    if not pd.isna(note) and note != np.nan:
        # Les moyennes de cette trajectoire
        donnees |= {
            (descr, "", "note"): note,
            (descr, NOM_STAT_GROUPE, "class."): classement,
            (descr, NOM_STAT_GROUPE, "min"): nmin,
            (descr, NOM_STAT_GROUPE, "moy"): nmoy,
            (descr, NOM_STAT_GROUPE, "max"): nmax,
        }

    # L'interclassement
    moy_tag = interclassement_taggue.moyennes_tags[tag]

    classement = moy_tag.get_class_for_df(etudid)
    nmin = moy_tag.get_min_for_df()
    nmax = moy_tag.get_max_for_df()
    nmoy = moy_tag.get_moy_for_df()

    if not pd.isna(note) and note != np.nan:
        nom_stat_promo = f"{NOM_STAT_PROMO} {diplome}"

        donnees |= {
            (descr, nom_stat_promo, "class."): classement,
            (descr, nom_stat_promo, "min"): nmin,
            (descr, nom_stat_promo, "moy"): nmoy,
            (descr, nom_stat_promo, "max"): nmax,
        }

    return donnees
