Stage 4: lobby & social (matchmaking, friends, blocks, chat+nudge, invitations, profile, email, multi-player drop-out)
Engine: multi-player drop-out-and-continue with a per-game tile disposition (remove default / return), resigned seats skipped and excluded from the win, leaver rack never revealed; 2-player behaviour unchanged. New domains (service/store, no HTTP yet): internal/social (friend request/accept graph, per-user blocks, per-game chat with nudge as a message kind, content filter via mvdan.cc/xurls/v2 + leet/separator normaliser + phone heuristic) and internal/lobby (in-memory variant-keyed matchmaking pool, friend-game invitations invite->accept with lazy 7-day expiry). account gains profile editing and the email confirm-code flow (Mailer seam: SMTP or log mailer). Migration 00003_social.sql + regenerated jet. main wires the new services into the server (accessors for the Stage 6 handlers); robot substitution stays in Stage 5, REST/stream/push in Stage 6/8. Docs (PLAN, ARCHITECTURE, FUNCTIONAL+ru, TESTING, README) updated.
This commit is contained in:
+26
-10
@@ -23,9 +23,13 @@ linking an identity that already has history merges it into the current
|
||||
account (stats summed, games/friends transferred).
|
||||
|
||||
### Lobby & matchmaking *(Stage 4)*
|
||||
Bottom tab menu: **my games**, **profile**. Auto-match (always 2 players) joins
|
||||
a `(variant, language)` pool; after 10 s with no human, the robot substitutes.
|
||||
Friend games (2–4) are formed by friend list, internal ID, or deep-link.
|
||||
Bottom tab menu: **my games**, **profile**. Auto-match (always 2 players) joins a
|
||||
per-variant pool and is paired with the next waiting human; after 10 s with no
|
||||
human the robot substitutes (the robot arrives in Stage 5). Friend games (2–4) are
|
||||
formed by inviting players from the friend list or by internal ID (deep-link
|
||||
invites arrive with the platform integration): the inviter chooses the settings
|
||||
and the game starts once every invitee has accepted — any decline cancels it, and
|
||||
an unanswered invitation expires after seven days.
|
||||
|
||||
### Playing a game *(Stage 3)*
|
||||
Place tiles, pass, exchange, or resign. A play is validated against the game's
|
||||
@@ -37,9 +41,12 @@ personal hint wallet once the per-game allowance is spent. The game ends when th
|
||||
bag empties and a player clears their rack, after 6 consecutive scoreless turns,
|
||||
by resignation, or by the per-game move timeout (5 minutes to 24 hours, default
|
||||
24 hours): a missed turn auto-resigns, except while the player is inside their
|
||||
daily away window. A resignation or timeout gives the win to the other player and
|
||||
the leaver keeps their score (two-player games; multi-player drop-out-and-continue
|
||||
arrives with the lobby in Stage 4).
|
||||
daily away window. In a two-player game a resignation or timeout gives the win to
|
||||
the other player and the leaver keeps their score. In a game with three or four
|
||||
players the leaver's seat is dropped and the others play on, the game ending when a
|
||||
single active player remains; the disposition of the leaver's tiles (returned to
|
||||
the bag or removed from play) is chosen when the game is created, and the leaver's
|
||||
rack is never shown to the others.
|
||||
|
||||
### Robot opponent *(Stage 5)*
|
||||
Indistinguishable-from-human substitute in auto-match. Decides once whether to
|
||||
@@ -47,12 +54,21 @@ play to win (~40%), targets a small score margin, plays with human-like timing
|
||||
and a night sleep window, and nudges/answers nudges like a person.
|
||||
|
||||
### Social: friends, block, chat, nudge *(Stage 4)*
|
||||
Add friends; block chat and/or friend requests independently; per-game chat;
|
||||
nudge the awaited opponent at most once per hour (platform-native push).
|
||||
Send a friend request and have it accepted (decline or cancel withdraws it,
|
||||
unfriending removes the friendship). Block globally — switch off incoming chat
|
||||
and/or friend requests — and block individual players (a per-user block hides that
|
||||
person's chat and stops requests and game invitations both ways; it also ends any
|
||||
existing friendship). Per-game chat is for quick reactions: messages are short
|
||||
(up to 60 characters) and may not contain links, email addresses or phone numbers,
|
||||
even disguised. Nudge the player whose turn is awaited at most once per hour (the
|
||||
nudge is part of the game chat); the out-of-app push is delivered via the platform.
|
||||
|
||||
### Profile & settings *(Stage 4)*
|
||||
Language (en/ru), display name, linked accounts, email binding, timezone, block
|
||||
toggles.
|
||||
Edit language (en/ru), display name, timezone, the daily away window and the block
|
||||
toggles, and bind an email by confirm-code: the backend emails a short code that,
|
||||
once entered, attaches the email to the account (an email already confirmed by
|
||||
another account cannot be taken — that is a merge, a later stage). Linked platform
|
||||
accounts and merge arrive in Stage 10.
|
||||
|
||||
### History & statistics *(Stage 3)*
|
||||
Finished games are archived in a dictionary-independent form and exportable to
|
||||
|
||||
Reference in New Issue
Block a user