// public/js/game.js import { getParam, renderList } from "./utils.js"; import { setupStartRound } from "./start-round.js"; const gameId = getParam("gameId"); const username = getParam("username"); // 1) Parameter prüfen if (!gameId || !username) { alert("Ungültige oder fehlende URL-Parameter!"); throw new Error("Missing gameId or username"); } // 2) Copy to clipboard (unverändert) (function copyCodeToClipboard(code) { if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(code) .then(() => console.log(`GameCode ${code} copied to clipboard`)) .catch(err => console.error("Clipboard write failed:", err)); } else { const ta = document.createElement("textarea"); ta.value = code; ta.style.position = "fixed"; ta.style.left = "-9999px"; document.body.appendChild(ta); ta.focus(); ta.select(); try { document.execCommand("copy"); console.log(`GameCode ${code} copied via execCommand`); } catch (err) { console.error("Fallback copy failed:", err); } document.body.removeChild(ta); } })(gameId); // 3) Visuelles Feedback (unverändert) const notice = document.createElement("div"); notice.textContent = `Spiel-Code ${gameId} in die Zwischenablage kopiert!`; Object.assign(notice.style, { /* … Styles … */ }); document.body.append(notice); setTimeout(() => notice.remove(), 3000); // 4) Spiel-Code ins DOM schreiben document.getElementById("gameId").textContent = gameId; // 5) WebSocket mit Reconnect-Logik let socket; function connectWebSocket() { const protocol = location.protocol === "https:" ? "wss" : "ws"; socket = new WebSocket( `${protocol}://${location.host}/ws/${gameId}?username=${encodeURIComponent(username)}` ); socket.addEventListener("open", () => { console.log("WebSocket connected. Requesting player list..."); socket.send(JSON.stringify({ type: "requestPlayers" })); setupStartRound(socket); }); socket.addEventListener("message", ({ data }) => { console.log("WS-Rohdaten:", data); const msg = JSON.parse(data); switch (msg.type) { case "players": console.log("Empfangene Spieler:", msg.players); renderList("#playersList", msg.players, username); break; case "reload": window.location.reload(); break; case "round-start": handleRoundStart(msg); break; case "round-result": handleRoundResult(msg); break; case "game-end": handleGameEnd(msg); break; default: console.warn("Unknown WS message type:", msg.type); } }); socket.addEventListener("close", () => { console.warn("WebSocket geschlossen, versuche erneut zu verbinden..."); setTimeout(connectWebSocket, 2000); }); socket.addEventListener("error", (e) => { console.error("WebSocket Fehler:", e); socket.close(); }); } connectWebSocket(); // Zugriff auf DOM-Elemente const startBtn = document.getElementById("startRound"); const roundArea = document.getElementById("roundArea"); const songEmbed = document.getElementById("songEmbed"); const optionsDiv = document.getElementById("options"); const resultP = document.getElementById("result"); const scoreboard = document.getElementById("scoreboard"); // 8) Funktion zum Anzeigen einer neuen Runde function handleRoundStart({ ownerOptions, songUri, allTracks, trackInfos }) { // UI zurücksetzen resultP.textContent = ""; optionsDiv.innerHTML = ""; songEmbed.innerHTML = ""; // Song einbetten const trackId = songUri.split(":")[2]; songEmbed.innerHTML = ` `; if (window.playOnSpotify && typeof window.playOnSpotify === "function") { window.playOnSpotify(songUri, username); } // Dynamische Kreisverteilung der Buttons // Warten, bis #options gerendert ist setTimeout(() => { const optsRect = optionsDiv.getBoundingClientRect(); const radius = Math.min(optsRect.width, optsRect.height) / 2 - 50; // 50px Abstand zum Rand ownerOptions.forEach((user, i) => { const btn = document.createElement("button"); btn.textContent = user; btn.classList.add("player-option"); const angle = 360 * i / ownerOptions.length; btn.style.transform = `rotate(${angle}deg) translateY(-${radius}px) rotate(${-angle}deg)`; btn.addEventListener("click", () => { socket.send(JSON.stringify({ type: "guess", username: username, guess: user })); optionsDiv.querySelectorAll("button").forEach(b => b.disabled = true); }); optionsDiv.appendChild(btn); }); }, 0); startBtn.hidden = true; roundArea.hidden = false; const songList = document.getElementById("songList"); songList.innerHTML = ""; if (Array.isArray(trackInfos)) { trackInfos.forEach(trackInfo => { const li = document.createElement("li"); li.textContent = trackInfo; songList.appendChild(li); }); } } // 9) Funktion zum Anzeigen des Ergebnisses function renderScoreboard(scores) { scoreboard.innerHTML = ""; Object.entries(scores).forEach(([user, pts]) => { const li = document.createElement("li"); li.textContent = `${user}: ${pts} Punkte`; scoreboard.append(li); }); } function handleRoundResult({ scores, guesses, owner }) { renderScoreboard(scores); resultP.innerHTML = ""; Object.entries(guesses).forEach(([user, guess]) => { const correct = guess === owner; const icon = correct ? "✅" : "❌"; const delta = correct ? "+3" : "-1"; const msg = `${icon} ${user} hat auf ${guess} getippt${correct ? " (richtig!)" : " (falsch)"} [${delta}]`; const p = document.createElement("p"); p.textContent = msg; resultP.appendChild(p); }); const nextBtn = document.getElementById("nextRound"); nextBtn.hidden = false; nextBtn.disabled = false; nextBtn.onclick = () => { socket.send(JSON.stringify({ type: "next-round" })); nextBtn.hidden = true; nextBtn.disabled = true; resultP.textContent = ""; startBtn.hidden = true; startBtn.disabled = true; roundArea.hidden = true; }; } function handleGameEnd({winner}) { resultP.textContent = `🎉 ${winner} hat gewonnen!`; setTimeout(() => { startBtn.hidden = false; roundArea.hidden = true; startBtn.disabled = false; scoreboard.innerHTML = ""; }, 6000); } // Spotify-Playback Funktion async function playOnSpotify(trackUri, username) { const deviceId = document.getElementById("deviceSelect")?.value; if (!deviceId) { alert("Bitte ein Wiedergabegerät auswählen!"); return; } try { const response = await fetch("/api/spotify/play", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username, device_id: deviceId, track_uri: trackUri }) }); if (!response.ok) { const error = await response.text(); alert(`Fehler beim Abspielen: ${error}`); } } catch (err) { alert(`Netzwerkfehler: ${err.message}`); } } window.playOnSpotify = playOnSpotify;