# PRD — Шашки Рояль (Russian Checkers)

## Original Problem Statement
Mobile-first Russian-checkers online multiplayer game.
Repo: https://github.com/altynkanafina1-ship-it/shashki-royale
Stack: Vite + React 19 + TypeScript + Supabase + Capacitor (Android).

## Architecture
- **Frontend**: Vite/React/TS at `/app/frontend`, port 3000.
- **Backend**: Supabase (Postgres + Realtime). Anon key only.
- **Mobile**: Capacitor 8 → Android (debug APK ~49 MB).
- Anonymous `player_id` in localStorage — no email/password auth.

## What was implemented (summary)

### Sessions 1–5 (UI/UX, APK, gamification, promo phase)
- Layout polish, exit confirmation, mandatory-capture indicator
- Capacitor Android build pipeline (Java 21 + Android SDK 34)
- Quickplay matchmaking with race protection
- Phase 2-6 gamification (DB tables remain, RPCs intact)
- Promo: SpinWheel, CelebrationModal, VIPBadge, LiveTicker, Tournaments, Store, /vip page

### Session 6 — CLIENT-DRIVEN SIMPLIFICATION (1-May-2026, current)
**Client feedback**: «Нас попросили сделать ШАШКИ. Просто шашки.» Удалили всю промо-надстройку.

**Удалено (компоненты)**:
- SpinWheel.tsx, LiveTicker.tsx, VIPBadge.tsx, CelebrationModal.tsx
- DailyLoginModal.tsx, QuestsPanel.tsx, AchievementsPanel.tsx, StreakBadge.tsx
- Tournaments.tsx, Store.tsx, VIPPage.tsx
- services/activityFeed.ts

**Удалено (роуты)**: /tournaments, /store, /vip

**Очищено**:
- Index.tsx — теперь компактная шапка (профиль + 🔊 + язык) + 3 кнопки (онлайн/локально/правила)
- Lobby.tsx — убраны иконки квестов/ачивок/streak, осталось 2 кнопки (Быстрая игра / Создать комнату по коду)
- OnlineGame.tsx — убран applyGameOutcome, оставлены только звуки win/lose

**Добавлено (Apple-level polish)**:
- `lib/sounds.ts` — Web Audio API синтез без внешних wav (move/capture/king/select/win/lose). Mute toggle в localStorage.
- Plain `🔊 / 🔇` кнопка в шапке Index.tsx
- Board.tsx animation rewrite:
  - duration 360ms (увеличено с 280ms для читаемости)
  - cubic-bezier(0.22, 0.61, 0.36, 1) — material-style ease-out
  - scale(1.04) + drop-shadow на лету — даёт «вес» и физику
  - move/capture/king звуки в нужных моментах
  - select звук при выборе шашки

### Tested
- Build OK (~610 KB main bundle, ~175 KB gzipped — на 13 KB меньше промо-версии)
- Smoke screenshot: главный/локальная игра/lobby рендерятся корректно
- Animation slide захвачен mid-frame (drop-shadow + scale видно)

### Database (без изменений)
Phase 2-6 миграция остаётся в Supabase. RPC можно использовать в будущем когда заказчик захочет вернуть гамификацию.

## Текущее состояние UI
| Экран | Назначение |
|---|---|
| `/` | Лого + 3 кнопки: Играть онлайн / Локально / Правила. Звук-toggle в шапке |
| `/local` | 1v1 на одном устройстве |
| `/lobby` | 2 кнопки: Быстрая игра / Создать комнату с кодом |
| `/online-game` | Сам матч (heartbeat, realtime + polling fallback) |
| `/profile`, `/wallet` | Имя, статистика, история транзакций |
| `/rules`, `/leaderboard` | Правила, рейтинг |

### Session 7 — SMOOTH ANIMATIONS + CUSTOM AUDIO (1-May-2026)
**Жалоба клиента**: «шашки рывками двигаются» (CSS-transition + React 19 batching → dropped frames).

