generated from Labyricorn/labyricorn-project-template
One commit for the work accumulated in the working tree since Step 6.3, which had never been split into per-step commits: - src/local-surfaces.js + src/surface-url.js (new); src/ui.js, src/validation.js, src/connection.js and public/index.html updated for local-surface hosting and generic surface rendering - tests: local-surfaces (20), scifi-surfaces (24) and postmessage-interop (7) new; connection/museum-gallery/surface-validation suites updated - reference exhibits: shared/contract-core.js defaults to Contract 5.3 (major 5, minor 3, xzbt 5.3); museum-gallery advertises its surface catalog; aquarium/haunted-house/planetarium adapters updated - SciFi-XZBT (Step 6.7A/6.7B): surface-mode.js + surface-bus.js, Observation-surface boot branch, local-change hooks, view.pillars / view.warp-flight targets; fixture byte-identical to G:/.vibe/SciFi-XZBT - SciFi-XZBT contract adapter handshake fix: the inbound bridge filter no longer gates on an exact advisory xzbt value (Contract 5.3 §6.5), only on its presence/type, matching the host's own envelope validation; the adapter now advertises contract minor 3 / version 5.3.0, which it already implemented via the 5.3 surfaces field. Root cause of the five failing postmessage-interop tests (host hello was silently dropped). - docs: architecture 6.4 and 6.7A, reference 6.6 and 6.7; evidence logs; test-fixtures/PROVENANCE.md resync record Test results: NGN 154/154 (was 149/154); postmessage-interop 7/7 (was 2/7); SciFi contract harness 21/21, real-adapter suite 32/32. git diff --check clean for changed files; two pre-existing trailing-whitespace lines remain in test-fixtures/reference-exhibits/scifi/index.html, copied verbatim from the authoritative SciFi source. Step 6.7 live verification (browser Observation, packaged standalone) is still pending and is not claimed here.
216 lines
6.7 KiB
JavaScript
216 lines
6.7 KiB
JavaScript
/*
|
|
* Planetarium — XZBT Exhibit Contract 5.3 adapter.
|
|
*
|
|
* Declares the catalog, binds targets to real exhibit services, and routes
|
|
* the native UI through the canonical mutation path. No state of its own.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var Core = window.XZBTContractCore;
|
|
|
|
var IDENTITY = {
|
|
product: 'Planetarium',
|
|
version: '1.0.0',
|
|
build: 'reference-exhibit'
|
|
};
|
|
|
|
var DESCRIPTORS = [
|
|
{
|
|
id: 'sky.constellation',
|
|
kind: 'selection',
|
|
label: 'Constellation',
|
|
description: 'Constellation currently tracked and drawn.',
|
|
options: [
|
|
{ value: 'orion', label: 'Orion' },
|
|
{ value: 'cygnus', label: 'Cygnus' },
|
|
{ value: 'scorpius', label: 'Scorpius' },
|
|
{ value: 'ursa-major', label: 'Ursa Major' },
|
|
{ value: 'cassiopeia', label: 'Cassiopeia' },
|
|
{ value: 'lyra', label: 'Lyra' }
|
|
],
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.magnitude-limit',
|
|
kind: 'range',
|
|
label: 'Magnitude limit',
|
|
description: 'Faintest stellar magnitude rendered. Higher values show more stars.',
|
|
min: 1, max: 6, step: 0.1, unit: 'mag',
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.azimuth',
|
|
kind: 'range',
|
|
label: 'Azimuth',
|
|
description: 'Compass bearing of the view, 0 to 1 of a full turn.',
|
|
min: 0, max: 1, step: 0.01,
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.altitude',
|
|
kind: 'range',
|
|
label: 'Altitude',
|
|
description: 'Elevation of the view above the horizon, 0 to 1.',
|
|
min: 0, max: 1, step: 0.01,
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.time-scale',
|
|
kind: 'range',
|
|
label: 'Time scale',
|
|
description: 'Rate at which sky time advances.',
|
|
min: 0, max: 4, step: 0.05, unit: 'x',
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.filter',
|
|
kind: 'selection',
|
|
label: 'Filter',
|
|
description: 'Optical filter applied to the view.',
|
|
options: [
|
|
{ value: 'none', label: 'None' },
|
|
{ value: 'light-pollution', label: 'Light pollution' },
|
|
{ value: 'h-alpha', label: 'H-alpha' },
|
|
{ value: 'oxygen-iii', label: 'Oxygen III' }
|
|
],
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.tracking',
|
|
kind: 'state',
|
|
valueType: 'boolean',
|
|
label: 'Tracking',
|
|
description: 'Whether the mount is tracking the selected constellation.',
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'sky.paused',
|
|
kind: 'state',
|
|
valueType: 'boolean',
|
|
label: 'Sky frozen',
|
|
description: 'Whether sky time is frozen.',
|
|
readable: true, writable: true, restorable: true,
|
|
category: 'sky', requires: []
|
|
},
|
|
{
|
|
id: 'action.advance-time',
|
|
kind: 'impulse',
|
|
label: 'Advance time',
|
|
description: 'Advance sky time. Optional argument: minutes (1 to 240).',
|
|
arguments: [
|
|
{ name: 'minutes', type: 'number', required: false, min: 1, max: 240, default: 10 }
|
|
],
|
|
readable: false, writable: false, restorable: false,
|
|
category: 'action', requires: []
|
|
},
|
|
{
|
|
id: 'action.reset-sky',
|
|
kind: 'impulse',
|
|
label: 'Reset sky',
|
|
description: 'Return sky time to epoch.',
|
|
readable: false, writable: false, restorable: false,
|
|
category: 'action', requires: []
|
|
},
|
|
{
|
|
id: 'action.toggle-tracking',
|
|
kind: 'impulse',
|
|
label: 'Toggle tracking',
|
|
description: 'Engage or disengage the mount.',
|
|
readable: false, writable: false, restorable: false,
|
|
category: 'action', requires: []
|
|
},
|
|
{
|
|
id: 'telemetry.visible-stars',
|
|
kind: 'state',
|
|
valueType: 'number',
|
|
label: 'Visible stars',
|
|
description: 'Stars currently above the magnitude limit.',
|
|
readable: true, writable: false, restorable: false,
|
|
category: 'telemetry', requires: []
|
|
},
|
|
{
|
|
id: 'telemetry.sky-time',
|
|
kind: 'state',
|
|
valueType: 'number',
|
|
unit: 'h',
|
|
label: 'Sky time',
|
|
description: 'Elapsed sky time in hours.',
|
|
readable: true, writable: false, restorable: false,
|
|
category: 'telemetry', requires: []
|
|
},
|
|
{
|
|
id: 'telemetry.moon-phase',
|
|
kind: 'state',
|
|
valueType: 'number',
|
|
label: 'Moon phase',
|
|
description: 'Lunar phase as a fraction of the cycle.',
|
|
readable: true, writable: false, restorable: false,
|
|
category: 'telemetry', requires: []
|
|
}
|
|
];
|
|
|
|
function createPlanetariumContract(exhibit, ui) {
|
|
var catalog = new Core.Catalog(DESCRIPTORS);
|
|
|
|
var capabilities = new Core.CapabilityRegistry();
|
|
capabilities.declare('render', 'ready');
|
|
|
|
var setters = {
|
|
'sky.constellation': function (v) { return exhibit.setConstellation(v); },
|
|
'sky.magnitude-limit': function (v) { return exhibit.setMagnitudeLimit(v); },
|
|
'sky.azimuth': function (v) { return exhibit.setAzimuth(v); },
|
|
'sky.altitude': function (v) { return exhibit.setAltitude(v); },
|
|
'sky.time-scale': function (v) { return exhibit.setTimeScale(v); },
|
|
'sky.filter': function (v) { return exhibit.setFilter(v); },
|
|
'sky.tracking': function (v) { return exhibit.setTracking(v); },
|
|
'sky.paused': function (v) { return exhibit.setPaused(v); }
|
|
};
|
|
|
|
var readers = {};
|
|
var ids = catalog.ids();
|
|
for (var i = 0; i < ids.length; i++) {
|
|
(function (id) {
|
|
readers[id] = function () { return exhibit.read(id); };
|
|
})(ids[i]);
|
|
}
|
|
|
|
var actions = {
|
|
'action.advance-time': function (args) { return exhibit.advanceTime(args); },
|
|
'action.reset-sky': function () { return exhibit.resetSky(); },
|
|
'action.toggle-tracking': function () { return exhibit.toggleTracking(); }
|
|
};
|
|
|
|
var core = new Core.ContractCore({
|
|
identity: IDENTITY,
|
|
catalog: catalog,
|
|
capabilities: capabilities,
|
|
setters: setters,
|
|
readers: readers,
|
|
actions: actions
|
|
});
|
|
|
|
ui.dispatchOverride = function (targetId, value) {
|
|
core.applyMutation(targetId, value, 'ui');
|
|
ui.sync();
|
|
};
|
|
ui.invokeOverride = function (targetId, args) {
|
|
core.invokeAction(targetId, args || {}, 'ui');
|
|
ui.sync();
|
|
};
|
|
|
|
exhibit.onChange = function () { ui.sync(); };
|
|
|
|
return core;
|
|
}
|
|
|
|
window.PlanetariumContract = { create: createPlanetariumContract, IDENTITY: IDENTITY };
|
|
})();
|