Klima 3D: Live-State-Hook für Lehrer-Spectator

Atlas-Auftrag aus _inbox/klima/2026-05-05-0140 — analog zum 2D-Hook,
plus 3D-spezifische Felder.

- game-3d.html: window.GGS_LIVE_STATE liefert {variant:'3d', tick, year,
  level, phase, budget, population, co2, temp, floodedPct, seaLevelCm,
  speed, measures, levelWon, tourism, hasShield, hasBeach, placing}.
  Aufruf alle ~4s durch live-client.js, gepostet an /api/live.
- klima-3d.php: Live-Client-Script-Tag nachgezogen (war nur in
  klima-2d.php). Wird wie üblich vor </body> injiziert.

Heartbeat → DB live_sessions, Lehrer-Cockpit zeigt Karten an mit
Live-Kennzahlen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-05 03:42:58 +02:00
parent 2378075915
commit e354a30a44
2 changed files with 40 additions and 4 deletions
+5 -2
View File
@@ -111,10 +111,13 @@ if ($html === false) {
$bp = BASE_PATH;
$baseTag = '<base href="' . htmlspecialchars($bp . '/sims/klima/', ENT_QUOTES) . '">';
$ctxJs = '<script>window.__GGS__ = ' . json_encode($ctx, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . ';</script>';
// Plattform-Live-Client: Heartbeat + Pause-Overlay + Spectator-Mode für ?view=teacher
$liveJs = '<script src="' . htmlspecialchars($bp . '/assets/js/live-client.js', ENT_QUOTES) . '" defer></script>';
// <base>-Tag direkt nach <head> einfügen, damit relative Pfade aus /sims/klima/ heraus auflösen
$html = preg_replace('/<head>/i', '<head>' . "\n" . $baseTag, $html, 1);
// Session-Kontext vor </body>
$html = str_replace('</body>', $ctxJs . "\n</body>", $html);
// Session-Kontext + Live-Client vor </body>
$html = str_replace('</body>', $ctxJs . "\n" . $liveJs . "\n</body>", $html);
$html = str_replace('href="/schueler"', 'href="' . cockpit_href() . '"', $html);
echo $html;
+35 -2
View File
@@ -793,7 +793,7 @@
HEADER
============================================================ -->
<header class="ggs-header" id="header">
<a href="../../" class="ggs-header-logo">
<a href="/schueler" class="ggs-header-logo">
<img src="../../assets/img/bildLogo.png" alt="" class="ggs-header-logo-icon">
<img src="../../assets/img/textlogo_geograsim.svg" alt="GeoGraSim" class="ggs-header-logo-text">
</a>
@@ -822,7 +822,7 @@
<button class="ggs-btn-ghost" id="btn-drone" title="Drohnen-Flug (Kamera dreht automatisch) ein/aus">🚁</button>
<button class="ggs-btn-ghost" id="btn-sound" title="SFX an/aus">🔊</button>
<button class="ggs-btn-ghost" id="btn-reset" title="Neu starten (Arbeitsstand löschen)">🔄</button>
<a href="../../" class="ggs-btn-ghost" title="Zurück">🏠</a>
<a href="/schueler" class="ggs-btn-ghost" title="Zurück zum Cockpit">🏠</a>
</div>
</header>
@@ -1544,6 +1544,34 @@ Object.assign(state, {
pendingCitizenEvent: null,
});
// Live-State-Hook für Lehrer-Spectator (s. _inbox/klima/2026-05-05-0140-…).
// Plattform-`live-client.js` ruft das alle ~4 s und sendet den Snapshot
// an `/api/live`. Selbe Felder wie 2D plus drei 3D-spezifische Flags
// (variant, placing, tourismus) und Citizen-Event-Indikatoren.
window.GGS_LIVE_STATE = function () {
if (!state) return null;
return {
variant: '3d',
tick: state.tick,
year: (state.startYear || 2025) + (state.tick || 0),
level: state.difficulty || state.level || null,
phase: state.phase || null,
budget: Math.round(state.budget || 0),
population: Math.round(state.population || 0),
co2: Math.round(state.co2Ppm || 0),
temp: +(state.currentTemp || 0).toFixed(2),
floodedPct: Math.round(state.floodedPct || 0),
seaLevelCm: Math.round(state.seaLevelCm || 0),
speed: state.speed || 0,
measures: Array.isArray(state.actionLog) ? state.actionLog.filter(a=>a.action==='buy').length : 0,
levelWon: !!state.levelWon,
tourism: !!state.tourismMode,
hasShield: !!state.hasMountainShield,
hasBeach: !!state.hasSandBeach,
placing: typeof placementId !== 'undefined' && placementId !== null ? placementId : null,
};
};
/* ============================================================
UI HELPERS
============================================================ */
@@ -5704,6 +5732,11 @@ const GLOSSAR_DB_KNOWN = new Set([
'klimawandel','kohlenstoffkreislauf','megawatt','methan','nachhaltigkeit',
'pariser-abkommen','permafrost','photovoltaik','ppm','treibhauseffekt',
'treibhausgas','wasserkraft','watt','windenergie',
// Klima-Sim-Begriffe (Migration 2026-05-02): 4 Aliasse + 14 Volleinträge
'windpark','solaranlage','erneuerbar','kohlekraftwerk',
'budget','strom','mangrove','klimafolgen','kuestenschutz',
'wartung','tourismus','blackout','steuern','temperatur',
'meeresspiegel','bevoelkerung','ueberflutung','co2_filter',
]);
function resolveGlossarDbKey(key) {
const aliased = KLIMA_TO_DB_KEY[key] || key;