Phase 1 of app.js modularization (Refs #409, Fixes #420). Adds four modules under modules/core/: - theme.js: exports NEXUS with full NEXUS.theme (colors, fonts, lineWeights, glowParams, opacity). NEXUS.colors preserved as backwards-compat alias. - state.js: exports zoneIntensity (shared mutable object), state (agentCount, blockHeight, starPulseIntensity, weather), and totalActivity(). - scene.js: creates and exports scene, camera, renderer, orbitControls, raycaster, lighting. Registers camera+renderer resize handler. Intentionally does not append renderer.domElement — app.js controls DOM insertion order. - ticker.js: single requestAnimationFrame loop. Exports subscribe(), unsubscribe(), start(), stop(). app.js registers animate() via tickerSubscribe and calls tickerStart() instead of RAF directly. app.js changes: - Imports NEXUS from theme.js (removes inline NEXUS definition) - Imports scene/camera/renderer/orbitControls/raycaster from scene.js (removes duplicate creation blocks) - Imports zoneIntensity/state/totalActivity from state.js (removes local defs) - animate() is now a ticker subscriber function, not a recursive RAF caller - _activeAgentCount → state.agentCount - _starPulseIntensity → state.starPulseIntensity - lastKnownBlockHeight → state.blockHeight - EffectComposer resize listener preserved separately in app.js node --check app.js passes. No visual regressions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 lines
1.6 KiB
JavaScript
50 lines
1.6 KiB
JavaScript
/**
|
|
* modules/core/state.js — Shared reactive data bus.
|
|
*
|
|
* Data modules write here; visual modules read from here.
|
|
* No fetch() calls live in this file — state is populated by data/ modules.
|
|
*
|
|
* Design:
|
|
* - zoneIntensity is exported directly so callers can mutate it by reference.
|
|
* - state holds scalar/object fields; mutate properties directly (state.agentCount = N).
|
|
* - totalActivity() is a derived getter over zoneIntensity.
|
|
*/
|
|
|
|
/**
|
|
* Per-zone commit activity intensity values (0..1).
|
|
* Keys are zone names matching HEATMAP_ZONES entries in app.js.
|
|
* Populated at init time once HEATMAP_ZONES is available.
|
|
* @type {Record<string, number>}
|
|
*/
|
|
export const zoneIntensity = {};
|
|
|
|
/**
|
|
* Global shared state — all fields are mutable by their respective data sources.
|
|
*/
|
|
export const state = {
|
|
/** Current Bitcoin block height. null until first fetch. @type {number|null} */
|
|
blockHeight: null,
|
|
|
|
/** Weather payload from Open-Meteo. null until first fetch. @type {object|null} */
|
|
weather: null,
|
|
|
|
/** Number of agents currently in 'working' status. Updated by agent status fetch. */
|
|
agentCount: 0,
|
|
|
|
/**
|
|
* Star pulse intensity driven by new Bitcoin block events.
|
|
* 0 = base brightness, 1 = peak. Decays each frame.
|
|
*/
|
|
starPulseIntensity: 0,
|
|
};
|
|
|
|
/**
|
|
* Returns mean activity level [0..1] across all agent zones.
|
|
* Used by matrix rain, energy beam, holographic earth, etc.
|
|
* @returns {number}
|
|
*/
|
|
export function totalActivity() {
|
|
const vals = Object.values(zoneIntensity);
|
|
return vals.reduce((s, v) => s + v, 0) / Math.max(vals.length, 1);
|
|
}
|