Backend: route analysis engine + GET /api/recorded-routes/{id}/analysis (epic #983) #984

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

Part of epic #983.

Lazy materialize-on-first-read analysis for recorded routes:

  • New recorded-route-analysis companion collection (AnalysisJson + AnalysisVersion, RouteId unique, owner field); recompute on read when version stale; DELETE removes it.
  • Pure static RouteAnalyzer: outlier rejection (acc>50m, 42 m/s cap, 3×-median spike) → smoothed position-derived speeds → rest detection (<0.5 m/s ≥20s + "paused" rests at segment gaps ≥5s) → walk/run/rest classification (2.3/1.9 m/s hysteresis, 10s debounce) → per-km splits → elevation gain/loss (median smoothing + 2m hysteresis) → fastest/slowest 500m sections → downsampled ghost track (≤1000 samples of cumulativeDistance/movingTime/elapsed parallel arrays for client-side ghost racing).
  • GET /api/recorded-routes/{id}/analysis → RouteAnalysisDto (canonical for iOS/web; index ranges = inclusive indices into upload-order points array).
  • Additive Segment int on RecordedGpsPointDto (default 0) + validator rules, so iOS stops flattening pause segments off the wire. RouteStatsCalculator formulas untouched (fixture parity).
  • Never log coordinates (existing domain privacy rule).
Part of epic #983. Lazy materialize-on-first-read analysis for recorded routes: - New `recorded-route-analysis` companion collection (AnalysisJson + AnalysisVersion, RouteId unique, owner field); recompute on read when version stale; DELETE removes it. - Pure static `RouteAnalyzer`: outlier rejection (acc>50m, 42 m/s cap, 3×-median spike) → smoothed position-derived speeds → rest detection (&lt;0.5 m/s ≥20s + "paused" rests at segment gaps ≥5s) → walk/run/rest classification (2.3/1.9 m/s hysteresis, 10s debounce) → per-km splits → elevation gain/loss (median smoothing + 2m hysteresis) → fastest/slowest 500m sections → downsampled ghost track (≤1000 samples of cumulativeDistance/movingTime/elapsed parallel arrays for client-side ghost racing). - `GET /api/recorded-routes/{id}/analysis` → `RouteAnalysisDto` (canonical for iOS/web; index ranges = inclusive indices into upload-order points array). - Additive `Segment` int on `RecordedGpsPointDto` (default 0) + validator rules, so iOS stops flattening pause segments off the wire. `RouteStatsCalculator` formulas untouched (fixture parity). - Never log coordinates (existing domain privacy rule).
Author
Owner

Resolved in spikersoft-backend PR #526 (merged to master). RouteAnalyzer + lazily-materialized GET /api/recorded-routes/{id}/analysis (versioned recorded-route-analysis collection), additive segment wire field + validator rules, delete-handler cleanup. Full solution build clean; Business/API/Data suites green (10,987 tests incl. the 13-scenario analyzer matrix). Closing.

Resolved in spikersoft-backend PR #526 (merged to `master`). RouteAnalyzer + lazily-materialized `GET /api/recorded-routes/{id}/analysis` (versioned `recorded-route-analysis` collection), additive `segment` wire field + validator rules, delete-handler cleanup. Full solution build clean; Business/API/Data suites green (10,987 tests incl. the 13-scenario analyzer matrix). Closing.
Sign in to join this conversation.