mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(bikeshare): preserve unknown availability counts
This commit is contained in:
1 parent
c6f92da962
commit
9bee985abb
4 files changed
+58
No files matched your search
@@ -74,6 +74,8 @@
|
|||||||
- Tool string length validation counts Unicode characters correctly, including characters outside the basic multilingual plane.
|
- Tool string length validation counts Unicode characters correctly, including characters outside the basic multilingual plane.
|
||||||
|
|
||||||
- Director timeline seeks cross the dateline along the short longitude arc.
|
- Director timeline seeks cross the dateline along the short longitude arc.
|
||||||
|
- Keep unknown GBFS availability counts neutral instead of turning null or empty
|
||||||
|
values into zero bikes.
|
||||||
|
|
||||||
- Recent Imagery continues past malformed records in full catalog pages, respects the requested record limit, and reports results as truncated when that limit drops valid records.
|
- Recent Imagery continues past malformed records in full catalog pages, respects the requested record limit, and reports results as truncated when that limit drops valid records.
|
||||||
|
|
||||||
|
|||||||
@@ -1275,6 +1275,9 @@ and stale/error responses remain unchanged. Each has a Node-only package entry
|
|||||||
under `gods-eye-view/server/providers/`. Portable terrain mechanics, traffic tile
|
under `gods-eye-view/server/providers/`. Portable terrain mechanics, traffic tile
|
||||||
math and GBFS source rules are available under `gods-eye-view/sources/`.
|
math and GBFS source rules are available under `gods-eye-view/sources/`.
|
||||||
The browser layers and their rendering remain in their existing modules.
|
The browser layers and their rendering remain in their existing modules.
|
||||||
|
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.
|
||||||
|
|
||||||
## Terrain height cache bound
|
## Terrain height cache bound
|
||||||
|
|
||||||
|
|||||||
@@ -394,3 +394,55 @@ for (const hook of ['configureServer', 'configurePreviewServer']) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test('unknown GBFS counts stay unknown through the source, model and station color', async () => {
|
||||||
|
const { createRendering } = await import('./rendering.js');
|
||||||
|
const { COLOR_NEUTRAL, COLOR_RED } = await import('./policy.js');
|
||||||
|
for (const missing of [null, '']) {
|
||||||
|
const source = createBikeshareSource({
|
||||||
|
fetchImpl: async () =>
|
||||||
|
Response.json({
|
||||||
|
data: {
|
||||||
|
stations: [
|
||||||
|
{
|
||||||
|
station_id: '2537',
|
||||||
|
num_bikes_available: missing,
|
||||||
|
num_docks_available: 4,
|
||||||
|
is_installed: true,
|
||||||
|
is_renting: true,
|
||||||
|
is_returning: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const model = createModel({});
|
||||||
|
const status = model
|
||||||
|
.parseStationStatus(await source.getStations(AUSTIN.stationStatusUrl))
|
||||||
|
.get('2537');
|
||||||
|
const rendering = createRendering({
|
||||||
|
state: {},
|
||||||
|
services: { render: {} },
|
||||||
|
parts: { model },
|
||||||
|
});
|
||||||
|
assert.equal(status.bikesAvailable, null);
|
||||||
|
assert.equal(
|
||||||
|
model.toNonNegativeInteger(status.bikesAvailable),
|
||||||
|
null,
|
||||||
|
'render-map normalization preserves unknown',
|
||||||
|
);
|
||||||
|
assert.equal(rendering.statusToColor(status, 12), COLOR_NEUTRAL);
|
||||||
|
assert.equal(rendering.resolveCapacity(missing, status), 4);
|
||||||
|
assert.equal(
|
||||||
|
rendering.statusToColor({ ...status, bikesAvailable: 0 }, 12),
|
||||||
|
COLOR_RED,
|
||||||
|
'reported zero is still empty',
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
model.toNonNegativeInteger(missing, 7),
|
||||||
|
7,
|
||||||
|
'caller fallback is preserved',
|
||||||
|
);
|
||||||
|
assert.equal(model.toNonNegativeInteger('3'), 3);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -25,6 +25,7 @@ export function normalizeGbfsBool(value, fallback = true) {
|
|||||||
* @returns {number|null}
|
* @returns {number|null}
|
||||||
*/
|
*/
|
||||||
export function toNonNegativeInteger(value, fallback = null) {
|
export function toNonNegativeInteger(value, fallback = null) {
|
||||||
|
if (value == null || value === '') return fallback;
|
||||||
const n = Number(value);
|
const n = Number(value);
|
||||||
if (!Number.isFinite(n) || n < 0) return fallback;
|
if (!Number.isFinite(n) || n < 0) return fallback;
|
||||||
return Math.round(n);
|
return Math.round(n);
|
||||||
|
|||||||
Reference in new issue
Block a user