forked from ScoDoc/ScoDoc
Améliorations diverses
This commit is contained in:
parent
b8cb592ac9
commit
828c619c74
@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
# Gestion scolarite IUT
|
# Gestion scolarite IUT
|
||||||
#
|
#
|
||||||
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. c All rights reserved.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -59,7 +59,7 @@ class EtudiantsJuryPE:
|
|||||||
self.identites: dict[int, Identite] = {} # ex. ETUDINFO_DICT
|
self.identites: dict[int, Identite] = {} # ex. ETUDINFO_DICT
|
||||||
"Les identités des étudiants traités pour le jury"
|
"Les identités des étudiants traités pour le jury"
|
||||||
|
|
||||||
self.cursus: dict[int, dict] = {}
|
self.trajectoires: dict[int, dict] = {}
|
||||||
"Les cursus (semestres suivis, abandons) des étudiants"
|
"Les cursus (semestres suivis, abandons) des étudiants"
|
||||||
|
|
||||||
self.trajectoires = {}
|
self.trajectoires = {}
|
||||||
@ -164,7 +164,7 @@ class EtudiantsJuryPE:
|
|||||||
"""
|
"""
|
||||||
etudids = [
|
etudids = [
|
||||||
etudid
|
etudid
|
||||||
for etudid, cursus_etud in self.cursus.items()
|
for etudid, cursus_etud in self.trajectoires.items()
|
||||||
if cursus_etud["diplome"] == self.annee_diplome
|
if cursus_etud["diplome"] == self.annee_diplome
|
||||||
and cursus_etud["abandon"] is False
|
and cursus_etud["abandon"] is False
|
||||||
]
|
]
|
||||||
@ -181,7 +181,7 @@ class EtudiantsJuryPE:
|
|||||||
"""
|
"""
|
||||||
etudids = [
|
etudids = [
|
||||||
etudid
|
etudid
|
||||||
for etudid, cursus_etud in self.cursus.items()
|
for etudid, cursus_etud in self.trajectoires.items()
|
||||||
if cursus_etud["diplome"] != self.annee_diplome
|
if cursus_etud["diplome"] != self.annee_diplome
|
||||||
or cursus_etud["abandon"] is True
|
or cursus_etud["abandon"] is True
|
||||||
]
|
]
|
||||||
@ -225,7 +225,7 @@ class EtudiantsJuryPE:
|
|||||||
if formsemestre.formation.is_apc()
|
if formsemestre.formation.is_apc()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cursus[etudid] = {
|
self.trajectoires[etudid] = {
|
||||||
"etudid": etudid, # les infos sur l'étudiant
|
"etudid": etudid, # les infos sur l'étudiant
|
||||||
"etat_civil": identite.etat_civil, # Ajout à la table jury
|
"etat_civil": identite.etat_civil, # Ajout à la table jury
|
||||||
"nom": identite.nom,
|
"nom": identite.nom,
|
||||||
@ -241,32 +241,36 @@ class EtudiantsJuryPE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Si l'étudiant est succeptible d'être diplomé
|
# Si l'étudiant est succeptible d'être diplomé
|
||||||
if self.cursus[etudid]["diplome"] == self.annee_diplome:
|
if self.trajectoires[etudid]["diplome"] == self.annee_diplome:
|
||||||
# Est-il démissionnaire : charge son dernier semestre pour connaitre son état ?
|
# Est-il démissionnaire : charge son dernier semestre pour connaitre son état ?
|
||||||
dernier_semes_etudiant = formsemestres[0]
|
dernier_semes_etudiant = formsemestres[0]
|
||||||
res = load_formsemestre_results(dernier_semes_etudiant)
|
res = load_formsemestre_results(dernier_semes_etudiant)
|
||||||
etud_etat = res.get_etud_etat(etudid)
|
etud_etat = res.get_etud_etat(etudid)
|
||||||
if etud_etat == scu.DEMISSION:
|
if etud_etat == scu.DEMISSION:
|
||||||
self.cursus[etudid]["abandon"] = True
|
self.trajectoires[etudid]["abandon"] = True
|
||||||
else:
|
else:
|
||||||
# Est-il réorienté ou a-t-il arrêté (volontairement) sa formation ?
|
# Est-il réorienté ou a-t-il arrêté (volontairement) sa formation ?
|
||||||
self.cursus[etudid]["abandon"] = arret_de_formation(
|
self.trajectoires[etudid]["abandon"] = arret_de_formation(
|
||||||
identite, cosemestres
|
identite, cosemestres
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_semestres_significatifs(self, etudid: int):
|
def get_semestres_significatifs(self, etudid: int):
|
||||||
"""Ensemble des semestres d'un étudiant, qui l'auraient amené à être diplomé
|
"""Ensemble des semestres d'un étudiant, qui :
|
||||||
l'année visée (supprime les semestres qui conduisent à une diplomation
|
|
||||||
postérieure à celle du jury visé)
|
* l'amènent à être diplômé à l'année visée
|
||||||
|
* l'auraient amené à être diplômé à l'année visée s'il n'avait pas redoublé et sera donc
|
||||||
|
diplômé plus tard
|
||||||
|
|
||||||
|
Supprime les semestres qui conduisent à une diplomation postérieure à celle du jury visé.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
etudid: L'identifiant d'un étudiant
|
etudid: L'identifiant d'un étudiant
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Un dictionnaire ``{fid: FormSemestre(fid)`` dans lequel les semestres
|
Un dictionnaire ``{fid: FormSemestre(fid)}`` dans lequel les semestres
|
||||||
amènent à une diplomation avant l'annee de diplomation du jury
|
amènent à une diplômation antérieur à celle de la diplômation visée par le jury jury
|
||||||
"""
|
"""
|
||||||
semestres_etudiant = self.cursus[etudid]["formsemestres"]
|
semestres_etudiant = self.trajectoires[etudid]["formsemestres"]
|
||||||
semestres_significatifs = {}
|
semestres_significatifs = {}
|
||||||
for fid in semestres_etudiant:
|
for fid in semestres_etudiant:
|
||||||
semestre = semestres_etudiant[fid]
|
semestre = semestres_etudiant[fid]
|
||||||
@ -281,7 +285,7 @@ class EtudiantsJuryPE:
|
|||||||
|
|
||||||
Cette structuration s'appuie sur les numéros de semestre: pour chaque Si, stocke :
|
Cette structuration s'appuie sur les numéros de semestre: pour chaque Si, stocke :
|
||||||
le dernier semestre (en date) de numéro i qu'il a suivi (1 ou 0 si pas encore suivi).
|
le dernier semestre (en date) de numéro i qu'il a suivi (1 ou 0 si pas encore suivi).
|
||||||
Ce semestre influera les interclassement par semestre dans la promo.
|
Ce semestre influera les interclassements par semestre dans la promo.
|
||||||
"""
|
"""
|
||||||
semestres_significatifs = self.get_semestres_significatifs(etudid)
|
semestres_significatifs = self.get_semestres_significatifs(etudid)
|
||||||
|
|
||||||
@ -293,14 +297,14 @@ class EtudiantsJuryPE:
|
|||||||
for fid, sem_sig in semestres_significatifs.items()
|
for fid, sem_sig in semestres_significatifs.items()
|
||||||
if sem_sig.semestre_id == i
|
if sem_sig.semestre_id == i
|
||||||
}
|
}
|
||||||
self.cursus[etudid][f"S{i}"] = semestres_i
|
self.trajectoires[etudid][f"S{i}"] = semestres_i
|
||||||
|
|
||||||
def get_formsemestres_terminaux_aggregat(
|
def get_formsemestres_finals_des_rcs(
|
||||||
self, aggregat: str
|
self, nom_rcs: str
|
||||||
) -> dict[int, FormSemestre]:
|
) -> dict[int, FormSemestre]:
|
||||||
"""Pour un aggrégat donné, ensemble des formsemestres terminaux possibles pour l'aggrégat
|
"""Pour un nom de RCS donné, ensemble des formsemestres finals possibles
|
||||||
(pour l'aggrégat '3S' incluant S1+S2+S3, a pour semestre terminal S3).
|
pour les RCS. Par ex. un RCS '3S' incluant S1+S2+S3 a pour semestre final un S3.
|
||||||
Ces formsemestres traduisent :
|
Les formsemestres finals obtenus traduisent :
|
||||||
|
|
||||||
* les différents parcours des étudiants liés par exemple au choix de modalité
|
* les différents parcours des étudiants liés par exemple au choix de modalité
|
||||||
(par ex: S1 FI + S2 FI + S3 FI ou S1 FI + S2 FI + S3 UFA), en renvoyant les
|
(par ex: S1 FI + S2 FI + S3 FI ou S1 FI + S2 FI + S3 UFA), en renvoyant les
|
||||||
@ -311,14 +315,14 @@ class EtudiantsJuryPE:
|
|||||||
renvoyant les formsemestre_id du S3 (1ère session) et du S3 (2ème session)
|
renvoyant les formsemestre_id du S3 (1ère session) et du S3 (2ème session)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
aggregat: L'aggrégat
|
nom_rcs: Le nom du RCS (parmi Sx, xA, xS)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Un dictionnaire ``{fid: FormSemestre(fid)}``
|
Un dictionnaire ``{fid: FormSemestre(fid)}``
|
||||||
"""
|
"""
|
||||||
formsemestres_terminaux = {}
|
formsemestres_terminaux = {}
|
||||||
for trajectoire_aggr in self.trajectoires.values():
|
for trajectoire_aggr in self.trajectoires.values():
|
||||||
trajectoire = trajectoire_aggr[aggregat]
|
trajectoire = trajectoire_aggr[nom_rcs]
|
||||||
if trajectoire:
|
if trajectoire:
|
||||||
# Le semestre terminal de l'étudiant de l'aggrégat
|
# Le semestre terminal de l'étudiant de l'aggrégat
|
||||||
fid = trajectoire.formsemestre_final.formsemestre_id
|
fid = trajectoire.formsemestre_final.formsemestre_id
|
||||||
@ -334,7 +338,7 @@ class EtudiantsJuryPE:
|
|||||||
"""
|
"""
|
||||||
nbres_semestres = []
|
nbres_semestres = []
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
nbres_semestres.append(self.cursus[etudid]["nb_semestres"])
|
nbres_semestres.append(self.trajectoires[etudid]["nb_semestres"])
|
||||||
if not nbres_semestres:
|
if not nbres_semestres:
|
||||||
return 0
|
return 0
|
||||||
return max(nbres_semestres)
|
return max(nbres_semestres)
|
||||||
@ -355,7 +359,7 @@ class EtudiantsJuryPE:
|
|||||||
|
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etudiant = self.identites[etudid]
|
etudiant = self.identites[etudid]
|
||||||
cursus = self.cursus[etudid]
|
cursus = self.trajectoires[etudid]
|
||||||
formsemestres = cursus["formsemestres"]
|
formsemestres = cursus["formsemestres"]
|
||||||
|
|
||||||
if cursus["diplome"]:
|
if cursus["diplome"]:
|
||||||
@ -442,7 +446,7 @@ def get_annee_diplome(etud: Identite) -> int | None:
|
|||||||
|
|
||||||
|
|
||||||
def get_semestres_apc(identite: Identite) -> list:
|
def get_semestres_apc(identite: Identite) -> list:
|
||||||
"""Liste des semestres d'un étudiant qui corresponde à une formation APC.
|
"""Liste des semestres d'un étudiant qui correspondent à une formation APC.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
identite: L'identité d'un étudiant
|
identite: L'identité d'un étudiant
|
||||||
@ -675,3 +679,19 @@ def nom_semestre_etape(semestre: FormSemestre, avec_fid=False) -> str:
|
|||||||
description.append(f"({semestre.formsemestre_id})")
|
description.append(f"({semestre.formsemestre_id})")
|
||||||
|
|
||||||
return " ".join(description)
|
return " ".join(description)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_trajectoire_to_sxtag_id(trajectoire: dict[int:FormSemestre]) -> (int, int):
|
||||||
|
"""Partant d'une trajectoire (dictionnaire de la forme {fid: FormSemestre}),
|
||||||
|
renvoie l'identifiant (rang_sem, fid du semestre_terminal) associé"""
|
||||||
|
if not trajectoire:
|
||||||
|
return None
|
||||||
|
rangs = [formsemestre.semestre_id for formsemestre in trajectoire.values()]
|
||||||
|
assert rangs == min(rangs), "Les trajectoires doivent être de même rang"
|
||||||
|
rang = min(rangs)
|
||||||
|
fid_terminal = list(trajectoire.values())[0].formsemestre_id
|
||||||
|
for fid, formsemestre in trajectoire.items():
|
||||||
|
if trajectoire[fid_terminal].date_fin <= formsemestre.date_fin:
|
||||||
|
fid_terminal = fid
|
||||||
|
return (rang, fid_terminal)
|
||||||
|
|
||||||
|
@ -50,13 +50,13 @@ from zipfile import ZipFile
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from app.pe import pe_semtag
|
from app.pe import pe_sxtag
|
||||||
from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE
|
from app.pe.pe_affichage import NOM_STAT_PROMO, SANS_NOTE, NOM_STAT_GROUPE
|
||||||
import app.pe.pe_affichage as pe_affichage
|
import app.pe.pe_affichage as pe_affichage
|
||||||
from app.pe.pe_etudiant import * # TODO A éviter -> pe_etudiant.
|
from app.pe.pe_etudiant import * # TODO A éviter -> pe_etudiant.
|
||||||
import app.pe.pe_rcs as pe_rcs
|
import app.pe.pe_rcs as pe_rcs
|
||||||
from app.pe.pe_rcstag import RCSTag
|
from app.pe.pe_rcstag import RCSTag
|
||||||
from app.pe.pe_ressemtag import ResSemTag
|
from app.pe.pe_ressemtag import ResSemBUTTag
|
||||||
from app.pe.pe_interclasstag import RCSInterclasseTag
|
from app.pe.pe_interclasstag import RCSInterclasseTag
|
||||||
|
|
||||||
|
|
||||||
@ -97,10 +97,10 @@ class JuryPE(object):
|
|||||||
pe_affichage.pe_print("*** Aucun étudiant diplômé")
|
pe_affichage.pe_print("*** Aucun étudiant diplômé")
|
||||||
else:
|
else:
|
||||||
self._gen_xls_diplomes(zipfile)
|
self._gen_xls_diplomes(zipfile)
|
||||||
self._gen_rcss()
|
|
||||||
self._gen_xls_resultats_semestres_taggues(zipfile)
|
self._gen_xls_ressembuttags(zipfile)
|
||||||
self._gen_xls_semestres_taggues(zipfile)
|
self._gen_xls_sxtags(zipfile)
|
||||||
# self._gen_xls_rcss_tags(zipfile)
|
self._gen_xls_rcss_tags(zipfile)
|
||||||
# self._gen_xls_interclassements_rcss(zipfile)
|
# self._gen_xls_interclassements_rcss(zipfile)
|
||||||
# self._gen_xls_synthese_jury_par_tag(zipfile)
|
# self._gen_xls_synthese_jury_par_tag(zipfile)
|
||||||
# self._gen_xls_synthese_par_etudiant(zipfile)
|
# self._gen_xls_synthese_par_etudiant(zipfile)
|
||||||
@ -134,17 +134,26 @@ class JuryPE(object):
|
|||||||
path="details",
|
path="details",
|
||||||
)
|
)
|
||||||
|
|
||||||
def _gen_xls_resultats_semestres_taggues(self, zipfile: ZipFile):
|
def _gen_xls_ressembuttags(self, zipfile: ZipFile):
|
||||||
"""Génère les semestres taggués (avec le calcul des moyennes) pour le jury PE"""
|
"""Calcule les moyennes par tag des résultats des Semestres BUT"""
|
||||||
pe_affichage.pe_print("*** Génère les résultats des semestres taggués")
|
pe_affichage.pe_print("*** Génère les ResSemBUTTag (résultats des semestres BUT taggués)")
|
||||||
self.res_sems_tags = compute_resultats_semestres_tag(self.etudiants)
|
|
||||||
|
formsemestres = get_formsemestres_etudiants(self.etudiants)
|
||||||
|
pe_affichage.pe_print(f" --> {len(formsemestres)} résultats de semestres à considérer")
|
||||||
|
|
||||||
|
ressembuttags = {}
|
||||||
|
for frmsem_id, formsemestre in formsemestres.items():
|
||||||
|
# Crée le semestre_tag et exécute les calculs de moyennes
|
||||||
|
ressembuttags[frmsem_id] = ResSemBUTTag(formsemestre)
|
||||||
|
|
||||||
|
return ressembuttags
|
||||||
|
|
||||||
# Intègre le bilan des semestres taggués au zip final
|
# Intègre le bilan des semestres taggués au zip final
|
||||||
output = io.BytesIO()
|
output = io.BytesIO()
|
||||||
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
|
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
|
||||||
output, engine="openpyxl"
|
output, engine="openpyxl"
|
||||||
) as writer:
|
) as writer:
|
||||||
for res_sem_tag in self.res_sems_tags.values():
|
for res_sem_tag in self.ressembuttags.values():
|
||||||
onglet = res_sem_tag.get_repr(verbose=False)
|
onglet = res_sem_tag.get_repr(verbose=False)
|
||||||
df = res_sem_tag.df_moyennes_et_classements()
|
df = res_sem_tag.df_moyennes_et_classements()
|
||||||
# écriture dans l'onglet
|
# écriture dans l'onglet
|
||||||
@ -153,14 +162,14 @@ class JuryPE(object):
|
|||||||
|
|
||||||
self.add_file_to_zip(
|
self.add_file_to_zip(
|
||||||
zipfile,
|
zipfile,
|
||||||
f"resultats_semestres_taggues_{self.diplome}.xlsx",
|
f"ResSemBUTTags_{self.diplome}.xlsx",
|
||||||
output.read(),
|
output.read(),
|
||||||
path="details",
|
path="details",
|
||||||
)
|
)
|
||||||
|
|
||||||
def _gen_rcss(self):
|
def _gen_rcss(self):
|
||||||
"""Génère les RCS (attribut `rcss_jury`), combinaisons de semestres suivis par les étudiants au sens
|
"""Génère les RCS (attribut `rcss_jury`), combinaisons de semestres suivis par les étudiants au sens
|
||||||
d'un nom de RCS (par ex: '3S').
|
d'un nom de RCS (par ex: 'S2' ou '3S').
|
||||||
"""
|
"""
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
"*** Génère les RCS (différentes combinaisons de semestres) des étudiants"
|
"*** Génère les RCS (différentes combinaisons de semestres) des étudiants"
|
||||||
@ -168,24 +177,35 @@ class JuryPE(object):
|
|||||||
self.rcss_jury = pe_rcs.RCSsJuryPE(self.diplome)
|
self.rcss_jury = pe_rcs.RCSsJuryPE(self.diplome)
|
||||||
self.rcss_jury.cree_rcss(self.etudiants)
|
self.rcss_jury.cree_rcss(self.etudiants)
|
||||||
|
|
||||||
def _gen_xls_semestres_taggues(self, zipfile: ZipFile):
|
def _gen_xls_sxtags(self, zipfile: ZipFile):
|
||||||
"""Génère les semestres taggués en s'appuyant sur les RCS de type Sx (pour
|
"""Génère les semestres taggués en s'appuyant sur les RCS de type Sx (pour
|
||||||
identifier les redoublements impactant les semestres taggués).
|
identifier les redoublements impactant les semestres taggués).
|
||||||
"""
|
"""
|
||||||
# Génère les moyennes des RCS de type Sx
|
# Génère les moyennes des RCS de type Sx
|
||||||
pe_affichage.pe_print("*** Calcule les moyennes de semestres = RCS de type Sx")
|
pe_affichage.pe_print("*** Calcule les moyennes des SxTag")
|
||||||
|
|
||||||
self.sems_tags = {}
|
# Les regroupements de Sx
|
||||||
for rcs_id, rcs in self.rcss_jury.rcss.items():
|
self.regroupements = {}
|
||||||
if rcs.nom.startswith("S"):
|
for rang in range(1, pe_comp.NBRE_SEMESTRES_DIPLOMANT+1):
|
||||||
self.sems_tags[rcs_id] = pe_semtag.SemTag(rcs, self.res_sems_tags)
|
self.regroupements[rang] = {}
|
||||||
|
for etudid in self.etudiants.etudiants_ids:
|
||||||
|
trajectoire = self.etudiants.cursus[etudid][f"S{rang}"]
|
||||||
|
self.regroupements[rang] |= trajectoire
|
||||||
|
|
||||||
|
# Les SxTag
|
||||||
|
self.sxtags = {}
|
||||||
|
for rang in range(1, pe_comp.NBRE_SEMESTRES_DIPLOMANT+1):
|
||||||
|
trajectoire = self.regroupements[rang]
|
||||||
|
sxtag_id = pe_sxtag.get_sxtag_from_semestres(trajectoire)
|
||||||
|
ressemstags = {fid: self.ressembuttags[fid] for fid in trajectoire}
|
||||||
|
self.sxtags[sxtag_id] = pe_sxtag.SxTag(sxtag_id, ressemtags)
|
||||||
|
|
||||||
# Intègre le bilan des semestres taggués au zip final
|
# Intègre le bilan des semestres taggués au zip final
|
||||||
output = io.BytesIO()
|
output = io.BytesIO()
|
||||||
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
|
with pd.ExcelWriter( # pylint: disable=abstract-class-instantiated
|
||||||
output, engine="openpyxl"
|
output, engine="openpyxl"
|
||||||
) as writer:
|
) as writer:
|
||||||
for sem_tag in self.sems_tags.values():
|
for sem_tag in self.sxtags.values():
|
||||||
onglet = sem_tag.get_repr(verbose=False)
|
onglet = sem_tag.get_repr(verbose=False)
|
||||||
df = sem_tag.df_moyennes_et_classements()
|
df = sem_tag.df_moyennes_et_classements()
|
||||||
# écriture dans l'onglet
|
# écriture dans l'onglet
|
||||||
@ -200,11 +220,11 @@ class JuryPE(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _gen_xls_rcss_tags(self, zipfile: ZipFile):
|
def _gen_xls_rcss_tags(self, zipfile: ZipFile):
|
||||||
"""Génère les RCS tagguées des RCS, en calculant les moyennes et les classements par tag
|
"""Génère les RCS taggués (autres que ceux de type Sx), etc...
|
||||||
pour chacune.
|
en calculant les moyennes et les classements par tag pour chaque RCS.
|
||||||
|
|
||||||
Stocke le résultat dans self.rccs_tag, un dictionnaire de
|
Stocke le résultat dans self.rccs_tag, un dictionnaire de
|
||||||
la forme ``{nom_aggregat: {fid_terminal: SetTag(fid_terminal)} }``
|
la forme ``{nom_aggregat: {fid_terminal: RCSTag(fid_terminal)} }``
|
||||||
|
|
||||||
Pour rappel : Chaque RCS est identifié par un nom d'aggrégat et par un formsemestre terminal.
|
Pour rappel : Chaque RCS est identifié par un nom d'aggrégat et par un formsemestre terminal.
|
||||||
|
|
||||||
@ -213,19 +233,13 @@ class JuryPE(object):
|
|||||||
* combinaisons '3S' : S1+S2+S3 en prenant en compte tous les S3 qu'ont fréquenté les
|
* 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.
|
é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:
|
Args:
|
||||||
etudiants: Les données des étudiants
|
etudiants: Les données des étudiants
|
||||||
semestres_tag: Les semestres tag (pour lesquels des moyennes par tag ont été calculés)
|
semestres_tag: Les semestres tag (pour lesquels des moyennes par tag ont été calculés)
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Génère les moyennes des RCS de type Sx
|
# Génère les moyennes des RCS de type Sx
|
||||||
pe_affichage.pe_print("*** Calcule les moyennes des RCS de type Sx")
|
pe_affichage.pe_print("*** Calcule les moyennes des RCS")
|
||||||
|
|
||||||
self.rcss_tags = {}
|
self.rcss_tags = {}
|
||||||
for rcs_id, rcs in self.rcss_jury.rcss.items():
|
for rcs_id, rcs in self.rcss_jury.rcss.items():
|
||||||
@ -409,7 +423,7 @@ class JuryPE(object):
|
|||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
trajectoire = self.rcss_jury.suivi[etudid][aggregat]
|
trajectoire = self.rcss_jury.suivi[etudid][aggregat]
|
||||||
if trajectoire:
|
if trajectoire:
|
||||||
tid = trajectoire.rcs_id
|
tid = trajectoire.sxtag_id
|
||||||
trajectoire_tagguee = self.rcss_tags[tid]
|
trajectoire_tagguee = self.rcss_tags[tid]
|
||||||
if (
|
if (
|
||||||
tag in trajectoire_tagguee.moyennes_tags
|
tag in trajectoire_tagguee.moyennes_tags
|
||||||
@ -555,7 +569,7 @@ class JuryPE(object):
|
|||||||
# La trajectoire de l'étudiant sur l'aggrégat
|
# La trajectoire de l'étudiant sur l'aggrégat
|
||||||
trajectoire = self.rcss_jury.suivi[etudid][aggregat]
|
trajectoire = self.rcss_jury.suivi[etudid][aggregat]
|
||||||
if trajectoire:
|
if trajectoire:
|
||||||
trajectoire_tagguee = self.rcss_tags[trajectoire.rcs_id]
|
trajectoire_tagguee = self.rcss_tags[trajectoire.sxtag_id]
|
||||||
if tag in trajectoire_tagguee.moyennes_tags:
|
if tag in trajectoire_tagguee.moyennes_tags:
|
||||||
# L'interclassement
|
# L'interclassement
|
||||||
interclass = self.interclassements_taggues[aggregat]
|
interclass = self.interclassements_taggues[aggregat]
|
||||||
@ -581,9 +595,8 @@ class JuryPE(object):
|
|||||||
|
|
||||||
def get_formsemestres_etudiants(etudiants: EtudiantsJuryPE) -> dict:
|
def get_formsemestres_etudiants(etudiants: EtudiantsJuryPE) -> dict:
|
||||||
"""Ayant connaissance des étudiants dont il faut calculer les moyennes pour
|
"""Ayant connaissance des étudiants dont il faut calculer les moyennes pour
|
||||||
le jury PE (attribut `self.etudiant_ids) et de leur cursus (semestres
|
le jury PE (attribut `self.etudiant_ids) et de leurs trajectoires (semestres
|
||||||
parcourus),
|
parcourus), renvoie un dictionnaire ``{fid: FormSemestre(fid)}``
|
||||||
renvoie un dictionnaire ``{fid: FormSemestre(fid)}``
|
|
||||||
contenant l'ensemble des formsemestres de leurs cursus, dont il faudra calculer
|
contenant l'ensemble des formsemestres de leurs cursus, dont il faudra calculer
|
||||||
la moyenne.
|
la moyenne.
|
||||||
|
|
||||||
@ -592,44 +605,17 @@ def get_formsemestres_etudiants(etudiants: EtudiantsJuryPE) -> dict:
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Un dictionnaire de la forme `{fid: FormSemestre(fid)}`
|
Un dictionnaire de la forme `{fid: FormSemestre(fid)}`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
semestres = {}
|
semestres = {}
|
||||||
for etudid in etudiants.etudiants_ids:
|
for etudid in etudiants.etudiants_ids:
|
||||||
for cle in etudiants.cursus[etudid]:
|
for cle in etudiants.trajectoires[etudid]:
|
||||||
if cle.startswith("S"):
|
if cle.startswith("S"):
|
||||||
semestres = semestres | etudiants.cursus[etudid][cle]
|
semestres = semestres | etudiants.trajectoires[etudid][cle]
|
||||||
return semestres
|
return semestres
|
||||||
|
|
||||||
|
|
||||||
def compute_resultats_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 = ResSemTag(frmsem_id)
|
|
||||||
|
|
||||||
# Stocke le semestre taggué
|
|
||||||
semestres_tags[frmsem_id] = formsemestretag
|
|
||||||
|
|
||||||
return semestres_tags
|
|
||||||
|
|
||||||
|
|
||||||
def compute_interclassements(
|
def compute_interclassements(
|
||||||
|
102
app/pe/pe_rcs.py
102
app/pe/pe_rcs.py
@ -12,9 +12,9 @@ Created on 01-2024
|
|||||||
import app.pe.pe_comp as pe_comp
|
import app.pe.pe_comp as pe_comp
|
||||||
|
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
|
from app.pe import pe_sxtag
|
||||||
from app.pe.pe_etudiant import EtudiantsJuryPE, get_dernier_semestre_en_date
|
from app.pe.pe_etudiant import EtudiantsJuryPE, get_dernier_semestre_en_date
|
||||||
|
|
||||||
|
|
||||||
TYPES_RCS = {
|
TYPES_RCS = {
|
||||||
"S1": {
|
"S1": {
|
||||||
"aggregat": ["S1"],
|
"aggregat": ["S1"],
|
||||||
@ -81,11 +81,11 @@ TOUS_LES_SEMESTRES = [cle for cle in TYPES_RCS if cle.startswith("S")]
|
|||||||
|
|
||||||
|
|
||||||
class RCS:
|
class RCS:
|
||||||
"""Modélise un ensemble de semestres d'étudiants
|
"""Modélise un ensemble de semestres finals d'étudiants
|
||||||
associé à un type de regroupement cohérent de semestres
|
associé à un type de regroupement cohérent de semestres
|
||||||
donné (par ex: 'S2', '3S', '2A').
|
donné (par ex: 'S2', '3S', '2A').
|
||||||
|
|
||||||
Si le RCS est un semestre de type Si, stocke le (ou les)
|
Si le RCS est un semestre de type Si, stocke le
|
||||||
formsemestres de numéro i qu'ont suivi l'étudiant pour atteindre le Si
|
formsemestres de numéro i qu'ont suivi l'étudiant pour atteindre le Si
|
||||||
(en général 1 si personnes n'a redoublé, mais 2 s'il y a des redoublants)
|
(en général 1 si personnes n'a redoublé, mais 2 s'il y a des redoublants)
|
||||||
|
|
||||||
@ -104,38 +104,40 @@ class RCS:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, nom_rcs: str, semestre_final: FormSemestre):
|
def __init__(self, nom_rcs: str, semestre_final: FormSemestre):
|
||||||
self.nom = nom_rcs
|
self.nom: str = nom_rcs
|
||||||
"""Nom du RCS"""
|
"""Nom du RCS"""
|
||||||
|
|
||||||
self.formsemestre_final = semestre_final
|
self.formsemestre_final: FormSemestre = semestre_final
|
||||||
"""FormSemestre terminal du RCS"""
|
"""FormSemestre terminal du RCS"""
|
||||||
|
|
||||||
self.rcs_id = (nom_rcs, semestre_final.formsemestre_id)
|
self.rcs_id: (str, int) = (nom_rcs, semestre_final.formsemestre_id)
|
||||||
"""Identifiant du RCS sous forme (nom_rcs, id du semestre_terminal)"""
|
"""Identifiant du RCS sous forme (nom_rcs, id du semestre_terminal)"""
|
||||||
|
|
||||||
self.semestres_aggreges = {}
|
# self.semestres_aggreges: dict[int:FormSemestre] = {}
|
||||||
"""Semestres regroupés dans le RCS"""
|
# """Semestres regroupés dans le RCS"""
|
||||||
|
|
||||||
|
self.sxtags_aggreges: dict[(str, int): pe_sxtag.SxTag] = {}
|
||||||
|
"""Les SxTag aggrégés"""
|
||||||
|
|
||||||
def get_formsemestre_id_final(self):
|
def get_formsemestre_id_final(self):
|
||||||
"""Renvoie l'identifiant du formsemestre final du RCS"""
|
"""Renvoie l'identifiant du formsemestre final du RCS"""
|
||||||
return self.formsemestre_final.formsemestre_id
|
return self.formsemestre_final.formsemestre_id
|
||||||
|
|
||||||
def add_semestres_a_aggreger(self, semestres: dict[int:FormSemestre]):
|
def add_sxtags_a_aggreger(self, sxtags: dict[(str,int): pe_sxtag.SxTag]):
|
||||||
"""Ajout de semestres aux semestres à regrouper
|
"""Ajout des SxTag aux semestres à regrouper
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
semestres: Dictionnaire ``{fid: FormSemestre(fid)}`` à ajouter
|
sxtags: Dictionnaire ``{(str,fid): SxTag}`` à ajouter
|
||||||
"""
|
"""
|
||||||
self.semestres_aggreges = self.semestres_aggreges | semestres
|
self.sxtags_aggreges = self.sxtags_aggreges | sxtags
|
||||||
|
|
||||||
def get_repr(self, verbose=True) -> str:
|
def get_repr(self, verbose=True) -> str:
|
||||||
"""Représentation textuelle d'un RCS
|
"""Représentation textuelle d'un RCS
|
||||||
basé sur ses semestres aggrégés"""
|
basé sur ses sxtags aggrégés"""
|
||||||
|
|
||||||
noms = []
|
noms = []
|
||||||
for fid in self.semestres_aggreges:
|
for sxtag_id, sxtag in self.sxtags_aggreges.items():
|
||||||
semestre = self.semestres_aggreges[fid]
|
noms.append(f"S{sxtag.semestre_id}")
|
||||||
noms.append(f"S{semestre.semestre_id}({fid})")
|
|
||||||
noms = sorted(noms)
|
noms = sorted(noms)
|
||||||
title = f"""{self.nom} ({
|
title = f"""{self.nom} ({
|
||||||
self.formsemestre_final.formsemestre_id}) {self.formsemestre_final.date_fin.year}"""
|
self.formsemestre_final.formsemestre_id}) {self.formsemestre_final.date_fin.year}"""
|
||||||
@ -145,7 +147,7 @@ class RCS:
|
|||||||
|
|
||||||
|
|
||||||
class RCSsJuryPE:
|
class RCSsJuryPE:
|
||||||
"""Classe centralisant toutes les regroupements cohérents de
|
"""Classe centralisant tous les regroupements cohérents de
|
||||||
semestres (RCS) des étudiants à prendre en compte dans un jury PE
|
semestres (RCS) des étudiants à prendre en compte dans un jury PE
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -163,21 +165,24 @@ class RCSsJuryPE:
|
|||||||
"""Dictionnaire associant, pour chaque étudiant et pour chaque type de RCS,
|
"""Dictionnaire associant, pour chaque étudiant et pour chaque type de RCS,
|
||||||
son RCS : {etudid: {nom_RCS: RCS}}"""
|
son RCS : {etudid: {nom_RCS: RCS}}"""
|
||||||
|
|
||||||
def cree_rcss(self, etudiants: EtudiantsJuryPE):
|
def cree_rcss(self, etudiants: EtudiantsJuryPE, sxtags: dict[(str, int), pe_sxtag.SxTag]):
|
||||||
"""Créé tous les RCS, au regard du cursus des étudiants
|
"""Créé tous les RCS, au regard du cursus des étudiants
|
||||||
analysés + les mémorise dans les données de l'étudiant
|
analysés et des SxTag calculés.
|
||||||
|
|
||||||
|
Les mémorise dans les données de chaque étudiant.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
etudiants: Les étudiants à prendre en compte dans le Jury PE
|
etudiants: Les étudiants à prendre en compte dans le Jury PE
|
||||||
|
pe_sxtag: Les Sx taggués
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for nom_rcs in pe_comp.TOUS_LES_SEMESTRES + TOUS_LES_RCS_AVEC_PLUSIEURS_SEM:
|
for nom_rcs in pe_comp.TOUS_LES_SEMESTRES + TOUS_LES_RCS_AVEC_PLUSIEURS_SEM:
|
||||||
# L'aggrégat considéré (par ex: 3S=S1+S2+S3), son nom de son semestre
|
# L'aggrégat considéré (par ex: 3S=S1+S2+S3), son nom de son semestre
|
||||||
# terminal (par ex: S3) et son numéro (par ex: 3)
|
# terminal (par ex: S3) et son numéro (par ex: 3)
|
||||||
noms_semestre_de_aggregat = TYPES_RCS[nom_rcs]["aggregat"]
|
noms_semestre_de_aggregat = TYPES_RCS[nom_rcs]["aggregat"] # ["S1", "S2", "S3"]
|
||||||
nom_semestre_terminal = noms_semestre_de_aggregat[-1]
|
nom_semestre_terminal = noms_semestre_de_aggregat[-1] # "S3"
|
||||||
|
|
||||||
for etudid in etudiants.cursus:
|
for etudid in etudiants.trajectoires:
|
||||||
if etudid not in self.suivi:
|
if etudid not in self.suivi:
|
||||||
self.suivi[etudid] = {
|
self.suivi[etudid] = {
|
||||||
aggregat: None
|
aggregat: None
|
||||||
@ -188,54 +193,57 @@ class RCSsJuryPE:
|
|||||||
# 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
|
||||||
# (par ex: son dernier S3 en date)
|
# (par ex: son dernier S3 en date)
|
||||||
semestres = etudiants.cursus[etudid][nom_semestre_terminal]
|
semestres = etudiants.trajectoires[etudid][nom_semestre_terminal]
|
||||||
if semestres:
|
if semestres:
|
||||||
formsemestre_final = get_dernier_semestre_en_date(semestres)
|
formsemestre_final = get_dernier_semestre_en_date(semestres)
|
||||||
|
|
||||||
# Ajout ou récupération de la trajectoire
|
# Ajout ou récupération de la trajectoire
|
||||||
trajectoire_id = (nom_rcs, formsemestre_final.formsemestre_id)
|
rcs_id = (nom_rcs, formsemestre_final.formsemestre_id)
|
||||||
if trajectoire_id not in self.rcss:
|
if rcs_id not in self.rcss:
|
||||||
trajectoire = RCS(nom_rcs, formsemestre_final)
|
rcs = RCS(nom_rcs, formsemestre_final)
|
||||||
self.rcss[trajectoire_id] = trajectoire
|
self.rcss[rcs_id] = rcs
|
||||||
else:
|
else:
|
||||||
trajectoire = self.rcss[trajectoire_id]
|
rcs = self.rcss[rcs_id]
|
||||||
|
|
||||||
# La liste des semestres de l'étudiant à prendre en compte
|
# La liste des semestres de l'étudiant à prendre en compte
|
||||||
# pour cette trajectoire
|
# pour cette trajectoire
|
||||||
semestres_a_aggreger = get_rcs_etudiant(
|
semestres_a_aggreger = get_trajectoire_etudiant(
|
||||||
etudiants.cursus[etudid], formsemestre_final, nom_rcs
|
etudiants.trajectoires[etudid], formsemestre_final, nom_rcs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Extrait les sxtags correspondants aux semestres à aggréger
|
||||||
|
# (par ex. des 2 semestres S1(18)+S1(26) récupère le sxtag S1(26)
|
||||||
|
sxtags_a_aggreger = {}
|
||||||
|
semestres_tries = pe_comp.tri_semestres_par_rang(semestres_a_aggreger)
|
||||||
|
for rang in semestres_tries:
|
||||||
|
sems = semestres_tries[rang] # les 1 ou 2 semestres de même rang suivi
|
||||||
|
sxtag_id = pe_sxtag.get_sxtag_from_semestres(sems, sxtags)
|
||||||
|
if not sxtag_id:
|
||||||
|
raise ValueError(f"Il manque un sxtag pour {sems}")
|
||||||
|
sxtags_a_aggreger[sxtag_id] = sxtags[sxtag_id]
|
||||||
|
|
||||||
# Ajout des semestres à la trajectoire
|
# Ajout des semestres à la trajectoire
|
||||||
trajectoire.add_semestres_a_aggreger(semestres_a_aggreger)
|
rcs.add_sxtags_a_aggreger(sxtags_a_aggreger)
|
||||||
|
|
||||||
# Mémoire la trajectoire suivie par l'étudiant
|
# Mémoire la trajectoire suivie par l'étudiant
|
||||||
self.suivi[etudid][nom_rcs] = trajectoire
|
self.suivi[etudid][nom_rcs] = rcs
|
||||||
|
|
||||||
|
|
||||||
def get_rcs_etudiant(
|
def get_trajectoire_etudiant(
|
||||||
semestres: dict[int:FormSemestre], formsemestre_final: FormSemestre, nom_rcs: str
|
semestres: dict[int:FormSemestre], formsemestre_final: FormSemestre, nom_rcs: str
|
||||||
) -> dict[int, FormSemestre]:
|
) -> dict[int, FormSemestre]:
|
||||||
"""Ensemble des semestres parcourus par un étudiant, connaissant
|
"""Ensemble des semestres parcourus (trajectoire)
|
||||||
les semestres de son cursus,
|
par un étudiant dans le cadre
|
||||||
dans le cadre du RCS visé et ayant pour semestre terminal `formsemestre_final`.
|
d'un RCS de type Sx, iA ou iS et ayant pour semestre terminal `formsemestre_final`.
|
||||||
|
|
||||||
Si le RCS est de type "Si", limite les semestres à ceux de numéro i.
|
Par ex: pour un RCS "3S", dont le formsemestre_terminal est un S3, regroupe
|
||||||
Par ex: si formsemestre_terminal est un S3 et nom_agrregat "S3", ne prend en compte que les
|
le ou les S1 qu'il a suivi (1 ou 2 si redoublement) + le ou les S2 + le ou les S3.
|
||||||
semestres 3.
|
|
||||||
|
|
||||||
Si le RCS est de type "iA" ou "iS" (incluant plusieurs numéros de semestres), prend en
|
|
||||||
compte les dit numéros de semestres.
|
|
||||||
|
|
||||||
Par ex: si formsemestre_terminal est un S3, ensemble des S1,
|
|
||||||
S2, S3 suivi pour l'amener au S3 (il peut y avoir plusieurs S1,
|
|
||||||
ou S2, ou S3 s'il a redoublé).
|
|
||||||
|
|
||||||
Les semestres parcourus sont antérieurs (en terme de date de fin)
|
Les semestres parcourus sont antérieurs (en terme de date de fin)
|
||||||
au formsemestre_terminal.
|
au formsemestre_terminal.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cursus: Dictionnaire {fid: FormSemestre(fid)} donnant l'ensemble des semestres
|
cursus: Dictionnaire {fid: Formsemestre} donnant l'ensemble des semestres
|
||||||
dans lesquels l'étudiant a été inscrit
|
dans lesquels l'étudiant a été inscrit
|
||||||
formsemestre_final: le semestre final visé
|
formsemestre_final: le semestre final visé
|
||||||
nom_rcs: Nom du RCS visé
|
nom_rcs: Nom du RCS visé
|
||||||
|
@ -38,7 +38,7 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
|
|
||||||
from app.comp.res_sem import load_formsemestre_results
|
from app.comp.res_sem import load_formsemestre_results
|
||||||
from app.pe import pe_affichage
|
from app.pe import pe_affichage
|
||||||
from app.pe.pe_ressemtag import ResSemTag
|
from app.pe.pe_ressemtag import ResSemBUTTag
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from app.pe.pe_rcs import RCS
|
from app.pe.pe_rcs import RCS
|
||||||
@ -48,26 +48,25 @@ from app.pe.pe_moytag import MoyennesTag
|
|||||||
|
|
||||||
|
|
||||||
class RCSTag(TableTag):
|
class RCSTag(TableTag):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, rcs: RCS, semestres_taggues: dict[int, ResSemTag]
|
self, rcs: RCS, semestres_taggues: dict[int, ResSemBUTTag]
|
||||||
):
|
):
|
||||||
"""Calcule les moyennes par tag d'une combinaison de semestres
|
"""Calcule les moyennes par tag d'une combinaison de semestres
|
||||||
(RCS), pour extraire les classements par tag pour un
|
(RCS), pour extraire les classements par tag pour un
|
||||||
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
groupe d'étudiants donnés. Le groupe d'étudiants est formé par ceux ayant tous
|
||||||
participé au semestre terminal.
|
participé au semestre terminal.
|
||||||
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
rcs: Un RCS (identifié par un nom et l'id de son semestre terminal)
|
rcs: Un RCS (identifié par un nom et l'id de son semestre terminal)
|
||||||
semestres_taggues: Les données sur les semestres taggués
|
semestres_taggues: Les données sur les semestres taggués
|
||||||
"""
|
"""
|
||||||
TableTag.__init__(self)
|
TableTag.__init__(self)
|
||||||
|
|
||||||
|
self.rcs_id: tuple(str, int) = rcs.rcs_id
|
||||||
self.rcs_id = rcs.rcs_id
|
|
||||||
"""Identifiant du RCS taggué (identique au RCS sur lequel il s'appuie)"""
|
"""Identifiant du RCS taggué (identique au RCS sur lequel il s'appuie)"""
|
||||||
|
|
||||||
self.rcs = rcs
|
self.rcs: RCS = rcs
|
||||||
"""RCS associé au RCS taggué"""
|
"""RCS associé au RCS taggué"""
|
||||||
|
|
||||||
self.nom = self.get_repr()
|
self.nom = self.get_repr()
|
||||||
@ -82,20 +81,21 @@ class RCSTag(TableTag):
|
|||||||
self.semestres_aggreges = rcs.semestres_aggreges
|
self.semestres_aggreges = rcs.semestres_aggreges
|
||||||
"""Les semestres aggrégés"""
|
"""Les semestres aggrégés"""
|
||||||
|
|
||||||
self.semestres_tags_aggreges = {}
|
self.res_sems_tags = {}
|
||||||
"""Les semestres tags associés aux semestres aggrégés"""
|
"""Les semestres tags associés aux semestres aggrégés"""
|
||||||
for frmsem_id in self.semestres_aggreges:
|
try:
|
||||||
try:
|
for frmsem_id in self.semestres_aggreges:
|
||||||
self.semestres_tags_aggreges[frmsem_id] = semestres_taggues[frmsem_id]
|
self.res_sems_tags[frmsem_id] = semestres_taggues[frmsem_id]
|
||||||
except:
|
except:
|
||||||
raise ValueError("Semestres taggués manquants")
|
raise ValueError("Semestres taggués manquants")
|
||||||
|
|
||||||
"""Les étudiants (état civil + cursus connu)"""
|
# Les étudiants (etuds, états civils & etudis)
|
||||||
self.etuds = nt.etuds
|
self.add_etuds(nt.etuds)
|
||||||
|
|
||||||
# assert self.etuds == trajectoire.suivi # manque-t-il des étudiants ?
|
# Les compétences (extraites des ues de tous les semestres)
|
||||||
self.etats_civils = {etud.etudid: etud.nomprenom for etud in self.etuds}
|
self.ues = self.comp_ues(tag="but")
|
||||||
|
|
||||||
|
# Les tags
|
||||||
self.tags_sorted = self.do_taglist()
|
self.tags_sorted = self.do_taglist()
|
||||||
"""Tags extraits de tous les semestres"""
|
"""Tags extraits de tous les semestres"""
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ class RCSTag(TableTag):
|
|||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""Egalité de 2 RCS taggués sur la base de leur identifiant"""
|
"""Egalité de 2 RCS taggués sur la base de leur identifiant"""
|
||||||
return self.rcs_id == other.rcs_id
|
return self.rcs_id == other.sxtag_id
|
||||||
|
|
||||||
def get_repr(self, verbose=False) -> str:
|
def get_repr(self, verbose=False) -> str:
|
||||||
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||||
@ -132,7 +132,7 @@ class RCSTag(TableTag):
|
|||||||
# Index du cube (etudids -> dim 0, tags -> dim 1)
|
# Index du cube (etudids -> dim 0, tags -> dim 1)
|
||||||
etudids = [etud.etudid for etud in self.etuds]
|
etudids = [etud.etudid for etud in self.etuds]
|
||||||
tags = self.tags_sorted
|
tags = self.tags_sorted
|
||||||
semestres_id = list(self.semestres_tags_aggreges.keys())
|
semestres_id = list(self.res_sems_tags.keys())
|
||||||
|
|
||||||
dfs = {}
|
dfs = {}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ class RCSTag(TableTag):
|
|||||||
df = pd.DataFrame(np.nan, index=etudids, columns=tags)
|
df = pd.DataFrame(np.nan, index=etudids, columns=tags)
|
||||||
|
|
||||||
# Charge les notes du semestre tag
|
# Charge les notes du semestre tag
|
||||||
notes = self.semestres_tags_aggreges[frmsem_id].notes
|
notes = self.res_sems_tags[frmsem_id].notes
|
||||||
|
|
||||||
# Les étudiants & les tags commun au dataframe final et aux notes du semestre)
|
# Les étudiants & les tags commun au dataframe final et aux notes du semestre)
|
||||||
etudids_communs = df.index.intersection(notes.index)
|
etudids_communs = df.index.intersection(notes.index)
|
||||||
@ -172,8 +172,8 @@ class RCSTag(TableTag):
|
|||||||
Une liste de tags triés par ordre alphabétique
|
Une liste de tags triés par ordre alphabétique
|
||||||
"""
|
"""
|
||||||
tags = []
|
tags = []
|
||||||
for frmsem_id in self.semestres_tags_aggreges:
|
for frmsem_id in self.res_sems_tags:
|
||||||
tags.extend(self.semestres_tags_aggreges[frmsem_id].tags_sorted)
|
tags.extend(self.res_sems_tags[frmsem_id].tags_sorted)
|
||||||
pe_affichage.pe_print(f"* Tags : {', '.join(tags)}")
|
pe_affichage.pe_print(f"* Tags : {', '.join(tags)}")
|
||||||
return sorted(set(tags))
|
return sorted(set(tags))
|
||||||
|
|
||||||
|
@ -37,37 +37,38 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
"""
|
"""
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
import app.pe.pe_etudiant
|
|
||||||
from app import db, ScoValueError
|
from app import db, ScoValueError
|
||||||
from app import comp
|
from app import comp
|
||||||
|
from app.comp.res_but import ResultatsSemestreBUT
|
||||||
from app.comp.res_sem import load_formsemestre_results
|
from app.comp.res_sem import load_formsemestre_results
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.models.moduleimpls import ModuleImpl
|
from app.models.moduleimpls import ModuleImpl
|
||||||
import app.pe.pe_affichage as pe_affichage
|
import app.pe.pe_affichage as pe_affichage
|
||||||
import app.pe.pe_etudiant as pe_etudiant
|
import app.pe.pe_etudiant as pe_etudiant
|
||||||
from app.pe.pe_tabletags import TableTag
|
import app.pe.pe_tabletags as pe_tabletags
|
||||||
from app.pe.pe_moytag import MoyennesTag
|
from app.pe.pe_moytag import MoyennesTag
|
||||||
from app.scodoc import sco_tag_module
|
from app.scodoc import sco_tag_module
|
||||||
from app.scodoc.codes_cursus import UE_SPORT
|
from app.scodoc.codes_cursus import UE_SPORT
|
||||||
|
|
||||||
|
|
||||||
class ResSemTag(TableTag):
|
class ResSemBUTTag(ResultatsSemestreBUT, pe_tabletags.TableTag):
|
||||||
"""
|
"""
|
||||||
Un ResSemTag représente les résultats des étudiants à un semestre, en donnant
|
Un ResSemBUTTag représente les résultats des étudiants à un semestre, en donnant
|
||||||
accès aux moyennes par tag.
|
accès aux moyennes par tag.
|
||||||
Il s'appuie principalement sur FormSemestre et sur ResultatsSemestreBUT.
|
Il s'appuie principalement sur FormSemestre et sur ResultatsSemestreBUT.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, formsemestre_id: int):
|
def __init__(self, formsemestre: FormSemestre):
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
formsemestre_id: Identifiant du ``FormSemestre`` sur lequel il se base
|
formsemestre: le ``FormSemestre`` sur lequel il se base
|
||||||
"""
|
"""
|
||||||
TableTag.__init__(self)
|
ResultatsSemestreBUT.__init__(self, formsemestre)
|
||||||
|
pe_tabletags.TableTag.__init__(self)
|
||||||
|
|
||||||
# Le semestre
|
# Le semestre
|
||||||
self.formsemestre_id = formsemestre_id
|
# self.formsemestre_id = self.formsemestre.formsemestre_id
|
||||||
self.formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
# self.formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
|
|
||||||
# Le nom du res_semestre taggué
|
# Le nom du res_semestre taggué
|
||||||
self.nom = self.get_repr(verbose=True)
|
self.nom = self.get_repr(verbose=True)
|
||||||
@ -75,25 +76,14 @@ class ResSemTag(TableTag):
|
|||||||
pe_affichage.pe_print(f"--> Résultats de semestre taggués {self.nom}")
|
pe_affichage.pe_print(f"--> Résultats de semestre taggués {self.nom}")
|
||||||
|
|
||||||
# Les résultats du semestre
|
# Les résultats du semestre
|
||||||
self.nt = load_formsemestre_results(self.formsemestre)
|
# self.nt = load_formsemestre_results(self.formsemestre)
|
||||||
|
|
||||||
# Les étudiants (etuds, états civils & etudis)
|
# Les étudiants (etuds, états civils & etudis) ajouté
|
||||||
self.add_etuds(self.nt.etuds)
|
self.add_etuds(self.etuds)
|
||||||
|
|
||||||
# Les notes, les modules implémentés triés, les étudiants, les coeffs,
|
|
||||||
# récupérés notamment de py:mod:`res_but`
|
|
||||||
self.sem_cube = self.nt.sem_cube
|
|
||||||
self.modimpls_sorted = self.nt.formsemestre.modimpls_sorted
|
|
||||||
self.modimpl_coefs_df = self.nt.modimpl_coefs_df
|
|
||||||
|
|
||||||
# Les inscriptions aux modules
|
|
||||||
self.modimpl_inscr_df = self.nt.modimpl_inscr_df
|
|
||||||
|
|
||||||
# Les UEs (et les dispenses d'UE)
|
# Les UEs (et les dispenses d'UE)
|
||||||
self.ues = self.nt.ues
|
|
||||||
ues_hors_sport = [ue for ue in self.ues if ue.type != UE_SPORT]
|
ues_hors_sport = [ue for ue in self.ues if ue.type != UE_SPORT]
|
||||||
self.ues_inscr_parcours_df = self.nt.load_ues_inscr_parcours()
|
self.ues_inscr_parcours_df = self.load_ues_inscr_parcours()
|
||||||
self.dispense_ues = self.nt.dispense_ues
|
|
||||||
|
|
||||||
# Les tags personnalisés et auto:
|
# Les tags personnalisés et auto:
|
||||||
tags_dict = self._get_tags_dict()
|
tags_dict = self._get_tags_dict()
|
||||||
@ -124,7 +114,7 @@ class ResSemTag(TableTag):
|
|||||||
|
|
||||||
# Ajoute les moyennes par UEs (et donc par compétence) + la moyenne générale (but)
|
# Ajoute les moyennes par UEs (et donc par compétence) + la moyenne générale (but)
|
||||||
df_ues = pd.DataFrame(
|
df_ues = pd.DataFrame(
|
||||||
{ue.id: self.nt.etud_moy_ue[ue.id] for ue in ues_hors_sport},
|
{ue.id: self.etud_moy_ue[ue.id] for ue in ues_hors_sport},
|
||||||
index=self.etudids,
|
index=self.etudids,
|
||||||
)
|
)
|
||||||
# moy_ues = self.nt.etud_moy_ue[ue_id]
|
# moy_ues = self.nt.etud_moy_ue[ue_id]
|
||||||
@ -150,7 +140,7 @@ class ResSemTag(TableTag):
|
|||||||
def get_repr(self, verbose=False):
|
def get_repr(self, verbose=False):
|
||||||
"""Nom affiché pour le semestre taggué"""
|
"""Nom affiché pour le semestre taggué"""
|
||||||
if verbose:
|
if verbose:
|
||||||
return f"{self.formsemestre} ({self.formsemestre_id})"
|
return f"{self.formsemestre} ({self.formsemestre.formsemestre_id})"
|
||||||
else:
|
else:
|
||||||
return pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True)
|
return pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True)
|
||||||
|
|
||||||
@ -209,7 +199,7 @@ class ResSemTag(TableTag):
|
|||||||
dict_tags = {"personnalises": dict(), "auto": dict()}
|
dict_tags = {"personnalises": dict(), "auto": dict()}
|
||||||
# Les tags perso
|
# Les tags perso
|
||||||
dict_tags["personnalises"] = get_synthese_tags_personnalises_semestre(
|
dict_tags["personnalises"] = get_synthese_tags_personnalises_semestre(
|
||||||
self.nt.formsemestre
|
self.formsemestre
|
||||||
)
|
)
|
||||||
noms_tags_perso = sorted(list(set(dict_tags["personnalises"].keys())))
|
noms_tags_perso = sorted(list(set(dict_tags["personnalises"].keys())))
|
||||||
pe_affichage.pe_print(
|
pe_affichage.pe_print(
|
||||||
@ -256,26 +246,6 @@ class ResSemTag(TableTag):
|
|||||||
raise ScoValueError(message)
|
raise ScoValueError(message)
|
||||||
|
|
||||||
|
|
||||||
def get_moduleimpl(modimpl_id) -> dict:
|
|
||||||
"""Renvoie l'objet modimpl dont l'id est modimpl_id"""
|
|
||||||
modimpl = db.session.get(ModuleImpl, modimpl_id)
|
|
||||||
if modimpl:
|
|
||||||
return modimpl
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_moy_ue_from_nt(nt, etudid, modimpl_id) -> float:
|
|
||||||
"""Renvoie la moyenne de l'UE d'un etudid dans laquelle se trouve
|
|
||||||
le module de modimpl_id
|
|
||||||
"""
|
|
||||||
# ré-écrit
|
|
||||||
modimpl = get_moduleimpl(modimpl_id) # le module
|
|
||||||
ue_status = nt.get_etud_ue_status(etudid, modimpl.module.ue.id)
|
|
||||||
if ue_status is None:
|
|
||||||
return None
|
|
||||||
return ue_status["moy"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_synthese_tags_personnalises_semestre(formsemestre: FormSemestre):
|
def get_synthese_tags_personnalises_semestre(formsemestre: FormSemestre):
|
||||||
"""Etant données les implémentations des modules du semestre (modimpls),
|
"""Etant données les implémentations des modules du semestre (modimpls),
|
||||||
synthétise les tags renseignés dans le programme pédagogique &
|
synthétise les tags renseignés dans le programme pédagogique &
|
||||||
|
@ -37,87 +37,79 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from app.comp.res_sem import load_formsemestre_results
|
from app.comp.res_sem import load_formsemestre_results
|
||||||
from app.models import UniteEns
|
from app.models import UniteEns, FormSemestre
|
||||||
from app.pe import pe_affichage
|
from app.pe import pe_affichage
|
||||||
from app.pe.pe_ressemtag import ResSemTag
|
from app.pe.pe_ressemtag import ResSemBUTTag
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from app.pe.pe_rcs import RCS
|
|
||||||
|
|
||||||
from app.pe.pe_tabletags import TableTag
|
from app.pe.pe_tabletags import TableTag
|
||||||
from app.pe.pe_moytag import MoyennesTag
|
from app.pe.pe_moytag import MoyennesTag
|
||||||
|
|
||||||
|
|
||||||
class SemTag(TableTag):
|
class SxTag(TableTag):
|
||||||
def __init__(self, rcs: RCS, res_sems_tags: dict[int, ResSemTag]):
|
def __init__(self, sxtag_id: (int, int), ressembuttags: dict[int, ResSemBUTTag]):
|
||||||
"""Calcule les moyennes/classements par tag à un RCS d'un seul semestre
|
"""Calcule les moyennes/classements par tag d'un semestre de type 'Sx'
|
||||||
(ici semestre) de type 'Sx' (par ex. 'S1', 'S2', ...) :
|
(par ex. 'S1', 'S2', ...) :
|
||||||
|
|
||||||
* pour les étudiants non redoublants, ce sont les moyennes/classements
|
* pour les étudiants non redoublants, ce sont les moyennes/classements
|
||||||
du semestre suivi
|
du semestre suivi
|
||||||
* pour les étudiants redoublants, c'est une fusion des moyennes/classements
|
* pour les étudiants redoublants, c'est une fusion des moyennes/classements
|
||||||
suivis les différents 'Sx' (donné par dans le rcs)
|
dans les (2) 'Sx' qu'il a suivi
|
||||||
|
|
||||||
Les **tags considérés** sont uniquement ceux du dernier semestre du RCS
|
Un SxTag peut donc regrouper plusieurs semestres.
|
||||||
|
|
||||||
|
Un SxTag est identifié par un tuple (x, fid) où x est le numéro (semestre_id)
|
||||||
|
du semestre et fid le formsemestre_id du semestre final (le plus récent) du
|
||||||
|
regrouprement.
|
||||||
|
|
||||||
|
Les **tags**, les **UE** et les inscriptions aux UEs (pour les etudiants)
|
||||||
|
considérés sont uniquement ceux du semestre final.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
rcs: Un RCS (identifié par un nom et l'id de son semestre terminal)
|
sxtag_id: L'identifiant de SxTag
|
||||||
res_sems_tags: Les données sur les résultats des semestres taggués
|
ressembuttags: Un dictionnaire de la forme `{fid: ResSemBUTTag(fid)}` donnant
|
||||||
|
les semestres à regrouper et les résultats/moyennes par tag des
|
||||||
|
semestres
|
||||||
"""
|
"""
|
||||||
TableTag.__init__(self)
|
TableTag.__init__(self)
|
||||||
|
|
||||||
self.rcs_id = rcs.rcs_id
|
assert sxtag_id and len(sxtag_id) == 2 and sxtag_id in ressembuttags
|
||||||
"""Identifiant du RCS taggué (identique au RCS sur lequel il s'appuie)"""
|
|
||||||
|
|
||||||
self.rcs = rcs
|
self.sxtag_id: (int, int) = sxtag_id
|
||||||
"""RCS associé au RCS taggué"""
|
"""Identifiant du SxTag de la forme (semestre_id, fid_semestre_final)"""
|
||||||
|
|
||||||
assert self.rcs.nom.startswith(
|
self.ressembuttags = ressembuttags
|
||||||
"S"
|
"""Les ResSemBUTTags à regrouper dans le SxTag"""
|
||||||
), "Un SemTag ne peut être utilisé que pour un RCS de la forme Sx"
|
|
||||||
self.nom = self.get_repr()
|
|
||||||
"""Représentation textuelle du RCS taggué"""
|
|
||||||
|
|
||||||
# Les données du formsemestre_terminal
|
# Les données du semestre final
|
||||||
self.formsemestre_terminal = rcs.formsemestre_final
|
self.fid_final = sxtag_id[1]
|
||||||
"""Le formsemestre terminal"""
|
self.ressembuttag_final = ressembuttags[self.fid_final]
|
||||||
|
"""Le ResSemBUTTag final"""
|
||||||
# Les résultats du formsemestre terminal
|
|
||||||
nt = load_formsemestre_results(self.formsemestre_terminal)
|
|
||||||
|
|
||||||
self.semestres_aggreges = rcs.semestres_aggreges
|
|
||||||
"""Les semestres aggrégés"""
|
|
||||||
|
|
||||||
self.res_sems_tags = {}
|
|
||||||
"""Les résultats des semestres taggués (limités aux semestres aggrégés)"""
|
|
||||||
try:
|
|
||||||
for frmsem_id in self.semestres_aggreges:
|
|
||||||
self.res_sems_tags[frmsem_id] = res_sems_tags[frmsem_id]
|
|
||||||
except:
|
|
||||||
raise ValueError("Résultats des semestres taggués manquants")
|
|
||||||
|
|
||||||
# Les étudiants (etuds, états civils & etudis)
|
# Les étudiants (etuds, états civils & etudis)
|
||||||
self.add_etuds(nt.etuds)
|
self.etuds = ressembuttags[self.fid_final].etuds
|
||||||
|
self.add_etuds(self.etuds)
|
||||||
|
|
||||||
# Les tags
|
# Les tags
|
||||||
self.tags_sorted = self.comp_tags_list()
|
self.tags_sorted = self.ressembuttag_final.tags_sorted
|
||||||
"""Tags (extraits uniquement du semestre terminal de l'aggrégat)"""
|
"""Tags (extraits uniquement du semestre final)"""
|
||||||
|
pe_affichage.pe_print(f"* Tags : {', '.join(self.tags_sorted)}")
|
||||||
|
|
||||||
# Les UEs
|
# Les UE
|
||||||
self.ues = self.comp_ues(tag="but")
|
self.ues = self.ressembuttag_final.moyennes_tags["but"].ues
|
||||||
|
|
||||||
|
# Les acronymes des UE
|
||||||
self.acronymes_ues_sorted = sorted([ue.acronyme for ue in self.ues.values()])
|
self.acronymes_ues_sorted = sorted([ue.acronyme for ue in self.ues.values()])
|
||||||
"""UEs extraites du semestre terminal de l'aggrégat (avec
|
|
||||||
check de concordance sur les UE des semestres_aggrégés)"""
|
|
||||||
|
|
||||||
# Les inscriptions aux UEs
|
# Les inscriptions des étudiants aux UEs
|
||||||
self.ues_inscr_parcours_df = self.comp_ues_inscr_parcours(tag="but")
|
# => ne conserve que les UEs du semestre final (pour les redoublants)
|
||||||
"""Les inscriptions aux UEs (extraites uniquement du semestre terminal)"""
|
self.ues_inscr_parcours_df = self.ressembuttag_final.moyennes_tags["but"].ues_inscr_parcours_df
|
||||||
|
|
||||||
self.moyennes_tags: dict[str, MoyennesTag] = {}
|
|
||||||
"""Moyennes/classements par tag (qu'ils soient personnalisés ou automatiques)"""
|
|
||||||
|
|
||||||
|
# Les moyennes par tag
|
||||||
self.moyennes_tags: dict[str, pd.DataFrame] = {}
|
self.moyennes_tags: dict[str, pd.DataFrame] = {}
|
||||||
"""Les notes aux UEs dans différents tags"""
|
"""Les notes aux UEs dans différents tags"""
|
||||||
|
|
||||||
# Masque des inscriptions
|
# Masque des inscriptions
|
||||||
inscr_mask = self.ues_inscr_parcours_df.to_numpy()
|
inscr_mask = self.ues_inscr_parcours_df.to_numpy()
|
||||||
for tag in self.tags_sorted:
|
for tag in self.tags_sorted:
|
||||||
@ -132,19 +124,19 @@ class SemTag(TableTag):
|
|||||||
inscr_mask,
|
inscr_mask,
|
||||||
)
|
)
|
||||||
# Les moyennes
|
# Les moyennes
|
||||||
self.moyennes_tags[tag] = MoyennesTag(tag,
|
self.moyennes_tags[tag] = MoyennesTag(
|
||||||
self.ues,
|
tag, self.ues, moys_ues, self.ues_inscr_parcours_df
|
||||||
moys_ues,
|
)
|
||||||
self.ues_inscr_parcours_df)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""Egalité de 2 RCS taggués sur la base de leur identifiant"""
|
"""Egalité de 2 SxTag sur la base de leur identifiant"""
|
||||||
return self.rcs_id == other.rcs_id
|
return self.sxtag_id == other.sxtag_id
|
||||||
|
|
||||||
def get_repr(self, verbose=False) -> str:
|
def get_repr(self, verbose=False) -> str:
|
||||||
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||||
est basée)"""
|
est basée)"""
|
||||||
return self.rcs.get_repr(verbose=verbose)
|
affichage = str(fid) for fid in self.res
|
||||||
|
return f"S{sxtag_id[0]}Tag ({'+'.join()})"
|
||||||
|
|
||||||
def compute_notes_ues_cube(self, tag, acronymes_ues_sorted):
|
def compute_notes_ues_cube(self, tag, acronymes_ues_sorted):
|
||||||
"""Construit le cube de notes des UEs (etudid x accronyme_ue x semestre_aggregé)
|
"""Construit le cube de notes des UEs (etudid x accronyme_ue x semestre_aggregé)
|
||||||
@ -153,7 +145,7 @@ class SemTag(TableTag):
|
|||||||
# Index du cube (etudids -> dim 0, ues -> dim 1, semestres -> dim2)
|
# Index du cube (etudids -> dim 0, ues -> dim 1, semestres -> dim2)
|
||||||
etudids = [etud.etudid for etud in self.etuds]
|
etudids = [etud.etudid for etud in self.etuds]
|
||||||
# acronymes_ues = sorted([ue.acronyme for ue in self.ues.values()])
|
# acronymes_ues = sorted([ue.acronyme for ue in self.ues.values()])
|
||||||
semestres_id = list(self.res_sems_tags.keys())
|
semestres_id = list(self.ressembuttags.keys())
|
||||||
|
|
||||||
dfs = {}
|
dfs = {}
|
||||||
|
|
||||||
@ -162,7 +154,7 @@ class SemTag(TableTag):
|
|||||||
df = pd.DataFrame(np.nan, index=etudids, columns=acronymes_ues_sorted)
|
df = pd.DataFrame(np.nan, index=etudids, columns=acronymes_ues_sorted)
|
||||||
|
|
||||||
# Charge les notes du semestre tag
|
# Charge les notes du semestre tag
|
||||||
sem_tag = self.res_sems_tags[frmsem_id]
|
sem_tag = self.ressembuttags[frmsem_id]
|
||||||
moys_tag = sem_tag.moyennes_tags[tag]
|
moys_tag = sem_tag.moyennes_tags[tag]
|
||||||
notes = moys_tag.notes_ues # dataframe etudids x ues
|
notes = moys_tag.notes_ues # dataframe etudids x ues
|
||||||
acronymes_ues_sem = list(
|
acronymes_ues_sem = list(
|
||||||
@ -192,43 +184,6 @@ class SemTag(TableTag):
|
|||||||
etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1)
|
etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1)
|
||||||
return etudids_x_ues_x_semestres
|
return etudids_x_ues_x_semestres
|
||||||
|
|
||||||
def comp_tags_list(self) -> list[str]:
|
|
||||||
"""Récupère les tag du semestre taggué associé au semestre final du RCS
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Une liste de tags triés par ordre alphabétique
|
|
||||||
"""
|
|
||||||
tags = []
|
|
||||||
dernier_frmid = self.formsemestre_terminal.formsemestre_id
|
|
||||||
dernier_semestre_tag = self.res_sems_tags[dernier_frmid]
|
|
||||||
tags = dernier_semestre_tag.tags_sorted
|
|
||||||
pe_affichage.pe_print(f"* Tags : {', '.join(tags)}")
|
|
||||||
return tags
|
|
||||||
|
|
||||||
def comp_ues(self, tag="but") -> dict[int, UniteEns]:
|
|
||||||
"""Récupère les UEs à aggréger, en s'appuyant sur la moyenne générale
|
|
||||||
(tag but) du semestre final du RCS
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Un dictionnaire donnant les UEs
|
|
||||||
"""
|
|
||||||
dernier_frmid = self.formsemestre_terminal.formsemestre_id
|
|
||||||
dernier_semestre_tag = self.res_sems_tags[dernier_frmid]
|
|
||||||
moy_tag = dernier_semestre_tag.moyennes_tags[tag]
|
|
||||||
return moy_tag.ues # les UEs
|
|
||||||
|
|
||||||
def comp_ues_inscr_parcours(self, tag="but") -> pd.DataFrame:
|
|
||||||
"""Récupère les informations d'inscription des étudiants aux UEs : ne
|
|
||||||
conserve que les UEs du semestre terminal (pour les redoublants)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Un dataFrame etudids x UE indiquant si un étudiant est inscrit à une UE
|
|
||||||
"""
|
|
||||||
dernier_frmid = self.formsemestre_terminal.formsemestre_id
|
|
||||||
dernier_semestre_tag = self.res_sems_tags[dernier_frmid]
|
|
||||||
moy_tag = dernier_semestre_tag.moyennes_tags[tag]
|
|
||||||
return moy_tag.ues_inscr_parcours_df
|
|
||||||
|
|
||||||
|
|
||||||
def compute_notes_ues(
|
def compute_notes_ues(
|
||||||
set_cube: np.array,
|
set_cube: np.array,
|
||||||
@ -261,8 +216,8 @@ def compute_notes_ues(
|
|||||||
mask = ~np.isnan(set_cube)
|
mask = ~np.isnan(set_cube)
|
||||||
|
|
||||||
# Entrées à garder dans le cube en fonction du mask d'inscription
|
# Entrées à garder dans le cube en fonction du mask d'inscription
|
||||||
inscr_mask_3D = np.stack([inscr_mask]*nb_semestres, axis=-1)
|
inscr_mask_3D = np.stack([inscr_mask] * nb_semestres, axis=-1)
|
||||||
set_cube = set_cube*inscr_mask_3D
|
set_cube = set_cube * inscr_mask_3D
|
||||||
|
|
||||||
# Enlève les NaN du cube pour les entrées manquantes : NaN -> -1.0
|
# Enlève les NaN du cube pour les entrées manquantes : NaN -> -1.0
|
||||||
set_cube_no_nan = np.nan_to_num(set_cube, nan=-1.0)
|
set_cube_no_nan = np.nan_to_num(set_cube, nan=-1.0)
|
||||||
@ -284,3 +239,16 @@ def compute_notes_ues(
|
|||||||
etud_moy_tag_df.fillna(np.nan)
|
etud_moy_tag_df.fillna(np.nan)
|
||||||
|
|
||||||
return etud_moy_tag_df
|
return etud_moy_tag_df
|
||||||
|
|
||||||
|
|
||||||
|
def get_sxtag_from_semestres(
|
||||||
|
formsemestres: dict[int:FormSemestre], sxtags: dict[(str, int):SxTag]
|
||||||
|
) -> (str, int):
|
||||||
|
"""Partant d'un dictionnaire de SxTags, renvoie l'identifiant (str, fid) du
|
||||||
|
sxtag correspondant aux semestres de formsemestres.
|
||||||
|
(Utilisé pour transformer une trajectoire d'étudiants (par ex. S1+S2+S1+S2+S3)
|
||||||
|
en une suite de sxtags (S1+S2+S3)
|
||||||
|
"""
|
||||||
|
for sxtag_id, sxtag in sxtags:
|
||||||
|
if set(formsemestres.keys()) == set(sxtag.semestres_aggreges.keys()):
|
||||||
|
return sxtag_id
|
@ -50,11 +50,11 @@ class TableTag(object):
|
|||||||
SemestreTag, TrajectoireTag, AggregatInterclassTag
|
SemestreTag, TrajectoireTag, AggregatInterclassTag
|
||||||
"""
|
"""
|
||||||
# Les étudiants
|
# Les étudiants
|
||||||
self.etuds: list[Identite] = None # A venir
|
# self.etuds: list[Identite] = None # A venir
|
||||||
"""Les étudiants"""
|
"""Les étudiants"""
|
||||||
self.etats_civils: dict[int, Identite] = None
|
# self.etats_civils: dict[int, Identite] = None
|
||||||
"""Les états civils"""
|
"""Les états civils"""
|
||||||
self.etudids: list[int] = None
|
# self.etudids: list[int] = None
|
||||||
"""Les etudids"""
|
"""Les etudids"""
|
||||||
|
|
||||||
def add_etuds(self, etuds: list[Identite]):
|
def add_etuds(self, etuds: list[Identite]):
|
||||||
@ -63,7 +63,7 @@ class TableTag(object):
|
|||||||
Args:
|
Args:
|
||||||
etuds: la liste des identités de l'étudiant
|
etuds: la liste des identités de l'étudiant
|
||||||
"""
|
"""
|
||||||
self.etuds = etuds
|
# self.etuds = etuds
|
||||||
self.etats_civils = {etud.etudid: etud.etat_civil for etud in self.etuds}
|
self.etats_civils = {etud.etudid: etud.etat_civil for etud in self.etuds}
|
||||||
self.etudids = list(self.etats_civils.keys())
|
self.etudids = list(self.etats_civils.keys())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user