feat(transit): register YRT/Viva off, named by Viva colour

York Region's feed is first-party infrastructure under an open licence that
permits commercial use and does not even require attribution. It is the one
feed that fills the gap north of Toronto, and it is switched off anyway.

The operator asks that its licence be accepted through a form collecting a
name, company, phone and email. No credential is issued and nothing gates
the endpoint — the licence body says use is itself acceptance — but a form
asking for contact details is close enough to the registration this registry
refuses that a person should decide it, not a poller. Barrie is off for the
same reason. Both are one line from on.

Viva route ids get labels: YRT publishes `601` where every station sign says
Viva Blue. The numeric local routes already read correctly and carry no
entry, so the table is six lines, not 125.

No vehicle in this feed carries a bearing; heading comes from observed
movement, as with Durham.
This commit is contained in:
Cliff Flood committed 2026-10-15 20:18:15 -04:00
1 parent 11dd914c2f
commit 8ccb0cd895
4 files changed
+69 -3

No files matched your search

+48
View File
@@ -184,6 +184,31 @@ function guelphRouteLabel(routeId) {
return GUELPH_ROUTE_NAMES[routeId] || routeId;
}
/**
* YRT publishes Viva bus rapid transit by route id (`601`), while every rider,
* station sign and map calls it "Viva Blue". The local routes are already the
* number on the bus and are left alone. Colours are from York Region's own
* published GTFS `routes.txt`; Viva Green (604) and Pink (606) are not in
* current service and so are absent here too.
*/
const YRT_VIVA_ROUTE_NAMES = Object.freeze({
601: 'Viva Blue',
60102: 'Viva Blue B',
603: 'Viva Purple',
60301: 'Viva Purple A',
605: 'Viva Orange',
607: 'Viva Yellow',
});
/**
* YRT route id to the name a rider would say.
* @param {string|null} routeId
* @returns {string|null}
*/
function yrtRouteLabel(routeId) {
return YRT_VIVA_ROUTE_NAMES[routeId] || routeId;
}
/**
* Registry of feeds. Order is presentation order in the stats/credit text.
* `loadRadiusKm` is the distance from `center` inside which the feed is polled.
@@ -490,6 +515,29 @@ export const TRANSIT_FEED_REGISTRY = Object.freeze([
}),
defaultMode: 'bus',
}),
Object.freeze({
id: 'yrt-york',
name: 'YRT/Viva',
operator:
'York Region Transit (YRT/Viva), The Regional Municipality of York',
region: 'York Region, ON',
center: Object.freeze({ lat: 44.025, lon: -79.436 }),
loadRadiusKm: 38,
url: 'https://rtu.york.ca/gtfsrealtime/VehiclePositions',
license: 'YRT Open Data Licence v2.0 (UK OGL-derived)',
licenseUrl:
'https://www.yrt.ca/en/about-us/open-data-licence-agreement.aspx',
attribution:
"Contains public transit Information made available under YRT's Open Data Licence",
defaultEnabled: false,
terms: Object.freeze({
quote:
'YRT grants You a worldwide, royalty-free, perpetual, non-exclusive licence to Use the Information subject to the conditions below ... Use the Information commercially ... Provide credit to YRT when using Information under this licence but are not required to. ... Please note: You must agree with and accept the above stated License Agreement in order to download YRT GTFS or real-time GTFS data.',
note: 'OFF for the same reason as Barrie: the operator asks that its licence be accepted through a form (forms.yrt.ca/YRT-GTFS-Data, which collects a name, company, phone and email and issues no credential) before the data is taken. Nothing gates the endpoint, and the licence body also says use is itself acceptance \u2014 but a form asking for contact details is close enough to the registration this registry refuses that a person, not a poller, should decide. Flip this one line once someone has answered it. The credit above is the licence\u2019s own wording and must be reproduced as given; attribution is optional here, and given anyway. Logos, trademarks and crests are carved out, so the credit stays text. Two data notes: no vehicle carries a bearing, so heading comes from observed movement; and one stuck unit reported a position ten hours old, which the layer shows as a stale report rather than hides.',
}),
defaultMode: 'bus',
routeLabel: yrtRouteLabel,
}),
]);
/**
+17
View File
@@ -390,3 +390,20 @@ test('Barrie is registered but unpolled until its licence is accepted', () => {
'never offered to the browser',
);
});
test('YRT is registered but unpolled until its licence form is answered', () => {
assert.equal(getRegisteredTransitFeed('yrt-york')?.name, 'YRT/Viva');
assert.equal(getTransitFeed('yrt-york'), null, 'not routable');
});
test('Viva bus rapid transit is named by its colour, not its route number', () => {
// YRT publishes `601` where every rider, map and station sign says
// "Viva Blue". The numeric local routes already read correctly and are
// left alone.
const yrt = getRegisteredTransitFeed('yrt-york');
assert.equal(transitRouteLabel(yrt, '601'), 'Viva Blue');
assert.equal(transitRouteLabel(yrt, '60301'), 'Viva Purple A');
assert.equal(transitRouteLabel(yrt, '607'), 'Viva Yellow');
assert.equal(transitRouteLabel(yrt, '105'), '105', 'a local bus is a number');
assert.equal(transitRouteLabel(yrt, '9899'), '9899');
});