SpotifyRoulette/src/main/resources/public/js/game.js

237 lines
7.8 KiB
JavaScript

// 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 = `
<iframe
src="https://open.spotify.com/embed/track/${trackId}"
width="100%" height="80" frameborder="0"
allow="encrypted-media">
</iframe>`;
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;