Merge branch 'main' into upstream/voice-alias-hint-budget

This commit is contained in:
Sameh Khamis committed 2026-11-02 07:07:55 -08:00
commit 473ea3b90b
4 files changed
+67 -1

No files matched your search

@@ -0,0 +1,3 @@
- Bike Share stations whose feed publishes no capacity now take it from each
status poll's bikes and docks instead of keeping the first poll's value or
the placeholder 15 (Aditya, @Rohilalala, #1447).
+2
View File
@@ -1898,6 +1898,8 @@ limit, as well as when a tile decodes or the source resets.
GBFS null or empty availability counts retain an unknown value through station
parsing and rendering; they use the neutral station color rather than reporting
an empty dock. Explicit zero and caller-supplied numeric fallbacks remain valid.
A station whose `station_information` publishes no capacity takes bikes plus
docks from each status poll (15 until its status arrives), not from the first.
## Terrain height cache bound
+59
View File
@@ -446,3 +446,62 @@ test('unknown GBFS counts stay unknown through the source, model and station col
assert.equal(model.toNonNegativeInteger('3'), 3);
}
});
test('a station without a published capacity re-derives it from every status poll', async () => {
const { createRendering } = await import('./rendering.js');
const { COLOR_YELLOW } = await import('./policy.js');
const model = createModel({});
const state = {
_cityRuntime: new Map(),
_stationRenderMap: new Map(),
_pointCollection: { add: (options) => ({ ...options }) },
};
const rendering = createRendering({
state,
services: { render: { governorRequestRender() {} } },
parts: { model },
});
const info = model.parseStationInformation({
data: {
stations: [
{ station_id: 'open', name: 'Open', lat: 30.26, lon: -97.74 },
{
station_id: 'fixed',
name: 'Fixed',
lat: 30.27,
lon: -97.75,
capacity: 13,
},
],
},
});
rendering.ensureCityPoints('austin', info);
const poll = (stations) =>
rendering.applyStatusToPoints(
'austin',
model.parseStationStatus({ data: { stations } }),
);
const open = state._stationRenderMap.get('austin:open');
const fixed = state._stationRenderMap.get('austin:fixed');
// The first poll has no row for the station: capacity is a placeholder.
poll([
{
station_id: 'fixed',
num_bikes_available: 4,
num_docks_available: 9,
},
]);
poll([
{ station_id: 'open', num_bikes_available: 10, num_docks_available: 20 },
{ station_id: 'fixed', num_bikes_available: 2, num_docks_available: 3 },
]);
assert.equal(open.capacity, 30, 'the first poll fixed the capacity');
assert.equal(open.point.color, COLOR_YELLOW, '10 of 30 is not plenty');
assert.equal(fixed.capacity, 13, 'a published capacity is kept');
poll([
{ station_id: 'open', num_bikes_available: 4, num_docks_available: 2 },
]);
assert.equal(open.capacity, 6);
});
+3 -1
View File
@@ -185,6 +185,7 @@ export function createRendering({
stationName: station.name,
point,
capacity: parts.model.toNonNegativeInteger(station.capacity),
publishedCapacity: parts.model.toNonNegativeInteger(station.capacity),
bikesAvailable: null,
docksAvailable: null,
isInstalled: station.isInstalled,
@@ -245,7 +246,8 @@ export function createRendering({
if (!record) continue;
const status = statusMap.get(record.stationId) || null;
const capacity = resolveCapacity(record.capacity, status);
// Resolve from the published capacity, not last poll's derived value.
const capacity = resolveCapacity(record.publishedCapacity, status);
record.capacity = capacity;
record.bikesAvailable = parts.model.toNonNegativeInteger(