Dynamic window metrics for cold start scenarios
All checks were successful
Deploy / deploy (push) Successful in 2m37s

Calculate metrics from first relevant event to now (capped at 30 days)
instead of a fixed 30-day window. This fixes inaccurate metrics for new
users who have only a few days of data.

Changes:
- Add _get_first_event_ts() and _calculate_window() helpers to stats.py
- Add window_days field to EggStats dataclass
- Update routes/eggs.py and routes/feed.py to use dynamic window
- Update templates to display "N-day avg" instead of "30-day avg"
- Use ceiling division for window_days to ensure first event is included

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-10 19:06:00 +00:00
parent 4c62840cdf
commit 86dc3a13d2
8 changed files with 456 additions and 59 deletions

View File

@@ -489,7 +489,7 @@ class TestEggStatsCaching:
def test_cached_stats_have_window_bounds(self, seeded_db, e2e_test1_setup):
"""Cached stats include window_start_utc and window_end_utc."""
ts_utc = e2e_test1_setup["ts_utc"]
get_egg_stats(seeded_db, e2e_test1_setup["location_id"], ts_utc)
stats = get_egg_stats(seeded_db, e2e_test1_setup["location_id"], ts_utc)
row = seeded_db.execute(
"""
@@ -500,7 +500,6 @@ class TestEggStatsCaching:
).fetchone()
assert row is not None
assert row[1] == ts_utc # window_end_utc
# Window is 30 days
thirty_days_ms = 30 * 24 * 60 * 60 * 1000
assert row[0] == ts_utc - thirty_days_ms # window_start_utc
# Cached bounds should match what get_egg_stats returned
assert row[0] == stats.window_start_utc
assert row[1] == stats.window_end_utc