from app.models.etudiants import Identite from app.models.formsemestre import FormSemestre from app.models.assiduites import Assiduite import app.scodoc.sco_utils as scu from datetime import datetime, date, time, timedelta # TOTALK: Réfléchir sur le fractionnement d'une assiduite prolongée def get_assiduites_stats( assiduites: Assiduite, metric: str = "all", filter: dict[str, object] = {} ) -> Assiduite: if filter != {}: for key in filter: if key == "etat": assiduites = filter_by_etat(assiduites, filter[key]) elif key == "date_fin": assiduites = filter_by_date(assiduites, filter[key], sup=False) elif key == "date_debut": assiduites = filter_by_date(assiduites, filter[key], sup=True) elif key == "moduleimpl_id": assiduites = filter_by_module_impl(assiduites, filter[key]) elif key == "formsemestre": assiduites = filter_by_formsemstre(assiduites, filter[key]) count: dict = get_count(assiduites) metrics: list[str] = metric.split(",") output: dict = {} for key in count: if key in metrics: output[key] = count[key] return output if output != {} else count def get_count(assiduites: Assiduite) -> dict[str, int or float]: output: dict[str, int or float] = {} output["compte"] = assiduites.count() output["heure"] = 0.0 output["journee"] = 0 output["demi"] = 0 all_assiduites: list[Assiduite] = assiduites.order_by(Assiduite.date_debut).all() current_day: date = None current_time: str = None MIDNIGHT: time = time(hour=0) NOON: time = time(hour=12) time_check = lambda d: (MIDNIGHT <= d.time() <= NOON) for ass in all_assiduites: delta: timedelta = ass.date_fin - ass.date_debut output["heure"] += delta.total_seconds() / 3600 ass_time: str = time_check(ass.date_debut) if current_day != ass.date_debut.date(): current_day = ass.date_debut.date() current_time = ass_time output["demi"] += 1 output["journee"] += 1 if current_time != ass_time: current_time = ass_time output["demi"] += 1 output["heure"] = round(output["heure"], 2) return output def filter_by_etat(assiduites: Assiduite, etat: str) -> Assiduite: """ Filtrage d'une collection d'assiduites en fonction de leur état """ etats: list[str] = list(etat.split(",")) etats = [scu.ETATS_ASSIDUITE.get(e, -1) for e in etats] return assiduites.filter(Assiduite.etat.in_(etats)) def filter_by_date( assiduites: Assiduite, date: datetime, sup: bool = True ) -> Assiduite: """ Filtrage d'une collection d'assiduites en fonction d'une date Sup == True -> les assiduites doivent débuter après 'date'\n Sup == False -> les assiduites doivent finir avant 'date' """ if date.tzinfo is None: first_assiduite: Assiduite = assiduites.first() if first_assiduite is not None: date: datetime = date.replace(tzinfo=first_assiduite.date_debut.tzinfo) if sup: return assiduites.filter(Assiduite.date_debut >= date) else: return assiduites.filter(Assiduite.date_fin <= date) def filter_by_module_impl( assiduites: Assiduite, module_impl_id: int or None ) -> Assiduite: """ Filtrage d'une collection d'assiduites en fonction de l'ID du module_impl """ return assiduites.filter(Assiduite.moduleimpl_id == module_impl_id) def filter_by_formsemstre(assiduites: Assiduite, formsemestre: FormSemestre): """ Filtrage d'une collection d'assiduites en fonction d'un formsemestre """ if formsemestre is None: return assiduites.filter(False) assiduites = assiduites.filter( Identite.query.filter_by(id=Assiduite.etudid).first() in formsemestre.etuds.all() ) assiduites = assiduites.filter(Assiduite.date_debut >= formsemestre.date_debut) return assiduites.filter(Assiduite.date_fin <= formsemestre.date_fin)