Initial commit: Своя Игра - multiplayer quiz game

This commit is contained in:
Cosmo
2026-03-21 05:00:06 +00:00
commit 1d46ad8b06
80 changed files with 9215 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
function GameBoard({ questions, usedQuestions, onSelectQuestion, currentRound, isHost }) {
const isQuestionUsed = (category, points, questionIndex) => {
// Ищем этот конкретный вопрос в использованных
// Сначала проверяем по questionIndex (новый метод)
const foundByIndex = usedQuestions.find(
q => q.category === category && q.points === points && q.questionIndex === questionIndex
);
if (foundByIndex) {
console.log(`✓ Question used (by index): cat="${category}", pts=${points}, idx=${questionIndex}`);
return true;
}
// Для обратной совместимости: если в usedQuestions нет questionIndex,
// проверяем, сколько вопросов с такими баллами уже использовано
const usedCount = usedQuestions.filter(
q => q.category === category && q.points === points
).length;
if (usedCount === 0) return false;
// Получаем категорию и находим индекс вопроса среди вопросов с такими же баллами
const categoryData = questions.find(cat => cat.name === category);
const questionsWithSamePoints = categoryData?.questions
.map((q, idx) => ({ ...q, originalIndex: idx }))
.filter(q => q.points === points) || [];
const positionAmongSamePoints = questionsWithSamePoints.findIndex(q => q.originalIndex === questionIndex);
// Если позиция вопроса меньше количества использованных, значит он уже использован
return positionAmongSamePoints >= 0 && positionAmongSamePoints < usedCount;
}
const getPointsForRound = (basePoints, round) => {
return round === 2 ? basePoints * 2 : basePoints
}
// Проверить сколько вопросов осталось в категории
const hasAvailableQuestions = (category) => {
return category.questions.some((q, idx) => !isQuestionUsed(category.name, q.points, idx))
}
// Фильтруем категории - показываем только те, где есть доступные вопросы
const availableCategories = questions.filter(hasAvailableQuestions)
// Лог для отладки
console.log('📋 GameBoard render:', {
totalCategories: questions.length,
availableCategories: availableCategories.length,
usedQuestions: usedQuestions
});
return (
<div className="bg-slate-800 p-3 md:p-6 rounded-xl shadow-xl border border-slate-700">
{!isHost && (
<div className="mb-3 md:mb-4 bg-blue-900 p-3 md:p-4 rounded-lg text-center">
<p className="text-white text-sm md:text-lg font-medium">
Ведущий выбирает вопросы. Будьте готовы отвечать!
</p>
</div>
)}
{isHost && (
<div className="mb-3 md:mb-4 bg-blue-900 p-3 md:p-4 rounded-lg text-center">
<p className="text-white text-sm md:text-lg font-bold">
Выберите вопрос
</p>
</div>
)}
{availableCategories.length > 0 ? (
<div className="space-y-2">
{availableCategories.map((category, catIdx) => (
<div key={catIdx} className="flex flex-col md:flex-row gap-2">
{/* Название категории */}
<div className="bg-blue-900 p-2 md:p-4 rounded-lg flex items-center justify-center border border-blue-700 md:min-w-[200px]">
<h3 className="text-white font-bold text-sm md:text-lg text-center">
{category.name}
</h3>
</div>
{/* Вопросы по номиналам */}
<div className="grid grid-cols-5 md:flex gap-1 md:gap-2 flex-1">
{category.questions.map((question, questionIndex) => {
const displayPoints = getPointsForRound(question.points, currentRound)
const isUsed = isQuestionUsed(category.name, question.points, questionIndex)
return (
<button
key={questionIndex}
onClick={() => !isUsed && isHost && onSelectQuestion(category.name, question.points)}
disabled={isUsed || !isHost}
className={`flex-1 p-3 md:p-6 rounded-lg font-bold text-base md:text-2xl transition-all duration-200 ${
isUsed
? 'bg-slate-700 text-gray-500 cursor-not-allowed border border-slate-600'
: isHost
? 'bg-blue-600 text-white hover:bg-blue-700 cursor-pointer shadow-lg border border-blue-500'
: 'bg-blue-600 text-white cursor-default opacity-60 border border-blue-500'
}`}
>
{isUsed ? '—' : displayPoints}
</button>
)
})}
</div>
</div>
))}
</div>
) : (
<div className="text-center py-8 md:py-12 bg-slate-700 rounded-lg border border-slate-600">
<p className="text-white text-lg md:text-2xl font-bold px-4">
Все вопросы раунда {currentRound} использованы!
</p>
</div>
)}
</div>
)
}
export default GameBoard