mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Merge branch 'main' into fix/tracked-info-vertical-rate
This commit is contained in:
476 files changed
+34589
-4748
No files matched your search
@@ -1,5 +1,9 @@
|
||||
import { ERROR_BACKOFF_INTERVAL } from './recordPolicy.js';
|
||||
|
||||
// Marks English the Layers panel translates when it shows the error. Kept
|
||||
// local: this module stays free of browser globals (package boundaries).
|
||||
const msg = (text) => text;
|
||||
|
||||
/** Own acquisition, cancellation, freshness and backoff independently of rendering. */
|
||||
export function createIngestion({
|
||||
feed,
|
||||
@@ -41,9 +45,10 @@ export function createIngestion({
|
||||
const sourceStale = snapshot.stale || snapshot.freshness === 'unknown';
|
||||
feed._backoff = sourceStale;
|
||||
feed._retryAt = 0;
|
||||
// i18n-ignore: English data; the panel shows it through FEED_ERROR_PATTERNS (ui/statusText.js)
|
||||
feed._lastError = sourceStale
|
||||
? sourceAgeMs == null
|
||||
? 'Source snapshot time unavailable'
|
||||
? msg('Source snapshot time unavailable')
|
||||
: `Source snapshot ${Math.max(2, Math.round(sourceAgeMs / 60_000))} min old`
|
||||
: null;
|
||||
feed._lastSource = snapshot.source;
|
||||
@@ -77,7 +82,9 @@ export function createIngestion({
|
||||
setSourceLabel(feed._lastSource);
|
||||
}
|
||||
feed._lastError =
|
||||
e?.name === 'LiveSourceError' ? e.message : 'Live data unavailable';
|
||||
e?.name === 'LiveSourceError'
|
||||
? e.message
|
||||
: msg('Live data unavailable');
|
||||
} finally {
|
||||
feed._activeUpdateControllers.delete(resourceController);
|
||||
}
|
||||
|
||||
@@ -13,9 +13,4 @@ export const MISSING_POLL_LIMIT = 3;
|
||||
export const ERROR_BACKOFF_INTERVAL = 20000;
|
||||
|
||||
/** Local equirectangular distance used for viewer-proximate floor sampling. */
|
||||
export function approxDistanceKm(lat1, lon1, lat2, lon2) {
|
||||
const dLat = (lat2 - lat1) * 111.32;
|
||||
const dLon =
|
||||
(lon2 - lon1) * 111.32 * Math.cos((((lat1 + lat2) / 2) * Math.PI) / 180);
|
||||
return Math.hypot(dLat, dLon);
|
||||
}
|
||||
export { approxDistanceKm } from '../../data/approxDistance.js';
|
||||
@@ -0,0 +1,18 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
approxDistanceKm,
|
||||
GROUND_FLOOR_CLAMP_RADIUS_KM,
|
||||
} from './recordPolicy.js';
|
||||
|
||||
test('approximate distance takes the short way across the antimeridian', () => {
|
||||
// 0.2° of longitude at Taveuni, Fiji (16.8° S) is about 21 km.
|
||||
for (const [lon1, lon2] of [
|
||||
[179.9, -179.9],
|
||||
[-179.9, 179.9],
|
||||
]) {
|
||||
const km = approxDistanceKm(-16.8, lon1, -16.8, lon2);
|
||||
assert.ok(Math.abs(km - 21.31) < 0.01, `${lon1} → ${lon2}: ${km} km`);
|
||||
assert.ok(km <= GROUND_FLOOR_CLAMP_RADIUS_KM);
|
||||
}
|
||||
});
|
||||
@@ -1,4 +1,6 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { formatNumber, t } from '../../i18n/index.js';
|
||||
import { unitLabel } from '../../ui/unitLabels.js';
|
||||
import { nextCockpitNearContacts } from '../../data/cockpitAirLod.js';
|
||||
import { trackedModelZoomActive } from '../../data/trackedModelRegime.js';
|
||||
import {
|
||||
@@ -130,6 +132,7 @@ export function createTracking({
|
||||
icao24,
|
||||
// Honesty cue: the contact is coasting on dead reckoning, so the
|
||||
// narrated position/velocity are last-known rather than live.
|
||||
// i18n-ignore: voice-context data, English for the model
|
||||
status: described.stale ? 'stale (missed polls)' : 'live',
|
||||
},
|
||||
};
|
||||
@@ -751,11 +754,18 @@ export function createTracking({
|
||||
// the tail number rather than raw hex.
|
||||
const cs = parts.queries._contactLabel(icao24, info);
|
||||
const altFt = Math.round((info.altitude || 0) * 3.28084);
|
||||
const fl = altFt >= 18000 ? `FL${Math.round(altFt / 100)}` : `${altFt} ft`;
|
||||
const spd = info.velocity ? `${Math.round(info.velocity * 1.944)} kts` : '';
|
||||
// Flight levels are an aviation code; feet and knots read in the active
|
||||
// language ("0 фт · 1 уз").
|
||||
const quantity = (value, unit) =>
|
||||
`${formatNumber(value, { useGrouping: false })} ${unitLabel(unit)}`;
|
||||
const fl =
|
||||
altFt >= 18000 ? `FL${Math.round(altFt / 100)}` : quantity(altFt, 'ft');
|
||||
const spd = info.velocity
|
||||
? quantity(Math.round(info.velocity * 1.944), 'kts')
|
||||
: '';
|
||||
const stale =
|
||||
flightState.records.missingPolls.get(icao24) || flightState.feed._backoff
|
||||
? 'STALE'
|
||||
? t('STALE')
|
||||
: '';
|
||||
const lines = [[cs, fl, spd, stale].filter(Boolean).join(' · ')];
|
||||
// Converted contacts report their class as TR-3B and nothing else — the
|
||||
|
||||
Reference in new issue
Block a user