Tag-Ansicht: echte Spieldauer + Ampelfarbe nach Erfolg + Sim-Symbol
Bug: fertig gespielte Laeufe (Farmer-Endbericht = 1 Assessment) erschienen als kurzer "Abbruch"-Balken (Dauer 0). Fix: - live.php summary: nutzt duration_ms -> Balken decken die echte Spielzeit ab und fluchten am Start; kein Falsch-Abbruch mehr. Neues Feld `score` (0-100) je Session (Score/Sterne); laufende Farmer-Sessions bekommen hit_rate als Live-Score. - teacher.html Tag-Balken: einheitliche Hoehe (Hoehe raus), Farbe = Ampel nach Erfolg (gruen->rot), App-Farbe ersetzt durch Sim-Symbol; Klick = Details. Legende angepasst. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+41
-27
@@ -1574,6 +1574,11 @@ function _liveSuccessColor(success) {
|
||||
unknown: '#7a8a9c',
|
||||
})[success] || '#7a8a9c';
|
||||
}
|
||||
// Ampelfarbe für den Tages-Erfolg (0–100): grün → hellgrün → gelb → orange → rot.
|
||||
function _tagTraffic(v) {
|
||||
v = Math.max(0, Math.min(100, v || 0));
|
||||
return v >= 80 ? '#1f7a3d' : v >= 65 ? '#7cb342' : v >= 50 ? '#f9c33b' : v >= 35 ? '#ef8b2c' : '#d8453a';
|
||||
}
|
||||
function _liveSuccessIcon(stars, success) {
|
||||
if (success === 'aborted') return '✗';
|
||||
if (success === 'running') return '⏳';
|
||||
@@ -2119,38 +2124,40 @@ async function renderLiveSummary() {
|
||||
var pctL = _msToPct(sess.startMs);
|
||||
var pctR = _msToPct(endMs);
|
||||
var pctW = Math.max(0.8, pctR - pctL); // mindestens 0.8 % sichtbar
|
||||
var simW = simWord(sess.simId), simC = simCode(sess.simId);
|
||||
var col = simColor(sess.simId); // eine Farbe je Sim
|
||||
var stars = (sess.stars != null) ? Math.max(0, Math.min(5, sess.stars)) : null;
|
||||
var icon = sess.simIcon || '📚';
|
||||
var simName = sess.simTitle || simWord(sess.simId);
|
||||
// Erfolg 0–100 (Score, sonst Sterne → %). Bestimmt die AMPELFARBE.
|
||||
var score = (sess.score != null) ? sess.score
|
||||
: (sess.stars != null ? Math.round(Math.max(0,Math.min(5,sess.stars))/5*100) : null);
|
||||
var aborted = sess.success === 'aborted';
|
||||
var completed = !aborted && stars != null; // fertig gespielt
|
||||
var inProgress = !aborted && stars == null; // noch dran / kein Ergebnis
|
||||
// Balkenhöhe = Maß für den Erfolg (mehr Sterne → höher). Abbruch/läuft: flach.
|
||||
var barH = completed ? (9 + Math.round(stars / 5 * 15)) : (aborted ? 9 : 12);
|
||||
// Rahmen kodiert den Zustand: fertig = geschlossen · noch dran = rechts offen ·
|
||||
// Abbruch = gestrichelt (+ ✖ am Ende).
|
||||
var border = completed ? 'border:1.5px solid rgba(20,20,20,.45);'
|
||||
: inProgress ? 'border:1.5px solid rgba(20,20,20,.4);border-right:0;'
|
||||
: 'border:1.5px dashed rgba(20,20,20,.45);';
|
||||
var stateWord = completed ? 'fertig' : aborted ? 'abgebrochen' : 'läuft noch';
|
||||
var inProgress = !aborted && (sess.isLive || sess.success === 'running');
|
||||
// Farbe = Erfolg (Ampel). Kein Wert → neutral grau. Abbruch → rot-gestrichelt.
|
||||
var col = aborted ? '#c0392b' : (score != null ? _tagTraffic(score) : '#aab2b8');
|
||||
var barH = 18; // EINHEITLICHE Höhe — der Erfolg steckt in der Farbe, nicht in der Höhe
|
||||
// Rahmen kodiert den Zustand: fertig = geschlossen · läuft = rechts gepunktet · Abbruch = gestrichelt
|
||||
var border = aborted ? 'border:1.5px dashed rgba(255,255,255,.7);'
|
||||
: inProgress ? 'border:1.5px solid rgba(255,255,255,.55);border-right:2px dotted #fff;'
|
||||
: 'border:1.5px solid rgba(20,20,20,.25);';
|
||||
var stateWord = inProgress ? 'läuft noch' : aborted ? 'abgebrochen' : 'fertig';
|
||||
var tip = (sess.simTitle||sess.simId) + (sess.lessonLabel?' · '+sess.lessonLabel:'')
|
||||
+ ' · ' + _fmtHM(sess.startMs) + '–' + _fmtHM(endMs)
|
||||
+ ' · ' + _liveFmtMin(realDurSec) + ' · ' + stateWord
|
||||
+ (stars!=null?' · '+stars+'/5★':'');
|
||||
// enger Balken → Kürzel, mittel → Wort, breit → Wort + Lektion
|
||||
var inner = (pctW < 2.5) ? '' : (pctW < 6) ? simC : (pctW < 11) ? simW : (simW + (sess.lessonLabel ? ' '+sess.lessonLabel : ''));
|
||||
+ (score!=null?' · Erfolg '+score+' %':'');
|
||||
// Symbol immer sichtbar; ab etwas Breite zusätzlich der Sim-Name
|
||||
var inner = (pctW < 2) ? '' : (pctW < 9 ? '<span style="font-size:.82rem">'+icon+'</span>'
|
||||
: '<span style="font-size:.82rem">'+icon+'</span> <span style="font-weight:700">'+esc(simName)+'</span>');
|
||||
var sessKey = s.studentId + ':' + sess.simId + ':' + (sess.lessonLabel||'_') + ':' + sess.startMs;
|
||||
html += '<div onclick="openLiveSessionDetail(\''+sessKey+'\')" '
|
||||
+ 'title="'+esc(tip)+'" '
|
||||
+ 'style="position:absolute;left:'+pctL+'%;width:'+pctW+'%;bottom:2px;height:'+barH+'px;'
|
||||
+ 'background:'+col+';color:#fff;border-radius:3px;'+border
|
||||
+ 'padding:0 .3rem;font-size:.6rem;font-weight:700;line-height:'+Math.max(9,barH-3)+'px;'
|
||||
+ 'style="position:absolute;left:'+pctL+'%;width:'+pctW+'%;top:5px;height:'+barH+'px;'
|
||||
+ 'background:'+col+';color:#fff;border-radius:4px;'+border
|
||||
+ 'padding:0 .35rem;font-size:.66rem;line-height:'+barH+'px;'
|
||||
+ 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;'
|
||||
+ 'text-shadow:0 1px 1px rgba(0,0,0,.35);box-shadow:0 1px 2px rgba(0,0,0,.12)">'
|
||||
+ esc(inner) + '</div>';
|
||||
+ 'text-shadow:0 1px 1px rgba(0,0,0,.3);box-shadow:0 1px 2px rgba(0,0,0,.12)">'
|
||||
+ inner + '</div>';
|
||||
if (aborted) {
|
||||
html += '<span style="position:absolute;left:'+pctR+'%;bottom:-1px;height:28px;line-height:28px;'
|
||||
+ 'font-size:.74rem;color:#b03a2a;font-weight:800;padding-left:1px;pointer-events:none">✖</span>';
|
||||
html += '<span style="position:absolute;left:'+pctR+'%;top:0;height:28px;line-height:28px;'
|
||||
+ 'font-size:.74rem;color:#b03a2a;font-weight:800;padding-left:2px;pointer-events:none">✖</span>';
|
||||
}
|
||||
});
|
||||
html += '</div>';
|
||||
@@ -2158,10 +2165,17 @@ async function renderLiveSummary() {
|
||||
html += '</div>';
|
||||
|
||||
html += '<div style="margin-top:.8rem;display:flex;gap:1rem;flex-wrap:wrap;font-size:.66rem;color:#5a5a5a;align-items:center">';
|
||||
html += '<span><b>Farbe</b> = Simulation · <b>Höhe</b> = Erfolg (höher = besser)</span>';
|
||||
html += '<span><span style="display:inline-block;width:16px;height:11px;background:#8a8a8a;border:1.5px solid rgba(20,20,20,.45);vertical-align:middle;margin-right:.25rem"></span>fertig</span>';
|
||||
html += '<span><span style="display:inline-block;width:16px;height:11px;background:#8a8a8a;border:1.5px solid rgba(20,20,20,.4);border-right:0;vertical-align:middle;margin-right:.25rem"></span>läuft noch</span>';
|
||||
html += '<span><span style="display:inline-block;width:16px;height:11px;background:#8a8a8a;border:1.5px dashed rgba(20,20,20,.45);vertical-align:middle;margin-right:.15rem"></span><span style="color:#b03a2a;font-weight:800">✖</span> Abbruch</span>';
|
||||
html += '<span style="display:inline-flex;align-items:center;gap:.3rem"><b>Farbe</b> = Erfolg:'
|
||||
+ '<span style="display:inline-flex;border-radius:2px;overflow:hidden">'
|
||||
+ '<span style="display:inline-block;width:13px;height:11px;background:#1f7a3d"></span>'
|
||||
+ '<span style="display:inline-block;width:13px;height:11px;background:#7cb342"></span>'
|
||||
+ '<span style="display:inline-block;width:13px;height:11px;background:#f9c33b"></span>'
|
||||
+ '<span style="display:inline-block;width:13px;height:11px;background:#ef8b2c"></span>'
|
||||
+ '<span style="display:inline-block;width:13px;height:11px;background:#d8453a"></span></span>'
|
||||
+ ' stark → schwach</span>';
|
||||
html += '<span><b>Symbol</b> = Simulation · <b>Klick</b> = Details</span>';
|
||||
html += '<span><span style="display:inline-block;width:16px;height:11px;background:#aab2b8;border:1.5px solid rgba(255,255,255,.55);border-right:2px dotted #fff;vertical-align:middle;margin-right:.25rem"></span>läuft noch</span>';
|
||||
html += '<span><span style="color:#b03a2a;font-weight:800">✖</span> Abbruch</span>';
|
||||
html += '</div>';
|
||||
|
||||
html += '</div>';
|
||||
|
||||
Reference in New Issue
Block a user