Flight queue UI: dotted map line, left-pane Queue sub-section, e2e (ISS-043 part 2)
CI / build + unit + e2e (pull_request) Failing after 6m51s

This commit is contained in:
2026-09-20 11:31:11 +00:00
parent 3395fb4f90
commit 408cd933f4
8 changed files with 592 additions and 5 deletions
+29 -1
View File
@@ -1,4 +1,4 @@
import type { StateSnapshot } from './game/state';
import type { PlaneState, StateSnapshot } from './game/state';
import { formatFuel } from './format';
import { positionAt } from './sim/movement';
@@ -164,3 +164,31 @@ export function routesGeoJson(
}
return { type: 'FeatureCollection', features };
}
// ISS-043 (v0.26.0): the dotted queue line — one LineString per FLYING plane with a non-empty
// queue, chaining dest → queue[0] → … → queue[n−1]: ONLY the not-yet-started legs (the active
// leg locationIcao→dest stays in routesGeoJson's solid layer). Arcs are concatenated with the
// shared joint point dropped once. A plane is skipped — never guessed — when its dest or any
// queued ICAO is missing from the airport index; empty collection when nothing qualifies.
export function queuedRoutesGeoJson(
planes: PlaneState[],
airportsByIcao: ReadonlyMap<string, AirportCoord>,
): FeatureCollection<MapLineFeature> {
const features: MapLineFeature[] = [];
for (const p of planes) {
if (p.status !== 'flying' || !p.destIcao || p.queue.length === 0) continue;
const pts = [p.destIcao, ...p.queue].map((icao) => airportsByIcao.get(icao));
if (pts.some((c) => c === undefined)) continue; // an endpoint is missing from the dataset — skip
const coords: [number, number][] = [];
for (let i = 0; i < pts.length - 1; i++) {
const arc = greatCircleArc(pts[i]!, pts[i + 1]!);
coords.push(...(i === 0 ? arc : arc.slice(1))); // drop the duplicated joint point
}
features.push({
type: 'Feature',
geometry: { type: 'LineString', coordinates: coords },
properties: { planeId: p.id },
});
}
return { type: 'FeatureCollection', features };
}