Files
Stride/docs/ROUTE_PLANNER.md
T

89 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Route planner
Open **Routes** in Stride. Select the start on the map, enter latitude/longitude,
search by typing a place/address and choosing a suggestion, or use your location.
Both start and finish support search with arrow-key/Enter selection. Suggestions
are biased towards the current map view, without restricting the search region.
Choose a loop or select a separate finish, distance (1–50 km),
hill difficulty, surface preference and ranking priority. Generated candidates show
their actual distance, ascent, route geometry, elevation profile and quality coverage.
Save a named route privately, reopen it, download GPX, or delete it.
## Configuration
Apply migrations with `uv run --locked flask --app app db upgrade`.
Set `ORS_API_KEY` in the web process environment and restart the web process.
For local development, the app also reads `instance/ors-api-key` when the environment
key is absent. This private file is ignored by Git; production only uses environment
configuration. Keep the file within your private Windows account/workspace.
For Dokku, configure `ORS_API_KEY` through your normal secret-management workflow.
The key stays server-side and is never included in rendered HTML or requests from
the browser. Obtain a key at https://openrouteservice.org/ and review the provider's
current quotas. The planner sends selected coordinates to the fixed ORS HTTPS
endpoint. Browser map tiles use the app's existing OpenStreetMap tile service.
Without a key, generation is disabled with a configuration notice; saved routes,
maps and export remain available. No synthetic routes are shown in the real app.
## Generation and ranking
The server makes at most three requests per generation, each with a 12-second
network timeout and a 4 MB response limit. Requests use `foot-walking`, elevation,
and `surface`/`waytype` extras. Loops use three deterministic round-trip seeds.
Point-to-point candidates include a direct route and two estimated side waypoints
to seek a longer route near the target. Duplicate geometries are removed. This
bounded search can return fewer than three routes and cannot guarantee a distance
or ascent target. The interface flags results outside ±5% distance.
Preferences rank candidates; they are not strict exclusions. Hill targets are
approximately 3, 12 or 25 metres ascent/km. The cost combines distance deviation,
ascent mismatch, mapped road share, missing surface coverage, optional repeated
edges and surface preference. The priority weights distance, hills or quality
more strongly. This is an explainable heuristic, not a safety or fitness score.
Quality percentages follow ORS documented waytype and surface IDs:
- Paths/tracks: path, track, cycleway and footway.
- Road share: state road, road and street; this does not measure traffic.
- Paved: paved, asphalt, concrete, legacy cobblestone, metal and paving stones.
- Missing surface data is unknown; absent extras do not become zero.
- Repeated distance estimates subsequent traversals of the same rounded geometry
edge in either direction. Different segmentation can miss repeated sections.
Crossing counts, lighting, current access and live traffic are unverified.
GPX includes the route and available elevation, without fictional timestamps.
No direct Garmin course upload is included in this version.
Place searches use the same server-side ORS key and a fixed geocoding endpoint.
Typing waits 650 ms before searching; old responses are discarded when the query
changes. Queries are bounded to 3–200 characters with at most five results and an
eight-second provider timeout. The authenticated POST endpoint requires CSRF and
is limited to 30 searches/minute and 600/day. Provider labels are inserted as text.
Start/finish pins use self-contained CSS markers, so no external marker images
are required. Selected pins can be dragged to adjust their location.
## Persistence and validation
Candidates and saved routes are server-side and owner-scoped. Other users,
including friends, cannot view, mutate or export them. Save and delete use CSRF
protection. Unsaved candidates older than one day are cleaned on the owner's next
generation. The library lists the latest 100 saved routes. Generation is limited
to six requests/minute and 60/day using the existing limiter storage configuration.
Offline tests mock ORS and cover input validation, ranking, point-to-point and
round-trip request shapes, deduplication, missing attributes, repeated sections,
CSRF, ownership, save/delete/export and draft cleanup. Live ORS verification needs
a configured API key; mocked tests do not establish live provider availability.
Live local verification on 2026-10-03 used public Centennial Park test coordinates.
Loop and point-to-point routing each returned three distinct candidates; private
save, reload and GPX export succeeded in a disposable in-memory test database.
The best loop was 5,030.9 m with 61.5 m ascent and 90% mapped paths/footways.
The local browser rendered the real route, quality figures and elevation profile
without console errors. The suite passed 129 tests. Live provider category IDs
arrive as decimal numbers; a regression test covers that response format.
Provider references:
https://giscience.github.io/openrouteservice/api-reference/endpoints/directions/extra-info/
https://giscience.github.io/openrouteservice/api-reference/endpoints/directions/extra-info/waytype
https://giscience.github.io/openrouteservice/api-reference/endpoints/directions/extra-info/surface