runner-ai-intelligence / src /domain /training /weekly_snapshot.py
avfranco's picture
HF Space deploy snapshot (minimal allow-list)
d64fd55
from typing import Optional
from pydantic import BaseModel, Field
from datetime import datetime, date
import uuid
class WeeklySnapshot(BaseModel):
"""Aggregated weekly snapshot for long-term tracking."""
id: uuid.UUID = Field(default_factory=uuid.uuid4)
runner_id: uuid.UUID
week_start_date: date
total_distance_km: float
avg_pace_sec_per_km: float
avg_hr: Optional[float] = None
max_hr: Optional[float] = None
total_time_sec: int
run_count: int
consistency_score: float
performance_brief: Optional[str] = None
performance_focus: Optional[str] = None
brief_generated_at: Optional[datetime] = None
brief_source_hash: Optional[str] = None
structure_status: Optional[dict] = None
charts: Optional[dict] = None
created_at: datetime = Field(default_factory=datetime.now)
@classmethod
def from_metrics(
cls,
runner_id: uuid.UUID,
week_start_date: date,
total_distance_km: float,
avg_pace_sec_per_km: float,
total_time_sec: int,
run_count: int,
consistency_score: float,
avg_hr: Optional[float] = None,
max_hr: Optional[float] = None,
performance_brief: Optional[str] = None,
brief_generated_at: Optional[datetime] = None,
brief_source_hash: Optional[str] = None,
structure_status: Optional[dict] = None,
charts: Optional[dict] = None,
) -> "WeeklySnapshot":
"""Construct a snapshot from aggregated weekly metrics."""
return cls(
runner_id=runner_id,
week_start_date=week_start_date,
total_distance_km=total_distance_km,
avg_pace_sec_per_km=avg_pace_sec_per_km,
total_time_sec=total_time_sec,
run_count=run_count,
consistency_score=consistency_score,
avg_hr=avg_hr,
max_hr=max_hr,
performance_brief=performance_brief,
brief_generated_at=brief_generated_at,
brief_source_hash=brief_source_hash,
structure_status=structure_status,
charts=charts,
)