+
@@ -126,7 +126,11 @@
/* ------------------ Persistence (no backend change) ------------------ */
const LS_KEY = 'leaderboardState'; // { title: string, board: array, ts: number }
- let answerTimer = null;
+
+ /* Timers */
+ let answerTimer = null; // existing auto-reveal timeout
+ let countdownInterval = null; // visible countdown updater
+ let countdownDeadline = 0;
function saveLeaderboardToStorage(title, board) {
try {
@@ -158,7 +162,7 @@
function showSidebar(titleText = 'Rangliste') {
document.body.classList.add('with-sidebar');
const panel = document.getElementById('final-results');
- panel.classList.remove('centerboard'); // NEW: ensure sidebar mode
+ panel.classList.remove('centerboard');
$('#finalResultsTitle').text(titleText);
$('#final-results').show();
}
@@ -184,6 +188,48 @@
showSidebar(title);
}
+ /* ------------------ COUNTDOWN-IN-ANSWER helpers ------------------ */
+ function showCountdownInAnswer(msTotal = 20000) {
+ stopCountdownInAnswer(); // clean slate
+
+ countdownDeadline = Date.now() + msTotal;
+
+ // Put a single LI into #perQ and show the host-results box
+ $('#perQ')
+ .empty()
+ .append(
+ `
+ ${(msTotal/1000).toFixed(1)}s
+ `
+ );
+ $('#host-results').show();
+
+ // Update every 100ms
+ countdownInterval = setInterval(() => {
+ const remainingMs = Math.max(0, countdownDeadline - Date.now());
+ const seconds = (remainingMs / 1000).toFixed(1);
+ $('#countdownValue').text(seconds);
+ if (remainingMs <= 0) {
+ stopCountdownInAnswer();
+ }
+ }, 100);
+ }
+
+ function stopCountdownInAnswer() {
+ if (countdownInterval) { clearInterval(countdownInterval); countdownInterval = null; }
+ }
+
+ function replaceCountdownWithAnswer(text) {
+ // Swap the LI content & styling to the “answer revealed” state
+ $('#countdownItem')
+ .removeClass('list-group-item-light')
+ .addClass('list-group-item-success')
+ .css('font-size', '2.5rem')
+ .html(`${text}`);
+ }
+
/* ------------------ Restore from storage on load ------------------ */
(function restoreFromStorageOnLoad() {
const stored = loadLeaderboardFromStorage();
@@ -216,9 +262,7 @@
console.log('Roster update:', data.players);
$('#roster').empty();
(data.players || []).forEach(name => {
- $('#roster').append(
- `
${name}`
- );
+ $('#roster').append(`
${name}`);
});
$('#startBtn').prop('disabled', (data.players || []).length === 0);
});
@@ -238,20 +282,24 @@
$('#host-question').show();
$('#qText').text(data.question || '');
$('#host-results').hide();
+ $('#perQ').empty();
$('#showAnswerBtn').prop({ disabled: false }).show();
$('#nextBtn').prop('disabled', true);
- $('#controlsBar').show(); // show sticky buttons
+ $('#controlsBar').show();
// Keep the sidebar visible during the game
showSidebar('Rangliste');
- /* NEW: (re)start the 21s auto-reveal timer */
+ // Auto-reveal after 20s
if (answerTimer) clearTimeout(answerTimer);
answerTimer = setTimeout(() => {
if (!$('#showAnswerBtn').prop('disabled')) {
$('#showAnswerBtn').trigger('click');
}
- }, 21000);
+ }, 20000);
+
+ // === Show countdown inside the answer area ===
+ showCountdownInAnswer(20000);
});
// Live overall leaderboard updates -> fill the right sidebar (top 10)
@@ -259,7 +307,6 @@
console.log('Overall leader:', data.board);
const board = (data && Array.isArray(data.board)) ? data.board : [];
renderAndShow('Rangliste', board);
- // Persist so a reload restores instantly
saveLeaderboardToStorage('Rangliste', board);
});
@@ -267,44 +314,42 @@
$('#nextBtn').off('click').on('click', () => {
console.log('Next question clicked');
if (answerTimer) { clearTimeout(answerTimer); answerTimer = null; }
+ stopCountdownInAnswer();
socket.emit('next_question');
});
// when host clicks “Show Answer”
$('#showAnswerBtn').off('click').on('click', () => {
if (answerTimer) { clearTimeout(answerTimer); answerTimer = null; }
+ stopCountdownInAnswer();
socket.emit('show_answer');
});
// once server confirms the answer is revealed
socket.on('answer_revealed', data => {
- $('#perQ').empty().append(
- `
${data.correct}`
- );
+ // Ensure the field is visible and swap countdown → answer
$('#host-results').show();
+ replaceCountdownWithAnswer(`${data.correct}`);
+
$('#showAnswerBtn').prop('disabled', true);
$('#nextBtn').prop('disabled', false);
if (answerTimer) { clearTimeout(answerTimer); answerTimer = null; }
+ stopCountdownInAnswer();
});
// Final results (use the same sidebar, change the title)
socket.on('game_over', data => {
$('#controlsBar').hide();
- /* NEW: clear any lingering timer */
if (answerTimer) { clearTimeout(answerTimer); answerTimer = null; }
+ stopCountdownInAnswer();
if (data && Array.isArray(data.board)) {
console.log('Game over');
$('#qrContainer, #startBtn, #rosterHeader, #roster, #host-question, #host-results').hide();
$('#newGameButton').show();
-
- // NEW: switch to centered leaderboard
showCenteredBoard('Finale Rangliste', data.board);
-
$('#startBtn').prop('disabled', true);
-
- // Persist final board for reload
saveLeaderboardToStorage('Finale Rangliste', data.board);
}
});
@@ -312,15 +357,11 @@
function showCenteredBoard(title, board) {
renderLeaderboard(board, 10);
$('#finalResultsTitle').text(title);
-
- // remove sidebar layout
document.body.classList.remove('with-sidebar');
-
- // switch the panel into centered mode + make sure it's visible
const panel = document.getElementById('final-results');
panel.classList.add('centerboard');
- panel.style.display = 'block'; // ← force visible
- $('#final-results').show(); // ← double-sure in jQuery land
+ panel.style.display = 'block';
+ $('#final-results').show();
}
/* ------------------ Initial UI state for lobby ------------------ */
diff --git a/templates/player.html b/templates/player.html
index c722d04..e1caa44 100644
--- a/templates/player.html
+++ b/templates/player.html
@@ -80,6 +80,9 @@