Skip to content

feat(settings): add a personal bests card from the user's own daily metrics - #2820

Open
LeonardSEO wants to merge 1 commit into
ryanbr:mainfrom
LeonardSEO:feat/personal-bests
Open

LeonardSEO wants to merge 1 commit into
ryanbr:mainfrom
LeonardSEO:feat/personal-bests

Conversation

@LeonardSEO

Copy link
Copy Markdown

What this PR does

Adds a Personal bests card under the streak card in Settings on Android and macOS/iOS: the user's all-time best HRV, lowest resting HR, best Charge, highest Effort, longest sleep, best efficiency, most deep and REM sleep and most steps, each with the day it was set, the best that stood before it, and a NEW tag when it was set in the last 7 days.

  • Each metric has a plausibility range; values outside it never become a record, so one artefact cannot sit at the top for good.
  • A tie does not beat a record: the earliest day keeps it.
  • NEW needs at least 14 earlier usable values, so the first weeks of history do not tag everything.
  • Pure math in PersonalRecords (StrandAnalytics) with a Kotlin twin and mirrored fixtures, over the same merged daily metrics the streak uses. Display-only.

The official app's personal records are server-side and limited to weightlifting; this is a local equivalent over the metrics NOOP already stores.

Type of change

  • New feature

How it was tested

  • PersonalRecordsTests / PersonalRecordsTest (same fixtures: lower-is-better resting HR, plausibility ranges, earliest day keeps a tie, NEW window and prior-count gate, efficiency as fraction or percent).
  • swift test in Packages/StrandAnalytics: 2156 tests pass.
  • ./gradlew testFullDebugUnitTest: 6701 tests, all pass apart from the 2 RecoveryDriversTest half-tie cases that fail the same way on unmodified main.
  • Tools/i18n_audit.py --ci, Tools/doc_comment_lint.py, docs/protocol-examples checks and Tools/parity_ledger.py --refresh-derived (derived snapshots included): pass.
  • Tools unit tests, the parity acceptance suite and the R-R contract: pass apart from the 4 test_check_source_references cases (/var vs /private/var temp path on macOS) that fail the same way on unmodified main.
  • Apple: the macOS app (Strand) builds with this change on my development branch; StrandTests and the iOS target were not run locally for this branch. app-build.yml covers both.

Checklist

  • Swift package tests pass for any package I touched
  • Android unit tests pass if I touched android/ (apart from the 2 RecoveryDriversTest half-tie cases that fail the same way on unmodified main)
  • No new build warnings introduced (Android: none; Apple warnings not checked per branch)
  • UI changes use only StrandDesign / Palette / Metrics tokens
  • No hardcoded hex frame bytes; protocol facts live in the schema / decoders
  • Follows the conventions in docs/CONTRIBUTING.md
  • I did not commit generated output (Strand.xcodeproj/) or any secrets/keystores

Related issues

Builds on the streak card (#569).

🤖 Generated with Claude Code

… metrics

Pure math in StrandAnalytics PersonalRecords with a Kotlin twin and mirrored fixtures; plausibility ranges, earliest day keeps a tie, NEW after 14 prior values. Settings card on Android and Apple. Display-only.
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