**Решение — 2-layer Board.tsx с framer-motion (motion v12)**:
- Layer 1: статические клетки 8×8 — обрабатывают клики/подсветки.
- Layer 2: `<motion.div>` шашки с **стабильными ID** (`w_0..w_11`, `b_0..b_11`) через `initialPieces()`. Absolute positioning, `animate={{x, y}}`, `transition: {type:'spring', stiffness:240, damping:26, mass:0.85}`.
- `AnimatePresence` для exit-анимации срубленных (rotate 180° + scale 0).
- Pieces overlay: `pointer-events:none` — клики проходят к клеткам.
- ResizeObserver следит за `cellSize`.
- Console errors: 0. Tested via testing_agent_v3_fork iteration_3.json — 90% rate, единственный bug (id'ы шли через fallback `w_new_*`) исправлен.

**Custom audio**:
- `lib/sounds.ts` — `sounds.move()` теперь играет `/sounds/move.mp3` (29 KB) через пул из 4× `HTMLAudioElement` (быстрые повторы без задержки). Fallback на синтез если Audio не доступен.
- capture/king/select/win/lose остались синтезированными.

**APK**:
- `dist/shashki-royale.apk` — 57.8 MB (BUILD SUCCESSFUL in 12m 39s, gradle 8.14.3, JDK 21, Android SDK 34).
- Содержит обновлённый bundle с motion-анимациями и move.mp3.

**Files changed**:
- `/app/frontend/src/components/Board.tsx` (полностью переписан, 2-layer)
- `/app/frontend/src/lib/sounds.ts` (move() → mp3 pool)
- `/app/frontend/src/game/pieces.ts` (без изменений — был создан до сессии)

### Session 8 — CHIPS ECONOMY + STAKE MARKET (19-May-2026)
**Цель сессии**: довести проект до 95% готовности под крипту, но без подключения. Полностью рабочие внутриигровые Chips + ставки + escrow + audit + crypto-prep tables.

**Реализовано**:
1. **SQL миграции** (требуют ручного применения в Supabase Dashboard):
   - `supabase/migrations/01_stakes_core.sql` (516 строк) — таблицы wallets / wallet_transactions / game_stakes + RPC create_stake_game / join_stake_game / process_stake_game_result (idempotent) / cancel_stake_game + RLS (read-only с клиента) + Realtime.
   - `supabase/migrations/02_audit_and_crypto_prep.sql` (новая, ~250 строк):
     - ALTER wallets: total_won / total_lost / total_deposited / total_withdrawn
     - ALTER wallet_transactions: idempotency_key UNIQUE + balance_before/after + metadata + новые типы (daily_bonus, quest_reward, provider_*)
     - Таблица `audit_logs` (RLS own-read-only)
     - Скелет-таблицы `payment_intents` + `withdrawal_requests` (для будущей крипты, статусы pending/processing/completed/failed)
     - RPC `log_audit_event` (helper)
     - RPC `grant_daily_bonus` — 100 Chips/день, idempotency_key = `daily_bonus:profile_id:YYYY-MM-DD`
     - RPC `create_or_get_profile` — единая инициализация (профиль + кошелёк + стартовый бонус 1000 Chips через idempotency_key)
     - Trigger `wallet_tx_aggregate_stats_trg` — авто-обновление total_won/total_lost при INSERT транзакций prize_payout/loss
   - `supabase/migrations/README_DEPLOY.md` — пошаговая инструкция применения + тесты + проверочные SQL запросы

2. **Frontend изменения**:
   - `pages/Index.tsx`: добавлена кнопка «Играть на Chips» с бейджем баланса; useProfile + getWallet
   - `pages/StakeLobbyPage.tsx`: FEE_OPTIONS [10,50,100,500]; заголовок «Игра на Chips»; убран символ ₿; терминология «жетоны» → «фишки»; pot отображается с учётом 5% комиссии
   - `pages/WalletPage.tsx`: переименовано «Монеты» → «Chips»; добавлена кнопка «Ежедневный бонус» (вызывает grant_daily_bonus); карточки total_won/total_lost; новые типы транзакций в TRANSACTION_LABELS
   - `pages/OnlineGame.tsx`: handleResign + handleOpponentLeftWin теперь триггерят stake payout через handleFinishGame (раньше — пропускалось!)
   - `services/economy.ts`: добавлена `grantDailyBonus(playerId)` + типы DailyBonusResult
   - `services/stakes.ts`: расширен Wallet type (total_won/total_lost/total_deposited/total_withdrawn) + WalletTransaction (idempotency_key/balance_before/balance_after/metadata + новые типы)

3. **Безопасность**:
   - Все wallet-операции через SECURITY DEFINER RPC (клиент не может менять баланс)
   - RLS на wallets/wallet_transactions/audit_logs/payment_intents/withdrawal_requests
   - Idempotent payout: `escrow_status IN ('paid','refunded')` блокирует повтор
   - Idempotent daily bonus через UNIQUE index на idempotency_key (`daily_bonus:profile:YYYY-MM-DD`)

**Не реализовано (намеренно)**:
- ❌ Реальная крипта / Stripe / Crypto webhooks
- ❌ Reconnect timer при disconnect (TODO)
- ❌ Лидерборд по выигрышам
- ❌ Audit log в UI (только в БД)

**Build статус**:
- TypeScript clean ✅
- Production build OK (591 KB main bundle, 177 KB gzipped) ✅
- APK rebuild не выполнен в этой сессии (Java + Android SDK были очищены из environment — нужно переустанавливать, ~20 мин). Web-версия полностью рабочая на preview URL.

### Session 9 — Stable Auth Flow + Reconnect Timer + UX Polish (19-May-2026)
**Контекст**: после Session 8 пользователь нашёл блокирующий баг — Google login возвращал
`400 Unsupported provider: provider is not enabled` (Google провайдер не настроен в Supabase Auth).
Также требовалось довести Chips/stake-флоу до продуктового уровня без forced login.

**Исправлено**:
1. **Google auth ошибка**:
   - `pages/auth/Login.tsx`: Google-кнопка обёрнута `{false && ...}` — полностью скрыта.
     Комментарий объясняет как вернуть: включить провайдер в Supabase Dashboard → удалить условие.
   - Логика OAuth (`signInWithGoogle`) оставлена в коде, готова к включению одним переключателем.

2. **Public routes для Chips-флоу**:
   - `components/ProtectedRoute.tsx`: `publicRoutes` расширены — `/stake-lobby`, `/wallet`, `/profile`, `/leaderboard`.
     Раньше `/stake-lobby` редиректил на `/auth/login` → Google ошибка.
     Теперь анонимный игрок (player_id из localStorage, `p_xxx`) сразу попадает на stake-lobby. 
     RLS защищает финансовые операции на сервере.

3. **Авто-создание профиля + wallet + 1000 Chips на главной**:
   - `pages/Index.tsx`: убран отдельный `usePlayerId+getWallet`, теперь использует `useProfile()`.
   - `useProfile` → `getOrCreateProfile` → RPC `get_or_create_profile` (создаёт профиль + wallet + стартовый бонус 1000 Chips, если нового).
   - Бейдж «1000 🪙» появляется на главной автоматически при первом входе.

4. **Reconnect timer (60 сек)**:
   - `pages/OnlineGame.tsx`: при detection «соперник вышел» (45с тишины + его ход) показывается модал
     с countdown «Авто-победа через 60с». По истечению — авто-вызов `handleOpponentLeftWin` → stake payout.
   - Idempotent: повторный вызов не повторит выплату (RPC проверяет `escrow_status IN ('paid','refunded')`).
   - Игрок может нажать «Забрать победу сразу» или «Ждать дальше» (скрывает модал; если соперник вернётся — игра продолжится).

5. **Smoke tests прошли (preview URL)**:
   - Index: «1000 🪙» бейдж виден после очистки localStorage и re-load
   - Кнопка «Играть на Chips» ведёт на `/stake-lobby` (без редиректа на login)
   - StakeLobby: видны 4 фильтра, баланс 1,000, empty-state «Создать первый стол»
   - Модал создания: ставки 10/50/100/500, payout = 19 при ставке 10 (10×2×0.95 ✓)
   - Login: Google-кнопка скрыта, есть только «Играть сразу» + email-форма
   - TypeScript clean (`tsc --noEmit` exit 0)

**Файлы изменённые в Session 9**:
- `src/pages/auth/Login.tsx` — Google btn hidden
- `src/components/ProtectedRoute.tsx` — public routes расширены
- `src/pages/Index.tsx` — useProfile вместо отдельного getWallet
- `src/pages/OnlineGame.tsx` — reconnect countdown + auto-payout

**SQL миграции (без изменений с Session 8)**: 
`01_stakes_core.sql` + `02_audit_and_crypto_prep.sql` + `README_DEPLOY.md` — готовы к ручному применению.

## Backlog (after demo approval)
- ULTRA Phase 1: Multi-wallet, Cashier UI, KYC tiers
- Real money modes (Stripe/Razorpay/USDT) — после получения лицензии
- Atomic quickplay через Postgres FOR UPDATE SKIP LOCKED RPC
- Heartbeat last_seen + reconciliation на /online-game
- Возврат gamification (если заказчик передумает) — DB и RPC уже есть

## Session 7 — Production polish (2026-05-21) ✅
**См. подробности в `/app/memory/CHANGELOG.md`**

Реализовано (по заказу клиента «довести игру до продуманного production-состояния»):
- 🔴 P0 **Multi-capture (двойное взятие) починен** — step-by-step через `captureChain` state.
- 🟠 UI cleanup: убраны "Срубл." и "Рейтинг:" из PlayerCard и LocalGame.
- 🟠 Auto-guest nickname `Player NNNN` (стабильный 4-значный суффикс).
- 🟠 Custom stake input "Своя ставка" в StakeLobbyPage (квики + кастом, min=1, max=balance, integer, 5% комиссия, breakdown).
- 🟠 Turn-status indicators проверены.
- 🟢 Production build OK, 59 vitest, Android debug APK v1.1.0 пересобран.

## Files of Reference (this session)
- `/app/frontend/src/game/gameLogic.ts` (REWRITTEN — step-by-step apply)
- `/app/frontend/src/game/rules.ts` (added `toSingleHopMoves`)
- `/app/frontend/src/game/types.ts` (`captureChain` shape changed)
- `/app/frontend/src/pages/LocalGame.tsx` (chain lock + removed Срубл.)
- `/app/frontend/src/pages/OnlineGame.tsx` (chain logic + deferred sync)
- `/app/frontend/src/pages/StakeLobbyPage.tsx` (custom-stake input + breakdown)
- `/app/frontend/src/components/PlayerCard.tsx` (no rating / no captured)
- `/app/frontend/src/services/profiles.ts` (generateGuestNickname; dead-code removed)
- `/app/frontend/src/services/stakes.ts` (validation: int 1..1_000_000)
- `/app/frontend/src/game/__tests__/gameLogic.test.ts` (NEW — 4 chain tests)
- `/app/frontend/src/services/__tests__/profiles.test.ts` (NEW — 4 nickname tests)
- `/app/shashki-royale-v1.1.0-debug.apk` (NEW — production APK, 17 MB)

## Test Credentials
See `/app/memory/test_credentials.md`.
