Cockpit: "Empfohlene Aktivitaet fuer dich" zweigeteilt - HEUTE (oben) + insgesamt (darunter)
HEUTE triagiert exakt gleich (support/more/work/good/idle), aber nur auf die heutigen Laeufe (Erfolg = Ø der heutigen Scores aus summary-Endpoint). Karten-Renderer in _ivTriageCards ausgelagert + wiederverwendet. Neuer summary-Fetch im Promise.all. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+61
-21
@@ -2725,6 +2725,29 @@ var IV_ICON={
|
||||
idle:'<circle cx="12" cy="12" r="9" stroke-dasharray="3 3"/><path d="M12 8v4l2 2"/>'};
|
||||
var IV_META={support:['Fördern','zuletzt schwächere Läufe','--ivns'],more:['Fordern','zuletzt sicher, kaum gefordert','--ivnm'],
|
||||
work:['Begleiten','zuletzt viel gearbeitet, wenig Ertrag','--ivnw'],good:['Bestätigen','zuletzt besser geworden','--ivngd'],idle:['Nicht aktiv','länger nicht mehr dran (oder noch nie)','--ivni']};
|
||||
var IV_WEEK_CAP = 10800; // eine Woche zählt max. 3 h aktive Zeit (Ausreißer-Schutz)
|
||||
|
||||
// Rendert die 5 Triage-Karten (support/more/work/good/idle) aus fertigen Gruppen.
|
||||
// Wiederverwendet für „HEUTE" und „insgesamt". todayMode passt Untertitel/Tooltips an.
|
||||
function _ivTriageCards(groups, maxSec, todayMode){
|
||||
var h='<div class="iv-grid">';
|
||||
['support','more','work','good','idle'].forEach(function(key){
|
||||
var rows=groups[key], m=IV_META[key];
|
||||
var sub=(todayMode && key==='idle')?'heute noch nicht dran':m[1];
|
||||
h+='<div class="iv-card" style="--iva:var('+m[2]+')"><div class="iv-chead"><span class="iv-ic"><svg viewBox="0 0 24 24">'+IV_ICON[key]+'</svg></span><div class="iv-ct"><h4>'+m[0]+'</h4><p>'+sub+'</p></div><span class="iv-cn num">'+rows.length+'</span></div>';
|
||||
if(rows.length){
|
||||
h+='<div class="iv-cols"><span></span><span title="'+(todayMode?'Ø Erfolg der heutigen Läufe':'Ø der letzten 3 Läufe')+', 0 – 100">Erfolg</span><span title="arbeitet gerade? blinkt live">Aktiv</span><span title="aktive Zeit pro Woche">Verlauf</span><span title="'+(todayMode?'heute aktiv?':'Tage seit dem letzten Lauf')+'">Zuletzt</span><span></span></div>';
|
||||
rows.forEach(function(r){
|
||||
h+='<button class="iv-prow" onclick="ivOpenStudent('+r.sid+')"><span class="iv-nm">'+esc(r.name)+'</span><span style="display:contents">'+ivErf(r.erf)+ivAkt(r.status)+ivSpark(r.secs,maxSec,IV_WEEK_CAP)+'</span>'+ivZuletzt(r.days)+'<svg class="iv-chev" viewBox="0 0 24 24"><path d="m9 6 6 6-6 6"/></svg></button>';
|
||||
});
|
||||
} else {
|
||||
h+='<div class="iv-cempty">'+(todayMode?'Heute niemand.':'Aktuell niemand betroffen.')+'</div>';
|
||||
}
|
||||
h+='</div>';
|
||||
});
|
||||
h+='</div>';
|
||||
return h;
|
||||
}
|
||||
|
||||
// Triage NUR aus der AKTUELLEN Leistung (Empfehlung = Reaktion auf das Zuletzt-
|
||||
// Gesehene, kein Allzeit-Rückblick): recentErfolg = Ø letzte 3 Läufe, daysSince =
|
||||
@@ -2762,13 +2785,13 @@ function _todayHelpReason(simId, st){
|
||||
}
|
||||
return 'stockt · braucht evtl. Hilfe';
|
||||
}
|
||||
function ivBuildOverview(cockpit, weeks, studentsCount, matrix){
|
||||
function ivBuildOverview(cockpit, weeks, studentsCount, matrix, todaySummary){
|
||||
ivInjectCss();
|
||||
var cs = (cockpit && cockpit.students) || [];
|
||||
var sc = (cockpit && cockpit.statusCounts) || {};
|
||||
// Verlauf-Map je Schüler. CAP gegen Ausreißer (z. B. Zwischenspeicher-Logs
|
||||
// mit aufgeblähter duration): eine Woche zählt max. 3 h aktive Zeit.
|
||||
var IV_WEEK_CAP=10800, wById={}, maxSec=1;
|
||||
// mit aufgeblähter duration): eine Woche zählt max. 3 h aktive Zeit (IV_WEEK_CAP).
|
||||
var wById={}, maxSec=1;
|
||||
((weeks&&weeks.students)||[]).forEach(function(w){ wById[w.studentId]=w; });
|
||||
// Plays je Schüler aus Matrix
|
||||
var playsById={};
|
||||
@@ -2830,23 +2853,38 @@ function ivBuildOverview(cockpit, weeks, studentsCount, matrix){
|
||||
h+='<div class="iv-stat"><span class="iv-lab">Simulationen</span><div class="iv-gfx"><span class="iv-bign num">'+simTotal+'</span></div><span class="iv-exp">Durchläufe insgesamt</span></div>';
|
||||
h+='</div>';
|
||||
// Triage
|
||||
var need=groups.support.length+groups.more.length+groups.work.length+groups.good.length+groups.idle.length;
|
||||
h+='<div class="iv-sec">Empfohlene Aktivität für dich.<span>'+need+' von '+studentsCount+'</span></div><div class="iv-grid">';
|
||||
['support','more','work','good','idle'].forEach(function(key){
|
||||
var rows=groups[key];
|
||||
var m=IV_META[key];
|
||||
h+='<div class="iv-card" style="--iva:var('+m[2]+')"><div class="iv-chead"><span class="iv-ic"><svg viewBox="0 0 24 24">'+IV_ICON[key]+'</svg></span><div class="iv-ct"><h4>'+m[0]+'</h4><p>'+m[1]+'</p></div><span class="iv-cn num">'+rows.length+'</span></div>';
|
||||
if(rows.length){
|
||||
h+='<div class="iv-cols"><span></span><span title="Ø der letzten 3 Läufe, 0 – 100">Erfolg</span><span title="arbeitet gerade? blinkt live">Aktiv</span><span title="aktive Zeit pro Woche">Verlauf</span><span title="Tage seit dem letzten Lauf">Zuletzt</span><span></span></div>';
|
||||
rows.forEach(function(r){
|
||||
h+='<button class="iv-prow" onclick="ivOpenStudent('+r.sid+')"><span class="iv-nm">'+esc(r.name)+'</span><span style="display:contents">'+ivErf(r.erf)+ivAkt(r.status)+ivSpark(r.secs,maxSec,IV_WEEK_CAP)+'</span>'+ivZuletzt(r.days)+'<svg class="iv-chev" viewBox="0 0 24 24"><path d="m9 6 6 6-6 6"/></svg></button>';
|
||||
});
|
||||
} else {
|
||||
h+='<div class="iv-cempty">Aktuell niemand betroffen.</div>';
|
||||
}
|
||||
h+='</div>';
|
||||
// === HEUTE-Triage: gleiche Logik, aber nur auf die HEUTIGEN Läufe bezogen ===
|
||||
var todayErfById={}, todayPlaysById={};
|
||||
((todaySummary&&todaySummary.students)||[]).forEach(function(su){
|
||||
var sess=(su.sessions||[]).filter(function(x){ return x.startMs; });
|
||||
if(!sess.length) return;
|
||||
var sco=[];
|
||||
sess.forEach(function(x){ var v=(x.score!=null)?x.score:(x.stars!=null?Math.round(x.stars/5*100):null); if(v!=null) sco.push(v); });
|
||||
todayPlaysById[su.studentId]=sess.length;
|
||||
todayErfById[su.studentId]= sco.length? Math.round(sco.reduce(function(a,b){return a+b;},0)/sco.length) : null;
|
||||
});
|
||||
h+='</div>';
|
||||
var heuteGroups={support:[],more:[],work:[],good:[],idle:[]}, heuteCalm=[];
|
||||
cs.forEach(function(s){
|
||||
var sid=s.studentId||s.id;
|
||||
var played=(todayPlaysById[sid]||0)>0;
|
||||
var tErf=todayErfById[sid];
|
||||
var w2=wById[sid], secs2=w2?w2.buckets.map(function(b){return Math.min(IV_WEEK_CAP, b.sum||0);}):[];
|
||||
while(secs2.length<10) secs2.unshift(0);
|
||||
var g2 = !played ? 'idle' : ivTriage(tErf, 0, todayPlaysById[sid], false);
|
||||
var row2={sid:sid, name:s.displayName, erf:played?tErf:null, status:s.status, secs:secs2, days:played?0:(s.daysSince!=null?s.daysSince:null)};
|
||||
if(g2) heuteGroups[g2].push(row2); else heuteCalm.push(s.displayName);
|
||||
});
|
||||
var heutePlayed=Object.keys(todayPlaysById).length;
|
||||
var need=groups.support.length+groups.more.length+groups.work.length+groups.good.length+groups.idle.length;
|
||||
|
||||
// 1) HEUTE (oben) — genau dieselbe Darstellung, nur auf heute gefiltert
|
||||
h+='<div class="iv-sec">Empfohlene Aktivität für dich — <b style="color:#2a5a2e">HEUTE</b><span>'+heutePlayed+' heute aktiv</span></div>';
|
||||
h+=_ivTriageCards(heuteGroups, maxSec, true);
|
||||
if(heuteCalm.length) h+='<div class="iv-calm"><span class="iv-dot"></span><span><b>Heute rund gelaufen — '+heuteCalm.length+'</b></span><span class="iv-names">'+heuteCalm.map(esc).join(' · ')+'</span></div>';
|
||||
|
||||
// 2) insgesamt (darunter) — der bisherige Allzeit-/Zuletzt-Blick
|
||||
h+='<div class="iv-sec" style="margin-top:1.5rem">Empfohlene Aktivität für dich — insgesamt<span>'+need+' von '+studentsCount+'</span></div>';
|
||||
h+=_ivTriageCards(groups, maxSec, false);
|
||||
if(calm.length) h+='<div class="iv-calm"><span class="iv-dot"></span><span><b>Läuft rund — '+calm.length+'</b></span><span class="iv-names">'+calm.map(esc).join(' · ')+'</span></div>';
|
||||
// Legende
|
||||
h+='<div class="iv-legend">'
|
||||
@@ -3172,7 +3210,7 @@ async function loadOverview() {
|
||||
if (!_modFilter.from) _modFilter.from = ggsSchoolYearStart();
|
||||
if (!_modFilter.to) _modFilter.to = ggsTodayStr();
|
||||
|
||||
var [matrix, activity, assignments, students, cockpit, weeks, today, modStats] = await Promise.all([
|
||||
var [matrix, activity, assignments, students, cockpit, weeks, today, modStats, todaySum] = await Promise.all([
|
||||
api('results?class_id=' + currentClassId + '&view=matrix'),
|
||||
api('results?class_id=' + currentClassId + '&view=activity&range=week'),
|
||||
api('assignments?class_id=' + currentClassId),
|
||||
@@ -3181,7 +3219,9 @@ async function loadOverview() {
|
||||
api('results?class_id=' + currentClassId + '&view=fleiss&range=weeks'),
|
||||
api('results?class_id=' + currentClassId + '&view=today'),
|
||||
api('results?class_id=' + currentClassId + '&view=mod_stats&from=' + _modFilter.from + '&to=' + _modFilter.to),
|
||||
api('live?summary=1&class_id=' + currentClassId + '&date=' + ggsTodayStr()),
|
||||
]);
|
||||
if (!todaySum || todaySum.error) todaySum = {students:[]};
|
||||
if (matrix.error) { host.innerHTML = '<p style="color:#c07a6b">'+esc(matrix.error)+'</p>'; return; }
|
||||
if (activity.error) activity = {series:[], buckets:[]};
|
||||
if (assignments.error) assignments = [];
|
||||
@@ -3222,7 +3262,7 @@ async function loadOverview() {
|
||||
var html = '';
|
||||
|
||||
// === NEU: Interventions-Übersicht (Erfolg · Aktiv · Verlauf + Triage) ===
|
||||
html += ivBuildOverview(cockpit, weeks, students.length, matrix);
|
||||
html += ivBuildOverview(cockpit, weeks, students.length, matrix, todaySum);
|
||||
|
||||
// === Sektion B: Aktive Klassen-Simulationen ===
|
||||
var active = (assignments || []).filter(function(a){return a.active;});
|
||||
|
||||
Reference in New Issue
Block a user