saving
This commit is contained in:
@@ -4,8 +4,9 @@ from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import pytest
|
||||
|
||||
from openrun.model import calibrate_tl_per_km, personal_records
|
||||
from openrun.model import calibrate_tl_per_km, personal_records, plan_to_daily_load
|
||||
|
||||
|
||||
def _act(aid: int, dist_km: float, pace: float, when: str = "2026-01-01") -> dict:
|
||||
@@ -114,3 +115,62 @@ def test_calibrate_tl_per_km_returns_nan_when_empty(tmp_conn) -> None:
|
||||
result = calibrate_tl_per_km(tmp_conn, lookback_days=None)
|
||||
assert result["n"] == 0
|
||||
assert np.isnan(result["median"])
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# plan_to_daily_load
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _plan_row(week_start: str, weekly_km: float, long_run_km: float) -> dict:
|
||||
return {"week_start": pd.Timestamp(week_start), "weekly_km": weekly_km, "long_run_km": long_run_km}
|
||||
|
||||
|
||||
def test_plan_distributes_weekly_km_across_7_days() -> None:
|
||||
"""A single 70 km / 28 km long-run week should emit 7 daily entries summing to 70·tl_per_km."""
|
||||
plan = pd.DataFrame([_plan_row("2026-05-04", 70.0, 28.0)]) # Mon 2026-05-04
|
||||
series = plan_to_daily_load(plan, tl_per_km=10.0)
|
||||
assert len(series) == 7
|
||||
assert series.sum() == pytest.approx(700.0)
|
||||
# Saturday (default 40 %) gets the biggest single load.
|
||||
saturday = pd.Timestamp("2026-05-09")
|
||||
assert series.idxmax() == saturday
|
||||
assert series[saturday] == pytest.approx(700.0 * 0.40)
|
||||
|
||||
|
||||
def test_plan_race_week_uses_race_day_tl_per_km() -> None:
|
||||
"""If a `race_dates` entry is inside the week, race day gets long_run_km × race_tl,
|
||||
and the remaining km distribute across Mon/Wed/Fri at training rate."""
|
||||
plan = pd.DataFrame([_plan_row("2026-05-04", 30.0, 20.0)])
|
||||
series = plan_to_daily_load(
|
||||
plan,
|
||||
tl_per_km=11.0,
|
||||
race_day_tl_per_km=7.0,
|
||||
race_dates=("2026-05-09",), # Saturday
|
||||
)
|
||||
sat = pd.Timestamp("2026-05-09")
|
||||
assert series[sat] == pytest.approx(20.0 * 7.0) # race load
|
||||
# Remaining km = 30 - 20 = 10. Spread across Mon/Wed/Fri @ 11.0 → 110 / 3 each.
|
||||
for d in [pd.Timestamp("2026-05-04"), pd.Timestamp("2026-05-06"), pd.Timestamp("2026-05-08")]:
|
||||
assert series[d] == pytest.approx(110.0 / 3, rel=1e-6)
|
||||
|
||||
|
||||
def test_plan_empty_returns_empty_series() -> None:
|
||||
assert plan_to_daily_load(pd.DataFrame(columns=["week_start", "weekly_km", "long_run_km"]),
|
||||
tl_per_km=10.0).empty
|
||||
|
||||
|
||||
def test_plan_zero_weekly_km_yields_zeros() -> None:
|
||||
"""A rest week (weekly_km=0) shouldn't crash and should produce 7 zero-load days."""
|
||||
plan = pd.DataFrame([_plan_row("2026-05-04", 0.0, 0.0)])
|
||||
series = plan_to_daily_load(plan, tl_per_km=10.0)
|
||||
assert (series == 0).all()
|
||||
assert len(series) == 7
|
||||
|
||||
|
||||
def test_plan_custom_weekday_weights() -> None:
|
||||
"""Pass a flat 1/7 split, expect equal load each day."""
|
||||
plan = pd.DataFrame([_plan_row("2026-05-04", 70.0, 28.0)])
|
||||
weights = {i: 1 / 7 for i in range(7)}
|
||||
series = plan_to_daily_load(plan, tl_per_km=10.0, weekday_weights=weights)
|
||||
assert series.std() == pytest.approx(0.0, abs=1e-9)
|
||||
assert series.iloc[0] == pytest.approx(100.0)
|
||||
|
||||
Reference in New Issue
Block a user