import { useState, useImperativeHandle, forwardRef, useEffect } from 'react' import Question from './Question' import Players from './Players' import PlayersModal from './PlayersModal' import QuestionsModal from './QuestionsModal' import { getCookie, setCookie, deleteCookie } from '../utils/cookies' import './Game.css' const Game = forwardRef(({ questions = [], currentQuestionIndex = 0, onQuestionIndexChange, onQuestionsChange, }, ref) => { const [players, setPlayers] = useState(() => { const savedPlayers = getCookie('gamePlayers') return savedPlayers || [] }) const [currentPlayerId, setCurrentPlayerId] = useState(() => { const savedId = getCookie('gameCurrentPlayerId') return savedId !== null ? savedId : null }) const [playerScores, setPlayerScores] = useState(() => { const savedScores = getCookie('gamePlayerScores') return savedScores || {} }) const [gameOver, setGameOver] = useState(() => { const savedGameOver = getCookie('gameOver') return savedGameOver === true }) const [revealedAnswers, setRevealedAnswers] = useState(() => { const savedAnswers = getCookie('gameRevealedAnswers') return savedAnswers || {} }) // Получаем открытые ответы для текущего вопроса const getCurrentRevealedAnswers = () => { return revealedAnswers[currentQuestionIndex] || [] } // Обновляем открытые ответы для текущего вопроса const updateRevealedAnswers = (newAnswers) => { setRevealedAnswers({ ...revealedAnswers, [currentQuestionIndex]: newAnswers, }) } const [isPlayersModalOpen, setIsPlayersModalOpen] = useState(false) const [isQuestionsModalOpen, setIsQuestionsModalOpen] = useState(false) // Сохраняем состояние в cookies при изменении useEffect(() => { if (players.length > 0) { setCookie('gamePlayers', players) } else { deleteCookie('gamePlayers') } }, [players]) useEffect(() => { if (currentPlayerId !== null) { setCookie('gameCurrentPlayerId', currentPlayerId) } else { deleteCookie('gameCurrentPlayerId') } }, [currentPlayerId]) useEffect(() => { if (Object.keys(playerScores).length > 0) { setCookie('gamePlayerScores', playerScores) } else { deleteCookie('gamePlayerScores') } }, [playerScores]) useEffect(() => { setCookie('gameRevealedAnswers', revealedAnswers) }, [revealedAnswers]) useEffect(() => { setCookie('gameOver', gameOver) }, [gameOver]) const currentQuestion = questions[currentQuestionIndex] const isLastQuestion = currentQuestionIndex === questions.length - 1 const handleShowAllAnswers = () => { if (!currentQuestion) return const allAnswerIndices = currentQuestion.answers.map((_, index) => index) updateRevealedAnswers(allAnswerIndices) } useImperativeHandle(ref, () => ({ openPlayersModal: () => setIsPlayersModalOpen(true), openQuestionsModal: () => setIsQuestionsModalOpen(true), newGame: () => { setPlayers([]) setCurrentPlayerId(null) setPlayerScores({}) setGameOver(false) setRevealedAnswers({}) }, showAllAnswers: handleShowAllAnswers, })) const handleAddPlayer = (name) => { const newPlayer = { id: Date.now(), name: name, } const updatedPlayers = [...players, newPlayer] setPlayers(updatedPlayers) // Если это первый участник, делаем его текущим if (updatedPlayers.length === 1) { setCurrentPlayerId(newPlayer.id) setPlayerScores({ [newPlayer.id]: 0 }) } else { setPlayerScores({ ...playerScores, [newPlayer.id]: 0 }) } } const handleSelectPlayer = (playerId) => { setCurrentPlayerId(playerId) } const handleRemovePlayer = (playerId) => { const updatedPlayers = players.filter(p => p.id !== playerId) setPlayers(updatedPlayers) const updatedScores = { ...playerScores } delete updatedScores[playerId] setPlayerScores(updatedScores) // Если удалили текущего участника, выбираем другого if (currentPlayerId === playerId) { if (updatedPlayers.length > 0) { setCurrentPlayerId(updatedPlayers[0].id) } else { setCurrentPlayerId(null) } } } const getNextPlayerId = () => { if (players.length === 0) return null if (players.length === 1) return currentPlayerId const currentIndex = players.findIndex(p => p.id === currentPlayerId) const nextIndex = (currentIndex + 1) % players.length return players[nextIndex].id } const handleAnswerClick = (answerIndex, points) => { const currentRevealed = getCurrentRevealedAnswers() if (currentRevealed.includes(answerIndex)) return if (!currentPlayerId) return if (!currentQuestion) return const isLastAnswer = currentRevealed.length === currentQuestion.answers.length - 1 updateRevealedAnswers([...currentRevealed, answerIndex]) // Добавляем очки текущему участнику setPlayerScores({ ...playerScores, [currentPlayerId]: (playerScores[currentPlayerId] || 0) + points, }) // Переходим к следующему участнику только если это не последний ответ if (!isLastAnswer) { const nextPlayerId = getNextPlayerId() if (nextPlayerId) { setTimeout(() => { setCurrentPlayerId(nextPlayerId) }, 500) } } else { // Если это последний ответ, переходим к следующему участнику перед следующим вопросом setTimeout(() => { const nextPlayerId = getNextPlayerId() if (nextPlayerId) { setCurrentPlayerId(nextPlayerId) } if (isLastQuestion) { setGameOver(true) } else { setTimeout(() => { nextQuestion() }, 500) } }, 2000) } } const nextQuestion = () => { if (onQuestionIndexChange) { onQuestionIndexChange(currentQuestionIndex + 1) } // Не сбрасываем открытые ответы - они сохраняются для каждого вопроса отдельно } const restartGame = () => { if (onQuestionIndexChange) { onQuestionIndexChange(0) } setGameOver(false) setRevealedAnswers({}) const initialScores = {} players.forEach(player => { initialScores[player.id] = 0 }) setPlayerScores(initialScores) if (players.length > 0) { setCurrentPlayerId(players[0].id) } } const newGame = () => { setPlayers([]) setCurrentPlayerId(null) setPlayerScores({}) setGameOver(false) setRevealedAnswers({}) if (onQuestionIndexChange) { onQuestionIndexChange(0) } } const handlePreviousQuestion = () => { if (currentQuestionIndex > 0 && onQuestionIndexChange) { onQuestionIndexChange(currentQuestionIndex - 1) // Открытые ответы сохраняются для каждого вопроса отдельно } } const handleNextQuestion = () => { if (currentQuestionIndex < questions.length - 1 && onQuestionIndexChange) { onQuestionIndexChange(currentQuestionIndex + 1) // Открытые ответы сохраняются для каждого вопроса отдельно } } if (gameOver) { // Находим победителя(ей) const scores = Object.values(playerScores) const maxScore = scores.length > 0 ? Math.max(...scores) : 0 const winners = players.filter(p => playerScores[p.id] === maxScore) return (

🎉 Игра окончена! 🎉

Итоговые результаты:

{players .sort((a, b) => (playerScores[b.id] || 0) - (playerScores[a.id] || 0)) .map((player) => (
{player.name} {playerScores[player.id] || 0} очков
))}
) } return (
setIsPlayersModalOpen(false)} players={players} onAddPlayer={handleAddPlayer} onRemovePlayer={handleRemovePlayer} /> setIsQuestionsModalOpen(false)} questions={questions} onUpdateQuestions={onQuestionsChange} />
{players.length > 0 && ( )}
{players.length > 0 && currentPlayerId ? (
{questions.length === 0 ? (

Добавьте вопросы, чтобы начать игру

) : currentQuestion ? ( 0} canGoNext={currentQuestionIndex < questions.length - 1} /> ) : (

Ошибка: вопрос не найден

)}
) : (

Добавьте участников, чтобы начать игру

)}
) }) Game.displayName = 'Game' export default Game