diff --git a/App/admin-lehrer-view.html b/App/admin-lehrer-view.html index ffecbc3..224eb50 100644 --- a/App/admin-lehrer-view.html +++ b/App/admin-lehrer-view.html @@ -51,6 +51,18 @@ .note li{margin:.15rem 0;line-height:1.4} .note code{background:#efe8d5;border-radius:3px;padding:0 4px;font-size:.72rem;color:#7a5a1a} .allgreen{margin:.6rem 1.1rem 1rem;background:#f0f7f1;border:1px solid #cfe6d2;border-left:4px solid #5a8a5e;border-radius:8px;padding:.55rem .85rem;font-size:.76rem;color:#3a6b3e} + .scorebox{margin:.2rem 1.1rem 1rem;background:#eef3f7;border:1px solid #d3e0e8;border-left:4px solid #4a7c8a;border-radius:8px;padding:.7rem .9rem;font-size:.78rem;color:#2f4a58} + .scorebox h4{font-size:.8rem;color:#2f5866;margin-bottom:.45rem;display:flex;align-items:center;gap:.4rem} + .scorebox .srow{display:grid;grid-template-columns:78px 1fr;gap:.5rem;margin:.28rem 0;align-items:start} + .scorebox .srow .lab{font-weight:700;color:#3a6072} + .scorebox code{background:#dde8ee;border-radius:3px;padding:0 4px;font-size:.72rem;color:#294a58;font-family:'Courier New',monospace} + .scorebox .flag{display:block;margin-top:.5rem;font-size:.73rem;color:#8a3a2a;background:#fbeee9;border:1px solid #ecc9bd;border-radius:6px;padding:.35rem .55rem} + .scorebox .flag b{color:#a5341f} + .gbox{background:#fff;border-radius:12px;box-shadow:0 1px 4px rgba(0,0,0,.04);padding:1.1rem 1.3rem;margin-bottom:1.2rem;border-left:4px solid #4a7c8a} + .gbox h2{font-size:1rem;color:#1f4b37;font-weight:800;margin-bottom:.5rem} + .gbox p{font-size:.82rem;line-height:1.5;color:#4a4a4a;margin-bottom:.5rem} + .gbox code{background:#eef3f5;border-radius:3px;padding:0 4px;font-size:.75rem;color:#294a58;font-family:'Courier New',monospace} + .gbox .rec{background:#f0f7f1;border:1px solid #cfe6d2;border-radius:8px;padding:.6rem .8rem;font-size:.8rem;color:#2f5e39;margin-top:.5rem} .foot{font-size:.72rem;color:#8a8a8a;text-align:center;margin-top:2rem} @@ -80,6 +92,14 @@ +
+

So entstehen Prozent & Sterne — und warum das heute uneinheitlich ist

+

Der Zeilen-Prozentwert in „Ergebnisse/Aktuell" entsteht in live.php · extractScore: liefert die Sim einen eigenen 0–100-Score, wird der genommen; sonst aus den Sternen: % = Sterne / 5 × 100.

+

Die Sterne berechnet jede App am Ende selbst — aus unterschiedlichen Kennzahlen und Schwellen (je Sim unten dokumentiert). Deshalb bedeuten 4★ heute nicht überall dasselbe.

+

Uneinheitlichkeiten: Busfahrt · Fluggesellschaft · Kofferdetektiv liefern nur 0–3 Sterne statt 0–5. Busfahrt/Fluggesellschaft senden als score rohe Punkte (nicht 0–100 → Zeilen-% verzerrt). Weltküche wertet pro Gericht statt pro Durchgang. Logistik überträgt weder Sterne noch Score. Ein echter 0–100-Live-Score existiert nur bei Klima, Fluss, Heli, Kofferdetektiv, Tourismusregion (abgeleitet Tourismustal).

+
Vorschlag (ein System): Jede App liefert genau eine Funktion → Leistungs-% (0–100) als Wahrheit (grün→rot-Balken). Sterne werden daraus mit denselben globalen Schwellen für alle abgeleitet (z. B. ≥90→5★ · ≥75→4 · ≥55→3 · ≥35→2 · sonst 1). Dann bedeuten Sterne überall dasselbe und % ↔ Sterne sind konsistent.
+
+

Alle Werte sind Beispieldaten zur Ansicht. Render-Logik gespiegelt aus teacher.html · renderLive(). Grün/Grau ist Atlas' Vorschlag — bitte prüfen & korrigieren.

@@ -393,7 +413,7 @@ var GREEN = { heli: ['missionId','planIndex','planCorrect','planAttempts','startScore','landingScore','totalStars','failed'], kofferdetektiv: ['progressPct','score','cases_solved','hints_revealed','wrong_guesses_total'], sonnensystem: ['completed','progressPct','achievementsUnlocked'], - tourismustal: ['scene','year','money','satisfaction','nature','goalsDone','buildings'], + tourismustal: ['scene','year','money','guestsToday','satisfaction','nature','goalsDone','buildings'], tourismusregion: ['mapId','wave','budget','revenue','avgStars','env','goalsDone'], logistik: ['levelId','balance','ordersDelivered','ordersLate','progressPct'], }; @@ -428,6 +448,74 @@ var GREY_REASON = { ordersOpen:'offene Aufträge im Moment', }; +/* ============================================================ + 3b) Bewertung je Sim — wie Sterne UND Prozent zustandekommen. + Quelle: Sterne-Audit der Game-Files (Formeln/Schwellen 1:1). + ============================================================ */ +var SCORING = { + farmer: { + stars:'0–5 aus totalScore (0–100, gewichtet: Konto 25% · Trefferquote 20% · CO₂ 15% · Krankheiten 10% · Sorten 10% · Länder 10% · Klimazonen 10%). Schwellen: ≥85→5 · ≥70→4 · ≥50→3 · ≥30→2 · sonst 1.', + pct:'Kein 0–100-Live-Score → Zeilen-% = Sterne/5×100 (im Ergebnis liegt zusätzlich data.score).', + }, + klima: { + stars:'0–5: Basis 2★ bei Sieg, dann +1 je Temp<17° · Temp<16,3° · Budget>200 · (Flut<20% & Bev.>90% Start). Deckel: Temp≥17°→max 3★, ≥18,5°→max 1★.', + pct:'Eigener 0–100-Score = TempScore(0–35)+FlutScore(0–25)+BudgetScore(0–20)+BevScore(0–20). Live-Score identisch → Zeilen-% = dieser Score.', + }, + fluss: { + stars:'0–5 aus Score: ≥85→5 · ≥70→4 · ≥55→3 · ≥35→2 · sonst 1.', + pct:'Score 0–100 = Ø(Biodiv, Wirtschaft, Hochwasserschutz) − 5×Siedlungsverluste. Live-Score vorhanden → Zeilen-% = Score.', + }, + energiemanager: { + stars:'0–5 aus Quote = ausgeglichene Blöcke / gesamt: ≥1,0→5 · ≥0,87→4 · ≥0,66→3 · ≥0,50→2 · sonst 1. Blackout-Deckel: 1×→max 3★, ≥2×→max 2★.', + pct:'Kein 0–100-Live-Score → Zeilen-% = Sterne/5×100.', + }, + 'eu-werkstatt': { + stars:'0–5 aus firstTryRate = saubere Erstversuche / Schritte: ≥1,0→5 · ≥0,85→4 · ≥0,65→3 · ≥0,40→2 · sonst 1.', + pct:'Kein 0–100-Live-Score → Zeilen-% = Sterne/5×100.', + }, + weltkueche: { + stars:'0–5 pro Gericht aus Fehlern: 0→5 · ≤1→4 · ≤3→3 · ≤6→2 · sonst 1.', + pct:'Live-score ist eine rohe Punktezahl (nicht 0–100) → Zeilen-% aktuell unklar.', + flags:['Wird pro Gericht gesendet, nicht pro Durchgang.','„Fehler in %" (Fehler ÷ Aktionen) gehört genau hierher — vergleichbar statt roher, gericht-abhängiger Zahl.'], + }, + busfahrt: { + stars:'nur 0–3 aus Ratio = Topo-Punkte / (Aufträge×3): ≥0,85→3 · ≥0,55→2 · ≥0,30→1 · sonst 0.', + pct:'Gesendeter score = rohe Topo-Punkte (nicht 0–100).', + flags:['0–3 statt 0–5 Sterne.','score ist keine 0–100-Zahl → Zeilen-% verzerrt.'], + }, + fluggesellschaft: { + stars:'nur 0–3 aus Ratio = Topo-Punkte / (Flüge×3): ≥0,85→3 · ≥0,55→2 · ≥0,30→1 · sonst 0.', + pct:'Gesendeter score = rohe Topo-Punkte (nicht 0–100).', + flags:['0–3 statt 0–5 Sterne.','score ist keine 0–100-Zahl → Zeilen-% verzerrt.'], + }, + heli: { + stars:'0–5 = round((PlanSterne + Start + Landung) / 3). PlanSterne aus Timing (Ø≥1,6→5 …) bzw. Klickgenauigkeit; Chefpilot-Übernahme → 0.', + pct:'Live-Score 0–100 = Sterne/5×100 (submit score = Sterne×20) → Zeilen-% = das.', + }, + kofferdetektiv: { + stars:'nur 0–3 aus q = score100/100: ≥0,7→3 · ≥0,45→2 · ≥0,2→1 · sonst 0.', + pct:'score100 = Punkte / (Fälle×100) × 100 (je Fall 100 P, −7/Hinweis, −15/Fehltipp, −20/Timeout). Live-Score = score100 → Zeilen-% = das.', + flags:['0–3 statt 0–5 Sterne.'], + }, + sonnensystem: { + stars:'1–5 aus Quote = Erstversuch-richtig / gesamt: ≥0,85→5 · ≥0,68→4 · ≥0,50→3 · ≥0,30→2 · sonst 1 (Minimum 1, nie 0).', + pct:'Kein 0–100-Live-Score (nur levelWon+Fortschritt; scoreQuote im data) → Zeilen-% = Sterne/5×100.', + }, + tourismustal: { + stars:'0–5 = min(5, erreichte Ziele + (Sieg?1:0)).', + pct:'Score 0–100 = erreichte Ziele / gesamt × 100; kein Live-0–100 → Zeilen-% = data.score bzw. Sterne/5×100.', + }, + tourismusregion: { + stars:'0–5 = round(Ø Besucher-Bewertung) (avgStars 0–5).', + pct:'Score 0–100 = gewichtet: Bewertung 35% · Wertschöpfung 25% · Nachhaltigkeit 20% · Lenkung 10% · Finanzen 10%. Live avgStars → Zeilen-% = Score.', + }, + logistik: { + stars:'0–5 aus Endkontostand: ≤0→0 · ≥16000→5 · ≥13000→4 · ≥10500→3 · ≥8500→2 · sonst 1.', + pct:'Kein Score/Stern wird ans Backend gesendet.', + flags:['Sterne & Score werden NICHT übertragen — im Lehrer-Cockpit erscheint für Logistik kein Stern/Prozent. Eigene Endpoints /api/assessment + /api/logistik-sessions.'], + }, +}; + /* ============================================================ 4) Testdaten je Sim (3 Schüler:innen: stark · schwach · mittel) ============================================================ */ @@ -522,6 +610,17 @@ var TEST = { var _LIVE_PAUSE_SEC = 90; function _liveIsActive(ls){ return ls.last_seen_ms && (NOW - ls.last_seen_ms) <= _LIVE_PAUSE_SEC*1000; } +function renderScoring(id){ + var sc = SCORING[id]; + if (!sc) return ''; + var h = '

🎯 So entsteht die Bewertung

'; + h += '
Sterne'+sc.stars+'
'; + h += '
Prozent'+sc.pct+'
'; + (sc.flags||[]).forEach(function(f){ h += '
⚠ '+f+'
'; }); + h += '
'; + return h; +} + function renderSim(meta){ var fields = LIVE_PRIMARY_FIELDS[meta.id] || []; var rows = TEST[meta.id] || []; @@ -596,6 +695,9 @@ function renderSim(meta){ }); h += ''; + // Bewertung: wie Sterne + Prozent entstehen + h += renderScoring(meta.id); + // Nach-Abschluss-Hinweis if (greyKeys.length){ h += '
Nach Abschluss NICHT relevant (nur live):