From 2160a99896d156bbe741d099af35afe71746f074 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 22 Aug 2026 23:19:23 +0200 Subject: [PATCH] Lehrer-Live: laufende Klima-Balken farbig (Ampel) + "Heute bereits erledigt" zeigt alle heutigen Durchgaenge - klima game-2d/3d: GGS_LIVE_STATE liefert laufenden Punktestand (score, gleiche Formel wie Endbewertung) - live.php summary: laufende Sessions jeder Sim bekommen Ampel-Score (nicht mehr nur Farmer) -> Tag-Ansicht faerbt laufende Balken statt grau - teacher.html _renderInactiveToday: zeigt jetzt ALLE heute abgeschlossenen Laeufe (auch von gerade aktiven Schueler:innen); nur das laufende Spiel bleibt oben. Titel -> "Heute bereits erledigt" Co-Authored-By: Claude Opus 4.8 --- App/php/api/live.php | 10 ++++++++-- App/sims/klima/game-2d.html | 14 ++++++++++++++ App/sims/klima/game-3d.html | 14 ++++++++++++++ App/teacher.html | 14 ++++++++------ 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/App/php/api/live.php b/App/php/api/live.php index d66310a..9e262d6 100644 --- a/App/php/api/live.php +++ b/App/php/api/live.php @@ -339,8 +339,14 @@ if ($method === 'GET') { $startMs = ((int)$lr['started_ts']) * 1000; $endMs = ((int)$lr['last_seen_ts']) * 1000; $durSec = max(0, intval(($endMs - $startMs) / 1000)); - // Live-Erfolgs-Score für die Ampelfarbe: Farmer = aktuelle Trefferquote. - $liveScore = ($simId === 'farmer' && isset($state['hit_rate'])) ? max(0, min(100, (int)$state['hit_rate'])) : null; + // Live-Erfolgs-Score für die Ampelfarbe: Farmer = aktuelle Trefferquote, + // sonst der vom Sim gelieferte laufende Punktestand (0–100, z. B. Klima). + $liveScore = null; + if ($simId === 'farmer' && isset($state['hit_rate'])) { + $liveScore = max(0, min(100, (int)$state['hit_rate'])); + } elseif (isset($state['score']) && is_numeric($state['score'])) { + $liveScore = max(0, min(100, (int)round($state['score']))); + } $byStudent[$sid]['sessions'][] = [ 'simId' => $simId, 'simTitle' => $mi['title'] ?? $simId, diff --git a/App/sims/klima/game-2d.html b/App/sims/klima/game-2d.html index 1d25e1b..2e87618 100644 --- a/App/sims/klima/game-2d.html +++ b/App/sims/klima/game-2d.html @@ -1330,8 +1330,22 @@ window.GGS_LIVE_STATE = function () { speed: state.speed || 0, measures: Array.isArray(state.actionLog) ? state.actionLog.filter(a=>a.action==='buy').length : 0, levelWon: !!state.levelWon, + // Laufender Punktestand (0–100, gleiche Formel wie am Ende) → Ampelfarbe im + // Lehrer-Live (Tag-Ansicht färbt laufende Balken danach ein). + score: _liveKlimaScore(), }; }; +// Live-Score aus dem aktuellen Stand — nur während des Spiels sinnvoll. +function _liveKlimaScore() { + if (!state || !state.diff) return null; + if (state.phase !== 'playing' && state.phase !== 'citizen' && state.phase !== 'end') return null; + var sp = state.diff.startPopulation || 6000; + var tempScore = Math.max(0, Math.min(35, 35 - ((state.currentTemp||0) - 15.5) * 20)); + var floodScore = Math.max(0, 25 - (state.floodedPct||0) * 0.8); + var budgetScore = Math.max(0, Math.min(20, (state.budget||0) / 10)); + var popScore = Math.max(0, Math.min(20, ((state.population||0) / sp) * 20)); + return Math.round(tempScore + floodScore + budgetScore + popScore); +} Object.assign(state, { phase: 'level-select', speed: 1, lastTickMs: 0, diff --git a/App/sims/klima/game-3d.html b/App/sims/klima/game-3d.html index ecac31f..1d869c9 100644 --- a/App/sims/klima/game-3d.html +++ b/App/sims/klima/game-3d.html @@ -1570,8 +1570,22 @@ window.GGS_LIVE_STATE = function () { hasShield: !!state.hasMountainShield, hasBeach: !!state.hasSandBeach, placing: typeof placementId !== 'undefined' && placementId !== null ? placementId : null, + // Laufender Punktestand (0–100, gleiche Formel wie am Ende) → Ampelfarbe im + // Lehrer-Live (Tag-Ansicht färbt laufende Balken danach ein). + score: _liveKlimaScore(), }; }; +// Live-Score aus dem aktuellen Stand — nur während des Spiels sinnvoll. +function _liveKlimaScore() { + if (!state || !state.diff) return null; + if (state.phase !== 'playing' && state.phase !== 'citizen' && state.phase !== 'end') return null; + var sp = state.diff.startPopulation || 6000; + var tempScore = Math.max(0, Math.min(35, 35 - ((state.currentTemp||0) - 15.5) * 20)); + var floodScore = Math.max(0, 25 - (state.floodedPct||0) * 0.8); + var budgetScore = Math.max(0, Math.min(20, (state.budget||0) / 10)); + var popScore = Math.max(0, Math.min(20, ((state.population||0) / sp) * 20)); + return Math.round(tempScore + floodScore + budgetScore + popScore); +} /* ============================================================ UI HELPERS diff --git a/App/teacher.html b/App/teacher.html index 4cfb91d..80b8275 100644 --- a/App/teacher.html +++ b/App/teacher.html @@ -1378,18 +1378,20 @@ async function _renderInactiveToday(activeSet) { if (!data || data.error || !Array.isArray(data.students)) return ''; var groups = []; data.students.forEach(function(s){ - if (activeSet && activeSet[s.studentId]) return; // gerade online → oben - var sess = (s.sessions||[]).filter(function(x){ return x.startMs; }); - if (!sess.length) return; // heute nichts gespielt - if (sess.some(function(x){ return x.isLive || x.success==='running'; })) return; // läuft noch → oben + // Alle HEUTE abgeschlossenen Durchgänge (das gerade laufende Spiel steht + // oben in der Live-Liste und wird hier ausgelassen). Auch für Schüler:innen, + // die gerade online sind — ihre schon fertigen Läufe sollen sichtbar bleiben. + var sess = (s.sessions||[]).filter(function(x){ return x.startMs && !x.isLive && x.success!=='running'; }); + if (!sess.length) return; // heute nichts abgeschlossen sess.sort(function(a,b){ return (a.startMs||0)-(b.startMs||0); }); // chronologisch var lastEnd = 0; sess.forEach(function(x){ if((x.endMs||0)>lastEnd) lastEnd = x.endMs||0; }); groups.push({ s:s, sess:sess, lastEnd:lastEnd }); }); if (!groups.length) return ''; groups.sort(function(a,b){ return b.lastEnd - a.lastEnd; }); // zuletzt aktive Person oben - var html = '
Heute bereits aktiv · '+groups.length+'
'; - html += '

Heute schon gearbeitet, gerade aber offline — alle Aktivitäten mit Uhrzeit und Leistung.

'; + var totalRuns = groups.reduce(function(n,g){ return n + g.sess.length; }, 0); + var html = '
Heute bereits erledigt · '+groups.length+' Schüler*innen · '+totalRuns+' Durchgänge
'; + html += '

Alle heute abgeschlossenen Durchgänge (Weltküche, Klima, Farmer …) mit Uhrzeit und Leistung. Gerade laufende Spiele stehen oben.

'; html += '
'; html += '' + ''
Schüler*in