iOS: ghost race mode + audio pacing cues + route analysis report (epic #983) #985

Closed
opened 2026-08-06 20:00:14 +00:00 by spikerj · 1 comment
Owner

Part of epic #983.

  • Ghost race: pure GhostComparator (projects live position onto ghost polyline, forward-biased matching for out-and-back routes, 75m corridor, pause-aware active time) + GhostRaceEngine observing ActivityRecorder (no recorder changes). "Race this" from history/detail; live gap chip (▲ ahead / ▼ behind / off-route); ghost path + position dot on the map; >100m start-proximity warning (non-blocking).
  • Audio: AudioCueService — rising/falling chime (bundled CAF) + AVSpeechSynthesizer spoken delta; .playback session with ducking, activated per cue; UIBackgroundModes += audio for locked-screen announcements.
  • Triggers: volume-button press while recording (hidden MPVolumeView + outputVolume KVO, debounced, baseline-clamped; user setting, default on), AnnounceGhostGapIntent App Intent for the Action Button, optional auto-announce every 60s/km.
  • Report: consume new GET recorded-routes/{id}/analysis; route colored walk/run/rest via data-driven MapLibre styling, fastest/slowest highlight casing, rest markers, per-km splits with pace bars; new list/detail GET client methods; "Sync to analyze" for unsynced routes.
  • Tests: GhostComparatorTests, GapAnnouncementTests, RouteAnalysisPresentationTests, DTO fixtures.
Part of epic #983. - **Ghost race**: pure `GhostComparator` (projects live position onto ghost polyline, forward-biased matching for out-and-back routes, 75m corridor, pause-aware active time) + `GhostRaceEngine` observing ActivityRecorder (no recorder changes). "Race this" from history/detail; live gap chip (▲ ahead / ▼ behind / off-route); ghost path + position dot on the map; >100m start-proximity warning (non-blocking). - **Audio**: `AudioCueService` — rising/falling chime (bundled CAF) + AVSpeechSynthesizer spoken delta; `.playback` session with ducking, activated per cue; `UIBackgroundModes += audio` for locked-screen announcements. - **Triggers**: volume-button press while recording (hidden MPVolumeView + outputVolume KVO, debounced, baseline-clamped; user setting, default on), `AnnounceGhostGapIntent` App Intent for the Action Button, optional auto-announce every 60s/km. - **Report**: consume new `GET recorded-routes/{id}/analysis`; route colored walk/run/rest via data-driven MapLibre styling, fastest/slowest highlight casing, rest markers, per-km splits with pace bars; new list/detail GET client methods; "Sync to analyze" for unsynced routes. - Tests: GhostComparatorTests, GapAnnouncementTests, RouteAnalysisPresentationTests, DTO fixtures.
Author
Owner

Resolved in spikersoft-ios PR #6 (merged to main). GhostComparator + GhostRaceEngine, chime+TTS AudioCueService (locked-screen capable, UIBackgroundModes += audio), volume-button trigger + AnnounceGhostGapIntent (Action Button) + auto-announce cadence, RouteAnalysisView consuming the new analysis endpoint, ghost/analysis map layers, upload now sends segment. All test suites green on iPhone 17 Pro sim; device slice builds clean.

Still outstanding (not blocking close): real-device field pass — locked-screen speech/ducking, volume-press reliability, Action Button, gap sign flip on an actual run. The record-follow UX gap found right after is #988 (PR #7). Closing.

Resolved in spikersoft-ios PR #6 (merged to `main`). GhostComparator + GhostRaceEngine, chime+TTS AudioCueService (locked-screen capable, `UIBackgroundModes += audio`), volume-button trigger + AnnounceGhostGapIntent (Action Button) + auto-announce cadence, RouteAnalysisView consuming the new analysis endpoint, ghost/analysis map layers, upload now sends `segment`. All test suites green on iPhone 17 Pro sim; device slice builds clean. Still outstanding (not blocking close): real-device field pass — locked-screen speech/ducking, volume-press reliability, Action Button, gap sign flip on an actual run. The record-follow UX gap found right after is #988 (PR #7). Closing.
Sign in to join this conversation.