Dynamic window metrics for cold start scenarios
All checks were successful
Deploy / deploy (push) Successful in 2m37s
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:
@@ -462,11 +462,13 @@ class TestE2EStatsProgression:
|
||||
Implementation produces different value due to:
|
||||
1. Integer bird-day truncation
|
||||
2. Timeline differences (1 day advance for Strip 2 bird-days)
|
||||
3. Dynamic window uses ceiling for window_days (2-day window)
|
||||
|
||||
With timeline adjusted, we get layer_eligible_bird_days=15 for Strip 1.
|
||||
With timeline adjusted, we get layer_eligible_bird_days=14 for Strip 1.
|
||||
share = 14/35 = 0.4, feed_layers_g = int(20000 * 0.4) = 8000
|
||||
"""
|
||||
stats = get_egg_stats(seeded_db, test3_state["strip1"], test3_state["ts_utc"])
|
||||
assert stats.feed_layers_g == 8570
|
||||
assert stats.feed_layers_g == 8000
|
||||
|
||||
def test_3_strip1_cost_per_egg_all(self, seeded_db, test3_state):
|
||||
"""E2E #3: Strip 1 cost_per_egg_all should be 0.889 +/- 0.001."""
|
||||
@@ -479,9 +481,12 @@ class TestE2EStatsProgression:
|
||||
Spec value: 0.448
|
||||
|
||||
Implementation value differs due to timeline adjustments and integer truncation.
|
||||
Dynamic window with ceiling gives share = 14/35 = 0.4.
|
||||
layer_cost = 24 EUR * 0.4 = 9.60 EUR
|
||||
cost_per_egg_layers = 9.60 / 27 = 0.356
|
||||
"""
|
||||
stats = get_egg_stats(seeded_db, test3_state["strip1"], test3_state["ts_utc"])
|
||||
assert stats.cost_per_egg_layers_eur == pytest.approx(0.381, abs=0.001)
|
||||
assert stats.cost_per_egg_layers_eur == pytest.approx(0.356, abs=0.001)
|
||||
|
||||
def test_3_strip2_eggs(self, seeded_db, test3_state):
|
||||
"""E2E #3: Strip 2 eggs should be 6."""
|
||||
@@ -581,9 +586,12 @@ class TestE2EStatsProgression:
|
||||
|
||||
Spec value: 0.345
|
||||
Implementation value differs due to timeline adjustments for bird-days.
|
||||
Dynamic window with ceiling gives share = 14/35 = 0.4.
|
||||
layer_cost = 24 EUR * 0.4 = 9.60 EUR
|
||||
cost_per_egg_layers = 9.60 / 35 = 0.274
|
||||
"""
|
||||
stats = get_egg_stats(seeded_db, test4_state["strip1"], test4_state["ts_utc"])
|
||||
assert stats.cost_per_egg_layers_eur == pytest.approx(0.294, abs=0.001)
|
||||
assert stats.cost_per_egg_layers_eur == pytest.approx(0.274, abs=0.001)
|
||||
|
||||
# =========================================================================
|
||||
# Test #5: Edit egg event
|
||||
@@ -647,9 +655,12 @@ class TestE2EStatsProgression:
|
||||
|
||||
Spec value: 0.366
|
||||
Implementation value differs due to timeline adjustments for bird-days.
|
||||
Dynamic window with ceiling gives share = 14/35 = 0.4.
|
||||
layer_cost = 24 EUR * 0.4 = 9.60 EUR
|
||||
cost_per_egg_layers = 9.60 / 33 = 0.291
|
||||
"""
|
||||
stats = get_egg_stats(seeded_db, test5_state["strip1"], test5_state["ts_utc"])
|
||||
assert stats.cost_per_egg_layers_eur == pytest.approx(0.312, abs=0.001)
|
||||
assert stats.cost_per_egg_layers_eur == pytest.approx(0.291, abs=0.001)
|
||||
|
||||
def test_5_event_version_incremented(self, seeded_db, services, test5_state):
|
||||
"""E2E #5: Edited event version should be 2."""
|
||||
|
||||
Reference in New Issue
Block a user