modified: templates/quiz_buzzer_multiplayer.html

This commit is contained in:
2025-11-15 18:14:58 +01:00
parent 575fcd3f8c
commit c488e5c4bc

View File

@@ -243,6 +243,9 @@
let decayRate = parseInt(localStorage.getItem('buzzer_decay_rate')) || 50;
let gameStarted = false;
let currentBuzzer = null;
let buzzedPlayers = []; // Liste der Spieler die schon gebuzzert haben
let canBuzz = false; // Kann man buzzern?
let pendingPoints = 0; // Punkte die noch nicht gezählt wurden
// Lade Team-Namen und Anzahl
const teamCount = parseInt(localStorage.getItem('team_count')) || 4;
@@ -256,6 +259,14 @@
{ id: 4, name: teamNames[3] || 'Spieler 4', score: {{ player_scores[3] if player_scores else 0 }} }
];
// Leertaste zum Buzzern
document.addEventListener('keydown', function(e) {
if (e.code === 'Space' && canBuzz && !currentBuzzer) {
e.preventDefault();
triggerBuzz();
}
});
window.onSpotifyWebPlaybackSDKReady = () => {
const token = '{{ access_token }}';
const player = new Spotify.Player({
@@ -330,6 +341,7 @@
gameStarted = true;
document.getElementById('startButton').classList.add('disabled');
document.getElementById('startButton').style.cursor = 'wait';
document.getElementById('buzzerHint').style.display = 'block';
const device_id = window.deviceId;
const startPosition = getOption('startPosition', 'start');
@@ -344,21 +356,19 @@
.then(() => {
console.log('Play command sent');
document.getElementById('startButton').style.display = 'none';
// Aktiviere Buzzer
for (let i = 1; i <= 4; i++) {
document.getElementById(`buzzer${i}`).classList.remove('disabled');
}
canBuzz = true;
})
.catch(error => console.error('Error starting playback:', error));
}
function startBuzzerTimer() {
startTime = Date.now();
canBuzz = true;
updateTimer();
}
function updateTimer() {
if (currentBuzzer) return;
if (!canBuzz && currentBuzzer) return;
const elapsed = (Date.now() - startTime) / 1000;
const timerDisplay = document.getElementById('buzzerTimer');
@@ -394,11 +404,11 @@
return points;
}
function buzz(playerId) {
function triggerBuzz() {
if (currentBuzzer !== null) return;
if (!gameStarted || !startTime) return;
if (!canBuzz) return;
currentBuzzer = playerId;
canBuzz = false; // Verhindere weitere Buzzes
buzzTime = Date.now();
const elapsed = (buzzTime - startTime) / 1000;
@@ -408,17 +418,33 @@
window.spotifyPlayer.pause();
}
// Markiere Spieler
document.getElementById(`player${playerId}`).classList.add('buzzed');
document.getElementById('currentPlayer').textContent = `${players[playerId - 1].name} hat gebuzzert!`;
// Zeige Spielerauswahl
document.getElementById('playerSelection').style.display = 'block';
document.getElementById('currentPlayer').textContent = 'Wer hat gebuzzert?';
pendingPoints = calculatePoints(elapsed);
}
// Deaktiviere alle Buzzer
for (let i = 1; i <= 4; i++) {
document.getElementById(`buzzer${i}`).classList.add('disabled');
function selectPlayer(playerId) {
if (buzzedPlayers.includes(playerId)) {
alert('Dieser Spieler hat bereits gebuzzert!');
return;
}
currentBuzzer = playerId;
buzzedPlayers.push(playerId);
// Markiere Spieler
document.getElementById(`player${playerId}`).classList.add('buzzed');
document.getElementById('currentPlayer').textContent = `${players[playerId - 1].name} antwortet...`;
// Verstecke Spielerauswahl, zeige Antwortfeld
document.getElementById('playerSelection').style.display = 'none';
document.getElementById('answerSection').classList.add('active');
window.earnedPoints = calculatePoints(elapsed);
window.earnedPoints = pendingPoints;
}
function buzz(playerId) {
selectPlayer(playerId);
}
function setCorrectAnswer() {
@@ -486,6 +512,10 @@
const guess = document.getElementById('answerInput').value;
if (!guess) return;
// Disable input während Prüfung
document.getElementById('answerInput').disabled = true;
document.querySelector('button[onclick="checkAnswer()"]').disabled = true;
fetch('/check_answer_buzzer', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -495,7 +525,8 @@
game_mode: currentGameMode,
playlist_id: '{{ playlist_id }}',
earned_points: window.earnedPoints,
player_id: currentBuzzer
player_id: currentBuzzer,
apply_points: false // Punkte NICHT sofort anwenden
})
})
.then(response => response.json())
@@ -503,45 +534,95 @@
const resultContainer = document.getElementById('resultContainer');
if (data.correct) {
players[currentBuzzer - 1].score += window.earnedPoints;
updateScoreboard();
// Speichere Punkte, aber wende sie noch NICHT an
pendingPoints = window.earnedPoints;
resultContainer.innerHTML = `
<div style="background:linear-gradient(135deg, rgba(76, 175, 80, 0.2) 0%, rgba(56, 142, 60, 0.2) 100%); padding:20px; border-radius:12px; border:2px solid #4CAF50;">
<h3 style="color:#4CAF50; margin-bottom:10px;">✅ ${i18n.correct || 'Correct'}</h3>
<h3 style="color:#4CAF50; margin-bottom:10px;">✅ ${i18n.correct || 'Richtig'}</h3>
<p style="font-size:1.5em; margin:10px 0;"><strong style="color:#1DB954;">+${window.earnedPoints}</strong> Punkte für ${players[currentBuzzer - 1].name}!</p>
<div style="margin-top:20px; padding:20px; background:rgba(15,20,25,0.8); border-radius:12px;">
<h4 style="color:#1DB954; margin-bottom:15px;">Song Info:</h4>
<p style="margin:8px 0;"><strong style="color:#1DB954;">Titel:</strong> <span style="color:#e0e0e0;">{{ track.name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">Künstler:</strong> <span style="color:#e0e0e0;">{{ track.artists[0].name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">Album:</strong> <span style="color:#e0e0e0;">{{ track.album.name | clean }}</span></p>
<a href="{{ track.external_urls.spotify }}" target="_blank" style="display:inline-block; margin-top:10px; padding:8px 16px; background:linear-gradient(135deg, #1DB954 0%, #1ed760 100%); color:#fff; text-decoration:none; border-radius:20px; font-weight:600;">Auf Spotify öffnen</a>
</div>
</div>
`;
document.getElementById('nextQuestionBtn').style.display = 'inline-block';
document.getElementById('nextQuestionBtn').onclick = function() {
// Wende Punkte beim Klick auf "Nächster Song" an
players[currentBuzzer - 1].score += pendingPoints;
updateScoreboard();
window.location.href = '/quiz/{{ playlist_id }}?mode={{ game_mode }}&buzzer=1&local_multiplayer=1';
};
} else {
// Minuspunkte: 25% der möglichen Punkte
const minusPoints = Math.floor(window.earnedPoints * 0.25);
pendingPoints = -minusPoints;
resultContainer.innerHTML = `
<div style="background:linear-gradient(135deg, rgba(244, 67, 54, 0.2) 0%, rgba(211, 47, 47, 0.2) 100%); padding:20px; border-radius:12px; border:2px solid #f44336;">
<h3 style="color:#f44336; margin-bottom:10px;">❌ ${i18n.incorrect || 'Incorrect'}</h3>
<p style="font-size:1.1em; margin:10px 0;">${i18n.your_answer || 'Your answer'}: <strong style="color:#f44336;">${guess}</strong></p>
<p style="font-size:1.1em; margin:10px 0;">${i18n.correct_answer || 'Correct answer'}: <strong style="color:#4CAF50;">${data.correct_answer}</strong></p>
<h3 style="color:#f44336; margin-bottom:10px;">❌ Falsch</h3>
<p style="font-size:1.1em; margin:10px 0;">Deine Antwort: <strong style="color:#f44336;">${guess}</strong></p>
<p style="font-size:1.1em; margin:10px 0;"><strong style="color:#f44336;">-${minusPoints}</strong> Punkte für ${players[currentBuzzer - 1].name}</p>
<div style="margin-top:20px;">
<button class="btn" onclick="continueGame()" style="background:linear-gradient(135deg, #FFA500 0%, #FF8C00 100%);">🔄 Weiterbuzzern</button>
<button class="btn" onclick="showSolution()" style="background:linear-gradient(135deg, #1DB954 0%, #1ed760 100%);">📝 Lösung anzeigen</button>
</div>
</div>
`;
}
if (data.comparison) {
resultContainer.innerHTML += `
<div style="margin-top:20px; padding:20px; background:rgba(15,20,25,0.8); border-radius:12px;">
<h4 style="color:#1DB954; margin-bottom:15px;">${i18n.song_info || 'Song Info'}:</h4>
<p style="margin:8px 0;"><strong style="color:#1DB954;">${i18n.title || 'Title'}:</strong> <span style="color:#e0e0e0;">{{ track.name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">${i18n.artist || 'Artist'}:</strong> <span style="color:#e0e0e0;">{{ track.artists[0].name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">${i18n.album || 'Album'}:</strong> <span style="color:#e0e0e0;">{{ track.album.name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">${i18n.year || 'Year'}:</strong> <span style="color:#e0e0e0;">{{ track.album.release_date[:4] }}</span></p>
<a href="{{ track.external_urls.spotify }}" target="_blank" style="display:inline-block; margin-top:10px; padding:8px 16px; background:linear-gradient(135deg, #1DB954 0%, #1ed760 100%); color:#fff; text-decoration:none; border-radius:20px; font-weight:600; transition:all 0.3s ease;">${i18n.open_on_spotify || 'Open on Spotify'}</a>
</div>
`;
}
document.getElementById('nextQuestionBtn').style.display = 'inline-block';
})
.catch(error => {
console.error('Error checking answer:', error);
});
}
function continueGame() {
// Wende Minuspunkte an
players[currentBuzzer - 1].score += pendingPoints;
updateScoreboard();
// Reset für nächsten Buzzer
document.getElementById('answerSection').classList.remove('active');
document.getElementById('answerInput').value = '';
document.getElementById('answerInput').disabled = false;
document.querySelector('button[onclick="checkAnswer()"]').disabled = false;
document.getElementById('resultContainer').innerHTML = '';
document.getElementById(`player${currentBuzzer}`).classList.remove('buzzed');
currentBuzzer = null;
canBuzz = true;
// Musik weiterspielen
if (window.spotifyPlayer) {
window.spotifyPlayer.resume();
}
// Timer weiterlaufen lassen
buzzTimer = requestAnimationFrame(updateTimer);
}
function showSolution() {
// Wende Minuspunkte an
players[currentBuzzer - 1].score += pendingPoints;
updateScoreboard();
const resultContainer = document.getElementById('resultContainer');
resultContainer.innerHTML = `
<div style="margin-top:20px; padding:20px; background:rgba(15,20,25,0.8); border-radius:12px; border:2px solid #1DB954;">
<h4 style="color:#1DB954; margin-bottom:15px;">Lösung:</h4>
<p style="margin:8px 0;"><strong style="color:#1DB954;">Titel:</strong> <span style="color:#e0e0e0;">{{ track.name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">Künstler:</strong> <span style="color:#e0e0e0;">{{ track.artists[0].name | clean }}</span></p>
<p style="margin:8px 0;"><strong style="color:#1DB954;">Album:</strong> <span style="color:#e0e0e0;">{{ track.album.name | clean }}</span></p>
<a href="{{ track.external_urls.spotify }}" target="_blank" style="display:inline-block; margin-top:10px; padding:8px 16px; background:linear-gradient(135deg, #1DB954 0%, #1ed760 100%); color:#fff; text-decoration:none; border-radius:20px; font-weight:600;">Auf Spotify öffnen</a>
</div>
`;
document.getElementById('nextQuestionBtn').style.display = 'inline-block';
}
function switchGameMode(mode) {
window.location.href = `/reset_quiz/{{ playlist_id }}?next_mode=${mode}&buzzer=1&local_multiplayer=1`;
}
@@ -592,23 +673,35 @@
<div class="current-player" id="currentPlayer">Drücke START um zu beginnen</div>
<!-- Buzzer Buttons -->
<div class="buzzer-grid">
<button class="player-buzzer start" id="startButton" onclick="startGame()">
<!-- Buzzer Hint -->
<div id="buzzerHint" style="text-align:center; font-size:1.5em; color:#1DB954; margin:20px 0; display:none;">
⌨️ Drücke LEERTASTE zum Buzzern!
</div>
<!-- Player Selection (versteckt bis gebuzzert) -->
<div id="playerSelection" style="display:none; text-align:center; margin:30px 0;">
<h3 style="margin-bottom:20px; color:#1DB954;">Wer hat gebuzzert?</h3>
<div class="buzzer-grid">
<button class="player-buzzer" id="selectPlayer1" onclick="selectPlayer(1)">
Spieler 1
</button>
<button class="player-buzzer" id="selectPlayer2" onclick="selectPlayer(2)">
Spieler 2
</button>
<button class="player-buzzer" id="selectPlayer3" onclick="selectPlayer(3)">
Spieler 3
</button>
<button class="player-buzzer" id="selectPlayer4" onclick="selectPlayer(4)">
Spieler 4
</button>
</div>
</div>
<!-- START Button -->
<div style="text-align:center; margin:30px 0;">
<button class="player-buzzer start" id="startButton" onclick="startGame()" style="width:300px; height:200px; font-size:2em;">
▶️<br>START
</button>
<button class="player-buzzer disabled" id="buzzer1" onclick="buzz(1)">
🔴<br>Spieler 1
</button>
<button class="player-buzzer disabled" id="buzzer2" onclick="buzz(2)">
🔴<br>Spieler 2
</button>
<button class="player-buzzer disabled" id="buzzer3" onclick="buzz(3)">
🔴<br>Spieler 3
</button>
<button class="player-buzzer disabled" id="buzzer4" onclick="buzz(4)">
🔴<br>Spieler 4
</button>
</div>
<!-- Answer Section -->