Skip to content

Latest commit

 

History

90 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Балда

Мобильная веб-игра для двух заранее разрешённых пользователей: grinch131@gmail.com и hinhillaa@gmail.com. Игроки входят через Google, по очереди добавляют по одной букве и проводят одним движением через клетки получившегося слова.

Подтверждённое состояние хранится в Firebase Realtime Database, синхронизируется между устройствами и восстанавливается после перезагрузки. Локальная копия используется только для просмотра при временном отсутствии сети.

Production URL: https://dougrinch.com/simple-games/.

Локальный запуск

Требуются Node.js 24, npm 11+ и Java 21.

nvm use
npm ci
cp .env.emulator.example .env.development.local

Запустите три процесса:

# Терминал 1
npm run dev:firebase:start

# Терминал 2
npm run dev:firebase:seed

# Терминал 3
npm run dev:app:start

Для локальной проверки push дополнительно скопируйте push-worker/.dev.vars.development.example в push-worker/.dev.vars.development, заполните локальную пару VAPID_PUBLIC_KEY и VAPID_PRIVATE_KEY и запустите:

npm run dev:push:start

При входе Auth Emulator покажет тестовый экран Google. Используйте один из двух разрешённых email. Для проверки синхронизации откройте приложение в двух отдельных профилях браузера и войдите разными игроками.

Как играть

  1. Дождитесь надписи «Мой ход».
  2. Нажмите на свободную клетку, которая касается заполненной клетки по стороне.
  3. Выберите одну из 33 русских букв на встроенной клавиатуре.
  4. Не отрывая палец, проведите через все клетки слова и отпустите на последней.
  5. Допустимый ход отправляется сразу. Слово должно включать новую букву, не повторять клетки и ранее принятые слова.

Нажатие на другую доступную пустую клетку заменяет текущую черновую букву и сразу открывает новый выбор. Если закрыть выбор, не указав букву, черновик не создаётся. Повторное короткое нажатие на черновую клетку удаляет букву, а свайп, начатый из неё, вводит путь слова. Автор последнего хода может нажать «Ой, шучушучу», а соперник — «Ненене, так нельзя». Обе кнопки полностью откатывают только последний принятый ход.

Проверки

npm run check
npm run coverage
npm run production:build
npm run production:push:bundle

npm run test:unit запускает unit- и component-тесты приложения без чтения локальной production-конфигурации. npm run test:firebase поднимает отдельный Realtime Database Emulator и проверяет границу доступа, конкурентное создание партии, атомарный ход, конфликт ревизий, откат и финальный результат. npm run test:worker запускает Worker в локальном Workerd с отдельной тестовой конфигурацией.

Архитектура

src/app/                         экраны приложения и оркестрация состояний
src/features/auth/               Google Sign-In и список игроков
src/games/balda/domain.ts        чистая игровая логика
src/games/balda/repository.ts    подписки, транзакции и синхронизация
src/games/balda/components/      поле, клавиатура и игровой экран
src/platform/firebase/           инициализация Firebase
src/platform/push/               подписка браузера и вызов Push Worker
src/platform/update/             проверка и применение новых сборок
src/platform/serviceWorker/      общая регистрация service worker
src/features/push/               пользовательский контрол уведомлений
src/features/update/             попап с изменениями после обновления
src/platform/games/              реестр типов игр
push-worker/                     Cloudflare Worker и Workerd-тесты
public/sw.js                     приём и открытие Web Push
tests/rules/                     Emulator-тесты доступа и транзакций
firebase-data/seed.json          schemaVersion и 1554 стартовых слова

UI не обращается к Firebase напрямую. Создание выполняется транзакцией над /gameTypes/balda, а ход и откат — транзакцией над текущей партией. Каждая операция проверяет актуальную ревизию и повторно валидирует состояние.

Онлайн-состояние определяется через /.info/connected. При разрыве связи действия блокируются. После reconnect приложение сначала перечитывает указатель и партию с сервера, после чего снова разрешает ввод.

Модель доступа и доверия

Текущие Security Rules намеренно упрощены:

  • точные email grinch131@gmail.com и hinhillaa@gmail.com могут читать, создавать, изменять и удалять любые данные Realtime Database;
  • неавторизованные пользователи и любые другие email не могут ничего читать или записывать.

Следовательно, правила защищают базу только от посторонних. Они не защищают словарь, завершённые партии или игровую геометрию от одного из двух разрешённых игроков. Оба игрока считаются доверенными и используют опубликованный клиент.

Firebase и публикация

Локальные production-переменные, включая VITE_PUSH_WORKER_URL, находятся в .env.production.local, а development-переменные для эмуляторов — в .env.development.local. Оба файла исключены из Git. В GitHub Actions production-значения задаются через Repository Variables. Пошаговая настройка сторонних сервисов описана в docs/external-services.md.

Отдельная инструкция по бесплатным системным push-уведомлениям через Cloudflare Workers находится в docs/push-notifications.md.

После изменения database.rules.json владелец вручную публикует правила:

npx firebase deploy --only database --project <FIREBASE_PROJECT_ID>

Повторно импортировать firebase-data/seed.json поверх рабочей production-базы нельзя. Любой pull request и ручной запуск из любой ветки проверяют проект и собирают Vite. Push в main или ручной запуск из main дополнительно создают готовые artifacts и публикуют приложение через GitHub Pages. Если с последнего успешного production workflow изменился push-worker/, тот же запуск публикует готовый Worker bundle в Cloudflare без повторной сборки.

Release notes и обновление клиента

Перед каждым новым non-merge коммитом нужно добавить ровно одну запись в конец release-notes.json. Номер id увеличивается на один, а text должен быть одной короткой строкой не длиннее 80 символов. Для служебного изменения используется точный текст Нутрянка. Старые записи изменять или удалять нельзя.

{
  "id": 2,
  "text": "Исправлено игровое поле"
}

Production-сборка проверяет базовую структуру release-notes.json при чтении файла.

Production-сборка публикует маленький version.json и отдельный release-notes.json. Открытый клиент проверяет только версию раз в минуту, при возвращении на вкладку и после восстановления сети. Новая сборка полностью перезагружает страницу, проверяет фактическое изменение sw.js и показывает все ещё не подтверждённые заметки в попапе «Приложение обновлено».

Ручная приёмка

На двух устройствах или в двух браузерных профилях:

  1. Войти обоими разрешёнными аккаунтами.
  2. Почти одновременно создать игру и убедиться, что появилась одна партия.
  3. Проверить стартовое слово, первый ход и синхронизацию счёта, очереди и поля.
  4. Отменить собственный ход, повторить его и оспорить вторым игроком.
  5. Проверить повторное слово, неправильный путь и выход за поле.
  6. Отключить сеть, перезагрузить страницу, восстановить сеть и сверить состояние.
  7. Заполнить поле, проверить результат и создать следующую игру.
  8. Убедиться, что третий Google-аккаунт не получает доступ.
  9. Перезагрузить опубликованный GitHub Pages URL напрямую.

Стартовый словарь

Список сформирован по морфологическому словарю OpenCorpora (CC BY-SA) и частотному списку University of Leeds Corpus (CC BY). Он содержит 1554 уникальных пятибуквенных слова.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages