14 KiB
Scrabble Game — Функциональная спецификация
Пользовательские сценарии по доменам: что делает каждая видимая пользователю
операция. Это зеркало FUNCTIONAL.md для владельца проекта;
авторитетна английская версия. Любую точечную правку переносим в том же
патче (переводим только изменённые абзацы). Разделы наполняются по мере этапов;
(Stage N) помечает, где пишется детализация.
Домены
Клиентское приложение (Stage 7 / 8)
Веб/приложение-клиент (Svelte + Vite) воплощает эти истории. Играбельный срез (Stage 7) покрывает вход (гость или email), лобби «мои игры», старт авто-подбора, игру на доске (постановка фишек перетаскиванием или тапом, пас, обмен, сдача), top-1 подсказку, безлимитную проверку слова с жалобой, чат и nudge в партии, обновления в реальном времени, переключение языка интерфейса (en/ru) и темы и профиль только для чтения. Stage 8 добавляет управление друзьями (в т.ч. одноразовые коды-приглашения) и блоками, дружеские приглашения в игру, редактирование профиля и привязку email, экран статистики и просмотр истории партии с экспортом GCG. В настройках также выбирается стиль подписей бонус-клеток (новичок / классика / без текста). Подсказка выставляет предложенные фишки на доску — игрок сам решает сделать ход, и подсказка не тратится, если ходов нет. Проверка слова принимает только алфавит варианта, запоминает ответы в рамках сессии и ограничивает частоту повторов.
Личность и сессии (Stage 1 / 6 / 9)
Игрок приходит с платформы (сначала Telegram), через email-вход или как
эфемерный гость. Gateway один раз валидирует доступ и выдаёт тонкий
session-токен; backend сопоставляет его с внутренним user_id. Запуск Telegram
Mini App авторизует по подписанным initData платформы, перекрашивает интерфейс
в цвета Telegram и — при первом контакте — задаёт язык интерфейса нового аккаунта по
языку Telegram-клиента. Гость — только сессия, с урезанными функциями (только
авто-подбор; без друзей, статистики и истории). Пока приложение открыто, клиент
держит живой стрим и получает обновления в реальном времени — ход соперника, ваш ход,
чат, nudge и найденный матч. Когда приложение закрыто, выбранные внеприложенческие
события (ваш ход, nudge, найденный матч, приглашение или заявка в друзья) приходят
вместо этого уведомлением в Telegram — если только игрок не оставил уведомления
только в приложении (настройка профиля, включена по умолчанию).
Аккаунты, привязка и слияние (Stage 1 / 10)
Первый контакт с платформы заводит постоянный аккаунт. Из профиля игрок привязывает другие платформенные личности или email через confirm-поток; привязка личности, у которой уже есть история, сливает её в текущий аккаунт (статистика суммируется, игры/друзья переносятся).
Лобби и подбор (Stage 4)
Нижнее tab-меню: мои игры, профиль. Авто-подбор (всегда 2 игрока) встаёт в пул по варианту и сводится со следующим ожидающим человеком; через 10 с без человека подставляется робот (робот — в Stage 5). Игры с друзьями (2–4) формируются приглашением игроков из списка друзей (приглашение, как и код друга, можно отправить deep-link'ом в Telegram, который откроет его сразу): инициатор выбирает настройки, и партия стартует, когда приняли все приглашённые — любой отказ отменяет приглашение, а без ответа приглашение протухает через семь дней.
Игровой процесс (Stage 3)
Выкладывание фишек, пас, обмен или сдача. Ход проверяется по словарю партии при сдаче и считается; безлимитный предпросмотр сообщает, сколько принёс бы предполагаемый ход и легален ли он. Инструмент проверки слова безлимитный и предлагает пожаловаться на любой результат. Подсказки управляются настройками партии — разрешены ли они и сколько их у каждого игрока на старте — и расходуют личный кошелёк подсказок после исчерпания внутриигрового лимита. Партия завершается, когда мешок пуст и игрок выложил стойку, после 6 подряд бесплодных ходов, по сдаче, либо по таймауту хода (от 5 минут до 24 часов, дефолт 24 часа): пропущенный ход означает авто-сдачу, кроме как когда игрок внутри своего суточного окна отсутствия (away). В партии на двоих сдача или таймаут отдают победу другому игроку, а вышедший сохраняет свои очки. В партии на троих-четверых место вышедшего убирается, остальные играют дальше, и партия завершается, когда остаётся один активный игрок; что делать с фишками вышедшего (вернуть в мешок или убрать из игры) выбирается при создании партии, а его стойка никогда не показывается остальным.
Робот-соперник (Stage 5)
Если авто-подбор не находит человека за десять секунд, свободное место занимает робот-соперник, и партия стартует без ожидания. Он задуман неотличимым от человека: один раз за партию решает, играть ли на победу (примерно в 40% случаев, так что человек выигрывает большинство партий), целится в близкий счёт, а не в разгром или поддавки, и ходит с человеческим темпом — чаще короткие раздумья, изредка долгие, и ночная пауза, подстроенная под день игрока. На nudge отвечает за несколько минут и сам шлёт nudge, когда игрок надолго пропал. Носит человекоподобное имя, не общается в чате и не принимает заявки в друзья.
Социальное: друзья, блок, чат, nudge (Stage 4 / 8)
Подружиться можно двумя способами: погасить одноразовый код, который выпускает другой игрок (шесть цифр, действует двенадцать часов), либо отправить заявку тому, с кем вы играли — он принимает, игнорирует (заявка истекает через тридцать дней, после чего её можно отправить снова) или отклоняет (отказ блокирует ваши повторные заявки, пока он сам не передаст вам код). Отмена своей висящей заявки снимает её; удаление расторгает дружбу. Глобальная блокировка — отключить входящие чат и/или заявки — и блокировка конкретного игрока (пер-юзер блок скрывает его чат и запрещает заявки и приглашения в игру в обе стороны, а также расторгает уже имеющуюся дружбу). Чат партии — для быстрых реакций: сообщения короткие (до 60 символов) и не должны содержать ссылок, email и телефонов, даже завуалированных. Nudge ожидаемого соперника — не чаще раза в час (nudge — часть игрового чата); внеприложенческий push доставляется через платформу.
Профиль и настройки (Stage 4 / 8)
Редактирование отображаемого имени (буквы, разделённые одиночными пробелом / «.» / «_», до 32 символов), таймзоны (выбор смещения от UTC), суточного окна отсутствия (away; сетка по 10 минут, не более 12 часов, с переходом через полночь) и переключателей блокировок, а также привязка email по confirm-коду: backend шлёт на почту короткий код, и после ввода email привязывается к аккаунту (email, уже подтверждённый другим аккаунтом, занять нельзя — это слияние, отдельный этап). Привязанные платформенные аккаунты и слияние появятся в Stage 11.
История и статистика (Stage 3 / 8)
Завершённые партии архивируются в независимом от словаря виде и экспортируются
в GCG; экспорт доступен только после завершения партии (экспорт идущей партии
раскрыл бы журнал ходов), и клиент делится файлом .gcg там, где платформа это
поддерживает, иначе скачивает его. Статистика (только у постоянных аккаунтов):
победы, поражения, ничьи, макс. очков за партию и макс. очков за один ход (лучший
ход, уже включающий все образованные им слова и бонус за все фишки).
Администрирование (Stage 10)
Оператор открывает серверную админ-консоль по адресу ${DOMAIN}/_gm — её рендерит
backend; gateway закрывает её HTTP Basic Auth на публичном порту и проксирует
один-в-один. В консоли можно смотреть пользователей (профиль, статистика,
identity, их игры) и игры (сводка + места), разбирать очередь жалоб на слова —
закрывая каждую как reject / accept-add / accept-remove — и управлять словарём:
резидентные версии по вариантам, горячая перезагрузка новой версии из
BACKEND_DICT_DIR/<version>/ и список ожидающих правок, выведенный из принятых
жалоб (он питает офлайн-пересборку и отмечается применённым после перезагрузки). Если
подключён Telegram-коннектор, оператор также может написать пользователю (по его
Telegram-identity) или отправить пост в игровой канал. Изменяющие действия
защищены проверкой same-origin; личность оператора не отслеживается.