Lehrer-View-Uebersicht: Vorschau einheitliches Leistungs-% (Sterne raus)
- Vorschau-Karte: %+Balken-Standardanzeige, 5-stufige Farbskala, Triage-Felder (Foerdern/Begleiten/Laeuft gut) aus %xFleiss mit Grenzen = Farbgrenzen (50/65), damit Farbe<->Feld immer stimmen. - Neue Spalte 'Leistung' je Sim: Vorschlags-Formel auf die Testdaten gerechnet (PERF), als pctBar + Triage-Chip. Busfahrt/Flug/Sonnensystem Naeherung (Rohwerte fehlen in Testdaten). - Bewertungs-Block je Sim um 'Vorschlag %' (PROPOSED_PCT) erweitert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -100,6 +100,7 @@
|
||||
<div class="rec"><b>Vorschlag (ein System):</b> Jede App liefert genau <b>eine Funktion → Leistungs-% (0–100)</b> als Wahrheit (grün→rot-Balken). Sterne werden daraus mit <b>denselben globalen Schwellen für alle</b> abgeleitet (z. B. ≥90→5★ · ≥75→4 · ≥55→3 · ≥35→2 · sonst 1). Dann bedeuten Sterne überall dasselbe und % ↔ Sterne sind konsistent.</div>
|
||||
</div>
|
||||
|
||||
<div id="preview"></div>
|
||||
<div class="toc" id="toc"></div>
|
||||
<div id="content"></div>
|
||||
<p class="foot">Alle Werte sind Beispieldaten zur Ansicht. Render-Logik gespiegelt aus <code>teacher.html · renderLive()</code>. Grün/Grau ist Atlas' Vorschlag — bitte prüfen & korrigieren.</p>
|
||||
@@ -516,6 +517,66 @@ var SCORING = {
|
||||
},
|
||||
};
|
||||
|
||||
/* ============================================================
|
||||
3c) VORSCHLAG — einheitliches Leistungs-% (0–100) je Sim,
|
||||
5-stufige Farbskala, %+Balken-Komponente, Triage (%×Fleiß).
|
||||
============================================================ */
|
||||
var PROPOSED_PCT = {
|
||||
farmer:'gewichteter 0–100-Score (wie heute intern berechnet) — künftig auch LIVE senden.',
|
||||
klima:'vorhandener 0–100-Score (Temp+Flut+Budget+Bev.) übernehmen.',
|
||||
fluss:'vorhandener Score Ø(Biodiv,Wirtschaft,Schutz) − 5×Verluste übernehmen.',
|
||||
energiemanager:'ausgeglichene Blöcke / (Tage×8) ×100 − 15 je Blackout.',
|
||||
'eu-werkstatt':'saubere Erstversuche / Schritte ×100 − 5 je Mülleimer.',
|
||||
weltkueche:'richtige / (richtige+falsche) ×100 (= 100 − Fehlerquote).',
|
||||
busfahrt:'Topo-Punkte / (Aufträge×3) ×100.',
|
||||
fluggesellschaft:'Topo-Punkte / (Flüge×3) ×100.',
|
||||
heli:'kontinuierlich aus PlanPct + Start + Landung (0–100), nicht gerundete Sterne.',
|
||||
kofferdetektiv:'vorhandener score100 (0–100) übernehmen.',
|
||||
sonnensystem:'Erstversuch-Quote ×100.',
|
||||
tourismustal:'Ziele/gesamt ×100, gewichtet mit Zufriedenheit/Natur.',
|
||||
tourismusregion:'vorhandener gewichteter 0–100-Score übernehmen.',
|
||||
logistik:'Kontostand→% (0 €→0, Zielbudget→100) — UND ans Backend senden.',
|
||||
};
|
||||
|
||||
// 5-stufige Farbskala (= _tagTraffic).
|
||||
function pctColor(v){ v=Math.max(0,Math.min(100,v||0)); return v>=80?'#1f7a3d':v>=65?'#7cb342':v>=50?'#f9c33b':v>=35?'#ef8b2c':'#d8453a'; }
|
||||
// Standard-Anzeige überall: Prozent in Ampelfarbe + dünner Balken darunter.
|
||||
function pctBar(pct){
|
||||
if (pct==null) return '<span style="color:#9a9a9a">—</span>';
|
||||
var c=pctColor(pct);
|
||||
return '<div style="min-width:72px">'
|
||||
+ '<div style="font-weight:800;color:'+c+';font-size:.86rem;font-variant-numeric:tabular-nums">'+pct+' %</div>'
|
||||
+ '<div style="margin-top:2px;height:6px;border-radius:99px;background:rgba(0,0,0,.07);overflow:hidden"><div style="height:100%;width:'+pct+'%;background:'+c+'"></div></div>'
|
||||
+ '</div>';
|
||||
}
|
||||
// Triage aus Leistungs-% × Aktivität — Grenzen = Farbgrenzen, damit Feld ↔ Farbe stimmen.
|
||||
function triage(pct, active){
|
||||
if (pct==null || !active) return {lab:'inaktiv', col:'#8a8a8a', bg:'#efeee8'};
|
||||
if (pct<50) return {lab:'Fördern', col:'#b04a3e', bg:'#f7e2dc'};
|
||||
if (pct<65) return {lab:'Begleiten', col:'#9a6a12', bg:'#f7edd6'};
|
||||
return {lab:'Läuft gut', col:'#3a6b3e', bg:'#dceadd'};
|
||||
}
|
||||
function triageChip(pct, active){ var t=triage(pct,active); return '<span style="display:inline-block;font-size:.62rem;font-weight:700;color:'+t.col+';background:'+t.bg+';padding:1px 7px;border-radius:10px">'+t.lab+'</span>'; }
|
||||
|
||||
// Vorschlags-Leistungs-% auf die Testdaten gerechnet (Vorschau).
|
||||
function _cl(v,a,b){ return Math.max(a,Math.min(b,v)); }
|
||||
var PERF = {
|
||||
klima:function(s){ var sp=(s.level>=3)?7000:6000; return Math.round(_cl(35-(s.temp-15.5)*20,0,35)+Math.max(0,25*(1-(s.floodedPct||0)/50))+_cl((s.budget||0)/10,0,20)+_cl((s.population||0)/sp*20,0,20)); },
|
||||
fluss:function(s){ return _cl(Math.round((s.biodiv+s.economy+s.flood)/3)-(s.settlementsLost||0)*5,0,100); },
|
||||
kofferdetektiv:function(s){ return s.score!=null?s.score:null; },
|
||||
tourismusregion:function(s){ return Math.round(0.6*((s.avgStars||0)/5*100)+0.4*(s.env||0)); },
|
||||
tourismustal:function(s){ if(!s.goalsTotal) return null; return Math.round(0.5*(s.goalsDone/s.goalsTotal*100)+0.3*(s.satisfaction||0)+0.2*(s.nature||0)); },
|
||||
heli:function(s){ if(s.totalStars!=null) return Math.round(s.totalStars/5*100); if(s.planTotal) return Math.round((s.planCorrect||0)/s.planTotal*100); return null; },
|
||||
farmer:function(s){ var money=_cl(50+(s.cash||0)/300,0,100),co2=_cl(100-(s.co2_kg||0)/80,0,100),dis=_cl(100-(s.diseases||0)*20,0,100),crop=_cl((s.crops_used||0)/10*100,0,100),country=_cl((s.countries||0)/6*100,0,100); return Math.round(0.25*money+0.20*(s.hit_rate||0)+0.15*co2+0.10*dis+0.10*crop+0.10*country+0.10*70); },
|
||||
energiemanager:function(s){ var d=(s.day||1)*(s.blockTotal||8); return _cl(Math.round((s.setBlocksBalanced||0)/d*100)-15*(s.blackouts||0),0,100); },
|
||||
'eu-werkstatt':function(s){ if(!s.stepsTotal) return null; return _cl(Math.round((s.firstTryHits||0)/s.stepsTotal*100)-5*(s.muelleimerCount||0),0,100); },
|
||||
weltkueche:function(s){ var t=(s.correctClicks||0)+(s.wrongClicks||0); return t?Math.round((s.correctClicks||0)/t*100):null; },
|
||||
busfahrt:function(s){ return s.orderIndex?Math.round((s.quizFirstTry||0)/s.orderIndex*100):null; },
|
||||
fluggesellschaft:function(s){ return s.orderIndex?Math.round((s.quizFirstTry||0)/s.orderIndex*100):null; },
|
||||
sonnensystem:function(s){ return s.taskTotal?Math.round((s.completed||0)/s.taskTotal*100):null; },
|
||||
logistik:function(s){ return s.balance==null?null:_cl(Math.round(s.balance/16000*100),0,100); },
|
||||
};
|
||||
|
||||
/* ============================================================
|
||||
4) Testdaten je Sim (3 Schüler:innen: stark · schwach · mittel)
|
||||
============================================================ */
|
||||
@@ -616,6 +677,7 @@ function renderScoring(id){
|
||||
var h = '<div class="scorebox"><h4>🎯 So entsteht die Bewertung</h4>';
|
||||
h += '<div class="srow"><span class="lab">Sterne</span><span>'+sc.stars+'</span></div>';
|
||||
h += '<div class="srow"><span class="lab">Prozent</span><span>'+sc.pct+'</span></div>';
|
||||
if (PROPOSED_PCT[id]) h += '<div class="srow" style="background:#eef7f0;border-radius:6px;padding:.25rem .4rem;margin-top:.35rem"><span class="lab" style="color:#3a6b3e">Vorschlag %</span><span style="color:#2f5e39">'+PROPOSED_PCT[id]+'</span></div>';
|
||||
(sc.flags||[]).forEach(function(f){ h += '<div class="flag">⚠ '+f+'</div>'; });
|
||||
h += '</div>';
|
||||
return h;
|
||||
@@ -640,6 +702,7 @@ function renderSim(meta){
|
||||
h += '<div class="tbl-scroll"><table class="live"><thead><tr>';
|
||||
h += '<th style="text-align:left">Schüler*in<span class="key">displayName</span></th>';
|
||||
h += '<th style="text-align:left;color:#8a8a8a">Seit<span class="key">missionStartedAt / started_at</span></th>';
|
||||
h += '<th style="text-align:left;background:#e7f4ea;border-bottom-color:#bcd9c2">🎯 Leistung<span class="key">leistung_pct (Vorschlag)</span><span class="tag g">EIN Wert</span></th>';
|
||||
fields.forEach(function(f){
|
||||
var align=f.align||'right';
|
||||
var isG=!!greenSet[f.k];
|
||||
@@ -670,6 +733,8 @@ function renderSim(meta){
|
||||
h += '<tr style="background:'+restBg+';'+(paused?'color:#9a9a9a;':'')+'box-shadow:'+accent+'">';
|
||||
h += '<td style="white-space:nowrap"><span style="display:inline-flex;align-items:center;gap:.4rem">'+(help?'<span title="stockt · braucht evtl. Hilfe">🆘</span>':(paused?'<span title="pausiert">⏸</span>':''))+avatarHtml+'<strong>'+esc(ls.displayName)+'</strong></span></td>';
|
||||
h += '<td style="white-space:nowrap;line-height:1.15"><div style="font-size:.78rem;color:#3a3a3a;font-weight:600">'+missionStr+'</div><div style="font-size:.62rem;color:#8a8a8a">'+simStr+' ges.</div></td>';
|
||||
var perfPct = (PERF[meta.id]) ? PERF[meta.id](s) : null;
|
||||
h += '<td style="background:#f2faf4;vertical-align:top">'+pctBar(perfPct)+'<div style="margin-top:3px">'+triageChip(perfPct, perfPct!=null)+'</div></td>';
|
||||
fields.forEach(function(f){
|
||||
var align=f.align||'right';
|
||||
var isG=!!greenSet[f.k];
|
||||
@@ -713,8 +778,30 @@ function renderSim(meta){
|
||||
return h;
|
||||
}
|
||||
|
||||
// Vorschau-Karte: neues Bewertungssystem (Skala · %+Balken · Triage)
|
||||
function renderPreviewCard(){
|
||||
var samples=[92,71,55,40,22];
|
||||
var h='<div class="gbox" style="border-left-color:#5a8a5e">';
|
||||
h+='<h2>🎯 Neues Bewertungssystem — Vorschau zum Abnehmen</h2>';
|
||||
h+='<p><b>Standard überall:</b> ein Leistungs-% (0–100) in der Ampelfarbe + dünner Balken darunter — Sterne fallen weg. Beispiele:</p>';
|
||||
h+='<div style="display:flex;gap:1.4rem;flex-wrap:wrap;margin:.4rem 0 .9rem">'+samples.map(function(v){return pctBar(v);}).join('')+'</div>';
|
||||
h+='<p><b>5-stufige Farbskala</b> (= bestehende Tag-Skala):</p>';
|
||||
h+='<div style="display:flex;gap:.5rem;flex-wrap:wrap;margin:.3rem 0 .9rem;font-size:.72rem">'
|
||||
+[['≥ 80','sehr gut',92],['65–79','gut',71],['50–64','solide',55],['35–49','wackelig',40],['< 35','kritisch',22]]
|
||||
.map(function(b){var c=pctColor(b[2]);return '<span style="display:inline-flex;align-items:center;gap:.35rem;background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:20px;padding:.2rem .6rem"><span style="width:14px;height:14px;border-radius:4px;background:'+c+'"></span><b>'+b[0]+' %</b> · '+b[1]+'</span>';}).join('')+'</div>';
|
||||
h+='<p><b>Triage-Felder aus %×Fleiß</b> — die Grenzen sind die Farbgrenzen, damit Balkenfarbe und Feld immer übereinstimmen:</p>';
|
||||
h+='<div style="display:flex;gap:1.2rem;flex-wrap:wrap;margin:.3rem 0 .6rem">'
|
||||
+[22,55,80].map(function(v){return '<div style="text-align:center">'+pctBar(v)+'<div style="margin-top:3px">'+triageChip(v,true)+'</div></div>';}).join('')
|
||||
+'<div style="text-align:center">'+pctBar(null)+'<div style="margin-top:3px">'+triageChip(null,false)+'</div></div>'+'</div>';
|
||||
h+='<div class="rec"><b>< 50 % → Fördern</b> · <b>50–64 % → Begleiten</b> · <b>≥ 65 % → Läuft gut</b> — jeweils nur, wenn aktiv gearbeitet wurde; sonst „inaktiv".</div>';
|
||||
h+='<p style="font-size:.72rem;color:#8a8a8a;margin-top:.6rem">Unten hat jede Tabelle die neue Spalte <b>🎯 Leistung</b> — die Vorschlags-Formel je Sim, auf die Testdaten gerechnet. Bei Busfahrt · Fluggesellschaft · Sonnensystem ist der Wert eine Näherung (Topo-/Erstversuch-Rohwerte fehlen in den Testdaten).</p>';
|
||||
h+='</div>';
|
||||
return h;
|
||||
}
|
||||
|
||||
// TOC + Inhalt aufbauen
|
||||
var toc = SIM_META.map(function(m){ return '<a href="#sim-'+m.id+'">'+m.icon+' '+esc(m.title)+'</a>'; }).join('');
|
||||
document.getElementById('preview').innerHTML = renderPreviewCard();
|
||||
document.getElementById('toc').innerHTML = toc;
|
||||
document.getElementById('content').innerHTML = SIM_META.map(renderSim).join('');
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user