Spaces:
Running
Running
| from typing import Optional, Literal | |
| from pydantic import BaseModel | |
| from datetime import date | |
| from enum import Enum | |
| class TrainingPhase(str, Enum): | |
| BASE = "base" | |
| BUILD = "build" | |
| PEAK = "peak" | |
| RECOVERY = "recovery" | |
| PLATEAU = "plateau" | |
| class RunnerPositioning(BaseModel): | |
| """ | |
| Domain model for representing a runner's positioning assessment. | |
| This is a deterministic interpretation of snapshots, trends, and goals. | |
| """ | |
| week_start_date: date | |
| # Core signals | |
| health_signal: Literal["RECOVERING", "OPTIMAL", "OVERREACHING", "UNKNOWN"] | |
| position_status: Literal["AHEAD", "ON_TRACK", "FALLING_BEHIND", "UNKNOWN"] | |
| goal_trajectory: Literal["IMPROVING", "STABLE", "DECLINING", "UNKNOWN"] | |
| recommended_focus: Literal["RECOVERY", "CONSISTENCY", "INTENSITY", "MAINTENANCE"] | |
| training_phase: TrainingPhase | |
| # Metadata | |
| comparison_available: bool = False | |
| signal_strength: float = 1.0 | |
| llm_used: bool = False | |
| summary: Optional[str] = None | |
| def compute( | |
| cls, | |
| week_start: date, | |
| total_distance: float, | |
| target_distance: Optional[float], | |
| consistency_score: float, | |
| pace_delta: float, | |
| hr_delta: Optional[float], | |
| distance_delta_pct: float, | |
| comparison_available: bool, | |
| training_phase: TrainingPhase = TrainingPhase.BASE | |
| ) -> "RunnerPositioning": | |
| """ | |
| Pure deterministic logic to compute positioning signals. | |
| No imports from outside the domain layer allowed. | |
| """ | |
| # ... (logic remains same, passed as arg from service) | |
| # 1. Health Signal | |
| if distance_delta_pct > 20.0 or (hr_delta is not None and hr_delta > 5.0): | |
| health_signal = "OVERREACHING" | |
| elif consistency_score < 0.6: | |
| health_signal = "RECOVERING" | |
| elif consistency_score > 0.8 and (hr_delta is None or hr_delta <= 0): | |
| health_signal = "OPTIMAL" | |
| else: | |
| health_signal = "UNKNOWN" | |
| # 2. Position Status (relative to goal distance) | |
| if target_distance and target_distance > 0: | |
| diff_pct = (total_distance - target_distance) / target_distance | |
| if diff_pct > 0.1: | |
| position_status = "AHEAD" | |
| elif diff_pct < -0.1: | |
| position_status = "FALLING_BEHIND" | |
| else: | |
| position_status = "ON_TRACK" | |
| else: | |
| position_status = "UNKNOWN" | |
| # 3. Goal Trajectory | |
| if pace_delta < -5.0 and consistency_score > 0.7: | |
| goal_trajectory = "IMPROVING" | |
| elif abs(pace_delta) <= 5.0 and consistency_score > 0.6: | |
| goal_trajectory = "STABLE" | |
| elif pace_delta > 5.0 or consistency_score < 0.5: | |
| goal_trajectory = "DECLINING" | |
| else: | |
| goal_trajectory = "UNKNOWN" | |
| # 4. Recommended Focus | |
| if health_signal == "OVERREACHING": | |
| recommended_focus = "RECOVERY" | |
| elif consistency_score < 0.7: | |
| recommended_focus = "CONSISTENCY" | |
| elif health_signal == "OPTIMAL" and goal_trajectory != "DECLINING": | |
| recommended_focus = "INTENSITY" | |
| else: | |
| recommended_focus = "MAINTENANCE" | |
| return cls( | |
| week_start_date=week_start, | |
| health_signal=health_signal, | |
| position_status=position_status, | |
| goal_trajectory=goal_trajectory, | |
| recommended_focus=recommended_focus, | |
| comparison_available=comparison_available, | |
| training_phase=training_phase | |
| ) | |