from __future__ import annotations from typing import Any DEFAULT_MET = 5.0 MET_BY_KEYWORD: list[tuple[str, float]] = [ ("триатлон", 10.0), ("марафон", 9.8), ("бег", 9.8), ("running", 9.8), ("run", 9.0), ("плаван", 8.0), ("swim", 8.0), ("велосипед", 7.5), ("cycling", 7.5), ("вел", 7.5), ("hiit", 8.0), ("кроссфит", 8.0), ("силов", 6.0), ("strength", 6.0), ("зал", 5.5), ("gym", 5.5), ("йога", 3.0), ("yoga", 3.0), ("ходьб", 3.5), ("walk", 3.5), ("прогул", 3.5), ] def infer_met(workout: dict[str, Any]) -> float | None: explicit = workout.get("met") if explicit is not None: return float(explicit) activity_type = str(workout.get("activity_type") or "").lower() title = str(workout.get("title") or "").lower() notes = str(workout.get("notes") or "").lower() haystack = f"{activity_type} {title} {notes}" for keyword, met in MET_BY_KEYWORD: if keyword in haystack: return met return None def estimate_workout_active_kcal(workout: dict[str, Any], *, weight_kg: float) -> float: active = workout.get("active_calories") if active is not None: return round(float(active), 1) duration = workout.get("duration_min") if not duration: return 0.0 met = infer_met(workout) if met is None: return 0.0 hours = float(duration) / 60.0 return round(met * weight_kg * hours, 1) def workouts_kcal_total(workouts: list[dict[str, Any]], *, weight_kg: float) -> float: if not workouts: return 0.0 return round(sum(estimate_workout_active_kcal(w, weight_kg=weight_kg) for w in workouts), 1)