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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user