fix(flights): read a 359.6° track as 0° in the voice context, not 360°

The voice context records for a selected flight or military contact
rounded the track without wrapping, so a contact on 359.5° or more was
described to the assistant as heading "360°". Both now wrap after
rounding: 359.6° reads "0°", 359.4° still reads "359°".
This commit is contained in:
Aditya committed 2026-10-28 18:11:42 +05:30
1 parent a4d3701c3c
commit ac0e124a67
5 files changed
+52 -3

No files matched your search

+22
View File
@@ -3,6 +3,7 @@ import assert from 'node:assert/strict';
import { createCivilFlightLayer } from './index.js';
import { createFlightState } from './state.js';
import { createEnrichment } from './enrichment.js';
import { createTracking } from './tracking.js';
function services() {
const names = [
@@ -124,3 +125,24 @@ test('a synchronous enrichment failure stays bounded and releases its slot', asy
await new Promise((done) => setImmediate(done));
assert.equal(flightState._enrichActive, 0);
});
test('voice context reads a track that rounds to north as 0°, not 360°', () => {
const tracking = createTracking({
flightState: {
feed: { _lastSource: 'Fixture aircraft' },
records: { data: new Map() },
},
services: services(),
parts: {
queries: {
_describeFlight: () => ({ track: 359.6, altitudeM: 9000 }),
_contactLabel: () => 'AAL1',
},
},
layer: {},
});
assert.equal(
tracking._contextSubjectMetadata('abc123').properties.heading,
'0°',
);
});
+2 -1
View File
@@ -125,8 +125,9 @@ export function createTracking({
speed: Number.isFinite(described.velocityMps)
? `${Math.round(described.velocityMps * 1.944)} kt`
: '',
// 359.5° and above rounds to north; modulo keeps it from reading 360°.
heading: Number.isFinite(described.track)
? `${Math.round(described.track)}°`
? `${Math.round(described.track) % 360}°`
: '',
route: route || '',
icao24,
+25
View File
@@ -2,6 +2,7 @@ import test from 'node:test';
import assert from 'node:assert/strict';
import { createMilitaryFlightLayer } from './index.js';
import { createFlightState } from './state.js';
import { createTracking } from './tracking.js';
function services() {
const names = [
@@ -211,3 +212,27 @@ test('a newly seen military contact appears at its delayed position, not ahead o
`expected about ${Math.round(expectedM)} m behind the fix, got ${Math.round(behindM)} m`,
);
});
test('voice context reads a track that rounds to north as 0°, not 360°', () => {
const stubs = services();
stubs.aircraftPresentation = { tr3bTypeLabel: (id, type) => type };
const tracking = createTracking({
flightState: {
feed: { _lastSource: 'Fixture aircraft' },
records: { data: new Map() },
},
services: stubs,
parts: {
queries: {
_describeFlight: () => ({ track: 359.6, callsign: 'RCH123' }),
_toCleanText: (value) => value || '',
_formatAltitude: () => '',
},
},
layer: {},
});
assert.equal(
tracking._contextSubjectMetadata('ae1234').properties.heading,
'0°',
);
});
+2 -1
View File
@@ -119,8 +119,9 @@ export function createTracking({
speed: Number.isFinite(described.velocityMps)
? `${Math.round(described.velocityMps * 1.944)} kt`
: '',
// 359.5° and above rounds to north; modulo keeps it from reading 360°.
heading: Number.isFinite(described.track)
? `${Math.round(described.track)}°`
? `${Math.round(described.track) % 360}°`
: '',
icao24,
// Honesty cue: the contact is coasting on dead reckoning, so the