forked from ScoDoc/ScoDoc
Mise en place des interclassements
This commit is contained in:
parent
283daae4d9
commit
82713752c2
@ -60,7 +60,9 @@ class EtudiantsJuryPE:
|
|||||||
self.trajectoires = {}
|
self.trajectoires = {}
|
||||||
|
|
||||||
"Les etudids des étudiants à considérer au jury (ceux qui seront effectivement diplômés)"
|
"Les etudids des étudiants à considérer au jury (ceux qui seront effectivement diplômés)"
|
||||||
|
self.etudiants_diplomes = {}
|
||||||
self.diplomes_ids = {}
|
self.diplomes_ids = {}
|
||||||
|
|
||||||
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
|
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
|
||||||
self.etudiants_ids = {}
|
self.etudiants_ids = {}
|
||||||
|
|
||||||
@ -112,7 +114,8 @@ class EtudiantsJuryPE:
|
|||||||
pe_tools.pe_print()
|
pe_tools.pe_print()
|
||||||
|
|
||||||
"""Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris"""
|
"""Les étudiants à prendre dans le diplôme, étudiants ayant abandonnés non compris"""
|
||||||
self.diplomes_ids = self.get_etudiants_diplomes()
|
self.etudiants_diplomes = self.get_etudiants_diplomes()
|
||||||
|
self.diplomes_ids = set(self.etudiants_diplomes.keys())
|
||||||
|
|
||||||
"""Les étudiants dont il faut calculer les moyennes"""
|
"""Les étudiants dont il faut calculer les moyennes"""
|
||||||
self.etudiants_ids = {etudid for etudid in self.identites}
|
self.etudiants_ids = {etudid for etudid in self.identites}
|
||||||
@ -122,16 +125,16 @@ class EtudiantsJuryPE:
|
|||||||
|
|
||||||
# Synthèse
|
# Synthèse
|
||||||
pe_tools.pe_print(
|
pe_tools.pe_print(
|
||||||
f" => {len(self.diplomes_ids)} étudiants à diplômer en {self.annee_diplome}"
|
f" => {len(self.etudiants_diplomes)} étudiants à diplômer en {self.annee_diplome}"
|
||||||
)
|
)
|
||||||
nbre_abandons = len(self.etudiants_ids) - len(self.diplomes_ids)
|
nbre_abandons = len(self.etudiants_ids) - len(self.etudiants_diplomes)
|
||||||
pe_tools.pe_print(f" => {nbre_abandons} étudiants éliminer pour abandon")
|
pe_tools.pe_print(f" => {nbre_abandons} étudiants éliminer pour abandon")
|
||||||
pe_tools.pe_print(
|
pe_tools.pe_print(
|
||||||
f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne"
|
f" => {len(self.formsemestres_jury_ids)} semestres dont il faut calculer la moyenne"
|
||||||
)
|
)
|
||||||
pe_tools.pe_print(
|
pe_tools.pe_print(
|
||||||
f" => quelques étudiants futurs diplômés : "
|
f" => quelques étudiants futurs diplômés : "
|
||||||
+ ", ".join([str(etudid) for etudid in list(self.diplomes_ids)[:10]])
|
+ ", ".join([str(etudid) for etudid in list(self.etudiants_diplomes)[:10]])
|
||||||
)
|
)
|
||||||
pe_tools.pe_print(
|
pe_tools.pe_print(
|
||||||
f" => semestres dont il faut calculer les moyennes : "
|
f" => semestres dont il faut calculer les moyennes : "
|
||||||
|
@ -5,6 +5,7 @@ from app.pe.pe_tools import PE_DEBUG, pe_print
|
|||||||
import app.pe.pe_etudiant as pe_etudiant
|
import app.pe.pe_etudiant as pe_etudiant
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
from app.pe.pe_trajectoire import Trajectoire, TrajectoiresJuryPE
|
from app.pe.pe_trajectoire import Trajectoire, TrajectoiresJuryPE
|
||||||
|
from app.pe.pe_trajectoiretag import TrajectoireTag
|
||||||
from app.comp import moy_sem
|
from app.comp import moy_sem
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -34,7 +35,7 @@ class AggregatInterclasseTag(pe_tagtable.TableTag):
|
|||||||
pe_tagtable.TableTag.__init__(self, nom_aggregat)
|
pe_tagtable.TableTag.__init__(self, nom_aggregat)
|
||||||
|
|
||||||
"""Les étudiants diplômés et leurs trajectoires (cf. trajectoires.suivis)"""
|
"""Les étudiants diplômés et leurs trajectoires (cf. trajectoires.suivis)"""
|
||||||
self.diplomes_ids = etudiants.diplomes_ids
|
self.diplomes_ids = etudiants.etudiants_diplomes
|
||||||
self.etudiants_diplomes = {etudid for etudid in self.diplomes_ids}
|
self.etudiants_diplomes = {etudid for etudid in self.diplomes_ids}
|
||||||
|
|
||||||
"""Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
|
"""Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
|
||||||
@ -53,9 +54,9 @@ class AggregatInterclasseTag(pe_tagtable.TableTag):
|
|||||||
|
|
||||||
"""Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
"""Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
||||||
celles associées aux diplomés"""
|
celles associées aux diplomés"""
|
||||||
self.suivis: dict[int, Trajectoire] = {}
|
self.suivi: dict[int, Trajectoire] = {}
|
||||||
for etudid in self.diplomes_ids:
|
for etudid in self.diplomes_ids:
|
||||||
self.suivis[etudid] = trajectoires_jury_pe.suivis[etudid][nom_aggregat]
|
self.suivi[etudid] = trajectoires_jury_pe.suivi[etudid][nom_aggregat]
|
||||||
|
|
||||||
"""Les tags"""
|
"""Les tags"""
|
||||||
self.tags_sorted = self.do_taglist()
|
self.tags_sorted = self.do_taglist()
|
||||||
@ -77,6 +78,11 @@ class AggregatInterclasseTag(pe_tagtable.TableTag):
|
|||||||
"nb_inscrits": len(moy_gen_tag),
|
"nb_inscrits": len(moy_gen_tag),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_repr(self) -> str:
|
||||||
|
"""Une représentation textuelle"""
|
||||||
|
return f"Aggrégat {self.nom}"
|
||||||
|
|
||||||
|
|
||||||
def do_taglist(self):
|
def do_taglist(self):
|
||||||
"""Synthétise les tags à partir des trajectoires_tagguées
|
"""Synthétise les tags à partir des trajectoires_tagguées
|
||||||
|
|
||||||
@ -89,8 +95,6 @@ class AggregatInterclasseTag(pe_tagtable.TableTag):
|
|||||||
tags.extend(trajectoire.tags_sorted)
|
tags.extend(trajectoire.tags_sorted)
|
||||||
return sorted(set(tags))
|
return sorted(set(tags))
|
||||||
|
|
||||||
def get_etudids(self):
|
|
||||||
return list(self.etudiants_diplomes.keys())
|
|
||||||
|
|
||||||
def compute_notes_matrice(self):
|
def compute_notes_matrice(self):
|
||||||
"""Construit la matrice de notes (etudid x tags)
|
"""Construit la matrice de notes (etudid x tags)
|
||||||
@ -101,7 +105,7 @@ class AggregatInterclasseTag(pe_tagtable.TableTag):
|
|||||||
nb_etudiants = len(self.diplomes_ids)
|
nb_etudiants = len(self.diplomes_ids)
|
||||||
|
|
||||||
"""Index de la matrice (etudids -> dim 0, tags -> dim 1)"""
|
"""Index de la matrice (etudids -> dim 0, tags -> dim 1)"""
|
||||||
etudids = [etud.etudid for etud in self.diplomes_ids]
|
etudids = list(self.diplomes_ids)
|
||||||
tags = self.tags_sorted
|
tags = self.tags_sorted
|
||||||
|
|
||||||
"""Partant d'un dataframe vierge"""
|
"""Partant d'un dataframe vierge"""
|
@ -47,30 +47,23 @@ import io
|
|||||||
import os
|
import os
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
import app.pe.pe_etudiant
|
|
||||||
import app.pe.pe_settag_interclasse
|
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.comp.res_sem import load_formsemestre_results
|
from app.comp.res_sem import load_formsemestre_results
|
||||||
from app.models import Formation, FormSemestre
|
from app.models import Formation, FormSemestre
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.pe.pe_semestretag import SemestreTag
|
from app.pe.pe_semestretag import SemestreTag
|
||||||
|
from app.pe.pe_interclasstag import AggregatInterclasseTag
|
||||||
|
from app.pe.pe_trajectoiretag import TrajectoireTag
|
||||||
|
|
||||||
from app.scodoc.gen_tables import GenTable, SeqGenTable
|
from app.scodoc.gen_tables import GenTable, SeqGenTable
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import (
|
from app.scodoc import codes_cursus
|
||||||
codes_cursus,
|
|
||||||
sco_formsemestre_inscriptions,
|
|
||||||
) # codes_cursus.NEXT -> sem suivant
|
|
||||||
from app.scodoc import sco_etud
|
|
||||||
from app.scodoc import sco_report
|
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.pe import pe_tagtable
|
|
||||||
from app.pe import pe_tools
|
from app.pe import pe_tools
|
||||||
from app.pe import pe_semestretag
|
from app.pe import pe_semestretag
|
||||||
from app.pe import pe_trajectoiretag
|
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||||
from app.pe.pe_trajectoire import TrajectoiresJuryPE
|
from app.pe.pe_trajectoire import TrajectoiresJuryPE, Trajectoire
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------
|
||||||
@ -143,6 +136,7 @@ class JuryPE(object):
|
|||||||
self.etudiants.find_etudiants(self.formation_id)
|
self.etudiants.find_etudiants(self.formation_id)
|
||||||
|
|
||||||
"""Génère les semestres taggués (avec le calcul des moyennes) pour le jury PE"""
|
"""Génère les semestres taggués (avec le calcul des moyennes) pour le jury PE"""
|
||||||
|
pe_tools.pe_print("*** Génère les semestres taggués")
|
||||||
self.semestres_taggues = compute_semestres_tag(self.etudiants)
|
self.semestres_taggues = compute_semestres_tag(self.etudiants)
|
||||||
|
|
||||||
if pe_tools.PE_DEBUG:
|
if pe_tools.PE_DEBUG:
|
||||||
@ -158,42 +152,50 @@ class JuryPE(object):
|
|||||||
"""Génère les trajectoires (combinaison de semestres suivis
|
"""Génère les trajectoires (combinaison de semestres suivis
|
||||||
par un étudiant pour atteindre le semestre final d'un aggrégat)
|
par un étudiant pour atteindre le semestre final d'un aggrégat)
|
||||||
"""
|
"""
|
||||||
|
pe_tools.pe_print(
|
||||||
|
"*** Génère les trajectoires (différentes combinaisons de semestres) des étudiants"
|
||||||
|
)
|
||||||
self.trajectoires = TrajectoiresJuryPE(self.diplome)
|
self.trajectoires = TrajectoiresJuryPE(self.diplome)
|
||||||
self.trajectoires.cree_trajectoires(self.etudiants)
|
self.trajectoires.cree_trajectoires(self.etudiants)
|
||||||
|
|
||||||
|
"""Génère les moyennes par tags des trajectoires"""
|
||||||
"""Génère les aggrégats de semestre (par ex: 1A, 3S, 5S) avec calcul
|
pe_tools.pe_print("*** Calcule les moyennes par tag des trajectoires possibles")
|
||||||
des moyennes pour le jury"""
|
|
||||||
self.trajectoires_tagguees = compute_trajectoires_tag(
|
self.trajectoires_tagguees = compute_trajectoires_tag(
|
||||||
self.etudiants, self.semestres_taggues
|
self.trajectoires, self.etudiants, self.semestres_taggues
|
||||||
)
|
)
|
||||||
|
|
||||||
if pe_tools.PE_DEBUG:
|
if pe_tools.PE_DEBUG:
|
||||||
"""Intègre le bilan des aggrégats de semestres au zip final"""
|
"""Intègre le bilan des trajectoires tagguées au zip final"""
|
||||||
for aggregat in self.trajectoires_tagguees:
|
for trajectoire_id in self.trajectoires_tagguees:
|
||||||
for fid in self.trajectoires_tagguees[aggregat]:
|
trajectoire_tagguee = self.trajectoires_tagguees[trajectoire_id]
|
||||||
set_tag = self.trajectoires_tagguees[aggregat][fid]
|
filename = trajectoire_tagguee.get_repr().replace(" ", "_") + ".csv"
|
||||||
filename = set_tag.nom.replace(" ", "_") + ".csv"
|
pe_tools.pe_print(f" - Export csv de {filename} ")
|
||||||
pe_tools.pe_print(f" - Export csv de {filename} ")
|
self.add_file_to_zip(
|
||||||
self.add_file_to_zip(
|
filename,
|
||||||
filename, set_tag.str_tagtable(), path="details_semestres"
|
trajectoire_tagguee.str_tagtable(),
|
||||||
)
|
path="details_semestres",
|
||||||
|
)
|
||||||
|
|
||||||
"""Génère les interclassements par (nom d') aggrégat"""
|
"""Génère les interclassements (par promo et) par (nom d') aggrégat"""
|
||||||
self.aggregats_taggues_interclasses = compute_interclassements(
|
pe_tools.pe_print("*** Génère les interclassements par aggrégat")
|
||||||
self.etudiants, #
|
self.interclassements_taggues = compute_interclassements(
|
||||||
self.trajectoires_tagguees,
|
self.etudiants, self.trajectoires, self.trajectoires_tagguees
|
||||||
)
|
)
|
||||||
# Les interclassements
|
|
||||||
# --------------------
|
|
||||||
if pe_tools.PE_DEBUG:
|
if pe_tools.PE_DEBUG:
|
||||||
pe_tools.pe_print(
|
"""Intègre le bilan des aggrégats (par promo) au zip final"""
|
||||||
"*** Création des interclassements au sein de la promo sur différentes combinaisons de semestres"
|
for nom_aggregat in self.interclassements_taggues:
|
||||||
)
|
interclass_tag = self.interclassements_taggues[nom_aggregat]
|
||||||
|
filename = interclass_tag.get_repr().replace(" ", "_") + ".csv"
|
||||||
|
pe_tools.pe_print(f" - Export csv de {filename} ")
|
||||||
|
self.add_file_to_zip(
|
||||||
|
filename,
|
||||||
|
interclass_tag.str_tagtable(),
|
||||||
|
path="details_semestres",
|
||||||
|
)
|
||||||
|
|
||||||
"""Synthèse des éléments du jury PE"""
|
"""Synthèse des éléments du jury PE"""
|
||||||
if False:
|
self.synthetise_juryPE()
|
||||||
self.synthetise_juryPE()
|
|
||||||
|
|
||||||
# Export des données => mode 1 seule feuille -> supprimé
|
# Export des données => mode 1 seule feuille -> supprimé
|
||||||
# filename = self.NOM_EXPORT_ZIP + "jurySyntheseDict_" + str(self.diplome) + '.xls'
|
# filename = self.NOM_EXPORT_ZIP + "jurySyntheseDict_" + str(self.diplome) + '.xls'
|
||||||
@ -243,7 +245,7 @@ class JuryPE(object):
|
|||||||
# Méthodes pour la synthèse du juryPE
|
# Méthodes pour la synthèse du juryPE
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
def synthetise_juryPE(self):
|
def synthetise_juryPE(self):
|
||||||
"""Synthétise tous les résultats du jury PE dans un dictionnaire"""
|
"""Synthétise tous les résultats du jury PE dans des dataframess"""
|
||||||
self.syntheseJury = {}
|
self.syntheseJury = {}
|
||||||
for etudid in self.etudiants.get_etudids(self.diplome):
|
for etudid in self.etudiants.get_etudids(self.diplome):
|
||||||
etudinfo = self.ETUDINFO_DICT[etudid]
|
etudinfo = self.ETUDINFO_DICT[etudid]
|
||||||
@ -663,9 +665,11 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE):
|
|||||||
return semestres_tags
|
return semestres_tags
|
||||||
|
|
||||||
|
|
||||||
def compute_trajectoires_tag(trajectoires: TrajectoiresJuryPE,
|
def compute_trajectoires_tag(
|
||||||
etudiants: EtudiantsJuryPE,
|
trajectoires: TrajectoiresJuryPE,
|
||||||
semestres_taggues: dict[int, SemestreTag]):
|
etudiants: EtudiantsJuryPE,
|
||||||
|
semestres_taggues: dict[int, SemestreTag],
|
||||||
|
):
|
||||||
"""Créée les trajectoires tagguées (combinaison aggrégeant plusieurs semestres au sens
|
"""Créée les trajectoires tagguées (combinaison aggrégeant plusieurs semestres au sens
|
||||||
d'un aggrégat (par ex: '3S')),
|
d'un aggrégat (par ex: '3S')),
|
||||||
en calculant les moyennes et les classements par tag pour chacune.
|
en calculant les moyennes et les classements par tag pour chacune.
|
||||||
@ -694,16 +698,16 @@ def compute_trajectoires_tag(trajectoires: TrajectoiresJuryPE,
|
|||||||
|
|
||||||
trajectoires_tagguees = {}
|
trajectoires_tagguees = {}
|
||||||
|
|
||||||
for trajectoire_id in trajectoires_tagguees:
|
for trajectoire_id in trajectoires.trajectoires:
|
||||||
trajectoire = trajectoires[trajectoire_id]
|
trajectoire = trajectoires.trajectoires[trajectoire_id]
|
||||||
nom = trajectoire.get_repr()
|
nom = trajectoire.get_repr()
|
||||||
|
|
||||||
pe_tools.pe_print(f" --> Fusion {nom}")
|
pe_tools.pe_print(f" --> Fusion {nom}")
|
||||||
|
|
||||||
"""Création de la trajectoire_tagguee associée"""
|
"""Création de la trajectoire_tagguee associée"""
|
||||||
trajectoire_tagguee = pe_trajectoiretag.TrajectoireTag(
|
trajectoire_tagguee = TrajectoireTag(
|
||||||
nom, trajectoire, semestres_taggues, etudiants
|
nom, trajectoire, semestres_taggues, etudiants
|
||||||
)
|
)
|
||||||
|
|
||||||
"""Mémorise le résultat"""
|
"""Mémorise le résultat"""
|
||||||
trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee
|
trajectoires_tagguees[trajectoire_id] = trajectoire_tagguee
|
||||||
@ -711,33 +715,22 @@ def compute_trajectoires_tag(trajectoires: TrajectoiresJuryPE,
|
|||||||
return trajectoires_tagguees
|
return trajectoires_tagguees
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def compute_interclassements(
|
def compute_interclassements(
|
||||||
etudiants: EtudiantsJuryPE, aggregats_taggues: dict[str, dict]
|
etudiants: EtudiantsJuryPE,
|
||||||
|
trajectoires_jury_pe: TrajectoiresJuryPE,
|
||||||
|
trajectoires_tagguees: dict[tuple, Trajectoire],
|
||||||
):
|
):
|
||||||
"""Interclasse les étudiants, (nom d') aggrégat par aggrégat,
|
"""Interclasse les étudiants, (nom d') aggrégat par aggrégat,
|
||||||
pour fournir un classement sur la promo. Le classement est établit au regard du nombre
|
pour fournir un classement sur la promo. Le classement est établi au regard du nombre
|
||||||
d'étudiants ayant participé au même aggrégat.
|
d'étudiants ayant participé au même aggrégat.
|
||||||
"""
|
"""
|
||||||
etudiants_diplomes = etudiants.get_etudiants_diplomes()
|
pe_tools.pe_print(" Interclassement sur la promo")
|
||||||
|
|
||||||
"""
|
aggregats_interclasses_taggues = {}
|
||||||
for i, nom in enumerate(pe_tools.PARCOURS.keys()):
|
for nom_aggregat in pe_tools.TOUS_LES_SEMESTRES + pe_tools.TOUS_LES_AGGREGATS:
|
||||||
settag = app.pe.pe_settag_interclasse.SetTagInterClasse(nom, diplome=diplome)
|
pe_tools.pe_print(f" --> {nom_aggregat}")
|
||||||
nbreEtudInscrits = settag.set_Etudiants(
|
interclass = AggregatInterclasseTag(
|
||||||
lesEtudids, self.etudiants.cursus, self.etudiants.identites
|
nom_aggregat, etudiants, trajectoires_jury_pe, trajectoires_tagguees
|
||||||
)
|
)
|
||||||
if nbreEtudInscrits > 0:
|
aggregats_interclasses_taggues[nom_aggregat] = interclass
|
||||||
pe_tools.pe_print("%d) %s avec interclassement sur la promo" % (i + 1, nom))
|
return aggregats_interclasses_taggues
|
||||||
if nom in pe_tools.TOUS_LES_SEMESTRES:
|
|
||||||
settag.set_SetTagDict(self.semestres_taggues)
|
|
||||||
else: # cas des aggrégats
|
|
||||||
settag.set_SetTagDict(self.aggregats_taggues[nom])
|
|
||||||
settag.comp_data_settag()
|
|
||||||
self.promoTagDict[nom] = settag
|
|
||||||
else:
|
|
||||||
pe_tools.pe_print(
|
|
||||||
"%d) Pas d'interclassement %s sur la promo faute de notes"
|
|
||||||
% (i + 1, nom)
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
|
@ -91,7 +91,8 @@ class TrajectoiresJuryPE:
|
|||||||
|
|
||||||
for etudid in etudiants.cursus:
|
for etudid in etudiants.cursus:
|
||||||
if etudid not in self.suivi:
|
if etudid not in self.suivi:
|
||||||
self.suivi[etudid] = {}
|
self.suivi[etudid] = {aggregat: None
|
||||||
|
for aggregat in pe_tools.TOUS_LES_SEMESTRES + pe_tools.TOUS_LES_AGGREGATS}
|
||||||
|
|
||||||
"""Le formsemestre terminal (dernier en date) associé au
|
"""Le formsemestre terminal (dernier en date) associé au
|
||||||
semestre marquant la fin de l'aggrégat
|
semestre marquant la fin de l'aggrégat
|
||||||
|
@ -122,6 +122,11 @@ class TrajectoireTag(pe_tagtable.TableTag):
|
|||||||
"nb_inscrits": len(moy_gen_tag),
|
"nb_inscrits": len(moy_gen_tag),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_repr(self):
|
||||||
|
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||||
|
est basée)"""
|
||||||
|
return self.trajectoire.get_repr()
|
||||||
|
|
||||||
def compute_notes_cube(self):
|
def compute_notes_cube(self):
|
||||||
"""Construit le cube de notes (etudid x tags x semestre_aggregé)
|
"""Construit le cube de notes (etudid x tags x semestre_aggregé)
|
||||||
nécessaire au calcul des moyennes de l'aggrégat
|
nécessaire au calcul des moyennes de l'aggrégat
|
||||||
|
Loading…
Reference in New Issue
Block a user