This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/static/world/state.js
2026-03-19 02:14:09 -04:00

96 lines
2.8 KiB
JavaScript

/**
* State reader — hardcoded JSON for Phase 2, WebSocket in Phase 3.
*
* Provides Timmy's current state to the scene. In Phase 2 this is a
* static default; the WebSocket path is stubbed for future use.
*/
const DEFAULTS = {
timmyState: {
mood: "focused",
activity: "Pondering the arcane arts",
energy: 0.6,
confidence: 0.7,
},
activeThreads: [],
recentEvents: [],
concerns: [],
visitorPresent: false,
updatedAt: new Date().toISOString(),
version: 1,
};
export class StateReader {
constructor() {
this.state = { ...DEFAULTS };
this.listeners = [];
this._ws = null;
}
/** Subscribe to state changes. */
onChange(fn) {
this.listeners.push(fn);
}
/** Notify all listeners. */
_notify() {
for (const fn of this.listeners) {
try {
fn(this.state);
} catch (e) {
console.warn("State listener error:", e);
}
}
}
/** Try to connect to the world WebSocket for live updates. */
connect() {
const proto = location.protocol === "https:" ? "wss:" : "ws:";
const url = `${proto}//${location.host}/api/world/ws`;
try {
this._ws = new WebSocket(url);
this._ws.onopen = () => {
const dot = document.getElementById("connection-dot");
if (dot) dot.classList.add("connected");
};
this._ws.onclose = () => {
const dot = document.getElementById("connection-dot");
if (dot) dot.classList.remove("connected");
};
this._ws.onmessage = (ev) => {
try {
const msg = JSON.parse(ev.data);
if (msg.type === "world_state" || msg.type === "timmy_state") {
if (msg.timmyState) this.state.timmyState = msg.timmyState;
if (msg.mood) {
this.state.timmyState.mood = msg.mood;
this.state.timmyState.activity = msg.activity || "";
this.state.timmyState.energy = msg.energy ?? 0.5;
}
this._notify();
}
} catch (e) {
/* ignore parse errors */
}
};
} catch (e) {
console.warn("WebSocket unavailable — using static state");
}
}
/** Current mood string. */
get mood() {
return this.state.timmyState.mood;
}
/** Current activity string. */
get activity() {
return this.state.timmyState.activity;
}
/** Energy level 0-1. */
get energy() {
return this.state.timmyState.energy;
}
}