forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -9,7 +9,7 @@
|
||||
from flask import g
|
||||
from app import log
|
||||
|
||||
PE_DEBUG = False
|
||||
PE_DEBUG = True
|
||||
|
||||
|
||||
# On stocke les logs PE dans g.scodoc_pe_log
|
||||
@ -22,14 +22,15 @@ def pe_start_log() -> list[str]:
|
||||
|
||||
def pe_print(*a):
|
||||
"Log (or print in PE_DEBUG mode) and store in g"
|
||||
if PE_DEBUG:
|
||||
msg = " ".join(a)
|
||||
print(msg)
|
||||
else:
|
||||
lines = getattr(g, "scodoc_pe_log")
|
||||
if lines is None:
|
||||
lines = pe_start_log()
|
||||
msg = " ".join(a)
|
||||
lines.append(msg)
|
||||
if PE_DEBUG:
|
||||
print(msg)
|
||||
else:
|
||||
log(msg)
|
||||
|
||||
|
||||
|
@ -76,6 +76,7 @@ class SemestreTag(TableTag):
|
||||
# Les étudiants
|
||||
self.etuds = self.nt.etuds
|
||||
self.etudiants = {etud.etudid: etud.etat_civil for etud in self.etuds}
|
||||
self.etudids = list(self.etudiants.keys())
|
||||
|
||||
# Les notes, les modules implémentés triés, les étudiants, les coeffs,
|
||||
# récupérés notamment de py:mod:`res_but`
|
||||
@ -94,12 +95,12 @@ class SemestreTag(TableTag):
|
||||
tags_personnalises = get_synthese_tags_personnalises_semestre(
|
||||
self.nt.formsemestre
|
||||
)
|
||||
noms_tags_perso = list(set(tags_personnalises.keys()))
|
||||
noms_tags_perso = sorted(list(set(tags_personnalises.keys())))
|
||||
|
||||
## Déduit des compétences
|
||||
dict_ues_competences = get_noms_competences_from_ues(self.nt.formsemestre)
|
||||
noms_tags_comp = list(set(dict_ues_competences.values()))
|
||||
noms_tags_auto = ["but"] + noms_tags_comp
|
||||
# dict_ues_competences = get_noms_competences_from_ues(self.nt.formsemestre)
|
||||
# noms_tags_comp = list(set(dict_ues_competences.values()))
|
||||
noms_tags_auto = ["but"] # + noms_tags_comp
|
||||
self.tags = noms_tags_perso + noms_tags_auto
|
||||
"""Tags du semestre taggué"""
|
||||
|
||||
@ -122,23 +123,31 @@ class SemestreTag(TableTag):
|
||||
"""
|
||||
raise ScoValueError(message)
|
||||
|
||||
ues_hors_sport = [ue for ue in self.ues if ue.type != UE_SPORT]
|
||||
|
||||
# Calcul des moyennes & les classements de chaque étudiant à chaque tag
|
||||
self.moyennes_tags = {}
|
||||
|
||||
for tag in tags_personnalises:
|
||||
# pe_affichage.pe_print(f" -> Traitement du tag {tag}")
|
||||
moy_gen_tag = self.compute_moyenne_tag(tag, tags_personnalises)
|
||||
self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_tag)
|
||||
moy_ues_tag = self.compute_moy_ues_tag(tag, tags_personnalises)
|
||||
moy_gen_tag = self.compute_moy_gen_tag(moy_ues_tag)
|
||||
|
||||
# Ajoute les moyennes générales de BUT pour le semestre considéré
|
||||
self.moyennes_tags[tag] = MoyenneTag(
|
||||
tag, ues_hors_sport, moy_ues_tag, moy_gen_tag
|
||||
)
|
||||
|
||||
# Ajoute les d'UE moyennes générales de BUT pour le semestre considéré
|
||||
# moy_gen_but = self.nt.etud_moy_gen
|
||||
# self.moyennes_tags["but"] = MoyenneTag("but", [], None, moy_gen_but, )
|
||||
|
||||
# Ajoute les moyennes par UEs (et donc par compétence) + la moyenne générale (but)
|
||||
df_ues = pd.DataFrame({ue.id: self.nt.etud_moy_ue[ue.id] for ue in ues_hors_sport},
|
||||
index = self.etudids)
|
||||
# moy_ues = self.nt.etud_moy_ue[ue_id]
|
||||
moy_gen_but = self.nt.etud_moy_gen
|
||||
self.moyennes_tags["but"] = MoyenneTag("but", moy_gen_but)
|
||||
self.moyennes_tags["but"] = MoyenneTag("but", ues_hors_sport, df_ues, moy_gen_but)
|
||||
|
||||
# Ajoute les moyennes par compétence
|
||||
for ue_id, competence in dict_ues_competences.items():
|
||||
if competence not in self.moyennes_tags:
|
||||
moy_ue = self.nt.etud_moy_ue[ue_id]
|
||||
self.moyennes_tags[competence] = MoyenneTag(competence, moy_ue)
|
||||
|
||||
self.tags_sorted = self.get_all_tags()
|
||||
"""Tags (personnalisés+compétences) par ordre alphabétique"""
|
||||
@ -156,8 +165,8 @@ class SemestreTag(TableTag):
|
||||
"""Nom affiché pour le semestre taggué"""
|
||||
return app.pe.pe_etudiant.nom_semestre_etape(self.formsemestre, avec_fid=True)
|
||||
|
||||
def compute_moyenne_tag(self, tag: str, tags_infos: dict) -> pd.Series:
|
||||
"""Calcule la moyenne des étudiants pour le tag indiqué,
|
||||
def compute_moy_ues_tag(self, tag: str, tags_infos: dict) -> pd.Series:
|
||||
"""Calcule la moyenne par UE des étudiants pour le tag indiqué,
|
||||
pour ce SemestreTag, en ayant connaissance des informations sur
|
||||
les tags (dictionnaire donnant les coeff de repondération)
|
||||
|
||||
@ -199,7 +208,12 @@ class SemestreTag(TableTag):
|
||||
self.dispense_ues,
|
||||
block=self.formsemestre.block_moyennes,
|
||||
)
|
||||
return moyennes_ues_tag
|
||||
|
||||
def compute_moy_gen_tag(self, moy_ues_tag: pd.DataFrame) -> pd.Series:
|
||||
"""Calcule la moyenne générale (toutes UE confondus)
|
||||
pour le tag considéré, en les pondérant par les crédits ECTS.
|
||||
"""
|
||||
# Les ects
|
||||
ects = self.ues_inscr_parcours_df.fillna(0.0) * [
|
||||
ue.ects for ue in self.ues if ue.type != UE_SPORT
|
||||
@ -207,7 +221,7 @@ class SemestreTag(TableTag):
|
||||
|
||||
# Calcule la moyenne générale dans le semestre (pondérée par le ECTS)
|
||||
moy_gen_tag = comp.moy_sem.compute_sem_moys_apc_using_ects(
|
||||
moyennes_ues_tag,
|
||||
moy_ues_tag,
|
||||
ects,
|
||||
formation_id=self.formsemestre.formation_id,
|
||||
skip_empty_ues=True,
|
||||
|
@ -42,19 +42,27 @@ import numpy as np
|
||||
|
||||
from app import ScoValueError
|
||||
from app.comp.moy_sem import comp_ranks_series
|
||||
from app.models import UniteEns
|
||||
from app.pe import pe_affichage
|
||||
from app.pe.pe_affichage import SANS_NOTE
|
||||
from app.scodoc import sco_utils as scu
|
||||
import pandas as pd
|
||||
|
||||
from app.scodoc.codes_cursus import UE_SPORT
|
||||
|
||||
TAGS_RESERVES = ["but"]
|
||||
|
||||
|
||||
class MoyenneTag:
|
||||
def __init__(self, tag: str, notes: pd.Series):
|
||||
def __init__(
|
||||
self,
|
||||
tag: str,
|
||||
ues: list[UniteEns],
|
||||
notes_ues: pd.DataFrame,
|
||||
notes_gen: pd.Series,
|
||||
):
|
||||
"""Classe centralisant la synthèse des moyennes/classements d'une série
|
||||
d'étudiants à un tag donné, en stockant un dictionnaire :
|
||||
d'étudiants à un tag donné, en stockant :
|
||||
|
||||
``
|
||||
{
|
||||
@ -69,16 +77,26 @@ class MoyenneTag:
|
||||
|
||||
Args:
|
||||
tag: Un tag
|
||||
note: Une série de notes (moyenne) sous forme d'un pd.Series()
|
||||
ues: La liste des UEs ayant servie au calcul de la moyenne
|
||||
notes_ues: Les moyennes (etudid x ues) aux différentes UEs et pour le tag
|
||||
notes_gen: Une série de notes (moyenne) sous forme d'un pd.Series() (toutes UEs confondues)
|
||||
"""
|
||||
self.tag = tag
|
||||
"""Le tag associé à la moyenne"""
|
||||
self.etudids = list(notes.index) # calcul à venir
|
||||
self.etudids = list(notes_gen.index) # calcul à venir
|
||||
"""Les id des étudiants"""
|
||||
self.inscrits_ids = notes[notes.notnull()].index.to_list()
|
||||
"""Les id des étudiants dont la moyenne est non nulle"""
|
||||
self.df: pd.DataFrame = self.comp_moy_et_stat(notes)
|
||||
"""Le dataframe retraçant les moyennes/classements/statistiques"""
|
||||
self.ues: list[UniteEns] = ues
|
||||
"""Les UEs sur lesquelles sont calculées les moyennes"""
|
||||
self.df_ues: dict[int, pd.DataFrame] = {}
|
||||
"""Les dataframes retraçant les moyennes/classements/statistiques des étudiants aux UEs"""
|
||||
for ue in self.ues: # if ue.type != UE_SPORT:
|
||||
notes = notes_ues[ue.id]
|
||||
self.df_ues[ue.id] = self.comp_moy_et_stat(notes)
|
||||
|
||||
self.inscrits_ids = notes_gen[notes_gen.notnull()].index.to_list()
|
||||
"""Les id des étudiants dont la moyenne générale est non nulle"""
|
||||
self.df_gen: pd.DataFrame = self.comp_moy_et_stat(notes_gen)
|
||||
"""Le dataframe retraçant les moyennes/classements/statistiques général"""
|
||||
self.synthese = self.to_dict()
|
||||
"""La synthèse (dictionnaire) des notes/classements/statistiques"""
|
||||
|
||||
@ -88,7 +106,8 @@ class MoyenneTag:
|
||||
|
||||
def comp_moy_et_stat(self, notes: pd.Series) -> dict:
|
||||
"""Calcule et structure les données nécessaires au PE pour une série
|
||||
de notes (souvent une moyenne par tag) dans un dictionnaire spécifique.
|
||||
de notes (pouvant être une moyenne d'un tag à une UE ou une moyenne générale
|
||||
d'un tag) dans un dictionnaire spécifique.
|
||||
|
||||
Partant des notes, sont calculés les classements (en ne tenant compte
|
||||
que des notes non nulles).
|
||||
@ -121,64 +140,65 @@ class MoyenneTag:
|
||||
|
||||
# Les nb d'étudiants & nb d'inscrits
|
||||
df["nb_etuds"] = len(self.etudids)
|
||||
df.loc[self.inscrits_ids, "nb_inscrits"] = len(self.inscrits_ids)
|
||||
# Les étudiants dont la note n'est pas nulle
|
||||
inscrits_ids = notes[notes.notnull()].index.to_list()
|
||||
df.loc[inscrits_ids, "nb_inscrits"] = len(inscrits_ids)
|
||||
|
||||
# Le classement des inscrits
|
||||
notes_non_nulles = notes[self.inscrits_ids]
|
||||
notes_non_nulles = notes[inscrits_ids]
|
||||
(class_str, class_int) = comp_ranks_series(notes_non_nulles)
|
||||
df.loc[self.inscrits_ids, "classement"] = class_int
|
||||
df.loc[inscrits_ids, "classement"] = class_int
|
||||
|
||||
# Le rang (classement/nb_inscrit)
|
||||
df["rang"] = df["rang"].astype(str)
|
||||
df.loc[self.inscrits_ids, "rang"] = (
|
||||
df.loc[self.inscrits_ids, "classement"].astype(int).astype(str)
|
||||
df.loc[inscrits_ids, "rang"] = (
|
||||
df.loc[inscrits_ids, "classement"].astype(int).astype(str)
|
||||
+ "/"
|
||||
+ df.loc[self.inscrits_ids, "nb_inscrits"].astype(int).astype(str)
|
||||
+ df.loc[inscrits_ids, "nb_inscrits"].astype(int).astype(str)
|
||||
)
|
||||
|
||||
# Les stat (des inscrits)
|
||||
df.loc[self.inscrits_ids, "min"] = notes.min()
|
||||
df.loc[self.inscrits_ids, "max"] = notes.max()
|
||||
df.loc[self.inscrits_ids, "moy"] = notes.mean()
|
||||
df.loc[inscrits_ids, "min"] = notes.min()
|
||||
df.loc[inscrits_ids, "max"] = notes.max()
|
||||
df.loc[inscrits_ids, "moy"] = notes.mean()
|
||||
|
||||
return df
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Renvoie un dictionnaire de synthèse des moyennes/classements/statistiques"""
|
||||
synthese = {
|
||||
"notes": self.df["note"],
|
||||
"classements": self.df["classement"],
|
||||
"min": self.df["min"].mean(),
|
||||
"max": self.df["max"].mean(),
|
||||
"moy": self.df["moy"].mean(),
|
||||
"nb_inscrits": self.df["nb_inscrits"].mean(),
|
||||
"notes": self.df_gen["note"],
|
||||
"classements": self.df_gen["classement"],
|
||||
"min": self.df_gen["min"].mean(),
|
||||
"max": self.df_gen["max"].mean(),
|
||||
"moy": self.df_gen["moy"].mean(),
|
||||
"nb_inscrits": self.df_gen["nb_inscrits"].mean(),
|
||||
}
|
||||
return synthese
|
||||
|
||||
def get_notes(self):
|
||||
"""Série des notes, arrondies à 2 chiffres après la virgule"""
|
||||
return self.df["note"].round(2)
|
||||
return self.df_gen["note"].round(2)
|
||||
|
||||
def get_rangs_inscrits(self) -> pd.Series:
|
||||
"""Série des rangs classement/nbre_inscrit"""
|
||||
return self.df["rang"]
|
||||
return self.df_gen["rang"]
|
||||
|
||||
def get_min(self) -> pd.Series:
|
||||
"""Série des min"""
|
||||
return self.df["min"].round(2)
|
||||
return self.df_gen["min"].round(2)
|
||||
|
||||
def get_max(self) -> pd.Series:
|
||||
"""Série des max"""
|
||||
return self.df["max"].round(2)
|
||||
return self.df_gen["max"].round(2)
|
||||
|
||||
def get_moy(self) -> pd.Series:
|
||||
"""Série des moy"""
|
||||
return self.df["moy"].round(2)
|
||||
|
||||
return self.df_gen["moy"].round(2)
|
||||
|
||||
def get_note_for_df(self, etudid: int):
|
||||
"""Note d'un étudiant donné par son etudid"""
|
||||
return round(self.df["note"].loc[etudid], 2)
|
||||
return round(self.df_gen["note"].loc[etudid], 2)
|
||||
|
||||
def get_min_for_df(self) -> float:
|
||||
"""Min renseigné pour affichage dans un df"""
|
||||
@ -195,7 +215,7 @@ class MoyenneTag:
|
||||
def get_class_for_df(self, etudid: int) -> str:
|
||||
"""Classement ramené au nombre d'inscrits,
|
||||
pour un étudiant donné par son etudid"""
|
||||
classement = self.df["rang"].loc[etudid]
|
||||
classement = self.df_gen["rang"].loc[etudid]
|
||||
if not pd.isna(classement):
|
||||
return classement
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user