v1.12.0 — takeoff & landing phases on the marker
CI / build + unit + e2e (pull_request) Failing after 7m29s

Every leg gains a 10-min takeoff phase at the origin and a 10-min
landing phase at the destination, each weather-scaled up to 2x via a
monotone condition rule (Clear < Cloudy < Rain < Fog). Single
composition in lib/sim/movement.ts: BASE_PHASE_MS, phaseFactor,
MAX_PHASE_FACTOR, legPhases; arrivalTimeFor and progressAt route
through it (progress is now piecewise — hold at origin / linear cruise
/ hold at destination), so engine arrival gate, client position/fuel
recompute and the job expiry floor all agree. Phases burn no fuel.

Marker shows the current phase next to the status in the popup
(mapData derives it from departureSimTime + clockMs; new
data-testid=plane-phase sibling). plane-status keeps the raw status.

Tests: movement.test.ts (phaseFactor bounds/monotonicity, origin-vs-dest
composition, piecewise progressAt), engine.test.ts (deleted local travelMs
mirror — all ~18 fixture clocks use the real composition), seed.test.ts
(phase-inclusive expiry floor mirrors). New e2e/phases.spec.ts asserts
'taking off' at the origin gate and 'landing' at the destination gate on
EDDF→LEMD using the same legPhases boundaries as the engine.
This commit is contained in:
2026-09-28 07:09:19 +00:00
parent db5ad639fb
commit 82e4c64206
12 changed files with 451 additions and 67 deletions
+4 -1
View File
@@ -326,12 +326,15 @@ export default function FlightMap({ state, hovered, applySnapshot, onLogout, isA
if (!f) return;
const p = f.properties as PlaneFeatureProps;
const routeLine = p.routeText ? `<br/><span data-testid="plane-route">${escapeHtml(p.routeText)}</span>` : '';
// v1.12.0: phase label next to the status — "flying · taking off" etc. plane-status keeps
// the raw status so existing assertions on it stay exact.
const phaseLine = p.phaseLabel ? `<span data-testid="plane-phase"> · ${p.phaseLabel}</span>` : '';
new maplibregl.Popup({ offset: 12 })
.setLngLat(f.geometry.coordinates as [number, number])
.setHTML(
`<div data-testid="plane-popup">` +
`<strong>${escapeHtml(p.modelLabel)}</strong><br/>` +
`<span data-testid="plane-status">${p.status}</span><br/>` +
`<span data-testid="plane-status">${p.status}</span>${phaseLine}<br/>` +
`fuel <span data-testid="plane-fuel">${p.fuelText}</span>` +
routeLine +
`</div>`,