Stand 2026-04-13: PHP/MySQL Infrastruktur, Flussmanagement, Stadt-Prototyp

- PHP/MySQL Backend (XAMPP + Produktionsserver)
- Front-Controller, API-Endpunkte, Session-Management
- Flussmanagement-Simulation (Echtzeit, Punkt-basierter Fluss)
- Stadt & Raumplanung (Prototyp, Top-Down Kachelsystem)
- Klimawaechter 3D: Deiche kleiner, Baeume kippen, Budget angepasst
- persistence.ts: Dualer Speicher (localStorage + Server-API)
- 6 Unit-Test-Dateien fuer bestehende Simulationen

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 16:43:42 +02:00
commit f22c5ebbfe
83 changed files with 22709 additions and 0 deletions
+297
View File
@@ -0,0 +1,297 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Lehrkräfte-Dashboard</title>
<link rel="icon" type="image/png" href="assets/img/logo.png">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }
:root {
--bg: #f7f6f3; --white: #fff; --text: #1a1a1a; --text2: #4a4a4a; --text3: #8a8a8a;
--fjord: #4a7c8a; --fjord-l: #dae8ec; --fjord-d: #3a6470;
--moss: #5a8a5e; --moss-l: #dceadd;
--sand: #c4a35a; --sand-l: #f2eacc;
--coral: #c07a6b; --coral-l: #f2ddd8;
}
body { font-family:'Inter',system-ui,sans-serif; background:var(--bg); color:var(--text); line-height:1.55; }
.nav { padding:.7rem 2rem; display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid rgba(0,0,0,.04); background:var(--white); }
.nav-brand { display:flex; align-items:center; gap:.5rem; font-weight:800; font-size:1rem; color:var(--fjord); text-decoration:none; }
.nav-brand img { width:28px; height:28px; border-radius:6px; }
.nav-user { display:flex; align-items:center; gap:.6rem; font-size:.85rem; }
.avatar { width:32px; height:32px; border-radius:50%; background:var(--fjord); color:#fff; display:flex; align-items:center; justify-content:center; font-weight:700; font-size:.78rem; }
.layout { display:grid; grid-template-columns:240px 1fr; min-height:calc(100vh - 60px); }
.sidebar { background:var(--white); border-right:1px solid rgba(0,0,0,.05); padding:1.2rem 1rem; }
.sidebar h4 { font-size:.65rem; font-weight:700; color:var(--text3); text-transform:uppercase; letter-spacing:.08em; margin:1rem 0 .4rem; }
.sidebar h4:first-child { margin-top:0; }
.sidebar a { display:block; padding:.4rem .7rem; color:var(--text2); text-decoration:none; border-radius:8px; font-size:.82rem; font-weight:500; margin-bottom:1px; transition:all .2s; }
.sidebar a:hover, .sidebar a.active { background:var(--fjord-l); color:var(--fjord); }
.main { padding:1.5rem 2rem; }
.page-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:1.2rem; }
.page-header h1 { font-size:1.6rem; font-weight:800; letter-spacing:-.02em; }
.page-header p { color:var(--text3); font-size:.85rem; }
.btn { display:inline-flex; align-items:center; gap:.4rem; padding:.5rem 1.1rem; border-radius:10px; font-weight:600; font-size:.82rem; border:none; cursor:pointer; transition:all .2s; text-decoration:none; }
.btn-p { background:var(--fjord); color:#fff; }
.btn-p:hover { background:var(--fjord-d); }
.btn-o { background:var(--white); color:var(--fjord); border:1.5px solid rgba(74,124,138,.3); }
.grid { display:grid; gap:1rem; }
.grid-3 { grid-template-columns:repeat(3,1fr); }
.grid-2 { grid-template-columns:1fr 1fr; }
.grid-4 { grid-template-columns:repeat(4,1fr); }
.card { background:var(--white); border-radius:14px; border:1px solid rgba(0,0,0,.04); padding:1.1rem; box-shadow:0 2px 10px rgba(0,0,0,.03); }
.card h3 { font-size:.78rem; font-weight:700; color:var(--text3); text-transform:uppercase; letter-spacing:.06em; margin-bottom:.6rem; }
.card-big-num { font-size:2rem; font-weight:900; letter-spacing:-.03em; }
.card-trend { font-size:.75rem; color:var(--moss); font-weight:600; margin-top:.2rem; }
/* Class table */
.classes-table { width:100%; border-collapse:collapse; font-size:.85rem; }
.classes-table th, .classes-table td { padding:.6rem .8rem; text-align:left; border-bottom:1px solid rgba(0,0,0,.05); }
.classes-table th { font-size:.7rem; font-weight:700; color:var(--text3); text-transform:uppercase; letter-spacing:.06em; }
.classes-table tr:hover { background:#fafaf8; }
.student-row { display:flex; align-items:center; gap:.5rem; }
.progress-bar { width:80px; height:6px; background:#e8e5dc; border-radius:3px; overflow:hidden; }
.progress-fill { height:100%; border-radius:3px; }
.badge { display:inline-block; padding:2px 9px; border-radius:6px; font-size:.68rem; font-weight:600; }
.b-on { background:var(--moss-l); color:var(--moss); }
.b-off { background:#f0eeea; color:var(--text3); }
.b-progress { background:var(--fjord-l); color:var(--fjord); }
.b-warn { background:var(--sand-l); color:var(--sand); }
/* Sim card with toggle */
.sim-toggle-card { display:flex; align-items:center; gap:.8rem; padding:.8rem; border-radius:10px; background:#fafaf8; border:1px solid rgba(0,0,0,.04); margin-bottom:.5rem; }
.sim-toggle-card-icon { font-size:1.5rem; }
.sim-toggle-card-info { flex:1; }
.sim-toggle-card-info h5 { font-size:.85rem; font-weight:700; }
.sim-toggle-card-info p { font-size:.72rem; color:var(--text3); }
.toggle { width:36px; height:20px; background:#d4d4d0; border-radius:10px; position:relative; cursor:pointer; transition:all .2s; }
.toggle.on { background:var(--moss); }
.toggle::after { content:''; position:absolute; top:2px; left:2px; width:16px; height:16px; background:#fff; border-radius:50%; transition:all .2s; box-shadow:0 1px 3px rgba(0,0,0,.2); }
.toggle.on::after { left:18px; }
.alert { background:var(--coral-l); border-left:3px solid var(--coral); padding:.6rem .8rem; border-radius:8px; font-size:.78rem; margin-bottom:.5rem; }
.alert strong { color:var(--coral); }
.demo-banner { background:var(--sand-l); color:var(--sand); padding:.5rem 1rem; text-align:center; font-size:.78rem; font-weight:600; }
</style>
</head>
<body>
<div class="demo-banner">⚠️ Demo-Mockup — alle Daten sind erfunden, kein Backend angeschlossen</div>
<nav class="nav">
<a href="index.html" class="nav-brand"><img src="assets/img/logo.png" alt="">GeoGraSim · Dashboard</a>
<div class="nav-user">
<span style="color:var(--text2)">Mag. Schroffenegger</span>
<div class="avatar">TS</div>
</div>
</nav>
<div class="layout">
<aside class="sidebar">
<h4>Übersicht</h4>
<a href="#" class="active">📊 Dashboard</a>
<a href="#">👥 Klassen</a>
<a href="#">🎯 Simulationen</a>
<a href="#">📈 Berichte</a>
<h4>Meine Klassen</h4>
<a href="#">1A — 24 Schüler*innen</a>
<a href="#">1B — 22 Schüler*innen</a>
<a href="#">2A — 25 Schüler*innen</a>
<a href="#">3B — 23 Schüler*innen</a>
<h4>Tools</h4>
<a href="#">🗳️ Live-Abstimmung</a>
<a href="#">📥 Export (PDF)</a>
<a href="#">⚙️ Einstellungen</a>
</aside>
<main class="main">
<div class="page-header">
<div>
<h1>Klasse 1A — Übersicht</h1>
<p>24 Schüler*innen · Letzte Aktivität: vor 2 Stunden</p>
</div>
<div style="display:flex;gap:.5rem">
<button class="btn btn-o">📥 Bericht exportieren</button>
<button class="btn btn-p">🚀 Simulation starten</button>
</div>
</div>
<!-- Top stats row -->
<div class="grid grid-4" style="margin-bottom:1rem">
<div class="card">
<h3>Aktive Schüler*innen</h3>
<div class="card-big-num" style="color:var(--fjord)">18 / 24</div>
<div class="card-trend">↗ +3 seit gestern</div>
</div>
<div class="card">
<h3>Abgeschlossene Simulationen</h3>
<div class="card-big-num" style="color:var(--moss)">142</div>
<div class="card-trend">↗ 87% Erfolgsquote</div>
</div>
<div class="card">
<h3>Durchschn. Lernzeit</h3>
<div class="card-big-num" style="color:var(--sand)">23 min</div>
<div class="card-trend" style="color:var(--text3)">pro Simulation</div>
</div>
<div class="card">
<h3>Identifizierte Fehlkonzepte</h3>
<div class="card-big-num" style="color:var(--coral)">5</div>
<div class="card-trend" style="color:var(--coral)">⚠ Aufmerksamkeit nötig</div>
</div>
</div>
<!-- Two column section -->
<div class="grid grid-2" style="margin-bottom:1rem">
<!-- Active simulation -->
<div class="card">
<h3>🔴 Live: Treibhauseffekt-Simulator</h3>
<p style="font-size:.85rem;margin:.5rem 0 .8rem;color:var(--text2)">12 von 24 Schüler*innen bearbeiten gerade die Simulation.</p>
<table class="classes-table">
<thead>
<tr><th>Schüler*in</th><th>Phase</th><th>Fortschritt</th><th>Zeit</th></tr>
</thead>
<tbody>
<tr>
<td><div class="student-row">👤 Anna B.</div></td>
<td><span class="badge b-progress">Observe</span></td>
<td><div class="progress-bar"><div class="progress-fill" style="width:75%;background:var(--fjord)"></div></div></td>
<td>14:32</td>
</tr>
<tr>
<td><div class="student-row">👤 Lukas F.</div></td>
<td><span class="badge b-on">Reflect</span></td>
<td><div class="progress-bar"><div class="progress-fill" style="width:90%;background:var(--moss)"></div></div></td>
<td>18:45</td>
</tr>
<tr>
<td><div class="student-row">👤 Sara M.</div></td>
<td><span class="badge b-progress">Predict</span></td>
<td><div class="progress-bar"><div class="progress-fill" style="width:30%;background:var(--fjord)"></div></div></td>
<td>05:12</td>
</tr>
<tr>
<td><div class="student-row">👤 Tim H.</div></td>
<td><span class="badge b-warn">Pausiert</span></td>
<td><div class="progress-bar"><div class="progress-fill" style="width:55%;background:var(--sand)"></div></div></td>
<td>09:20</td>
</tr>
<tr>
<td><div class="student-row">👤 Emma K.</div></td>
<td><span class="badge b-on">Reflect</span></td>
<td><div class="progress-bar"><div class="progress-fill" style="width:95%;background:var(--moss)"></div></div></td>
<td>21:08</td>
</tr>
</tbody>
</table>
</div>
<!-- Insights -->
<div class="card">
<h3>💡 Erkannte Fehlkonzepte</h3>
<div class="alert">
<strong>Ozonloch ≠ Treibhauseffekt</strong><br>
7 Schüler*innen haben in ihrer Vorhersage erwähnt, dass das "Ozonloch" für die Erwärmung verantwortlich sei.
→ Empfehlung: Im Plenum klarstellen.
</div>
<div class="alert">
<strong>Lineare statt logarithmische Beziehung</strong><br>
5 Schüler*innen haben "doppelt so viel CO₂ = doppelt so warm" angenommen.
→ Empfehlung: Klimasensitivität gemeinsam besprechen.
</div>
<div class="alert">
<strong>Albedo nicht verstanden</strong><br>
3 Schüler*innen haben Albedo nicht verändert. → Optionale Vertiefung anbieten.
</div>
<h3 style="margin-top:1rem">🎯 Lernziele-Erreichung (Klasse)</h3>
<div style="font-size:.78rem;margin-top:.4rem">
<div style="display:flex;justify-content:space-between;margin-bottom:.3rem"><span>Treibhauseffekt verstehen</span><strong>83%</strong></div>
<div class="progress-bar" style="width:100%"><div class="progress-fill" style="width:83%;background:var(--moss)"></div></div>
<div style="display:flex;justify-content:space-between;margin:.6rem 0 .3rem"><span>CO₂-Temperatur-Zusammenhang</span><strong>71%</strong></div>
<div class="progress-bar" style="width:100%"><div class="progress-fill" style="width:71%;background:var(--fjord)"></div></div>
<div style="display:flex;justify-content:space-between;margin:.6rem 0 .3rem"><span>Abgrenzung zum Ozonloch</span><strong>54%</strong></div>
<div class="progress-bar" style="width:100%"><div class="progress-fill" style="width:54%;background:var(--sand)"></div></div>
</div>
</div>
</div>
<!-- Module freischaltung -->
<div class="card" style="margin-bottom:1rem">
<h3>⚙️ Module für Klasse 1A freigeschaltet</h3>
<div class="grid grid-2" style="margin-top:.8rem">
<div class="sim-toggle-card">
<div class="sim-toggle-card-icon">🌡️</div>
<div class="sim-toggle-card-info">
<h5>Treibhauseffekt-Simulator</h5>
<p>1. Klasse · 20 min · Schwierigkeit: Standard</p>
</div>
<div class="toggle on"></div>
</div>
<div class="sim-toggle-card">
<div class="sim-toggle-card-icon">🌋</div>
<div class="sim-toggle-card-info">
<h5>Erdbeben-Simulator</h5>
<p>1. Klasse · 25 min · Schwierigkeit: Standard</p>
</div>
<div class="toggle on"></div>
</div>
<div class="sim-toggle-card">
<div class="sim-toggle-card-icon"></div>
<div class="sim-toggle-card-info">
<h5>Energiemix-Simulator</h5>
<p>2. Klasse · 25 min · Erst nächstes Jahr</p>
</div>
<div class="toggle"></div>
</div>
<div class="sim-toggle-card">
<div class="sim-toggle-card-icon">🏗️</div>
<div class="sim-toggle-card-info">
<h5>Raumplanung Gemeinde</h5>
<p>3. Klasse · 45 min · Erst in 2 Jahren</p>
</div>
<div class="toggle"></div>
</div>
</div>
</div>
<!-- Live abstimmung -->
<div class="card">
<h3>🗳️ Live-Abstimmung starten</h3>
<p style="font-size:.85rem;color:var(--text2);margin:.4rem 0 .8rem">Stelle deiner Klasse eine Frage. Das Ergebnis fließt direkt in die laufende Simulation ein.</p>
<div style="display:flex;gap:.5rem">
<input type="text" placeholder="z.B.: Sollten wir die CO₂-Werte von 2050 simulieren?" style="flex:1;padding:.6rem 1rem;border:1px solid rgba(0,0,0,.1);border-radius:10px;font-family:inherit;font-size:.85rem">
<button class="btn btn-p">Abstimmung starten</button>
</div>
</div>
</main>
</div>
<script>
// Toggle functionality
document.querySelectorAll('.toggle').forEach(t => {
t.addEventListener('click', () => t.classList.toggle('on'))
})
</script>
</body>
</html>