Skip to content

Estimate daily calories on-device when the wearable reports none - #98

Merged
saksham2001 merged 3 commits into
mainfrom
claude/festive-villani-c12e0d
Aug 6, 2026
Merged

Estimate daily calories on-device when the wearable reports none#98
saksham2001 merged 3 commits into
mainfrom
claude/festive-villani-c12e0d

Conversation

@saksham2001

Copy link
Copy Markdown
Owner

Summary

Rings that don't report calories (TK18/LuckRing) — and history syncs on rings that do (Colmi sends calories only in live packets) — left days showing "—". This adds an on-device daily estimate: Mifflin-St Jeor BMR accrued over elapsed minutes + net active energy from workouts (existing Keytel/MET engine), all-day HR (Keytel gated at 60% HRmax so resting HR spikes never count), and cadence-tiered step energy from history buckets. Each interval is attributed to exactly one estimator, so nothing double-counts.

A device-reported value always wins at read time (ActivityDaily.effectiveCalories), so this only fills days with no device calories; extending to all wearables later is a one-line gate change. The calorie goal ring keeps measuring the active-energy portion vs the 500 kcal goal; the displayed number is the total.

Recompute hooks: history-bucket sync (batched, flushed at sync done), live packets from no-calorie devices (throttled), workout finish/edit/delete, late HR backfill, profile changes, launch backfill. New estimatedActiveCalories field on ActivityDaily is an additive lightweight migration.

Type of change

  • ✨ New feature (non-breaking change that adds functionality)

How was this tested?

  • Added / updated unit tests (PulseLoopTests) — 17 new tests in DailyCalorieEstimatorTests (formula values, FLEX gating, overlap exclusion, midnight proration, device-wins selection, re-sync idempotency)
  • Ran the test suite locally — full suite green
  • Tested with demo data (-seedDemo YES, no hardware) — new -demoEstimatedCalories YES launch arg reshapes seeded days into ring-history days; Today/Activity show the estimated total instead of "—"

Privacy & data

  • This change does not send health data off-device without explicit user action.
  • No secrets, API keys, or personal data are committed.

Checklist

  • My code follows the project's style (SwiftLint passes).
  • I ran the tests and they pass.

@saksham2001
saksham2001 merged commit ac01555 into main Aug 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant