Lehrer-Aktivitätsstreifen: Farbe je Sim, Höhe=Erfolg, Rahmen=Zustand
Tages-Balken neu kodiert (nach Thomas' Spec): - Eine Farbe pro Simulation (simColor, stabil per Hash). - Balkenhöhe = Maß für den Erfolg (mehr Sterne → höher) → Leistungen auf einen Blick vergleichbar. - Rahmen kodiert den Zustand: fertig gespielt = geschlossener dünner Rahmen · noch dran = rechts offener Rahmen · Abbruch = gestrichelt + ✖ am Ende. - Beschriftung: 3-Buchstaben-Kürzel (eng) → Wort → Wort+Lektion (Platz). - Legende entsprechend erneuert. Datenbasis vorhanden: live.php summary liefert success (inkl. 'aborted'), stars, completed pro Session. Offen für v2: „läuft noch"-Balken aus aktiven live_sessions einblenden (Tag-View ist bisher assessments-basiert = Abschlüsse). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+37
-25
@@ -1487,6 +1487,13 @@ var SIM_LABELS = {
|
||||
};
|
||||
function simWord(id){ return (SIM_LABELS[id] && SIM_LABELS[id].w) || id; }
|
||||
function simCode(id){ return (SIM_LABELS[id] && SIM_LABELS[id].c) || String(id||'').slice(0,3).toUpperCase(); }
|
||||
// Stabile, unterscheidbare Farbe je Sim (eine Farbe pro Simulation) — Hash→Farbton.
|
||||
function simColor(id){
|
||||
if (SIM_LABELS[id] && SIM_LABELS[id].col) return SIM_LABELS[id].col;
|
||||
var s = String(id||''), h = 0;
|
||||
for (var i=0;i<s.length;i++) h = (h*33 + s.charCodeAt(i)) % 360;
|
||||
return 'hsl('+h+',48%,42%)';
|
||||
}
|
||||
// Rückwärtskompatibel: LIVE_SIM_SHORT[id] = Wort je Sim.
|
||||
var LIVE_SIM_SHORT = Object.keys(SIM_LABELS).reduce(function(o,k){ o[k]=SIM_LABELS[k].w; return o; }, {});
|
||||
function _liveFmtMin(sec) {
|
||||
@@ -2049,44 +2056,49 @@ 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);
|
||||
var simC = simCode(sess.simId);
|
||||
var lbl = simW + (sess.lessonLabel ? ' '+sess.lessonLabel : '');
|
||||
var color = _liveSuccessColor(sess.success);
|
||||
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 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 tip = (sess.simTitle||sess.simId) + (sess.lessonLabel?' · '+sess.lessonLabel:'')
|
||||
+ ' · ' + _fmtHM(sess.startMs) + '–' + _fmtHM(endMs)
|
||||
+ ' · ' + _liveFmtMin(realDurSec)
|
||||
+ (sess.stars!=null?' · '+sess.stars+'/5★':'');
|
||||
// enger Balken → 3-Buchstaben-Kürzel, mittel → Wort, breit → Wort + Lektion
|
||||
var inner = (pctW < 2.5) ? '' : (pctW < 6) ? simC : (pctW < 11) ? simW : lbl;
|
||||
+ ' · ' + _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 : ''));
|
||||
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+'%;top:2px;height:24px;'
|
||||
+ 'background:'+color+';color:#fff;border-radius:3px;'
|
||||
+ 'padding:0 .35rem;font-size:.62rem;font-weight:700;line-height:24px;'
|
||||
+ '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;'
|
||||
+ 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;'
|
||||
+ 'box-shadow:0 1px 2px rgba(0,0,0,.1)">'
|
||||
+ 'text-shadow:0 1px 1px rgba(0,0,0,.35);box-shadow:0 1px 2px rgba(0,0,0,.12)">'
|
||||
+ esc(inner) + '</div>';
|
||||
// Nach Abschluss immer die Sterne (gold) am Balkenende zeigen
|
||||
if (sess.stars != null) {
|
||||
var _sc = Math.max(0, Math.min(5, sess.stars));
|
||||
var _starTxt = '★'.repeat(_sc) + '<span style="color:#d9d2be">' + '★'.repeat(5-_sc) + '</span>';
|
||||
var _rightEdge = pctR > 82;
|
||||
html += '<span style="position:absolute;'
|
||||
+ (_rightEdge ? 'right:'+(100-pctR)+'%;padding-right:4px;' : 'left:'+pctR+'%;padding-left:3px;')
|
||||
+ 'top:0;height:28px;line-height:28px;font-size:.62rem;color:#e0a838;font-weight:700;'
|
||||
+ 'letter-spacing:.5px;white-space:nowrap;pointer-events:none">'+_starTxt+'</span>';
|
||||
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 += '</div>';
|
||||
});
|
||||
html += '</div>';
|
||||
|
||||
html += '<div style="margin-top:.8rem;display:flex;gap:.6rem;flex-wrap:wrap;font-size:.65rem;color:#5a5a5a">';
|
||||
[['good','★ ≥ 4 — gut'],['mid','★ 2-3 — mittel'],['bad','★ ≤ 1 — schwach'],['aborted','abgebrochen'],['running','läuft noch']].forEach(function(p){
|
||||
html += '<span><span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:'+_liveSuccessColor(p[0])+';vertical-align:middle;margin-right:.25rem"></span>'+p[1]+'</span>';
|
||||
});
|
||||
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 += '</div>';
|
||||
|
||||
html += '</div>';
|
||||
|
||||
Reference in New Issue
Block a user