Files
Stride/docs/ROUTE_PLANNER.md
T

5.4 KiB
Raw Blame History

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