Add running fitness history and configurable heart rate zones

This commit is contained in:
Peter Stockings
2026-10-22 23:20:35 +11:00
parent b8eb6d10f8
commit 95e751d05c
15 changed files with 534 additions and 2 deletions
+46
View File
@@ -0,0 +1,46 @@
"""Explicit automatic and manual five-zone configuration for running load."""
from datetime import date, datetime
from itertools import pairwise
from zoneinfo import ZoneInfo
# Published as Stride's formula, not an exact reproduction of Strava's zones.
ZONE_FRACTIONS = (0.65, 0.80, 0.87, 0.95)
def zones(user, today=None):
today = today or datetime.now(ZoneInfo(user.timezone)).date()
config = user.hr_zones or {"mode": "auto"}
mode = config.get("mode", "auto")
maximum = None
if mode == "custom":
boundaries = config["boundaries"]
source = "Manual zone boundaries"
else:
maximum = config.get("max_hr") if mode == "max" else None
if maximum is not None:
source = "Manual maximum HR"
elif config.get("birthday"):
birthday = date.fromisoformat(config["birthday"])
age = (
today.year
- birthday.year
- ((today.month, today.day) < (birthday.month, birthday.day))
)
maximum = 220 - age
source = "Automatic · 220 minus age · updates on your birthday"
else:
maximum = 190
source = "Automatic · default maximum 190 bpm (birthday not set)"
boundaries = [round(maximum * fraction) for fraction in ZONE_FRACTIONS]
labels = [f"0–{boundaries[0] - 1}"]
labels += [f"{a}–{b - 1}" for a, b in pairwise(boundaries)]
labels += [f"{boundaries[-1]}+"]
return {
"boundaries": boundaries,
"source": source,
"max_hr": maximum,
"mode": mode,
"labels": labels,
"config": config,
}