Files
rippr/docs/v3/V3-09-route-following.md
uhryniuk e2ccd4b250 Defer V3-08/V3-09, add V3-17 to investigate self-hosted OSRM
Per request: V3-08's routing-engine direction is decided (self-hosted OSRM over a hosted API or the public demo instance) but standing one up is split into its own ticket, V3-17, since provisioning a server is different work from the app code that calls it. V3-08 and V3-09 are marked Deferred pending V3-17.

V3-17 also names a real tension worth flagging rather than quietly ignoring: this backlog's own organizing principle is 'v3 is everything buildable with no server,' and a self-hosted OSRM instance is a server -- so V3-08/V3-09 sit oddly under docs/v3/ once V3-17 exists. Left unresolved by design (a documentation call for later), noted in both V3-17 and BACKLOG.md's v4 section rather than silently renumbering tickets that are already cross-referenced throughout the docs.
2026-08-17 19:56:44 -05:00

54 lines
2.3 KiB
Markdown

# V3-09 — Follow a planned route while riding
**Phase** Route planning · **Depends on** V3-04, V3-08 (itself blocked on V3-17) · **Size** M · **Status** Deferred
## Goal
Pick a saved route before starting, see it on the live map underneath your actual track,
and afterwards compare what you rode against what you planned.
## Context
The payoff that makes V3-07 and V3-08 worth building, and the point where route planning
meets the live map. Not navigation — no turn-by-turn, no voice. Just the line you meant to
follow, drawn under the line you actually rode.
## Design
Attach an optional `routeId` to `Trip`. That is enough for both the live overlay and the
after-the-fact comparison.
Live: the planned route in a muted colour, the recorded track drawn over it in the existing
speed colours. Immediately obvious when you have left the plan.
Afterwards, on trip detail: both lines, plus how far you deviated and how the real duration
compared with the estimate — which also, over time, tells you how honest the ETA is.
**Deliberately not:** rerouting, off-route alerts, or anything that demands attention while
riding. A rider glancing at handlebars wants a picture, not an interruption.
## Implementation
1. `routeId` on `Trip` — **third migration**
2. Route picker on the record screen before Start, defaulting to none
3. Live map renders the planned polyline beneath the track
4. Trip detail renders both, with a comparison block
5. Deviation: max and mean distance from the recorded points to the planned polyline —
`perpendicularDistanceMeters` already exists and is parity-proven
## Acceptance criteria
- [ ] A route can be selected before starting, or not
- [ ] Both lines render, visually distinguishable
- [ ] Deviation and duration-vs-estimate appear on trip detail
- [ ] A ride with no route behaves exactly as today
- [ ] Deleting a route does not delete rides that referenced it
## Tests
- Deviation maths against a known track and route
- Repository: deleting a route nulls `routeId` rather than cascading to the trip —
**the cascade direction here is the opposite of segments and is easy to get wrong**
- Widget: both polylines present when a route is attached
## Risks
The `Route` → `Trip` foreign key must **not** cascade. Deleting an old plan must never
delete the ride you did.
## Out of scope
Turn-by-turn, off-route alerts, rerouting.