mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
fix(tools): exclude unknown altitude from requested aircraft bands (#1115)
aircraft_in_area compared a nullable altitude, so a contact with neither barometric nor geometric altitude matched max_altitude_m as though it were at zero. Require a reported finite altitude only when a band is requested; unfiltered queries keep the contact.
This commit is contained in:
1 parent
e5ee6696b1
commit
fa8e3e989f
4 files changed
+66
No files matched your search
@@ -0,0 +1,2 @@
|
||||
- Exclude aircraft without a reported altitude from requested altitude bands;
|
||||
unfiltered aircraft queries still retain them (rudycelekli, #1115).
|
||||
@@ -100,6 +100,9 @@ shared `area` argument (place name, bounding box, or point and radius) and cap
|
||||
lists at 25 rows by default. Voice offers the same queries next to its app
|
||||
actions: the session lists them, and the browser runs them through the same
|
||||
catalog, loaded on first use. See [tools and the MCP server](TOOLS.md).
|
||||
Aircraft altitude-band queries require a reported barometric or geometric altitude
|
||||
for each match, so a grounded contact that reports none is left out of a band too.
|
||||
Queries without an altitude band retain unknown-altitude contacts.
|
||||
|
||||
Catalog calls check their cancellation signal immediately before executing a
|
||||
tool. Already-cancelled queries do not start; cancellation after execution starts
|
||||
|
||||
@@ -111,6 +111,8 @@ export const aircraftInArea = defineTool({
|
||||
(record) =>
|
||||
areaContains(area, { lat: record.latitude, lon: record.longitude }) &&
|
||||
!(args.airborne_only && record.onGround) &&
|
||||
((args.min_altitude_m == null && args.max_altitude_m == null) ||
|
||||
Number.isFinite(altitude(record))) &&
|
||||
(args.min_altitude_m == null ||
|
||||
altitude(record) >= args.min_altitude_m) &&
|
||||
(args.max_altitude_m == null ||
|
||||
|
||||
@@ -388,3 +388,62 @@ test('the real OpenSky source marks an hour-old snapshot stale for searches', as
|
||||
assert.deepEqual(result.data.stale_feeds, ['civil']);
|
||||
assert.match(result.summary, /may be stale\.$/);
|
||||
});
|
||||
|
||||
test('altitude bands require a reported altitude from normalized OpenSky records', async () => {
|
||||
const { normalizeOpenSkyAircraft } =
|
||||
await import('../../sources/live/aircraft.js');
|
||||
const state = (id, baro, geometric) =>
|
||||
normalizeOpenSkyAircraft([
|
||||
id,
|
||||
'TEST',
|
||||
'Test',
|
||||
1767225600,
|
||||
1767225600,
|
||||
0,
|
||||
0,
|
||||
baro,
|
||||
false,
|
||||
10,
|
||||
90,
|
||||
0,
|
||||
[],
|
||||
geometric,
|
||||
]);
|
||||
const records = [
|
||||
state('abc001', null, null),
|
||||
state('abc002', 0, null),
|
||||
state('abc003', null, 50),
|
||||
state('abc004', 500, null),
|
||||
];
|
||||
const catalog = composeCatalog({
|
||||
tools: coreTools,
|
||||
services: {
|
||||
aircraft: { getSnapshot: async () => ({ records }) },
|
||||
},
|
||||
});
|
||||
const area = { bbox: [-1, -1, 1, 1] };
|
||||
assert.equal(
|
||||
(await catalog.call('aircraft_in_area', { area })).data.total,
|
||||
4,
|
||||
'unfiltered answers retain unknown altitude',
|
||||
);
|
||||
for (const band of [
|
||||
{ max_altitude_m: 100 },
|
||||
{ min_altitude_m: -500, max_altitude_m: 100 },
|
||||
]) {
|
||||
const result = await catalog.call('aircraft_in_area', { area, ...band });
|
||||
assert.deepEqual(
|
||||
result.data.rows.map((row) => row.id),
|
||||
['abc002', 'abc003'],
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.data.rows.map((row) => row.altitude_m),
|
||||
[0, 50],
|
||||
);
|
||||
}
|
||||
const minimum = await catalog.call('aircraft_in_area', {
|
||||
area,
|
||||
min_altitude_m: -500,
|
||||
});
|
||||
assert.equal(minimum.data.total, 3);
|
||||
});
|
||||
Reference in new issue
Block a user