Spaces:
Running
Running
| from domain.goals.goal_trajectory import GoalTrajectory | |
| class GoalTrajectoryEngine: | |
| def compute( | |
| self, goal, weekly_snapshot, weekly_trend=None, runner_profile=None | |
| ): | |
| if not goal or not weekly_snapshot: | |
| return None | |
| current_km = weekly_snapshot.total_distance_km or 0 | |
| target_val = getattr(goal, "target_value", 0) | |
| unit = getattr(goal, "unit", "km") | |
| goal_type = getattr(goal, "type", "goal") | |
| name = f"{goal_type} {target_val} {unit}" | |
| # ---- Weekly Volume Goal ---- | |
| if getattr(goal, "type", None) == "volume": | |
| target_km = goal.target_value | |
| progress_pct = (current_km / target_km) * 100 if target_km else 0 | |
| if current_km >= target_km * 1.1: | |
| status = "ahead" | |
| elif current_km >= target_km * 0.9: | |
| status = "on_track" | |
| else: | |
| status = "behind" | |
| milestone = f"Maintain ≥{target_km:.1f} km/week" | |
| return GoalTrajectory( | |
| goal_name=name, | |
| target_date=getattr(goal, "target_date", None), | |
| status=status, | |
| progress_pct=progress_pct, | |
| expected_weekly_km=target_km, | |
| current_weekly_km=current_km, | |
| next_milestone=milestone | |
| ) | |
| # ---- Race Goal ---- | |
| if getattr(goal, "type", None) == "race": | |
| target_km = goal.target_value | |
| baseline = None | |
| if runner_profile and runner_profile.baseline_weekly_km: | |
| baseline = runner_profile.baseline_weekly_km | |
| else: | |
| baseline = current_km | |
| expected_weekly_km = max(baseline, target_km * 1.5) | |
| progress_pct = ( | |
| (current_km / expected_weekly_km) * 100 if expected_weekly_km else 0 | |
| ) | |
| if current_km >= expected_weekly_km * 1.1: | |
| status = "ahead" | |
| elif current_km >= expected_weekly_km * 0.9: | |
| status = "on_track" | |
| else: | |
| status = "behind" | |
| milestone = f"Reach ~{expected_weekly_km:.1f} km/week" | |
| return GoalTrajectory( | |
| goal_name=name, | |
| target_date=getattr(goal, "target_date", None), | |
| status=status, | |
| progress_pct=progress_pct / 100.0, | |
| expected_weekly_km=expected_weekly_km, | |
| current_weekly_km=current_km, | |
| next_milestone=milestone | |
| ) | |
| return None | |