Gesamt/Fleiss: laufende Sessions als blinkende Saeule im aktuellen Bucket
Statt separatem Top-Streifen (rueckgebaut): results.php view=fleiss spielt laufende live_sessions in den aktuellen Bucket (Stunde/Wochentag/Tag/Monat) ein, markiert ihn `live`. renderFleiss laesst diese Saeule blinken (roter Rahmen). So sieht man Bens laufendes Spiel direkt bei "Fleiss pro Schueler*in". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -369,6 +369,16 @@ if ($view === 'fleiss') {
|
||||
default: Response::error('range muss day|week|weeks|month|year sein');
|
||||
}
|
||||
|
||||
// Aktueller Bucket-Index (für LAUFENDE, noch nicht abgegebene Sessions).
|
||||
$nowBucketIdx = -1;
|
||||
switch ($range) {
|
||||
case 'day': $nowBucketIdx = (int)date('G'); break; // Stunde 0–23
|
||||
case 'week': $nowBucketIdx = (int)date('N') - 1; break; // Mo=0 … So=6
|
||||
case 'month': $nowBucketIdx = (int)date('j') - 1; break; // Tag 1–31
|
||||
case 'year': $nowBucketIdx = (int)date('n') - 1; break; // Monat 1–12
|
||||
case 'weeks': $nowBucketIdx = isset($bmap) ? ($bmap[(int)date('oW')] ?? -1) : -1; break;
|
||||
}
|
||||
|
||||
// Optional Modul-Filter
|
||||
$params = [$classId];
|
||||
$modSql = '';
|
||||
@@ -463,6 +473,39 @@ if ($view === 'fleiss') {
|
||||
$moduleAgg[$sim]['totalSec'] += $sec;
|
||||
}
|
||||
|
||||
// 5b) LAUFENDE Sessions (noch kein Assessment abgegeben) in den aktuellen
|
||||
// Bucket einspielen — als „live" markiert, damit die Säule dort blinkt.
|
||||
if ($nowBucketIdx >= 0) {
|
||||
$liveRows = $db->fetchAll(
|
||||
"SELECT ls.student_id, ls.module_id,
|
||||
UNIX_TIMESTAMP(ls.started_at) AS started_ts,
|
||||
UNIX_TIMESTAMP(ls.last_seen) AS last_seen_ts
|
||||
FROM live_sessions ls
|
||||
WHERE ls.class_id = ? AND ls.last_seen > NOW() - INTERVAL 90 SECOND",
|
||||
[$classId]
|
||||
);
|
||||
foreach ($liveRows as $lr) {
|
||||
$sid = (int)$lr['student_id'];
|
||||
if (!isset($byStudent[$sid])) continue;
|
||||
$sim = $lr['module_id'];
|
||||
if ($moduleId !== 'ALL' && $moduleId !== '' && $sim !== $moduleId) continue;
|
||||
$sec = max(0, (int)$lr['last_seen_ts'] - (int)$lr['started_ts']);
|
||||
$b = &$byStudent[$sid]['buckets'][$nowBucketIdx];
|
||||
$b['sum'] += $sec;
|
||||
$byMod = (array)$b['byModule'];
|
||||
$byMod[$sim] = ($byMod[$sim] ?? 0) + $sec;
|
||||
$b['byModule'] = $byMod;
|
||||
$b['live'] = true; // Client lässt diese Säule blinken
|
||||
$b['liveModule'] = $sim;
|
||||
unset($b);
|
||||
$byStudent[$sid]['totalSec'] += $sec;
|
||||
if (!isset($moduleAgg[$sim])) {
|
||||
$info = $moduleMap[$sim] ?? null;
|
||||
$moduleAgg[$sim] = ['id'=>$sim,'name'=>$info?$info['name']:$sim,'icon'=>$info?$info['icon']:'📘','color'=>$info?$info['color']:'#888','totalSec'=>0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 6) Global-Max-Bucket-Sec für klassenweite Säulen-Skalierung
|
||||
foreach ($byStudent as $sid => &$st) {
|
||||
foreach ($st['buckets'] as $b) {
|
||||
|
||||
Reference in New Issue
Block a user