mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Release God's Eye View as open source
This commit is contained in:
1 parent
a5aaea7e16
commit
880a672b5e
433 files changed
+219893
-23
No files matched your search
@@ -0,0 +1,169 @@
|
||||
// One-click transfer pipeline for clicked world targets (pre-launch defect #4).
|
||||
// The layer only announces the click; the UI owns the camera.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import * as Cesium from 'cesium';
|
||||
import {
|
||||
WORLD_CLICK_FOCUS_DURATION_SEC,
|
||||
WORLD_FOCUS_FRAMING,
|
||||
WORLD_FOCUS_REQUEST_EVENT,
|
||||
flyToWorldTarget,
|
||||
isValidWorldFocusTarget,
|
||||
registerWorldFocusRequestListener,
|
||||
requestWorldFocus,
|
||||
routeWorldFocusRequest,
|
||||
} from './worldFocus.js';
|
||||
|
||||
const POSITION = Cesium.Cartesian3.fromDegrees(-97.74, 30.26, 0);
|
||||
|
||||
function stubCamera() {
|
||||
const calls = { cancelFlight: 0, flights: [] };
|
||||
return {
|
||||
calls,
|
||||
heading: Cesium.Math.toRadians(45),
|
||||
cancelFlight() { calls.cancelFlight += 1; },
|
||||
flyToBoundingSphere(sphere, options) { calls.flights.push({ sphere, options }); },
|
||||
};
|
||||
}
|
||||
|
||||
test('a focus request carries the clicked target to any registered listener', () => {
|
||||
const target = new EventTarget();
|
||||
const seen = [];
|
||||
const dispose = registerWorldFocusRequestListener(target, (event) => seen.push(event.detail));
|
||||
assert.equal(requestWorldFocus({ kind: 'vessel', position: POSITION, id: '123' }, target), true);
|
||||
assert.equal(seen.length, 1);
|
||||
assert.equal(seen[0].kind, 'vessel');
|
||||
assert.equal(seen[0].id, '123');
|
||||
// Disposal is idempotent and removes the exact listener.
|
||||
dispose();
|
||||
dispose();
|
||||
requestWorldFocus({ kind: 'vessel', id: '123', position: POSITION }, target);
|
||||
assert.equal(seen.length, 1);
|
||||
});
|
||||
|
||||
test('requests without a kind or a position are dropped, never dispatched', () => {
|
||||
const target = new EventTarget();
|
||||
let count = 0;
|
||||
target.addEventListener(WORLD_FOCUS_REQUEST_EVENT, () => { count += 1; });
|
||||
assert.equal(requestWorldFocus({ position: POSITION }, target), false);
|
||||
assert.equal(requestWorldFocus({ kind: 'vessel' }, target), false);
|
||||
assert.equal(requestWorldFocus(null, target), false);
|
||||
assert.equal(count, 0);
|
||||
});
|
||||
|
||||
test('routing hands the request to the UI policy, which owns the flight', () => {
|
||||
const order = [];
|
||||
const result = routeWorldFocusRequest(
|
||||
{ detail: { kind: 'fire', id: 'fire-1', position: POSITION } },
|
||||
(detail, fly) => {
|
||||
order.push(`policy:${detail.kind}`);
|
||||
return fly();
|
||||
},
|
||||
(detail) => {
|
||||
order.push(`fly:${detail.kind}`);
|
||||
return 'flew';
|
||||
},
|
||||
);
|
||||
// The policy runs FIRST — it releases the follow camera before the flight.
|
||||
assert.deepEqual(order, ['policy:fire', 'fly:fire']);
|
||||
assert.equal(result, 'flew');
|
||||
});
|
||||
|
||||
test('a refusing policy (cockpit owns the camera) never reaches the flight', () => {
|
||||
let flights = 0;
|
||||
const result = routeWorldFocusRequest(
|
||||
{ detail: { kind: 'vessel', id: '123', position: POSITION } },
|
||||
() => false,
|
||||
() => { flights += 1; },
|
||||
);
|
||||
assert.equal(result, false);
|
||||
assert.equal(flights, 0);
|
||||
});
|
||||
|
||||
test('malformed requests are inert', () => {
|
||||
assert.equal(routeWorldFocusRequest(null, () => 'x', () => 'y'), false);
|
||||
assert.equal(routeWorldFocusRequest({ detail: { kind: 'vessel' } }, () => 'x', () => 'y'), false);
|
||||
});
|
||||
|
||||
// A request that cannot fly must never cost the user their tracking: the UI
|
||||
// policy releases the follow camera, so validation happens BEFORE it runs.
|
||||
test('an unflyable request never reaches the release policy', () => {
|
||||
const unflyable = [
|
||||
{ kind: 'plane', position: POSITION }, // no framing for this kind
|
||||
{ kind: 'vessel', position: { x: NaN, y: 0, z: 0 } }, // malformed position
|
||||
{ kind: 'vessel', position: { x: 0, y: 0 } }, // truthy but incomplete
|
||||
{ kind: 'vessel', id: '123', position: { x: 0, y: 0, z: 0 } }, // ECEF origin
|
||||
{ kind: 'fire', id: 'fire-1', position: { x: 1, y: 1, z: 1 } }, // finite but inside Earth
|
||||
{ kind: 'vessel', position: 'somewhere' },
|
||||
{ kind: 'vessel', position: POSITION }, // missing owner id
|
||||
{ position: POSITION },
|
||||
];
|
||||
for (const detail of unflyable) {
|
||||
assert.equal(isValidWorldFocusTarget(detail), false, JSON.stringify(detail));
|
||||
let policyRuns = 0;
|
||||
const result = routeWorldFocusRequest(
|
||||
{ detail },
|
||||
() => { policyRuns += 1; return 'released'; },
|
||||
() => 'flew',
|
||||
);
|
||||
assert.equal(result, false, JSON.stringify(detail));
|
||||
assert.equal(policyRuns, 0, `the policy must not run for ${JSON.stringify(detail)}`);
|
||||
// Nor may such a request be dispatched in the first place.
|
||||
assert.equal(requestWorldFocus(detail, new EventTarget()), false);
|
||||
}
|
||||
assert.equal(isValidWorldFocusTarget({ kind: 'vessel', id: '123', position: POSITION }), true);
|
||||
assert.equal(isValidWorldFocusTarget({ kind: 'fire', id: 'fire-1', position: POSITION }), true);
|
||||
});
|
||||
|
||||
test('the transfer flight supersedes any flight in progress and keeps the operator heading', () => {
|
||||
const camera = stubCamera();
|
||||
assert.equal(flyToWorldTarget({ camera }, { kind: 'vessel', id: '123', position: POSITION }), true);
|
||||
assert.equal(camera.calls.cancelFlight, 1, 'a prior flight must be cancelled, not queued');
|
||||
assert.equal(camera.calls.flights.length, 1);
|
||||
const { sphere, options } = camera.calls.flights[0];
|
||||
assert.equal(sphere.radius, WORLD_FOCUS_FRAMING.vessel.radiusM);
|
||||
assert.equal(options.duration, WORLD_CLICK_FOCUS_DURATION_SEC);
|
||||
assert.equal(options.offset.range, WORLD_FOCUS_FRAMING.vessel.rangeM);
|
||||
// Heading is preserved so the transfer never spins the operator around.
|
||||
assert.equal(options.offset.heading, camera.heading);
|
||||
assert.equal(options.easingFunction, Cesium.EasingFunction.CUBIC_IN_OUT);
|
||||
});
|
||||
|
||||
test('fires frame wider than vessels — a fire is read by its surroundings', () => {
|
||||
const camera = stubCamera();
|
||||
flyToWorldTarget({ camera }, { kind: 'fire', id: 'fire-1', position: POSITION });
|
||||
const { sphere, options } = camera.calls.flights[0];
|
||||
assert.equal(sphere.radius, WORLD_FOCUS_FRAMING.fire.radiusM);
|
||||
assert.equal(options.offset.range, WORLD_FOCUS_FRAMING.fire.rangeM);
|
||||
assert.ok(WORLD_FOCUS_FRAMING.fire.rangeM > WORLD_FOCUS_FRAMING.vessel.rangeM);
|
||||
assert.ok(WORLD_FOCUS_FRAMING.fire.radiusM > WORLD_FOCUS_FRAMING.vessel.radiusM);
|
||||
});
|
||||
|
||||
test('every framing is a real oblique standoff, not a nadir or an inside-out sphere', () => {
|
||||
const kinds = Object.keys(WORLD_FOCUS_FRAMING);
|
||||
assert.deepEqual(kinds.sort(), ['fire', 'vessel']);
|
||||
for (const kind of kinds) {
|
||||
const framing = WORLD_FOCUS_FRAMING[kind];
|
||||
// Looking DOWN at the target, but obliquely — a nadir drop reads as a map.
|
||||
assert.ok(framing.pitchDeg < 0, `${kind}: pitch must look down, got ${framing.pitchDeg}`);
|
||||
assert.ok(framing.pitchDeg > -80, `${kind}: pitch must stay oblique, got ${framing.pitchDeg}`);
|
||||
// Standing off outside the framed sphere, at a human-readable distance.
|
||||
assert.ok(framing.radiusM > 0, `${kind}: radius must be positive`);
|
||||
assert.ok(
|
||||
framing.rangeM > framing.radiusM,
|
||||
`${kind}: range ${framing.rangeM} must stand off outside radius ${framing.radiusM}`,
|
||||
);
|
||||
assert.ok(framing.rangeM <= 10000, `${kind}: range must stay close-in, got ${framing.rangeM}`);
|
||||
}
|
||||
// Exact shipped values — a silent retune must show up as a failing test.
|
||||
assert.deepEqual({ ...WORLD_FOCUS_FRAMING.vessel }, { radiusM: 150, rangeM: 1200, pitchDeg: -30 });
|
||||
assert.deepEqual({ ...WORLD_FOCUS_FRAMING.fire }, { radiusM: 400, rangeM: 3000, pitchDeg: -35 });
|
||||
});
|
||||
|
||||
test('unknown kinds and missing viewers issue no flight', () => {
|
||||
const camera = stubCamera();
|
||||
assert.equal(flyToWorldTarget({ camera }, { kind: 'plane', position: POSITION }), false);
|
||||
assert.equal(flyToWorldTarget({ camera }, { kind: 'vessel' }), false);
|
||||
assert.equal(flyToWorldTarget(null, { kind: 'vessel', position: POSITION }), false);
|
||||
assert.equal(camera.calls.flights.length, 0);
|
||||
});
|
||||
Reference in new issue
Block a user