Tag-Ansicht: pausierte Laeufe als halbhoher weiterlaufender Balken

live.php meldet paused (Idle-Pause/Sim-Pause/phase=paused) + activeUntilMs (letzte
Interaktion). renderLiveSummary: Hauptbalken volle Hoehe bis Pausenbeginn, danach
halbhoher gedaempfter "Pausen-Schwanz" der mit der Zeit weiterwaechst. Legende + tz.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 12:02:27 +02:00
parent 5633d3f9f9
commit 3c28794012
2 changed files with 45 additions and 18 deletions
+25 -14
View File
@@ -347,21 +347,32 @@ if ($method === 'GET') {
} elseif (isset($state['score']) && is_numeric($state['score'])) {
$liveScore = max(0, min(100, (int)round($state['score'])));
}
// Pausiert? (Idle-Pause-Overlay oder Sim-Pause). activeUntilMs = letzter
// Interaktionszeitpunkt → der Balken kann ab da halbhoch weitergezeichnet
// werden, solange die Pause läuft.
// Pausiert: Plattform-Idle-Pause, Sim-Pause ODER die Sim meldet phase=paused
// (z. B. Klima bei Geschwindigkeit 0). activeUntilMs = letzter Interaktions-
// zeitpunkt → ab da wird der Balken halbhoch weitergezeichnet.
$isPaused = !empty($state['__idlePaused']) || !empty($state['__paused'])
|| (isset($state['phase']) && $state['phase'] === 'paused');
$activeUntil = isset($state['__lastInteractionAt']) ? (int)$state['__lastInteractionAt'] : 0;
$byStudent[$sid]['sessions'][] = [
'simId' => $simId,
'simTitle' => $mi['title'] ?? $simId,
'simIcon' => $mi['icon'] ?? '📚',
'lessonKind' => $lessonKind,
'lessonLabel' => $lessonLabel,
'startMs' => $startMs,
'endMs' => $endMs,
'durationSec' => $durSec,
'stars' => null,
'score' => $liveScore,
'completed' => null,
'success' => 'running',
'rowCount' => 1,
'isLive' => true,
'simId' => $simId,
'simTitle' => $mi['title'] ?? $simId,
'simIcon' => $mi['icon'] ?? '📚',
'lessonKind' => $lessonKind,
'lessonLabel' => $lessonLabel,
'startMs' => $startMs,
'endMs' => $endMs,
'durationSec' => $durSec,
'stars' => null,
'score' => $liveScore,
'completed' => null,
'success' => 'running',
'rowCount' => 1,
'isLive' => true,
'paused' => $isPaused,
'activeUntilMs'=> ($activeUntil > $startMs && $activeUntil < $endMs) ? $activeUntil : 0,
];
$byStudent[$sid]['totalSec'] += $durSec;
}
+20 -4
View File
@@ -2230,7 +2230,12 @@ async function renderLiveSummary() {
var realDurSec = _liveRealDurSec(sess);
var endMs = sess.startMs + realDurSec * 1000;
var pctL = _msToPct(sess.startMs);
var pctR = _msToPct(endMs);
// Pausierter Lauf: der Hauptbalken (volle Höhe) reicht nur bis zum Pausenbeginn,
// danach zeichnen wir einen halbhohen „Pausen-Schwanz" bis jetzt weiter.
var isPausedRun = (sess.isLive || sess.success === 'running') && sess.paused
&& sess.activeUntilMs && sess.activeUntilMs > sess.startMs && sess.activeUntilMs < endMs;
var mainEndMs = isPausedRun ? sess.activeUntilMs : endMs;
var pctR = _msToPct(mainEndMs);
var pctW = Math.max(0.8, pctR - pctL); // mindestens 0.8 % sichtbar
var icon = sess.simIcon || '📚';
var simName = sess.simTitle || simWord(sess.simId);
@@ -2246,9 +2251,10 @@ async function renderLiveSummary() {
var border = aborted ? 'border:1.5px dashed rgba(255,255,255,.7);'
: inProgress ? 'border:1.5px solid rgba(255,255,255,.7);border-right:2px dotted #fff;'
: 'border:1.5px solid rgba(20,20,20,.25);';
// Laufende Spiele: langsam blinkender Block (Balken wächst ohnehin mit der Zeit).
var anim = inProgress ? 'animation:_tagblink 1.8s ease-in-out infinite;' : '';
var stateWord = inProgress ? 'läuft noch' : aborted ? 'abgebrochen' : 'fertig';
// Laufende Spiele: langsam blinkender Block. Pausiert → Hauptbalken ruhig
// (der halbhohe Schwanz blinkt stattdessen).
var anim = (inProgress && !sess.paused) ? 'animation:_tagblink 1.8s ease-in-out infinite;' : '';
var stateWord = !inProgress ? (aborted ? 'abgebrochen' : 'fertig') : (sess.paused ? 'pausiert ⏸' : 'läuft noch');
var tip = (sess.simTitle||sess.simId) + (sess.lessonLabel?' · '+sess.lessonLabel:'')
+ ' · ' + _fmtHM(sess.startMs) + '' + _fmtHM(endMs)
+ ' · ' + _liveFmtMin(realDurSec) + ' · ' + stateWord
@@ -2265,6 +2271,15 @@ async function renderLiveSummary() {
+ 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;'
+ 'text-shadow:0 1px 1px rgba(0,0,0,.3);box-shadow:0 1px 2px rgba(0,0,0,.12)">'
+ inner + '</div>';
// Pausen-Schwanz: halbhoch, gedämpft, blinkt langsam — „läuft noch, aber gerade ruhig".
if (isPausedRun) {
var halfH = 9;
var tailW = Math.max(0.6, _msToPct(endMs) - pctR);
html += '<div title="pausiert seit '+_fmtHM(mainEndMs)+'" '
+ 'style="position:absolute;left:'+pctR+'%;width:'+tailW+'%;top:'+(5+barH-halfH)+'px;height:'+halfH+'px;'
+ 'background:'+col+';opacity:.42;border-radius:0 3px 3px 0;'
+ 'border:1px dashed rgba(255,255,255,.6);animation:_tagblink 2.4s ease-in-out infinite"></div>';
}
if (aborted) {
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>';
@@ -2285,6 +2300,7 @@ async function renderLiveSummary() {
+ ' 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="display:inline-flex;align-items:flex-end;width:16px;height:11px;vertical-align:middle;margin-right:.25rem"><span style="width:8px;height:11px;background:#aab2b8"></span><span style="width:8px;height:6px;background:#aab2b8;opacity:.42"></span></span>pausiert</span>';
html += '<span><span style="color:#b03a2a;font-weight:800"></span> Abbruch</span>';
html += '</div>';