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.
| Source | Where it comes from | What it covers | Confidence |
|---|
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
| Module | Lines | Stmts | Covered | What it does |
|---|
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 wrong | What found it | State |
|---|
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.
| Node | Line | Nearest stop |
|---|