# GeoGraSim — Sim-Spec für externe KI-Entwicklung **Stand: 2026-06-12** · Ergänzung zu [`module-interface.md`](module-interface.md) und [`integration-konzept.md`](integration-konzept.md). > **Wichtig:** Dieses Dokument fasst nur das Neue / Geänderte seit Juni 2026 zusammen und bündelt die für eine externe KI essentiellen Schnittstellen. Die historischen Files bleiben gültig für: Sprache (Lernarbeit statt Spiel · Leichte Sprache), iPad-Pattern, Persistenz/Resume, Datei-Struktur, Datenmodell-Grundlagen. --- ## 0. TL;DR — Was eine neue Sim aus Plattform-Sicht ist ``` App/sims//game.html ← deine HTML-Datei App/sims//engine.js ← optional, separate JS-Logik App/sims//assets/ ← optional, sim-eigene Bilder/Sounds App/pages/.php ← PHP-Wrapper (Plattform-Standard, Atlas legt an) ``` Plus 1 Eintrag in der DB-Tabelle `module_info` (Title, Icon, Status, sort_order — Atlas macht das). Die Sim selbst ist ein **selbst-laufender Browser-Frontend-Block**. Sie spricht mit der Plattform NUR über die 4 Window-Globals (siehe §2) und einen einzigen HTTP-Endpoint `/api/progress.php` zum Speichern (siehe §3). --- ## 1. Plattform-Conventions (Stand Juni 2026) Drei Window-Globals + ein optionales Lib. Vollständige Doku im Header von [`/assets/js/live-client.js`](../assets/js/live-client.js). ### 1.1 `window.__GGS__` — Plattform setzt, Sim liest Wird vom PHP-Wrapper VOR der Sim-Logik gesetzt: ```js window.__GGS__ = { sessionId: 'uuid', // anonyme Session studentId: 12, // optional, null bei Gast classId: 3, // optional simId: 'kofferdetektiv', simName: 'Kofferdetektiv', level: 1, baseUrl: '/geograsim/App', // oder '' auf Prod apiUrl: '/geograsim/App/php/api', basePath: '/geograsim/App', mode: 'free', // 'free' | 'teacher_started' | 'locked' forcedLevel: null, // wenn 'teacher_started': Pflicht-Level easy: false, // Leichte Sprache aktiv? }; ``` Wenn `__GGS__` nicht da ist, läuft die Sim trotzdem (Dev/Direkt-URL) — sie sollte robust mit `undefined` umgehen. ### 1.2 `window.GGS_LIVE_STATE` — Sim setzt eine Funktion Funktion, die einen Snapshot des aktuellen Sim-Zustands zurückgibt. Wird vom Plattform-Live-Client alle 4 s aufgerufen und ans Lehrer-Cockpit gestreamt. ```js window.GGS_LIVE_STATE = function () { if (!gameReady) return null; return { simId: 'kofferdetektiv', phase: 'fall-3-zoll', // freier Text — was passiert gerade progressPct: 60, // 0-100, didaktische Empfehlung score: 42, // wenn schon scorebar health: 'good', // good | ok | struggle (für Status-Punkt) // weitere sim-spezifische Felder — Cockpit picked sich, was es kann }; }; ``` **Fallstrick** (echter Bug von Fluss am 2026-06-11): Nutze KEINE Property `params` auf einem Objekt, wenn `params` nicht direkt darauf existiert. `if (!game.params)` true → Snapshot null → Cockpit zeigt „meldet keine Live-Werte" obwohl die Sim läuft. Lies State direkt aus dem Computed-Result. ### 1.3 `window.GGS_TUTORIAL` — Sim registriert Replay-Hook Damit der ℹ-Button im Header das Onboarding nochmal öffnet: ```js window.GGS_TUTORIAL = { simId: 'kofferdetektiv', title: '🕵️ Kofferdetektiv', replay: function () { startTutorial(); }, // deine eigene Funktion }; ``` Der Button wird in der Sim selbst eingefügt (siehe §4.2 Header-Standard). ### 1.4 `window.__GGS_LIVE__` — Plattform setzt, Sim liest Read-only Proxy, von [`live-client.js`](../assets/js/live-client.js) bereitgestellt: ```js window.__GGS_LIVE__ = { activeMs: number, // aktive Spielzeit (gecappt bei 7_200_000 = 120 min) idleMs: number, // Zeit seit letzter Interaktion sessionStartedAt: timestamp, lastInteractionAt: timestamp, capped: boolean, MAX_SESSION_MS: 7200000, IDLE_THRESHOLD_MS: 90000, }; ``` **Wann lesen:** Beim Submit als `duration_ms` — bitte `__GGS_LIVE__.activeMs` statt `Date.now() - start` benutzen. Sonst landet auch Idle-Zeit (Tab vergessen) in der DB. Plattform-Cap zusätzlich im Backend defensiv. ### 1.5 Reservierte `__`-Heartbeat-Keys Der Live-Client mischt automatisch in jeden `GGS_LIVE_STATE`-Snapshot: ``` state.__activeMs, state.__idleMs, state.__lastInteractionAt, state.__sessionStartedAt, state.__capped ``` **Niemals überschreiben** — Cockpit liest diese aus. --- ## 2. Plattform-Bibliotheken (optional einbindbar) ### 2.1 Glossar-Tooltip ```html ``` Im Markup: ```html Zollkontrolle ``` Wirkung: Tap/Klick → Popup mit Kurztext + Link zum vollen Glossar-Eintrag. Tooltip-CSS wird automatisch injiziert. Hat zentralen Style — nicht selbst CSS für `.ggs-g` schreiben. Vorgehen für neue Glossar-Begriffe: in der DB-Tabelle `glossar` anlegen, `module_id` setzen. Atlas oder Glossar-Instanz macht das. ### 2.2 Quick-Intro (Mini-Onboarding-Modal) Für Sims OHNE volles Tutorial. Bietet ein einheitliches Modal beim 1. Besuch + Replay-Funktion. ```html ``` Verhalten: 1. Besuch → Modal auto-open. localStorage merkt sich „gesehen" (`ggs.intro.`). Library registriert automatisch `window.GGS_TUTORIAL.replay()`. ℹ-Header-Button öffnet das Modal wieder. Du kannst alternativ ein **volles, sim-spezifisches Tutorial** bauen (mehrere Schritte mit Bildern + Glossar-Begriffen — siehe weltkueche/game.html als Referenz). Dann musst du nur `window.GGS_TUTORIAL = {simId, title, replay: deineFunktion}` selbst setzen. ### 2.3 Live-Client (live-client.js) Wird vom PHP-Wrapper automatisch eingebunden — Sim muss nichts tun. Library trackt Idle (siehe §1.4), sendet Heartbeats an `/api/live.php`, pollt Pause-Flag. --- ## 3. Submit-Pfad — Wie die Sim ihre Daten persistiert Drei Aktionen via `POST /api/progress.php` mit JSON-Body. Auth läuft automatisch über die Session-Cookie aus `__GGS__`. ### 3.1 Live-Fortschritt (optional, alle paar Aktionen) ```js fetch(__GGS__.apiUrl + '/progress.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, credentials: 'same-origin', body: JSON.stringify({ sim_id: 'kofferdetektiv', action: 'update', data: { phase: 'fall-3', score: 42 }, }), }); ``` Selten nötig — GGS_LIVE_STATE deckt das eigentlich ab. Nur wenn du persistente Zwischenstände in der DB willst. ### 3.2 Reflexionsantwort (zwischen Phasen) ```js fetch(__GGS__.apiUrl + '/progress.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, credentials: 'same-origin', body: JSON.stringify({ sim_id: 'kofferdetektiv', action: 'reflection', data: { level: 1, question: 'Was war dein schwierigster Fall?', answer: 'Der Koffer aus Kenia', }, }), }); ``` ### 3.3 Abschluss-Submit (Pflicht — am Ende einer Stufe) ```js fetch(__GGS__.apiUrl + '/progress.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, credentials: 'same-origin', body: JSON.stringify({ sim_id: 'kofferdetektiv', action: 'submit_assessment', data: { level: 1, stars: 3, score: 72, duration_ms: (window.__GGS_LIVE__ && window.__GGS_LIVE__.activeMs) || 0, completed: true, results: { // SIM-SPEZIFISCHE Felder. Die Plattform-Benchmark-Engine // erwartet von dir konkrete Keys (siehe §5) — bitte mit Atlas // abstimmen, bevor du das Schema festschreibst. cases_solved: 8, cases_total: 10, correct_first_try: 6, wrong_decisions: 1, glossar_consulted: 4, }, }, }), }); ``` **Wichtig:** `results` ist sim-spezifisches JSON. Es wird in `assessments.results` als String gespeichert und sowohl im Lehrer-Cockpit (live.php) als auch im Ergebnisse-Tab (results.php) ausgelesen. Konventionen pro Sim folgen aus der Benchmark-Formel — siehe §5. --- ## 4. Design-System (Pflicht) CSS-Variablen + Layout-Klassen aus [`/assets/css/design-system.css`](../assets/css/design-system.css). ### 4.1 Farb-Variablen ```css --ggs-fjord /* Primärblau, Headlines */ --ggs-fjord-dark /* Dunkler Akzent */ --ggs-moss /* Erfolg/Grün */ --ggs-sand /* Kosten/Neutral */ --ggs-coral /* Gefahr/Rot */ --ggs-orange /* Warnung */ ``` UI-Farben sind NICHT die Bild-Palette (siehe §6). ### 4.2 Header-Standard (Plattform-konform) ```html
Kofferdetektiv Stufe 1
📚 🏠
``` **Regel:** ℹ = Tutorial-Replay (Plattform-Convention). Wenn deine Sim einen anderen Info-Inhalt hat (z.B. Fachinfo/Glossar in Farmer), kommt der mit eigenem Icon — `📖` für Glossar, `📚` für Lehrplan. ### 4.3 Layout-Zonen `ggs-sim-layout` 3-Spalten-Grid (Status links, Sim Mitte, Aktionen rechts). Details in [`module-interface.md`](module-interface.md) §5. ### 4.4 Cockpit-Sichtbarkeit (LIVE_PRIMARY_FIELDS) Damit deine Sim im Lehrer-Cockpit sinnvolle Spalten zeigt, muss Atlas in [`teacher.html`](../teacher.html) einen `LIVE_PRIMARY_FIELDS['kofferdetektiv']`-Eintrag setzen. Beispiel: ```js 'kofferdetektiv': [ {k:'health', label:'Status', align:'center', fmt: v => LIVE_VALUE_LABELS.health[v] || '—'}, {k:'phase', label:'Phase'}, {k:'progressPct', label:'Fortschritt', fmt: v => _liveBar(v, 0, 100, 'mid')}, {k:'score', label:'🏅 Score', fmt: v => _liveBar(v, 0, 100, 'high')}, {k:'cases_solved', label:'Gelöst'}, {k:'correct_first_try',label:'1.-Versuch ✓'}, ], ``` Range-Bars: Helfer `_liveBar(val, min, max, goodWhen)`. `goodWhen`: `'high'` (grün ab 60% Range), `'low'` (invers — niedrig=gut), `'mid'` (neutral grau). **Vorgehen für externe KI:** Liefere Atlas einfach die Liste deiner GGS_LIVE_STATE-Felder + welche davon Range-Bars wert sind. Atlas patcht teacher.html. --- ## 5. Benchmark-Engine — Sim braucht eine Scoring-Formel Die Plattform berechnet pro Submission einen 0–100-Modul-Score (für Lehrer-Cockpit Top 3 / Bottom 3 und Ergebnisse-Tab). Die Formel lebt in [`App/php/lib/Benchmark.php`](../php/lib/Benchmark.php) als private statische Methode. Pro neuer Sim: **du lieferst die Formel-Idee, Atlas integriert sie**. Beispiel-Briefing (Kofferdetektiv): ``` scoreKofferdetektiv($results) { $solved = $results['cases_solved'] ?? 0; $total = $results['cases_total'] ?? 0; $firstTry = $results['correct_first_try'] ?? 0; $wrong = $results['wrong_decisions'] ?? 0; if ($total === 0) return null; $base = ($solved / $total) * 70; // 70 % Lösung $bonus = ($firstTry / $total) * 30; // 30 % Sauberkeit $malus = min(20, $wrong * 5); // bis -20 für Fehlentscheidung return max(0, min(100, $base + $bonus - $malus)); } ``` Wichtig: - Wenn keine bewertbaren Daten → `null` (lieber „noch keine Bewertung" als geratene Zahl). - Pro Modul max. die 3 besten Sessions zählen — macht die Engine selbst. --- ## 6. Bildstil — Flat Scandinavian Für ALLE Bilder in der Sim (Onboarding, Kategorie-Icons, Karten-Backgrounds, Charakter-Avatare): **Palette:** ``` Background #e8e4d8 (warmer Sand) Primär #1f4b37 (Forest) Sekundär #4a7c4e (Moss) Akzent #e8c547 (Honey) Detail #b04a3e (Coral, sparsam) ``` **DALL-E-Prompt-Block (Standard):** ``` Flat scandinavian illustration, geometric shapes, soft warm color palette (#1f4b37 forest, #4a7c4e moss, #e8c547 honey, #e8e4d8 sand background, #b04a3e coral accent sparingly). No people unless explicit, no text, no photo-realism. Clean educational style for children 10-14, Sek I. [hier deine Sim-Szene]. Square 1024x1024. ``` Auflösungen: - Onboarding-Karten: 1024×1024 → WebP, max 200 KB - Sim-eigene Bilder: 512×512 oder 1024×1024 je nach Verwendung - Glossar-Illustrationen: 512×512 (Atlas verwaltet das zentral) Standorte: `App/sims//assets/img/` für sim-eigene; `App/assets/img/glossar/` für Glossar. --- ## 7. Sprache (Pflicht — schon in [`module-interface.md`](module-interface.md) §4a) Kurz zur Erinnerung: | Nicht | Sondern | |---|---| | spielen, Spiel | arbeiten mit, Simulation, bearbeiten | | Spieler:in | Lernende, Bearbeiter:in | | Game Over | Ziel verfehlt / Durchgang beendet | | Highscore | Beste Leistung | | Lehrkraft | **Lehrperson** (österreichisches Pädagog:innen-Bildungsgesetz) | Begründung: Wygotski-basierte Lernarbeit-Sprache. Wenn die Sim für Schüler:innen sichtbar wird, gilt das strikt. Plus: Sek-I-Tonalität (10–14 Jahre). Nicht infantil, nicht erwachsen. Du-Form, aber höflich. --- ## 8. Persistenz, iPad-Pattern, Leichte Sprache Alle drei sind in [`module-interface.md`](module-interface.md) abgehandelt und gelten weiter: - **Persistenz (§7b):** localStorage Autosave + Server-Mirror, Reload führt nie zum Neustart, expliziter Reset-Button mit Bestätigung. - **iPad (§4c):** 1180×820 Referenz, Touch-Ziele 36–40 px, kein Hover-Kleber, `font-size: 16px` für Inputs. - **Leichte Sprache (§4b):** Plattform-DB liefert Easy-Varianten von Glossar/Lehrplan automatisch, wenn Lehrperson das pro Schüler:in setzt. --- ## 9. Workflow für eine neue Sim (Pragmatisch) 1. **Konzept-Skizze** an Atlas: Was lernen sie? Wie ist die Mechanik? Welche Stufen? Welche Lehrplan-Anbindung? 2. **Atlas legt an:** - `module_info`-Eintrag (Title, Icon, Status='entwurf', sort_order) - `App/pages/.php`-Wrapper - Routing in `.htaccess` - Glossar-Begriffe einsammeln (an Glossar-Instanz weitergeben) 3. **Externe KI baut** `App/sims//`: - `game.html` mit Plattform-Header + GGS_LIVE_STATE + GGS_TUTORIAL/QuickIntro - Engine in JS (vanilla, kein Build-Step) - Submit-Pfad bei Phasen-Ende - localStorage-Autosave 4. **Atlas integriert:** - `LIVE_PRIMARY_FIELDS['']` in teacher.html - `Benchmark::score()` in Benchmark.php - Playwright-Tests in `.dontDeploy/playwright/tests/stufe1-smoke/` - Deploy + Test 5. **Status auf `aktiv`** schalten (über admin-modules.html oder direktes SQL). --- ## 10. Test-Pattern (Stufe 1 Smoke) Pro Sim mindestens 1 Test in `.dontDeploy/playwright/tests/stufe1-smoke/`: ```js test('Sim kofferdetektiv · __GGS__ + live-client + GGS_LIVE_STATE', async ({ page }) => { await page.goto('https://geograsim.at/kofferdetektiv'); await page.waitForTimeout(2500); const info = await page.evaluate(() => ({ ggs: typeof window.__GGS__, state: typeof window.GGS_LIVE_STATE, tutorial: typeof window.GGS_TUTORIAL, })); expect(info.ggs).toBe('object'); expect(info.state).toBe('function'); expect(info.tutorial).toBe('object'); }); ``` Existing Pattern in [`sim-platform-context.spec.js`](../../.dontDeploy/playwright/tests/stufe1-smoke/sim-platform-context.spec.js) deckt alle Sims ab — Atlas ergänzt deinen Sim-Slug dort. --- ## 11. Referenz-Sims als Vorbild Wenn die externe KI ein gutes Vorbild für die Code-Struktur braucht: - **`App/sims/weltkueche/game.html`** — full Tutorial-Pattern + Glossar-Tooltip in Tutorial-Texten + saubere Submit-Logik. Mittelgroß (~2000 LoC). - **`App/sims/busfahrt/game.html`** — Karten-basierte Sim mit Quick-Intro statt full Tutorial. Topbar mit eigenem Styling. - **`App/sims/eu-werkstatt/game.html`** — Drag-and-Drop / Card-Sorting-Pattern. - **`App/sims/sonnensystem/game.html`** — 3D-Canvas (Three.js) + state-driven Aufgaben. Die externe KI sollte **mindestens eine dieser Sims lesen**, bevor sie ihre eigene baut — um Plattform-Header, Glossar-Anbindung und Submit-Pattern abzukucken. --- ## 12. Was die externe KI explizit NICHT machen soll - Keine eigenen URL-Routen / .htaccess-Eingriffe — Atlas macht das. - Keine Schema-Änderungen an DB-Tabellen ohne Rückfrage. - Keine API-Calls in Endpoints, die nicht in §3 stehen. - Keine eigenen Plattform-Bibliotheken in `/assets/js/` ergänzen — wenn dir was zentral fehlt, melde es Atlas. - Keine Spiel-Sprache. Ernsthaft — siehe §7. - Keine echten KI-Calls IM Produkt (OpenAI/Claude/Anthropic-API). Auswertung ist parametrisch. (Tutorial-Inhalte mit KI vorgenerieren ist OK, im Produkt landet das als statischer Content.) --- ## 13. Erstkontakt-Briefing für die externe KI (Copy-Paste) ``` Du baust ein neues GeoGraSim-Sim-Modul namens "". Plattform-Kontext + Conventions: docs/sim-spec-2026-06-12.md (dieses Doc) + docs/module-interface.md. Hard Constraints: - Vanilla HTML/JS/CSS. Kein Build-Step. Kein React/TypeScript. - Plattform-Header genau wie in §4.2. - window.GGS_LIVE_STATE() liefern (§1.2). - window.GGS_TUTORIAL setzen oder ggs-quick-intro.js nutzen (§1.3 / §2.2). - Submit am Ende via POST /api/progress.php (§3.3). - duration_ms aus __GGS_LIVE__.activeMs lesen (§1.4). - Sprache: Lernarbeit, nicht Spiel (§7). - iPad-tauglich (siehe module-interface.md §4c). - Persistenz: Reload darf nie neu starten (siehe module-interface.md §7b). Liefere am Ende: - App/sims//game.html (+ engine.js wenn separat) - Liste deiner GGS_LIVE_STATE-Felder + welche Range-Bars Sinn machen - Vorschlag für Scoring-Formel (Benchmark §5) - Glossar-Begriffe, die du im Tutorial verwendest Atlas integriert dann teacher.html, Benchmark.php, .htaccess, DB. ``` --- ## 14. Ansprechpartner & Files-Map | Fragen zu | Wer / Wo | |---|---| | Plattform-API / live-client / Cockpit | Atlas, `/assets/js/live-client.js`, `/teacher.html`, `/php/api/live.php` | | Submit-Endpoint, assessments-Schema | Atlas, `/php/api/progress.php`, `/php/api/assessment.php` | | Benchmark-Formel pro Sim | Atlas, `/php/lib/Benchmark.php` | | Glossar-Begriffe / Tooltip-Pattern | Glossar-Instanz / Atlas, DB-Tabelle `glossar` + `/assets/js/glossar-tooltip.js` | | Lehrplan-Anbindung / Kompetenz-Mapping | Lehrplan-Instanz / Atlas, DB-Tabellen `kompetenzen`/`kompetenz_modules`/`lehrplan_anchors` | | Design-System-Klassen | `/assets/css/design-system.css` | | Bildstil + DALL-E-Prompts | Atlas, §6 hier + Memory `reference_bildstil` | --- **Fragen?** An Atlas (Plattform-Instanz). Diese Spec wird laufend gepflegt — bei jeder neuen Convention bitte hier ein Update einreichen statt Side-Doc.