# Route-time and contribution lab

Open `index.html` directly in a current browser. It contains all data, CSS and
JavaScript. No server, installation, API key, analytics, network request or upload
is required. Source/attribution links contact external sites only when clicked.
The form does not save values between sessions. Download computed CSV before
closing if you need to retain your assumptions.

## Observed, modeled, and invented

- Observed API responses: eight public civic-point searches, seven outbound
  routes, one directed-return table. These are observed *API outputs*, not
  observed driving journeys.
- Modeled outputs: OSRM car-graph route geometry, meters, seconds, and road snaps.
  No live traffic, truck restrictions, fleet observation or ferry timetable.
- Invented examples: USD collections, costs, crew, on-site hours, wage rate,
  available hours and optional opportunity cost. Replace with your inputs.
- Circle and 40-minute thresholds are planning examples. They do not define a
  continuous drive-time boundary or Google advertising eligibility.

## Selection and collection

Seattle City Hall is a reproducible public central reference, not a contractor's
shop. Seven destinations were chosen before routing to cover several nearby
civic centers and directions across Lake Washington and Puget Sound: Bellevue,
Kirkland, Redmond, Renton, Burien, Bainbridge Island and Bremerton. The entire
selected set is retained. It is not a representative sample of customers,
Seattle, another city or the United States.

`points.json` contains actual Nominatim search-result coordinates,
OpenStreetMap object IDs/links, search URLs and UTC retrieval times. `raw/`
contains unmodified JSON response bytes and request metadata sidecars.
Coordinates are civic object point representations, not verified vehicle
entrances. The provider snaps them to its road network; snap positions,
distances and road names are retained.

Collection: 2026-10-24 UTC. Point searches were sequential and cached.
Routing provider: https://routing.openstreetmap.de/routed-car/
Profile in request: `driving`; endpoint selects the provider's car graph.
There were **8 routing API requests**: seven outbound routes with full GeoJSON
geometry and steps, and one seven-to-one return table for distance and duration.
No alternatives or fallback speeds were requested. Requests used identifying
application User-Agent and Referer headers, with at least 1.2 seconds between
completed requests. Sidecar `retrieved_utc` records the request-start UTC time. No `data_version` was returned. The deployed profile is not
independently pinned; raw responses preserve this collection's exact outputs.

All seven outbound responses contained driving-mode steps only. The long
Bainbridge Island and Bremerton paths do not evaluate an alternative ferry
journey, waiting, timetable or fare. This observation does not establish that
all ferry routes are excluded by every version of the provider's profile.

### Primary sources and policies read on collection date

- API: https://project-osrm.org/docs/v5.24.0/api/
- Provider/English policy: https://routing.openstreetmap.de/about.html
- Policy pointer: https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy
- Full German policy: https://www.fossgis.de/arbeitsgruppen/osm-server/nutzungsbedingungen/
  returned Anubis access denied; no bypass attempted. The English excerpt
  requires attribution, valid identity, <=1 request/second, no heavy usage or
  scraping. This was a small one-off collection.
- Geocoding: https://operations.osmfoundation.org/policies/nominatim/
  No heavy use; absolute maximum 1 request/second, identifying User-Agent,
  attribution, one machine/thread for small one-off lookup, cached results.
  The public service is not a generic geocoding backend for this tool. The
  fixed eight-point collector never runs in the browser.
- Data: https://www.openstreetmap.org/copyright
- License: https://opendatacommons.org/licenses/odbl/1-0/
- Google: https://support.google.com/google-ads/answer/1722043

The supplied https://project-osrm.org/docs/v26.4.0/http/ returned 404; available
official v5.24.0 documentation defines the response fields used.

## Units, equations and unknowns

Straight-line miles: Haversine from original lon/lat on a sphere of mean radius
3958.7613 statute miles. One mile = 1609.344 meters. One minute = 60 seconds.
Threshold boundaries are inclusive. Plot projection is equirectangular at origin
latitude, with a great-circle radius outline.

Default travel = actual outbound + separately modeled return, not twice the
outbound. Outbound-only excludes return. An unavailable metric stays
`null`/unknown and blocks contribution if needed by the chosen travel assumption.
Zero financial amounts are valid. Blank/negative/nonfinite inputs and invalid
crew counts show errors. Radius above 200 miles exceeds the local plot's range.

Vehicle cash = selected travel miles × vehicle cash per mile (one vehicle).
Extra wages = selected elapsed travel hours × technicians × wage cost, if enabled.
Cash contribution = collections − variable job costs − vehicle cash − extra wages.
Fixed overhead, advertising, taxes and profit are not reserved automatically.
Actual tolls/fares can be added to variable job costs. If charges differ by
destination, analyze each separately: that input applies to every row.

Uncheck travel wages if already included in variable job costs. Keep vehicle
travel cash outside job costs when using the mileage charge. Optional additional
foregone contribution is a residual per technician-hour after wages already
accounted for; it must not contain that wage again. Decision contribution = cash
contribution − optional residual opportunity cost. This is a decision measure,
not cash accounting profit. Use zero without supported additional opportunity
cost. No value for free capacity is imputed.

Crew-hours = technicians × (on-site elapsed hours + selected travel hours).
Jobs fitting entered hours = floor(available technician-hours / crew-hours).
Zero job+travel duration returns unknown fit. This is an arithmetic upper bound,
not a shift-, skill- or appointment-aware scheduler.

## Reproduce offline

Opening HTML needs no runtime. To repeat tests or rebuild using existing Node
and Python standard library:

```sh
node --test core.test.mjs
python3 build.py
```

`build.py` derives `snapshot.json`, `snapshot.csv`, standalone `index.html` and
`route-time-kit.zip` entirely from saved responses. It makes no network calls.
It embeds `core.js`, `ui.js` and data into `index.template.html`. ZIP contains the
same HTML, data, raw evidence, source, tests and this README. It excludes itself
and Python cache files.

Fourteen core tests cover units, Haversine, thresholds, missing routes,
financial validation, zero, overflow, directed return, crew/vehicle arithmetic,
labor inclusion, optional opportunity cost, CSV and actual snapshot fixtures.
Bellevue's expected round-trip travel is 33.57333333333333 minutes; sample cash
contribution $153.16772776982424.

Optional, with Playwright already installed in a resolvable parent folder:

```sh
node browser.test.mjs
```

This opens local HTML at 390px, switches offline, checks selection, blank input,
reset, zero collections, keyboard SVG selection, CSV download and zero network
requests/page errors. It installs nothing and does not validate real driving.
Set `ROUTE_SCREENSHOT` to a local PNG path to capture the final view.

`collect.py` and `collect-routes.py` document the original fixed one-off network
collection. Do not rerun by default: use cached evidence. A deliberate new
collection requires current policy review, identity headers, sequential limits,
licensing and retention of the original snapshot. Graph/profile changes may
produce different results.

## License and attribution

OSM-derived point/route dataset and geographic plot:
**© OpenStreetMap contributors, ODbL 1.0**.
https://www.openstreetmap.org/copyright
https://opendatacommons.org/licenses/odbl/1-0/
Routing: OSRM https://project-osrm.org/ / FOSSGIS
https://routing.openstreetmap.de/about.html
Fix the map: https://www.openstreetmap.org/fixthemap

Original Lonta calculator/UI/build/test code: MIT, copyright 2026 Lonta AI.
See LICENSE.txt. ODbL data rights are separate from the code license.
