diff --git a/server/controller/game.js b/server/controller/game.js index dc07400..fa655b8 100644 --- a/server/controller/game.js +++ b/server/controller/game.js @@ -14,6 +14,9 @@ const gameStates = {}; const initializeGameState = (roomId) => { if (!gameStates[roomId]) { + const selectedPlaylist = roomController.getWinningPlaylist(roomId); + console.log(`Initializing game with winning playlist: ${selectedPlaylist}`); + gameStates[roomId] = { round: 0, phase: 'waiting', @@ -29,6 +32,7 @@ const initializeGameState = (roomId) => { guessing: 10 }, lastFrequency: 440, + selectedPlaylist: selectedPlaylist, }; const users = roomController.getRoomUsers(roomId); @@ -82,7 +86,8 @@ const determineNextComposer = (roomId, gameState, users) => { // Then modify the selectSongAndOptions function to use the shuffle: const selectSongAndOptions = async (gameState) => { try { - const availableIds = await youtubeService.getAvailableSongIds(); + console.log(`Fetching songs from playlist: ${gameState.selectedPlaylist}`); + const availableIds = await youtubeService.getAvailableSongIds(gameState.selectedPlaylist); if (!availableIds || availableIds.length === 0) { console.error("No song IDs available for selection"); diff --git a/server/controller/room.js b/server/controller/room.js index ce7876c..f5fb176 100644 --- a/server/controller/room.js +++ b/server/controller/room.js @@ -166,4 +166,34 @@ module.exports.voteForPlaylist = (roomId, userId, playlistId) => { module.exports.getPlaylistVotes = (roomId) => { return rooms[roomId]?.playlistVotes || {}; +}; + +module.exports.getWinningPlaylist = (roomId) => { + const room = rooms[roomId]; + if (!room || !room.playlistVotes) { + console.log(`No votes found for room ${roomId}, using default playlist`); + return Object.values(require('../services/youtubeService').PLAYLISTS)[0]; + } + + let maxVotes = 0; + let winningPlaylist = null; + + console.log(`Calculating winning playlist for room ${roomId}`); + console.log('Current votes:', room.playlistVotes); + + Object.entries(room.playlistVotes).forEach(([playlistId, voters]) => { + console.log(`Playlist ${playlistId} has ${voters.length} votes`); + if (voters.length > maxVotes) { + maxVotes = voters.length; + winningPlaylist = playlistId; + } + }); + + if (!winningPlaylist) { + console.log('No winning playlist found, using default'); + winningPlaylist = Object.values(require('../services/youtubeService').PLAYLISTS)[0]; + } + + console.log(`Selected winning playlist: ${winningPlaylist}`); + return winningPlaylist; }; \ No newline at end of file diff --git a/server/handler/connection.js b/server/handler/connection.js index 2d47f1e..bbcd82e 100644 --- a/server/handler/connection.js +++ b/server/handler/connection.js @@ -301,11 +301,20 @@ module.exports = (io) => (socket) => { socket.on("get-playlist-songs", async () => { try { - const songs = await youtubeService.fetchPlaylistSongs(); + const roomId = roomController.getUserRoom(socket.id); + if (!roomId) { + throw new Error("User not in a room"); + } + + const gameState = gameController.getGameState(roomId); + const playlistId = gameState?.selectedPlaylist || null; + + console.log(`Fetching songs for playlist ${playlistId}`); + const songs = await youtubeService.fetchPlaylistSongs(playlistId); socket.emit("playlist-songs", { songs }); } catch (error) { console.error("Error sending playlist songs:", error); - socket.emit("playlist-songs", { songs: youtubeService.getDefaultSongs() }); + socket.emit("playlist-songs", { songs: [] }); } }); diff --git a/server/index.js b/server/index.js index daa52bd..dbb7752 100644 --- a/server/index.js +++ b/server/index.js @@ -21,8 +21,14 @@ const roomController = require('./controller/room'); const gameController = require('./controller/game'); roomController.setCleanupGameState(gameController.cleanupGameState); -// Handle socket connections -io.on("connection", require("./handler/connection")(io)); +io.on("connection", (socket) => { + try { + require("./handler/connection")(io)(socket); + } catch (error) { + console.error('Error handling socket connection:', error); + socket.emit('error', { message: 'Internal server error' }); + } +}); server.on('error', (error) => { console.error('Server error:', error); diff --git a/server/services/youtubeService.js b/server/services/youtubeService.js index 8d8770d..f3087c3 100644 --- a/server/services/youtubeService.js +++ b/server/services/youtubeService.js @@ -12,23 +12,30 @@ const PLAYLISTS = { const API_KEY = process.env.YOUTUBE_API_KEY; -let cachedSongs = null; -let lastFetchTime = 0; +const cachedSongsByPlaylist = {}; + const CACHE_TTL = 3600000; // 1 hour /** * Fetches songs from YouTube playlist and returns them */ -const fetchPlaylistSongs = async () => { +const fetchPlaylistSongs = async (playlistId = null) => { + if (!playlistId) { + console.warn("No playlist ID provided, using default"); + playlistId = PLAYLISTS.seventies; // default fallback + } + const now = Date.now(); - if (cachedSongs && cachedSongs.length > 0 && (now - lastFetchTime) < CACHE_TTL) { - console.log("Returning cached YouTube songs:", cachedSongs.length); - return cachedSongs; + if (cachedSongsByPlaylist[playlistId] && + cachedSongsByPlaylist[playlistId].songs.length > 0 && + (now - cachedSongsByPlaylist[playlistId].timestamp) < CACHE_TTL) { + console.log(`Using cached songs for playlist ${playlistId}`); + return cachedSongsByPlaylist[playlistId].songs; } try { - console.log("Fetching songs from YouTube API..."); - const playlistUrl = `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&maxResults=50&playlistId=${PLAYLIST_ID}&key=${YOUTUBE_API_KEY}`; + console.log(`Fetching fresh songs from YouTube API for playlist ${playlistId}...`); + const playlistUrl = `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&maxResults=50&playlistId=${playlistId}&key=${YOUTUBE_API_KEY}`; const response = await fetch(playlistUrl); const data = await response.json(); @@ -38,7 +45,6 @@ const fetchPlaylistSongs = async () => { } if (!data.items || !data.items.length) { - console.error("No items found in YouTube playlist"); throw new Error("No songs found in the playlist"); } @@ -47,35 +53,24 @@ const fetchPlaylistSongs = async () => { youtubeId: item.contentDetails.videoId, title: item.snippet.title, artist: item.snippet.videoOwnerChannelTitle || "Unknown Artist", - coverUrl: item.snippet.thumbnails.high?.url || item.snippet.thumbnails.default?.url || - "https://place-hold.it/500x500/333/fff?text=No%20Thumbnail", + coverUrl: item.snippet.thumbnails.high?.url || item.snippet.thumbnails.default?.url, + playlistId: playlistId })); - cachedSongs = songs; - lastFetchTime = now; - console.log("Fetched and cached YouTube songs:", songs.length); + cachedSongsByPlaylist[playlistId] = { + songs, + timestamp: now + }; return songs; } catch (error) { - console.error("Error fetching YouTube playlist:", error); - - if (cachedSongs && cachedSongs.length > 0) { - console.log("Using last cached songs due to API error"); - return cachedSongs; - } - - return [{ - id: 1, - title: "Could not load songs", - artist: "API Error", - coverUrl: "https://place-hold.it/500x500/f00/fff?text=Error", - youtubeId: "dQw4w9WgXcQ" - }]; + console.error(`Error fetching YouTube playlist ${playlistId}:`, error); + return cachedSongsByPlaylist[playlistId]?.songs || getDefaultSongs(); } }; -const getAvailableSongIds = async () => { - const songs = await fetchPlaylistSongs(); +const getAvailableSongIds = async (playlistId) => { + const songs = await fetchPlaylistSongs(playlistId); return songs.map(song => song.id); };