forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -170,6 +170,7 @@ TOUS_LES_SEMESTRES = PARCOURS[AGGREGAT_DIPLOMANT]["aggregat"]
|
||||
TOUS_LES_AGGREGATS = [cle for cle in PARCOURS.keys() if not cle.startswith("S")]
|
||||
TOUS_LES_PARCOURS = list(PARCOURS.keys())
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def calcul_age(born: datetime.date) -> int:
|
||||
"""Calcule l'age connaissant la date de naissance ``born``. (L'age est calculé
|
||||
@ -185,11 +186,7 @@ def calcul_age(born: datetime.date) -> int:
|
||||
return None
|
||||
|
||||
today = datetime.date.today()
|
||||
return (
|
||||
today.year
|
||||
- born.year
|
||||
- ((today.month, today.day) < (born.month, born.day))
|
||||
)
|
||||
return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
|
||||
|
||||
|
||||
def remove_accents(input_unicode_str):
|
||||
@ -286,7 +283,9 @@ def add_pe_stuff_to_zip(zipfile, ziproot):
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def get_annee_diplome_semestre(sem_base, nbre_sem_formation=6) -> int:
|
||||
def get_annee_diplome_semestre(
|
||||
sem_base: FormSemestre | dict, nbre_sem_formation: int = 6
|
||||
) -> int:
|
||||
"""Pour un semestre ``sem_base`` donné (supposé être un semestre d'une formation BUT à 6 semestres)
|
||||
et connaissant le numéro du semestre, ses dates de début et de fin du semestre, prédit l'année à laquelle
|
||||
sera remis le diplôme BUT des étudiants qui y sont scolarisés
|
||||
@ -339,7 +338,9 @@ def get_annee_diplome_semestre(sem_base, nbre_sem_formation=6) -> int:
|
||||
return annee_fin + nbreAnRestant + increment
|
||||
|
||||
|
||||
def get_cosemestres_diplomants(annee_diplome: int, formation_id: int) -> list:
|
||||
def get_cosemestres_diplomants(
|
||||
annee_diplome: int, formation_id: int
|
||||
) -> dict[int, FormSemestre]:
|
||||
"""Ensemble des cosemestres donnant lieu à diplomation à l'``annee_diplome``
|
||||
et s'intégrant à la formation donnée par son ``formation_id``.
|
||||
|
||||
@ -381,4 +382,3 @@ def get_cosemestres_diplomants(annee_diplome: int, formation_id: int) -> list:
|
||||
cosemestres[fid] = cosem
|
||||
|
||||
return cosemestres
|
||||
|
||||
|
@ -66,11 +66,15 @@ class EtudiantsJuryPE:
|
||||
|
||||
"Les etudids des étudiants dont il faut calculer les moyennes/classements (même si d'éventuels abandons)"
|
||||
self.etudiants_ids = {}
|
||||
"""Les étudiants inscrits dans les co-semestres (ceux du jury mais aussi d'autres ayant été réorientés ou ayant abandonnés)"""
|
||||
|
||||
self.cosemestres: dict[int, FormSemestre] = None
|
||||
"Les cosemestres donnant lieu à même année de diplome"
|
||||
|
||||
def find_etudiants(self, formation_id: int):
|
||||
"""Liste des étudiants à prendre en compte dans le jury PE, en les recherchant
|
||||
de manière automatique par rapport à leur année de diplomation ``annee_diplome``
|
||||
dans la formation ``formation_id``.
|
||||
dans la formation ``formation_id``. XXX TODO voir si on garde formation_id qui n'est pas utilisé ici
|
||||
|
||||
Les données obtenues sont stockées dans les attributs de EtudiantsJuryPE.
|
||||
|
||||
@ -79,21 +83,18 @@ class EtudiantsJuryPE:
|
||||
|
||||
*Remarque* : ex: JuryPE.get_etudiants_in_jury()
|
||||
"""
|
||||
"Les cosemestres donnant lieu à même année de diplome"
|
||||
cosemestres = pe_comp.get_cosemestres_diplomants(self.annee_diplome, None)
|
||||
self.cosemestres = cosemestres
|
||||
pe_comp.pe_print(
|
||||
"1) Recherche des coSemestres -> %d trouvés" % len(cosemestres)
|
||||
)
|
||||
|
||||
"""Les étudiants inscrits dans les co-semestres (ceux du jury mais aussi d'autres ayant été réorientés ou ayant abandonnés)"""
|
||||
pe_comp.pe_print(f"1) Recherche des coSemestres -> {len(cosemestres)} trouvés")
|
||||
|
||||
pe_comp.pe_print("2) Liste des étudiants dans les différents co-semestres")
|
||||
self.etudiants_ids = get_etudiants_dans_semestres(cosemestres)
|
||||
pe_comp.pe_print(
|
||||
" => %d étudiants trouvés dans les cosemestres" % len(self.etudiants_ids)
|
||||
)
|
||||
|
||||
"""Analyse des parcours étudiants pour déterminer leur année effective de diplome
|
||||
"""Analyse des parcours étudiants pour déterminer leur année effective de diplome
|
||||
avec prise en compte des redoublements, des abandons, ...."""
|
||||
pe_comp.pe_print("3) Analyse des parcours individuels des étudiants")
|
||||
|
||||
@ -142,9 +143,13 @@ class EtudiantsJuryPE:
|
||||
+ ", ".join([str(fid) for fid in list(self.formsemestres_jury_ids)])
|
||||
)
|
||||
# Les abandons :
|
||||
self.abandons = sorted([self.cursus[etudid]['nom']
|
||||
for etudid in self.cursus if etudid not in self.diplomes_ids])
|
||||
|
||||
self.abandons = sorted(
|
||||
[
|
||||
self.cursus[etudid]["nom"]
|
||||
for etudid in self.cursus
|
||||
if etudid not in self.diplomes_ids
|
||||
]
|
||||
)
|
||||
|
||||
def get_etudiants_diplomes(self) -> dict[int, Identite]:
|
||||
"""Identités des étudiants (sous forme d'un dictionnaire `{etudid: Identite(etudid)}`
|
||||
@ -198,10 +203,12 @@ class EtudiantsJuryPE:
|
||||
"etudid": etudid, # les infos sur l'étudiant
|
||||
"etat_civil": identite.etat_civil, # Ajout à la table jury
|
||||
"nom": identite.nom,
|
||||
"entree": formsemestres[-1].date_debut.year, # La date d'entrée à l'IUT
|
||||
"entree": formsemestres[-1].date_debut.year, # La date d'entrée à l'IUT
|
||||
"diplome": annee_diplome(identite), # Le date prévisionnelle de son diplôme
|
||||
"formsemestres": semestres_etudiant, # les semestres de l'étudiant
|
||||
"nb_semestres": len(semestres_etudiant), # le nombre de semestres de l'étudiant
|
||||
"nb_semestres": len(
|
||||
semestres_etudiant
|
||||
), # le nombre de semestres de l'étudiant
|
||||
"abandon": False, # va être traité en dessous
|
||||
}
|
||||
|
||||
@ -250,7 +257,6 @@ class EtudiantsJuryPE:
|
||||
} # les semestres de n°i de l'étudiant
|
||||
self.cursus[etudid][nom_sem] = semestres_i
|
||||
|
||||
|
||||
def get_trajectoire(self, etudid: int, formsemestre_final: FormSemestre):
|
||||
"""Ensemble des semestres parcourus par
|
||||
un étudiant pour l'amener à un semestre terminal.
|
||||
@ -372,7 +378,7 @@ class EtudiantsJuryPE:
|
||||
"""
|
||||
nbres_semestres = []
|
||||
for etudid in self.diplomes_ids:
|
||||
nbres_semestres.append( self.cursus[etudid]["nb_semestres"] )
|
||||
nbres_semestres.append(self.cursus[etudid]["nb_semestres"])
|
||||
return max(nbres_semestres)
|
||||
|
||||
|
||||
@ -417,10 +423,7 @@ def annee_diplome(identite: Identite) -> int:
|
||||
formsemestres = identite.get_formsemestres()
|
||||
if formsemestres:
|
||||
return max(
|
||||
[
|
||||
pe_comp.get_annee_diplome_semestre(sem_base)
|
||||
for sem_base in formsemestres
|
||||
]
|
||||
[pe_comp.get_annee_diplome_semestre(sem_base) for sem_base in formsemestres]
|
||||
)
|
||||
else:
|
||||
return None
|
||||
@ -502,8 +505,6 @@ def arret_de_formation(identite: Identite, cosemestres: list[FormSemestre]) -> b
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]) -> FormSemestre:
|
||||
"""Renvoie le dernier semestre en **date de fin** d'un dictionnaire
|
||||
de semestres (potentiellement non trié) de la forme ``{fid: FormSemestre(fid)}``.
|
||||
@ -523,5 +524,3 @@ def get_dernier_semestre_en_date(semestres: dict[int, FormSemestre]) -> FormSeme
|
||||
return dernier_semestre
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
from app.pe.pe_tabletags import TableTag
|
||||
from app.pe.pe_etudiant import EtudiantsJuryPE
|
||||
from app.pe.pe_trajectoire import Trajectoire, TrajectoiresJuryPE
|
||||
@ -27,16 +26,14 @@ class AggregatInterclasseTag(TableTag):
|
||||
trajectoires_jury_pe: TrajectoiresJuryPE,
|
||||
trajectoires_taggues: dict[tuple, TrajectoireTag],
|
||||
):
|
||||
""""""
|
||||
"""Table nommée au nom de l'aggrégat (par ex: 3S"""
|
||||
# Table nommée au nom de l'aggrégat (par ex: 3S)
|
||||
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)""" # TODO
|
||||
self.diplomes_ids = etudiants.etudiants_diplomes
|
||||
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
|
||||
self.trajectoires: dict[int, Trajectoire] = {}
|
||||
for trajectoire_id in trajectoires_jury_pe.trajectoires:
|
||||
trajectoire = trajectoires_jury_pe.trajectoires[trajectoire_id]
|
||||
@ -49,8 +46,8 @@ class AggregatInterclasseTag(TableTag):
|
||||
trajectoire_id
|
||||
]
|
||||
|
||||
"""Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
||||
celles associées aux diplomés"""
|
||||
# Les trajectoires suivies par les étudiants du jury, en ne gardant que
|
||||
# celles associées aux diplomés
|
||||
self.suivi: dict[int, Trajectoire] = {}
|
||||
for etudid in self.diplomes_ids:
|
||||
self.suivi[etudid] = trajectoires_jury_pe.suivi[etudid][nom_aggregat]
|
||||
@ -58,10 +55,10 @@ class AggregatInterclasseTag(TableTag):
|
||||
"""Les tags"""
|
||||
self.tags_sorted = self.do_taglist()
|
||||
|
||||
"""Construit la matrice de notes"""
|
||||
# Construit la matrice de notes
|
||||
self.notes = self.compute_notes_matrice()
|
||||
|
||||
"""Synthétise les moyennes/classements par tag"""
|
||||
# Synthétise les moyennes/classements par tag
|
||||
self.moyennes_tags = {}
|
||||
for tag in self.tags_sorted:
|
||||
moy_gen_tag = self.notes[tag]
|
||||
@ -79,7 +76,6 @@ class AggregatInterclasseTag(TableTag):
|
||||
"""Une représentation textuelle"""
|
||||
return f"Aggrégat {self.nom}"
|
||||
|
||||
|
||||
def do_taglist(self):
|
||||
"""Synthétise les tags à partir des trajectoires_tagguées
|
||||
|
||||
@ -87,39 +83,35 @@ class AggregatInterclasseTag(TableTag):
|
||||
Une liste de tags triés par ordre alphabétique
|
||||
"""
|
||||
tags = []
|
||||
for trajectoire_id in self.trajectoires_taggues:
|
||||
trajectoire = self.trajectoires_taggues[trajectoire_id]
|
||||
for trajectoire in self.trajectoires_taggues.values():
|
||||
tags.extend(trajectoire.tags_sorted)
|
||||
return sorted(set(tags))
|
||||
|
||||
|
||||
def compute_notes_matrice(self):
|
||||
"""Construit la matrice de notes (etudid x tags)
|
||||
retraçant les moyennes obtenues par les étudiants dans les semestres associés à
|
||||
l'aggrégat (une trajectoire ayant pour numéro de semestre final, celui de l'aggrégat).
|
||||
"""
|
||||
nb_tags = len(self.tags_sorted)
|
||||
nb_etudiants = len(self.diplomes_ids)
|
||||
# nb_tags = len(self.tags_sorted) unused ?
|
||||
# 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 = list(self.diplomes_ids)
|
||||
tags = self.tags_sorted
|
||||
|
||||
"""Partant d'un dataframe vierge"""
|
||||
# Partant d'un dataframe vierge
|
||||
df = pd.DataFrame(np.nan, index=etudids, columns=tags)
|
||||
|
||||
for trajectoire_id in self.trajectoires_taggues:
|
||||
"""Charge les moyennes par tag de la trajectoire tagguée"""
|
||||
notes = self.trajectoires_taggues[trajectoire_id].notes
|
||||
for notes in self.trajectoires_taggues.values():
|
||||
# Charge les moyennes par tag de la trajectoire tagguée
|
||||
|
||||
"""Etudiants/Tags communs entre la trajectoire_tagguée et les données interclassées"""
|
||||
# Etudiants/Tags communs entre la trajectoire_tagguée et les données interclassées
|
||||
etudids_communs = df.index.intersection(notes.index)
|
||||
tags_communs = df.columns.intersection(notes.columns)
|
||||
|
||||
"""Injecte les notes par tag"""
|
||||
# Injecte les notes par tag
|
||||
df.loc[etudids_communs, tags_communs] = notes.loc[
|
||||
etudids_communs, tags_communs
|
||||
]
|
||||
|
||||
return df
|
||||
|
||||
|
@ -107,13 +107,14 @@ class JuryPE(object):
|
||||
self.formation_id = formation_id
|
||||
|
||||
"Un zip où ranger les fichiers générés"
|
||||
self.nom_export_zip = "Jury_PE_%s" % self.diplome
|
||||
self.nom_export_zip = f"Jury_PE_{self.diplome}"
|
||||
self.zipdata = io.BytesIO()
|
||||
self.zipfile = ZipFile(self.zipdata, "w")
|
||||
|
||||
"""Chargement des étudiants à prendre en compte dans le jury"""
|
||||
pe_comp.pe_print(
|
||||
f"*** Recherche et chargement des étudiants diplômés en {self.diplome} pour la formation {self.formation_id}"
|
||||
f"""*** Recherche et chargement des étudiants diplômés en {
|
||||
self.diplome} pour la formation {self.formation_id}"""
|
||||
)
|
||||
self.etudiants = EtudiantsJuryPE(self.diplome) # Les infos sur les étudiants
|
||||
self.etudiants.find_etudiants(self.formation_id)
|
||||
@ -133,7 +134,7 @@ class JuryPE(object):
|
||||
filename, formsemestretag.str_tagtable(), path="details_semestres"
|
||||
)
|
||||
|
||||
"""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)
|
||||
"""
|
||||
pe_comp.pe_print(
|
||||
@ -197,7 +198,7 @@ class JuryPE(object):
|
||||
open(filename, "rb").read(),
|
||||
)
|
||||
|
||||
"""Fin !!!! Tada :)"""
|
||||
# Fin !!!! Tada :)
|
||||
|
||||
def add_file_to_zip(self, filename: str, data, path=""):
|
||||
"""Add a file to our zip
|
||||
@ -256,7 +257,7 @@ class JuryPE(object):
|
||||
|
||||
etudids = list(self.diplomes_ids)
|
||||
|
||||
"""Récupération des données des étudiants"""
|
||||
# Récupération des données des étudiants
|
||||
administratif = {}
|
||||
nbre_semestres_max = self.etudiants.nbre_etapes_max_diplomes()
|
||||
|
||||
@ -279,11 +280,11 @@ class JuryPE(object):
|
||||
etapes = pe_affichage.etapes_du_cursus(formsemestres, nbre_semestres_max)
|
||||
administratif[etudid] |= etapes
|
||||
|
||||
"""Construction du dataframe"""
|
||||
# Construction du dataframe
|
||||
df = pd.DataFrame.from_dict(administratif, orient="index")
|
||||
|
||||
"""Tri par nom/prénom"""
|
||||
df.sort_values(by=["Nom", "Prenom"], inplace = True)
|
||||
# Tri par nom/prénom
|
||||
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
||||
return df
|
||||
|
||||
def df_tag(self, tag):
|
||||
@ -348,11 +349,11 @@ class JuryPE(object):
|
||||
}
|
||||
|
||||
# Fin de l'aggrégat
|
||||
"""Construction du dataFrame"""
|
||||
# Construction du dataFrame
|
||||
df = pd.DataFrame.from_dict(donnees, orient="index")
|
||||
|
||||
"""Tri par nom/prénom"""
|
||||
df.sort_values(by=["Nom", "Prenom"], inplace = True)
|
||||
# Tri par nom/prénom
|
||||
df.sort_values(by=["Nom", "Prenom"], inplace=True)
|
||||
return df
|
||||
|
||||
def table_syntheseJury(self, mode="singlesheet"): # was str_syntheseJury
|
||||
@ -400,10 +401,10 @@ def compute_semestres_tag(etudiants: EtudiantsJuryPE) -> dict:
|
||||
|
||||
pe_comp.pe_print(f" --> Semestre taggué {nom} sur la base de {formsemestre}")
|
||||
|
||||
"""Créé le semestre_tag et exécute les calculs de moyennes"""
|
||||
# Crée le semestre_tag et exécute les calculs de moyennes
|
||||
formsemestretag = SemestreTag(nom, frmsem_id)
|
||||
|
||||
"""Stocke le semestre taggué"""
|
||||
# Stocke le semestre taggué
|
||||
semestres_tags[frmsem_id] = formsemestretag
|
||||
|
||||
return semestres_tags
|
||||
|
@ -63,7 +63,7 @@ def _pe_view_sem_recap_form(formsemestre_id):
|
||||
target="_blank" rel="noopener noreferrer">
|
||||
voir la documentation
|
||||
</a>.
|
||||
Cette fonction (en Scodoc9) n'est prévue que pour le BUT.
|
||||
Cette fonction (en Scodoc9) n'est prévue que pour le BUT.
|
||||
<br>
|
||||
Rendez-vous donc sur un semestre de BUT.
|
||||
</p>
|
||||
|
Loading…
Reference in New Issue
Block a user