Skip to content

AlemzhanJ/chooseApp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 

Repository files navigation

Chooser App

Краткое описание проекта

Chooser App - это интерактивное веб-приложение, созданное для вечеринок и компаний друзей. Оно позволяет выбрать случайного участника из группы с помощью простого и забавного процесса: все игроки одновременно кладут пальцы на сенсорный экран устройства. Приложение поддерживает два режима игры:

  1. Простой режим: Быстро выбирается один "счастливчик".
  2. Режим с заданиями: Выбранному игроку выдается задание. Задания могут браться из встроенной базы данных или генерироваться с помощью Искусственного Интеллекта (Google Gemini), если включена соответствующая опция. В этом режиме также можно включить ограничение по времени.

Приложение построено на стеке MERN (MongoDB, Express, React, Node.js).

Инструкции по установке и запуску

Требования

  • Node.js (рекомендуется LTS версия, например, 18.x или 20.x)
  • npm (обычно идет с Node.js)
  • Аккаунт MongoDB Atlas (или локально установленная MongoDB)
  • API ключ Google Generative AI (для функции AI-заданий). Получить ключ

Установка

  1. Клонируйте репозиторий:
    git clone https://github.com/AlemzhanJ/chooseApp
    cd chooseApp
  2. Установите зависимости для бэкенда:
    cd server
    npm install
  3. Установите зависимости для фронтенда:
    cd ../client
    npm install

Настройка

  1. Бэкенд:
    • Перейдите в директорию server/.
    • Создайте файл .env.
    • Добавьте в него строку подключения к вашей MongoDB:
      MONGODB_URI=mongodb+srv://<user>:<password>@<cluster-url>/<database-name>?retryWrites=true&w=majority
      
      (Замените <...> на ваши реальные данные)
    • Добавьте порт для сервера (по умолчанию 5000):
      PORT=5000
      
    • Добавьте ваш API ключ для Google Gemini:
      GEMINI_API_KEY=ВАШ_GOOGLE_GEMINI_API_KEY
      
  2. Фронтенд:
    • В файле client/package.json уже настроен proxy для перенаправления запросов /api на http://localhost:5000 во время локальной разработки.

Запуск

  1. Запустите бэкенд (из директории server/):

    npm run dev

    Сервер запустится на порту, указанном в .env (или 5000). Вы должны увидеть сообщения о старте сервера и подключении к MongoDB.

  2. Запустите фронтенд (из директории client/, в новом окне терминала):

    npm start

    Приложение откроется в браузере по адресу http://localhost:3000.

  3. Инициализация: Настройка MERN-проекта с базовой структурой для бэкенда (Express, Mongoose) и фронтенда (Create React App).

  4. Проектирование: Определение схем MongoDB для Задач (Task) и Игр (Game), разработка API эндпоинтов для управления ими.

  5. Реализация UI: Создание основных экранов (Старт, Настройки, Игра) и компонентов (Область касания, Анимация выбора, Отображение задания/победителя) с использованием React и CSS.

  6. Интеграция: Связывание фронтенда с бэкендом через API-сервис (axios), реализация игрового цикла.

  7. Обработка касаний: Использование Touch Events API для отслеживания нескольких одновременных касаний.

  8. Рефакторинг: Вынесение логики API-вызовов в отдельный сервис (services/api.js), замена стандартных кнопок на переиспользуемый компонент (Button.js).

  9. AI-интеграция (Бонус): Добавление сервиса для взаимодействия с Google Gemini API (ai-service.js), создание эндпоинта для генерации задач, интеграция с логикой игры и UI.

  10. Улучшения UI: Добавление пояснений для игроков, улучшение читаемости элементов.

  11. Подготовка к деплою: Настройка CORS, создание шаблона README.md.

Уникальные подходы или методологии

  • Обработка Multi-Touch: Использование нативного Touch Events API для определения количества и удержания пальцев на экране.
  • Генерация контента AI: Интеграция с Google Gemini API (@google/generative-ai) для динамической генерации игровых заданий по запросу пользователя, с учетом выбранной сложности.
  • Анимация выбора: Визуализация процесса выбора путем поочередного подсвечивания активных пальцев с ускорением (реализовано через setTimeout и CSS).
  • Структура API: Использование сервисного слоя (services/api.js) на фронтенде для инкапсуляции логики взаимодействия с бэкендом.

Обсуждение компромиссов

  • Анимация: Использована простая JavaScript/CSS анимация поочередного подсвечивания вместо более сложных визуальных эффектов для ускорения разработки.
  • Обновление состояния: Приложение не использует WebSocket или Server-Sent Events для обновлений в реальном времени. Состояние игры обновляется после действий пользователя или при перезагрузке (в GameScreen есть TODO на эту тему).
  • Сохранение AI-задач: Сгенерированные AI задачи не сохраняются в базу данных по умолчанию для простоты. Они генерируются "на лету".
  • Аутентификация: Эндпоинт для добавления новых задач (POST /api/tasks) не защищен, предполагается, что база данных будет наполнена заранее или доступ будет ограничен другими способами (например, на уровне сети при деплое).

