GODSIGH/js/layers/events.js
jing 6c7b945848 phases 2-5: satellite, aircraft, ship, infra & event layers
- satellites: Celestrak TLE -> SGP4 -> time-dynamic entities w/ glowing orbit
  paths; per-source cap + reordering so COSMOS/ISS aren't starved by the 72-sat
  Gaofen fleet (now ~97 sats, diverse); chunked propagation, orbital InfoBox
- aircraft: global OpenSky ADS-B -> BillboardCollection primitive (6444 planes
  verified), altitude-banded, quota/scrub/visibility-gated polling, click overlay
- ships: [DEMO] fleet through Hormuz incl. toll-route carrier, dark-vessel AIS
  gap, Fujairah idle cluster; optional aisstream.io live path
- infra: choke-point rings, Petroline + Habshan-Fujairah pipelines, 9 facilities
- events: [DEMO] time-anchored pulsing markers that appear as the slider crosses
- authored + adversarially hardened via parallel agent workflow

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 12:25:51 +10:00

88 lines
3.2 KiB
JavaScript

// SPEC §6.5 — DEMO time-anchored event markers.
// Each marker's availability starts at its event time (now + offset) and runs to
// ctx.stop, so it APPEARS as the timeline slider crosses its moment. Every marker
// is an ILLUSTRATIVE PLACEHOLDER for a future real event feed — NOT a real record.
export default function create(ctx) {
const { viewer, CONFIG, lib, ui, Cesium, now, stop } = ctx;
const eventsDS = new Cesium.CustomDataSource('events');
viewer.dataSources.add(eventsDS);
const DISCLAIMER =
'ILLUSTRATIVE PLACEHOLDER — this is a DEMO marker, not a real strike/event ' +
'record. It stands in for a future real event feed.';
// offsetHours = when the marker appears (relative to wall-clock now).
const markers = [
{
name: 'Command installation strike [DEMO]',
lon: 51.4, lat: 32.6, offsetHours: -3,
blurb: 'Simulated ground strike on a command installation (inland Iran, approx coords).',
},
{
name: 'Recon satellite pass correlation [DEMO]',
lon: 51.4, lat: 32.6, offsetHours: -2,
blurb: 'Simulated correlation of a recon satellite pass with the site above (approx coords).',
},
{
name: 'Tanker incident [DEMO]',
lon: 56.5, lat: 26.5, offsetHours: 1,
blurb: 'Simulated tanker incident in the Strait of Hormuz (approx coords).',
},
{
name: 'Air-defense activation [DEMO]',
lon: 54.4, lat: 27.2, offsetHours: 3,
blurb: 'Simulated air-defense radar activation near the northern Gulf coast (approx coords).',
},
];
const color = lib.cz(CONFIG.colors.event);
let added = 0;
for (const m of markers) {
const eventTime = Cesium.JulianDate.addHours(now, m.offsetHours, new Cesium.JulianDate());
const when = m.offsetHours < 0
? `now ${m.offsetHours}h`
: `now +${m.offsetHours}h`;
eventsDS.entities.add({
name: m.name,
position: Cesium.Cartesian3.fromDegrees(m.lon, m.lat),
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({ start: eventTime, stop }),
]),
point: {
// Browser-time pulse: correct to run at render time (per SPEC note).
pixelSize: new Cesium.CallbackProperty(() => 8 + 4 * Math.sin(Date.now() / 300), false),
color,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 1.5,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
label: {
text: m.name,
font: '12px sans-serif',
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 3,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -14),
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
description:
`<p><strong>${m.name}</strong></p>` +
`<p>${m.blurb}</p>` +
`<p>Appears at: ${when} (${m.lat.toFixed(2)}, ${m.lon.toFixed(2)}).</p>` +
`<p style="color:#ff9f40"><strong>${DISCLAIMER}</strong></p>`,
});
added += 1;
}
ui.addLayer('events', 'Events [DEMO]', true, (on) => { eventsDS.show = on; });
ui.setStatus('events', `${added} markers [DEMO]`, 'ok');
return { id: 'events' };
}