---
von: klima
an: atlas
datum: 2026-04-29
status: neu
betrifft: Klima-Beitrag zur Lehrer-Ergebnisseite — Erfolgs-Parameter + Field-Mapping
---

# Klima-Beitrag zur Lehrer-Ergebnisseite

Thomas möchte die Lehrer-Seite „Ergebnisse" (Tab in `App/teacher.html`,
Z. 628 ff.) ausbauen:

- **Modul-Filter** über alle Einträge
- **Modul-spezifische Spalten** mit den entscheidenden Erfolgs-Parametern
- **Game-Over-Indikator** pro Zeile
- **Fleiß-Übersicht** mit Filtern Tag / Woche / Monat / Jahr (Zeit pro
  Schüler:in, gesamt + pro Modul)

Da das die zentrale Lehrer-Seite und cross-modular ist, gehört das in
deine Hand. Ich liefere hiermit den Klima-Block fertig — die anderen
Module musst du analog koordinieren.

## Klima — entscheidende Erfolgs-Parameter

Die Engine speichert pro abgeschlossenem Durchgang via
`endLevel() → POST /api/assessment.php` ein `results`-JSON. Diese
Felder sind die didaktisch entscheidenden:

| Spalte (Lehrer-Sicht)   | JSON-Pfad in `results`     | Sinn                                                |
|-------------------------|----------------------------|-----------------------------------------------------|
| Ergebnis-Icon           | abgeleitet (siehe unten)   | 🏆 / 💸 / 🌊 / 🌫 / 🌡 / ⏸                          |
| Endgrund                | `endReason`                | `won` · `pleite` · `ueberflutet` · `co2-top` · `temp-top` |
| Jahr erreicht           | `tick` + Engine-startYear  | bis 2175 = 75 Ticks = Vollerfolg                    |
| Sterne                  | `stars`                    | 0–5                                                 |
| Score                   | `score`                    | 0–100                                               |
| CO₂ (ppm)               | `final_co2`                | < 450 = Klimaziel · ≥ 700 = Game-Over               |
| Temperatur (°C)         | `final_temperature`        | < 17 = Pariser Ziel · ≥ 19 = Game-Over              |
| Budget (Mio €)          | `final_budget`             | > 0 = Pflicht · > 100 = Sparfuchs                   |
| Überflutet (%)          | `final_flooded_pct`        | < 30 = Pflicht · < 5 = ausgezeichnet                |
| Bevölkerung             | `final_population`         | nicht unter Startwert sinken lassen                 |
| Maßnahmen gebaut        | `measures_bought`          | Aktivitätsindex                                     |
| Events erlebt           | `events_survived`          | Reaktionsbreite                                     |
| Spielzeit               | `duration_ms` (Top-Level)  | für Fleiß-Spalte                                    |

## Game-Over-Erkennung

```js
const won = endReason === 'won';
const gameOver = endReason && endReason !== 'won';   // true bei 'pleite' /
                                                     // 'ueberflutet' / 'co2-top' /
                                                     // 'temp-top'
```

Icon-Mapping:
- `won` → 🏆
- `pleite` → 💸
- `ueberflutet` → 🌊
- `co2-top` → 🌫
- `temp-top` → 🌡
- kein `endReason` (vorzeitig abgebrochen) → ⏸

## Variante 2D vs 3D

In `assessments.sim_id` steht aktuell für beide Varianten `'klima'`. Wenn
du im Lehrer-UI 2D/3D unterscheiden willst, müsste der Wrapper das beim
Senden mitliefern (z.B. `simVariant: '2d' | '3d'`). Das wäre eine
kleine Engine-Refactor-Erweiterung — kann ich machen, sobald du sagst
ob's relevant ist. Vorerst egal: dieselbe Engine, dieselbe Bewertung.

## Fleiß-Übersicht — Vorschlag

Aus `assessments.duration_ms` und `submitted_at`:

- Pro Schüler:in: `SUM(duration_ms) GROUP BY session_id`
- Pro Modul: `SUM(duration_ms) GROUP BY sim_id`
- Pro Zeitfenster: `WHERE submitted_at >= NOW() - INTERVAL X`

Filter Tag/Woche/Monat/Jahr → Standard-DATE_SUB-Pattern.

Wenn du auch **laufende** Sessions (nicht nur completed) mitzählen
willst: das fehlt aktuell in `assessments`. Müsste über
`student_sessions.last_seen_at` oder einen zusätzlichen Heartbeat
laufen. Mehraufwand, aber didaktisch wahrscheinlich wertvoll
(Schüler:innen, die viel reinklicken aber nichts abschließen).

## Was bei mir vorbereitet ist

Engine + 2D + 3D senden bereits `endReason`, `levelWon`, `stars`,
`score`, `final_*`, `measures_bought`, `events_survived`, `duration_ms`
in der `results`-JSON. Du kannst direkt parsen, ich muss nichts
anpassen.

Ausnahme: der Integrations-Auftrag (mode-check + Assessment-Calls in
running-Phase + neuer End-Screen) wartet noch auf Thomas-Go. Sobald
das passiert ist, kommen Zwischenstände alle ~30 s mit dazu.

## Bestätigen

- status: gelesen
- Wenn du die Spalten so übernimmst, brauche ich keine Rückmeldung —
  meld dich nur, wenn dir ein Feld fehlt oder du `simVariant` willst
