58 lines
1.6 KiB
Python
58 lines
1.6 KiB
Python
def minutes_to_str(minutes: int) -> str:
|
|
sign = "-" if minutes < 0 else ""
|
|
minutes = abs(minutes)
|
|
return f"{sign}{minutes // 60}h{minutes % 60:02d}"
|
|
|
|
|
|
_REFERENCE_MINUTES = {
|
|
"WORK": 465,
|
|
"TT": 465,
|
|
"FORMATION": 465,
|
|
"GARDE": 600,
|
|
"ASTREINTE": 0,
|
|
"RTT": 0,
|
|
"CONGE": 0,
|
|
"MALADE": 0,
|
|
"FERIE": 0,
|
|
}
|
|
|
|
|
|
def work_minutes_reference(day_type: str) -> int:
|
|
return _REFERENCE_MINUTES.get(day_type, 465)
|
|
|
|
|
|
def week_balance_minutes(actual_minutes: int, reference_minutes: int) -> int:
|
|
return actual_minutes - reference_minutes
|
|
|
|
|
|
import statistics as _stats
|
|
|
|
|
|
def monthly_stats(entries: list) -> dict:
|
|
"""
|
|
Calcule médiane journalière et médiane hebdomadaire (semaines ISO)
|
|
pour un groupe d'entrées. Les absences (total_minutes=0) sont incluses.
|
|
"""
|
|
if not entries:
|
|
return {"median_daily_min": 0, "median_weekly_min": 0}
|
|
|
|
daily = [e.total_minutes() for e in entries]
|
|
median_daily = int(_stats.median(daily))
|
|
|
|
weekly: dict[tuple, int] = {}
|
|
for e in entries:
|
|
key = e.date.isocalendar()[:2] # (year, isoweek)
|
|
weekly[key] = weekly.get(key, 0) + e.total_minutes()
|
|
|
|
median_weekly = int(_stats.median(weekly.values()))
|
|
|
|
return {"median_daily_min": median_daily, "median_weekly_min": median_weekly}
|
|
|
|
|
|
def count_day_types(entries: list) -> dict[str, int]:
|
|
"""Retourne un dict {day_type: count} pour une liste d'entrées, sans les zéros."""
|
|
counts: dict[str, int] = {}
|
|
for entry in entries:
|
|
counts[entry.day_type] = counts.get(entry.day_type, 0) + 1
|
|
return counts
|