From c9eb0e77643c817fc4e203a50f6fa32ae5607fc6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 23 Aug 2026 12:16:10 +0200 Subject: [PATCH] Cockpit: "Empfohlene Aktivitaet fuer dich" zweigeteilt - HEUTE (oben) + insgesamt (darunter) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- App/teacher.html | 82 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/App/teacher.html b/App/teacher.html index 965d9d8..b53dfef 100644 --- a/App/teacher.html +++ b/App/teacher.html @@ -2725,6 +2725,29 @@ var IV_ICON={ idle:''}; 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='
'; + ['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+='
'+IV_ICON[key]+'

'+m[0]+'

'+sub+'

'+rows.length+'
'; + if(rows.length){ + h+='
ErfolgAktivVerlaufZuletzt
'; + rows.forEach(function(r){ + h+=''; + }); + } else { + h+='
'+(todayMode?'Heute niemand.':'Aktuell niemand betroffen.')+'
'; + } + h+='
'; + }); + h+='
'; + 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+='
Simulationen
'+simTotal+'
Durchläufe insgesamt
'; h+=''; // Triage - var need=groups.support.length+groups.more.length+groups.work.length+groups.good.length+groups.idle.length; - h+='
Empfohlene Aktivität für dich.'+need+' von '+studentsCount+'
'; - ['support','more','work','good','idle'].forEach(function(key){ - var rows=groups[key]; - var m=IV_META[key]; - h+='
'+IV_ICON[key]+'

'+m[0]+'

'+m[1]+'

'+rows.length+'
'; - if(rows.length){ - h+='
ErfolgAktivVerlaufZuletzt
'; - rows.forEach(function(r){ - h+=''; - }); - } else { - h+='
Aktuell niemand betroffen.
'; - } - h+='
'; + // === 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+='
'; + 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+='
Empfohlene Aktivität für dich — HEUTE'+heutePlayed+' heute aktiv
'; + h+=_ivTriageCards(heuteGroups, maxSec, true); + if(heuteCalm.length) h+='
Heute rund gelaufen — '+heuteCalm.length+''+heuteCalm.map(esc).join(' · ')+'
'; + + // 2) insgesamt (darunter) — der bisherige Allzeit-/Zuletzt-Blick + h+='
Empfohlene Aktivität für dich — insgesamt'+need+' von '+studentsCount+'
'; + h+=_ivTriageCards(groups, maxSec, false); if(calm.length) h+='
Läuft rund — '+calm.length+''+calm.map(esc).join(' · ')+'
'; // Legende h+='
' @@ -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 = '

'+esc(matrix.error)+'

'; 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;});