# 100 к 1 - Multiplayer Game Интерактивная веб-игра "100 к 1" с поддержкой мультиплеера и локальной игры. ## 🎮 Возможности ### 🌐 Мультиплеер (NEW!) - **Игровые комнаты** с уникальными кодами - **QR-коды** для быстрого присоединения - **Real-time синхронизация** через WebSocket - **Роли**: Ведущий, Игрок, Зритель - **Статистика игр** с историей ### 🏠 Локальная игра - Оригинальная версия для одного устройства - Управление участниками - Редактирование вопросов - Автосохранение прогресса ## 🛠 Технологический стек ### Frontend - **React 18.2** + **Vite 5.0** - **React Router v6** - маршрутизация - **Socket.IO Client** - WebSocket - **Axios** - HTTP клиент - **QRCode** - генерация QR-кодов ### Backend - **NestJS** - TypeScript фреймворк - **PostgreSQL** - база данных (запускается отдельно в Coolify) - **Prisma ORM** - работа с БД - **Socket.IO** - WebSocket сервер - **JWT** - авторизация - **ConfigModule** - управление переменными окружения ## 📁 Структура проекта ``` sto_k_odnomu/ ├── backend/ # NestJS Backend │ ├── src/ │ │ ├── auth/ # Авторизация (JWT, анонимные) │ │ ├── rooms/ # Модуль комнат │ │ ├── questions/ # Паки вопросов │ │ ├── game/ # WebSocket игра │ │ ├── stats/ # Статистика │ │ └── prisma/ # Prisma сервис │ ├── prisma/ │ │ ├── schema.prisma # Схема БД │ │ └── seed.ts # Seed данные │ ├── src/ # React Frontend │ ├── pages/ # Страницы │ │ ├── Home.jsx # Главная │ │ ├── CreateRoom.jsx # Создание комнаты │ │ ├── JoinRoom.jsx # Присоединение │ │ ├── RoomPage.jsx # Лобби комнаты │ │ └── LocalGame.jsx # Локальная игра │ ├── services/ # API & WebSocket │ ├── context/ # React Context │ ├── hooks/ # Custom hooks │ └── components/ # Компоненты игры │ └── PLAN.md # Детальный план разработки ``` ## 🚀 Быстрый старт ### 1. Backend **Требования:** - PostgreSQL должен быть запущен отдельно (например, в Coolify) - Переменные окружения должны быть настроены в системе или через Coolify **Переменные окружения:** - `DATABASE_URL` - строка подключения к PostgreSQL - `JWT_SECRET` - секретный ключ для JWT токенов - `PORT` - порт для backend (по умолчанию 3000) - `HOST` - хост для backend (по умолчанию 0.0.0.0) - `CORS_ORIGIN` - домен frontend приложения, с которого разрешены запросы к backend (по умолчанию http://localhost:5173) **Важно:** `CORS_ORIGIN` - это домен, где работает frontend, а не backend. Например, если frontend на `https://example.com`, а backend на `https://api.example.com`, то `CORS_ORIGIN` должен быть `https://example.com`. ```bash cd backend # Установить зависимости npm install # Выполнить миграции npx prisma migrate dev --name init # Заполнить демо-данными (опционально) npm run prisma:seed # Запустить backend npm run start:dev ``` Backend: http://localhost:3000 ### 2. Frontend ```bash # В корне проекта npm install npm run dev ``` Frontend: http://localhost:5173 ## 🎯 Как играть ### Мультиплеер 1. **Главная страница** → Выберите действие 2. **Создать комнату**: - Выберите пак вопросов - Настройте параметры - Поделитесь кодом/QR с игроками 3. **Присоединиться**: - Введите 6-значный код комнаты - Или отсканируйте QR-код 4. **Начать игру** (ведущий) 5. Игроки открывают ответы в реальном времени ### Локальная игра 1. Главная → **Локальная игра** 2. Добавьте участников (👥) 3. Играйте на одном устройстве ## 📊 API Endpoints ### REST API - **Auth**: `/auth/anonymous`, `/auth/register`, `/auth/login` - **Rooms**: `/rooms` (POST, GET), `/rooms/:code`, `/rooms/:id/join` - **Questions**: `/questions/packs` (CRUD) - **Stats**: `/stats/game-history/:userId`, `/stats/user/:userId` ### WebSocket Events **Client → Server:** - `joinRoom`, `startGame`, `revealAnswer`, `updateScore`, `nextQuestion`, `endGame` **Server → Client:** - `roomUpdate`, `gameStarted`, `answerRevealed`, `scoreUpdated`, `questionChanged`, `gameEnded` ## 🗄️ База данных ### Модели (Prisma) - **User** - пользователи (анонимные/зарегистрированные) - **Room** - игровые комнаты - **Participant** - участники (HOST/PLAYER/SPECTATOR) - **QuestionPack** - паки вопросов - **GameHistory** - история игр ### Seed данные - Демо пользователь - 2 пака вопросов (общие, семейные) ## ⚙️ Переменные окружения Приложение использует переменные окружения напрямую через `@nestjs/config`. Все переменные должны быть настроены в системе или через Coolify: ### Backend переменные: - `DATABASE_URL` - строка подключения к PostgreSQL (например: `postgresql://user:password@host:5432/dbname`) - `JWT_SECRET` - секретный ключ для JWT токенов (см. ниже как сгенерировать) - `PORT` - порт для backend (по умолчанию 3000) - `HOST` - хост для backend (по умолчанию 0.0.0.0) - `CORS_ORIGIN` - **домен frontend приложения**, с которого разрешены запросы к backend (по умолчанию http://localhost:5173) **Важно:** `CORS_ORIGIN` - это домен, где работает frontend, а не backend. Это настройка безопасности, которая говорит backend, с каких доменов принимать запросы. Например: - Frontend: `https://example.com` - Backend: `https://api.example.com` - `CORS_ORIGIN` должен быть: `https://example.com` **Поддержка нескольких origins:** Можно указать несколько доменов через запятую: ``` CORS_ORIGIN=https://party-games.online,https://www.party-games.online,http://localhost:5173 ``` ### Frontend переменные: - `VITE_API_URL` - URL backend API (по умолчанию http://localhost:3000) - `VITE_WS_URL` - URL WebSocket сервера (по умолчанию http://localhost:3000) **Почему префикс `VITE_`?** Vite (инструмент сборки) требует префикс `VITE_` для переменных окружения, которые должны быть доступны в клиентском коде. Это сделано для безопасности — только переменные с этим префиксом встраиваются в собранный JavaScript код. **Как это работает:** - В коде используется `import.meta.env.VITE_API_URL` (см. `src/services/api.js`) - Vite заменяет эти значения на этапе сборки - Без префикса `VITE_` переменная не будет доступна в браузере **Пример использования:** ```javascript // В коде frontend const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000'; ``` **Примечание:** PostgreSQL должен быть запущен отдельно как отдельное приложение в Coolify. ### 🔑 Как сгенерировать JWT_SECRET? `JWT_SECRET` - это секретный ключ для подписи и проверки JWT токенов. Он должен быть: - **Случайным** и криптографически стойким - **Длинным** (минимум 32 символа, рекомендуется 64+) - **Уникальным** для каждого приложения - **Секретным** - никогда не коммитьте в Git! #### Способы генерации: **1. Используя Node.js:** ```bash node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" ``` **2. Используя OpenSSL:** ```bash openssl rand -hex 64 ``` **3. Используя Python:** ```bash python3 -c "import secrets; print(secrets.token_hex(64))" ``` **4. Онлайн генераторы:** - Можно использовать, но не рекомендуется для production - Пример: https://generate-secret.vercel.app/64 #### Пример сгенерированного ключа: ``` a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2g3h4i5j6k7l8m9n0o1p2q3r4s5t6u7v8w9x0y1z2 ``` #### Где использовать: 1. **В Coolify**: Добавьте переменную окружения `JWT_SECRET` в настройках приложения 2. **Локально для разработки**: Можно использовать `.env` файл (но не коммитить его!) **⚠️ ВАЖНО:** - Используйте **разные** `JWT_SECRET` для development и production - Если измените `JWT_SECRET`, все существующие токены станут недействительными - Храните секрет в безопасности - это критически важно для безопасности приложения ## 📝 Разработка ### Backend ```bash cd backend npm run start:dev # Dev режим npm run build # Сборка npm run test # Тесты npx prisma studio # DB GUI ``` ### Frontend ```bash npm run dev # Dev сервер npm run build # Сборка npm run preview # Preview build ``` ## 🔐 Безопасность - JWT токены для авторизации - CORS настройка - Валидация данных (class-validator) - PostgreSQL для надёжного хранения ## 📄 Документация - [Backend README](backend/README.md) - детальная документация backend - [PLAN.md](PLAN.md) - полный план разработки - [API Documentation](backend/README.md#-api-endpoints) - REST и WebSocket API - [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - решение проблем с деплоем (502 ошибки, CORS и т.д.) ## 🎨 Особенности - ❄️ Новогодняя анимация снежинок - 🎨 Адаптивный дизайн - 💾 Автосохранение прогресса - 🔄 Real-time синхронизация - 📱 QR-коды для присоединения - 📊 Статистика и история игр ## 🚧 Roadmap - [x] Backend инфраструктура - [x] Frontend интеграция - [x] WebSocket real-time - [x] Игровые комнаты - [x] QR-коды - [ ] Таймер ответов - [ ] Экспорт статистики (PDF) - [ ] Публичные комнаты - [ ] Рейтинг игроков ## 📜 Лицензия Private project --- **Сделано с ❤️ для семейных праздников**