Известные ошибки или проблемы

  • Удаление игр: Завершенные игры автоматически удаляются при выходе пользователя с экрана игры (GameScreen) путем вызова DELETE /api/games/:gameId (реализовано как fire-and-forget).
  • Совместимость Touch Events: Работа FingerPlacementArea зависит от корректной реализации Touch Events API браузером и устройством. На редких или старых устройствах могут быть нюансы.
  • Тестирование касаний: Без сенсорного экрана тестирование функции размещения пальцев затруднено (кнопка симуляции была удалена). Необходимо использовать реальное устройство или инструменты разработчика в браузере.
  • Зависимость от внешних сервисов: Работа AI-генерации зависит от доступности Google Gemini API и наличия правильного API-ключа. Возможны ошибки при проблемах с сетью или API.
  • Деплой: При деплое необходимо корректно настроить переменные окружения (MONGODB_URI, GEMINI_API_KEY, PORT), CORS и IP Whitelist в MongoDB Atlas.

Процесс отладки (Ключевые моменты)

В ходе разработки у меня возник ряд сложных проблем, потребовавших итеративной отладки:

  1. Несоответствие выбранного игрока и исполнителя задания:

    • Проблема: Анимация выбора на клиенте останавливалась на одном игроке, а задание после вызова API назначалось другому.
    • Причина: Изначально и клиент (визуально), и сервер (логически) выбирали случайного игрока независимо.
    • Решение: Изменена логика. Клиент выбирает игрока в конце анимации и отправляет его ID на сервер. Сервер валидирует этот ID и использует его для назначения задания, устраняя расхождение.
  2. Задание не завершалось при удержании пальца в зонах ДА/НЕТ:

    • Проблема: Игрок удерживал палец в зоне ответа более 2 секунд, но игра не реагировала, задание продолжалось.
    • Причина: Обнаружено несколько проблем:
      • Некорректная передача аргументов (action и fingerId) из компонента FingerPlacementArea в обработчик handleTaskAction в GameScreen.
      • Ошибка на сервере в updatePlayerStatus при поиске игрока из-за неверного сравнения типов fingerId (число и строка).
      • Потенциальные проблемы с обновлением состояния React (gameData, currentTaskDetails) после асинхронных вызовов API, что приводило к отображению устаревшего состояния.
    • Решение:
      • Исправлен порядок аргументов при вызове колбэка onTaskAction.
      • Исправлено сравнение fingerId на сервере с использованием parseInt.
      • Упрощена логика обновления состояния в handlePlayerAction на клиенте для немедленного отображения результата.
      • Активно использовалась отладочная информация, выводимая прямо в интерфейс приложения, для отслеживания состояния и ответов API в реальном времени на мобильном устройстве.
  3. Визуальные проблемы с подсветкой выбранного игрока:

    • Проблема: Выбранный игрок не подсвечивался красным цветом после завершения анимации или подсветка сразу сбрасывалась.
    • Причина: Конфликт между установкой подсветки после ответа API и ее сбросом в функции очистки useEffect анимации, а также проблемы с timing'ом обновления состояния React.
    • Решение: Логика установки и сброса highlightedFingerId была скорректирована, чтобы избежать преждевременного сброса и обеспечить своевременное отображение.

Этот итеративный процесс отладки с анализом логов (как серверных, так и клиентских через UI) позволил выявить и устранить неочевидные ошибки взаимодействия между фронтендом, бэкендом и асинхронными операциями. Клиентские логи при этом отслеживать было невозможно, потому что тестирование и отладка - всё на телефоне. Я не знал, как пользоваться инструментами разработчика на телефоне, поэтому мне пришлось писать код для отладочных боксов со всех нужной информацией. Также в процессе я сделал очень много коммитов, потому что каждое изменения мне нужно было деплоить, чтобы я мог протестировать изменения именно на телефоне (разбираться с ngrok было лень).

Выбор технического стека (MERN)

Стек MERN (MongoDB, Express, React, Node.js) был выбран по следующим причинам:

  • Node.js/Express: Позволяет использовать JavaScript для бэкенда, что упрощает разработку при наличии опыта с JS/React. Express - минималистичный и гибкий фреймворк для создания API.
  • MongoDB: Гибкость NoSQL схемы хорошо подходит для проекта, где структура данных (особенно для Игр) может развиваться. Mongoose предоставляет удобный интерфейс для работы с MongoDB из Node.js.
  • React: Мощная и популярная библиотека для создания динамических пользовательских интерфейсов. Компонентный подход упрощает разработку и поддержку UI.
  • Единый язык: Использование JavaScript на всех уровнях (фронтенд, бэкенд) ускоряет разработку и упрощает обмен кодом/логикой.
  • Большое сообщество: Обширная документация, множество библиотек и активное сообщество для всех частей стека.

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published