Toronto-Transit-Distance-Matrix · port 5000

Which stops you can reach, and when you would get there

A local Flask app that answers three questions about getting around Toronto: how far you can get in a given time, how to make a particular trip, and what time you will actually arrive. Every travel time is computed here, against the TTC's own timetable and its live service feed. No API key and no billing account — both feeds are open, and the map tiles are plain OpenStreetMap.

Where each number comes from, and how much to trust it

Three different kinds of number appear on the same screen and they do not deserve equal confidence, so every wait carries its source and the page shows it. This is the app's one real opinion.

The source is on every leg of every trip, not a global setting.
SourceWhere it comes fromWhat it coversConfidence

A trip, for a particular departure

POST /api/trips with a departAt of "17:20", an ISO timestamp, or "now". Union to Finch, planned against the timetable:


  

Two kinds of alternative, because "another option" means two things: different routings for the same departure, and later departures on the same routing — which is the one you want when deciding whether to hurry.

Two things worth knowing about the routing

A wait is charged for every boarding

routing.py charges one wait, at the origin, and its transfer edges cost a flat three minutes for the platform walk with no wait for the next vehicle — so a trip with two changes undercounted by two waits. itinerary.py fixes that, and fixing it forces the search state: riding a train through a station has to be free while changing lines there is not, so a state is (stop, line you are riding) rather than just a stop.

Leaving later cannot get you there earlier

Transit is FIFO, and that property is what lets Dijkstra work on a clock rather than on fixed weights. It is not an assumption left implicit — test_leaving_later_never_arrives_earlier asserts it, and if it ever failed the time-dependent search would be unsound rather than merely wrong.

The timetable index, and why it expires

tools/build_schedule.py streams the TTC's 207 MB GTFS archive once and writes a small index of departures. Everything works without it, on live headways and modelled waits, and every response says which it used.

The graph it searches

Every module, by size

Where the tests are

Bugs, and what found each one

Every one of these was real, and none was found by reading the code. The suite exists because of them: it started at 38 tests in the commit that fixed the first four.

What was wrongWhat found itState

What is modelled, and what is simply missing

The honest list. Each of these is a place the app can be confidently wrong, which is why the wait source is on every leg rather than in a footnote.

The nine node-line pairs with no stop nearby

The graph is hand-built, so a node sits near a real stop rather than on it. The index records the distance per match and refuses anything over 900 m, which leaves these falling back to modelled waits — recorded rather than assumed away.

NodeLineNearest stop