import "./styles.sass"; import {SocketContext} from "@/common/contexts/SocketContext"; import {useContext, useState, useEffect, useRef, useCallback} from "react"; import MusicSlider from "@/pages/Game/components/MusicSlider"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import { faMessage, faMusic, faHeadphones, faClock, faCrown, faPaperPlane, faCheckCircle, faVolumeUp, faStepForward } from "@fortawesome/free-solid-svg-icons"; import { fetchPlaylistSongs } from "@/services/youtubeService.js"; import YouTubePlayer from "../../components/YouTubePlayer/YouTubePlayer"; export const Game = () => { const {send, on, socket, connected, connect} = useContext(SocketContext); useEffect(() => { if (!connected) { connect(); } }, [connected, connect]); const [role, setRole] = useState(null); const [round, setRound] = useState(1); const [phase, setPhase] = useState("waiting"); const [timeLeft, setTimeLeft] = useState(30); const [frequency, setFrequency] = useState(440); const [currentSong, setCurrentSong] = useState(null); const [songOptions, setSongOptions] = useState([]); const [scores, setScores] = useState({}); const [selectedSong, setSelectedSong] = useState(null); const [guessResult, setGuessResult] = useState(null); const [isHost, setIsHost] = useState(false); const [hasGuessed, setHasGuessed] = useState(false); const [messages, setMessages] = useState([]); const [inputValue, setInputValue] = useState(""); const [connectedUsers, setConnectedUsers] = useState([]); const [username, setUsername] = useState(""); const messageEndRef = useRef(null); const timerIntervalRef = useRef(null); const [allSongs, setAllSongs] = useState([]); const [songsLoading, setSongsLoading] = useState(false); const [composerIsPlaying, setComposerIsPlaying] = useState(false); useEffect(() => { if (!connected) return; const eventHandlers = { "roles-assigned": (roles) => { const myRole = roles[socket?.id]; if (myRole) { setRole(myRole); setMessages(prev => [...prev, { system: true, text: myRole === "composer" ? "Du bist der Komponist! Spiele den Song mit dem Tonregler." : "Du bist ein Rater! Höre die Frequenzen und versuche, den Song zu erkennen." }]); } }, "song-selected": setCurrentSong, "round-started": (data) => { setRound(data.round); setPhase("composing"); setTimeLeft(data.timeRemaining); }, "guessing-phase-started": (data) => { console.log("Guessing phase started:", data); setPhase("guessing"); setTimeLeft(data.timeRemaining); setSongOptions(data.songOptions || []); }, "guess-result": (result) => { setGuessResult(result.isCorrect); setCurrentSong(result.correctSong); }, "round-results": (results) => { setPhase("results"); const scoresWithNames = {}; Object.entries(results.scores).forEach(([userId, score]) => { const user = connectedUsers.find(u => u.id === userId); scoresWithNames[userId] = { score: score, name: user?.name || results.playerNames?.[userId] || "Player" }; }); setScores(scoresWithNames); if (!currentSong) { setCurrentSong(results.selectedSong); } }, "room-users-update": (users) => { setConnectedUsers(users); const currentUser = users.find(u => u.id === socket?.id); if (currentUser) setUsername(currentUser.name); }, "host-status": (status) => setIsHost(status.isHost), "chat-message": (msg) => setMessages(prev => [...prev, msg]), "user-connected": (userData) => { setMessages(prev => [...prev, { system: true, text: `${userData.name} ist beigetreten` }]); setConnectedUsers(prev => [...prev, userData]); }, "user-disconnected": (userId) => { setConnectedUsers(prev => { const user = prev.find(u => u.id === userId); if (user) { setMessages(prevMsgs => [...prevMsgs, { system: true, text: `${user.name} hat den Raum verlassen` }]); } return prev.filter(u => u.id !== userId); }); }, "frequency-update": (data) => { if (phase === "composing") { console.log("Received frequency update:", data.frequency); setFrequency(data.frequency); setComposerIsPlaying(data.isPlaying); // Make sure isPlaying is handled } }, "phase-changed": (data) => { console.log("Phase changed:", data); setPhase(data.phase); if (data.timeRemaining) { setTimeLeft(data.timeRemaining); } }, "chat-message-confirmation": (msg) => { setMessages(prev => prev.map(prevMsg => { if (!prevMsg.system && prevMsg.text === msg.text && prevMsg.sender !== msg.sender) { console.log(`Updating message sender from "${prevMsg.sender}" to "${msg.sender}"`); return { ...prevMsg, sender: msg.sender }; } return prevMsg; })); }, }; const cleanupFunctions = Object.entries(eventHandlers).map( ([event, handler]) => on(event, handler) ); if (connected) { send("get-room-users"); send("check-host-status"); } return () => cleanupFunctions.forEach(cleanup => cleanup()); }, [socket, on, send, role, currentSong, phase, connected, connectedUsers]); useEffect(() => { if (timerIntervalRef.current) clearInterval(timerIntervalRef.current); if (phase !== "waiting" && phase !== "results") { timerIntervalRef.current = setInterval(() => { setTimeLeft(prev => Math.max(0, prev - 1)); }, 1000); } return () => { if (timerIntervalRef.current) clearInterval(timerIntervalRef.current); }; }, [phase]); useEffect(() => { messageEndRef.current?.scrollIntoView({behavior: "smooth"}); }, [messages]); useEffect(() => { if (!connected || !socket) return; const loadSongs = async () => { try { setSongsLoading(true); console.log("Fetching songs with active socket:", socket?.id); const songs = await fetchPlaylistSongs(socket); console.log(`Successfully loaded ${songs.length} songs`); setAllSongs(songs); } catch (error) { console.error("Error loading songs:", error); } finally { setSongsLoading(false); } }; loadSongs(); }, [socket, connected]); useEffect(() => { if (!allSongs.length || !currentSong || !currentSong.id) return; const enhancedSong = allSongs.find(song => song.id === currentSong.id); if (enhancedSong && enhancedSong !== currentSong) { setCurrentSong(enhancedSong); } }, [allSongs, currentSong]); useEffect(() => { if (!allSongs.length || !songOptions.length) return; const enhancedOptions = songOptions.map(option => { if (option.id && !option.title) { return allSongs.find(song => song.id === option.id) || option; } return option; }); if (JSON.stringify(enhancedOptions) !== JSON.stringify(songOptions)) { setSongOptions(enhancedOptions); } }, [allSongs, songOptions]); const handleFrequencyChange = useCallback((newFrequency, isPlaying) => { setFrequency(newFrequency); setComposerIsPlaying(isPlaying); if (role === "composer") { send("submit-frequency", { frequency: newFrequency, isPlaying }); } }, [role, send]); const handleSendMessage = useCallback(() => { if (inputValue.trim()) { const currentUser = connectedUsers.find(u => u.id === socket?.id); const senderName = currentUser?.name || username || "Player"; const messageData = { text: inputValue, sender: senderName }; send("send-message", messageData); setMessages(prev => [...prev, messageData]); setInputValue(""); } }, [inputValue, send, socket?.id, connectedUsers, username]); const handleSongSelect = useCallback((song) => { setSelectedSong(song); }, []); const handleSubmitGuess = useCallback(() => { if (!selectedSong || phase !== 'guessing') return; console.log("Submitting guess:", selectedSong.id); send("submit-guess", { songId: selectedSong.id }); setMessages(prev => [...prev, { system: true, text: `Du hast "${selectedSong.title}" von ${selectedSong.artist} gewählt.` }]); setHasGuessed(true); }, [selectedSong, send, phase]); const handleNextRound = useCallback(() => { send("next-round"); setSelectedSong(null); setGuessResult(null); setTimeLeft(0); }, [send]); const handlePlayerReady = useCallback(() => { console.log("Player ready"); }, []); const renderPhaseContent = () => { switch (phase) { case "waiting": return (
Use the player above to listen, and the tone slider to play!
Höre genau zu und versuche, den Song zu erkennen!
Die Rater versuchen nun, deinen Song zu erraten...
Welchen Song hat der Komponist gespielt?
{songOptions.length === 0 ? (Lade Songoptionen...
Deine Antwort wurde eingereicht!
) : ( )}Die Rater haben versucht, deinen Song zu erraten.
Der richtige Song war:
Warten auf Rundenwechsel durch Host...
)}