// Seed data for the mock transport. Enough to exercise the playable slice locally // (pnpm start) with no backend: a profile, one active mid-game whose board already // has tiles, and two finished games. Coordinates are 0-indexed (centre 7,7). Words do // not need to be strictly legal here — this is a visual/interaction fixture; real // legality and scoring come from the backend. import type { AccountRef, ChatMessage, GameView, Invitation, MoveRecord, Profile, Seat, Session, Stats, } from '../model'; export const ME = 'me'; export const SESSION: Session = { token: 'mock-token', userId: ME, isGuest: true, displayName: 'You', }; export const PROFILE: Profile = { userId: ME, displayName: 'You', preferredLanguage: 'en', timeZone: 'UTC', awayStart: '00:00', awayEnd: '07:00', hintBalance: 3, blockChat: false, blockFriendRequests: false, isGuest: false, notificationsInAppOnly: true, }; // Seed social/account data for the mock (pnpm start + Playwright). The mock profile // is a durable account so the Stage 8 surfaces (friends, stats, history) are reachable. export const MOCK_FRIENDS: AccountRef[] = [ { accountId: 'ann', displayName: 'Ann' }, { accountId: 'kaya', displayName: 'Kaya' }, ]; export const MOCK_INCOMING: AccountRef[] = [{ accountId: 'rick', displayName: 'Rick' }]; export const MOCK_STATS: Stats = { wins: 7, losses: 4, draws: 1, maxGamePoints: 421, maxWordPoints: 95 }; export function mockInvitations(): Invitation[] { return [ { id: 'inv1', inviter: { accountId: 'kaya', displayName: 'Kaya' }, invitees: [{ accountId: ME, displayName: 'You', seat: 1, response: 'pending' }], variant: 'english', turnTimeoutSecs: 86400, hintsAllowed: true, hintsPerPlayer: 1, dropoutTiles: 'remove', status: 'pending', gameId: '', expiresAtUnix: Math.floor(Date.now() / 1000) + 7 * 86400, }, ]; } function seat(s: number, accountId: string, displayName: string, score: number, isWinner = false): Seat { return { seat: s, accountId, displayName, score, hintsUsed: 0, isWinner }; } function play( player: number, dir: 'H' | 'V', tiles: Array<[number, number, string]>, words: string[], score: number, total: number, ): MoveRecord { const ts = tiles.map(([row, col, letter]) => ({ row, col, letter, blank: false })); return { player, action: 'play', dir, mainRow: ts[0]?.row ?? 7, mainCol: ts[0]?.col ?? 7, tiles: ts, words, count: words.length, score, total, }; } export interface MockGame { view: GameView; moves: MoveRecord[]; rack: string[]; bagLen: number; hintsRemaining: number; chat: ChatMessage[]; } // --- active game G1: english, You (seat 0) vs Ann (seat 1), your turn --- const G1_MOVES: MoveRecord[] = [ play(0, 'H', [ [7, 5, 'H'], [7, 6, 'E'], [7, 7, 'L'], [7, 8, 'L'], [7, 9, 'O'], ], ['HELLO'], 16, 16), play(1, 'V', [ [6, 9, 'W'], [8, 9, 'R'], [9, 9, 'L'], [10, 9, 'D'], ], ['WORLD'], 9, 9), play(0, 'H', [ [8, 10, 'A'], [8, 11, 'T'], ], ['RAT'], 3, 19), play(1, 'V', [ [9, 10, 'N'], [10, 10, 'D'], ], ['AND'], 4, 13), ]; function activeGame(): MockGame { return { view: { id: 'g1', variant: 'english', dictVersion: 'v1', status: 'active', players: 2, toMove: 0, turnTimeoutSecs: 86400, moveCount: G1_MOVES.length, endReason: '', seats: [seat(0, ME, 'You', 19), seat(1, 'ann', 'Ann', 13)], }, moves: G1_MOVES, rack: ['R', 'E', 'T', 'I', 'N', 'A', '?'], bagLen: 58, hintsRemaining: 1, chat: [ { id: 'c1', gameId: 'g1', senderId: 'ann', kind: 'message', body: 'good luck!', createdAtUnix: Math.floor(Date.now() / 1000) - 3600, }, ], }; } // --- finished games --- function finishedG2(): MockGame { return { view: { id: 'g2', variant: 'english', dictVersion: 'v1', status: 'finished', players: 2, toMove: 0, turnTimeoutSecs: 86400, moveCount: 2, endReason: 'normal', seats: [seat(0, ME, 'You', 320, true), seat(1, 'kaya', 'Kaya', 281)], }, moves: [ play(0, 'H', [ [7, 6, 'Q'], [7, 7, 'U'], [7, 8, 'I'], [7, 9, 'Z'], ], ['QUIZ'], 48, 48), play(1, 'V', [ [6, 9, 'J'], [8, 9, 'A'], [9, 9, 'M'], ], ['JAZM'], 30, 30), ], rack: [], bagLen: 0, hintsRemaining: 0, chat: [], }; } function finishedG3(): MockGame { return { view: { id: 'g3', variant: 'russian', dictVersion: 'v1', status: 'finished', players: 2, toMove: 0, turnTimeoutSecs: 86400, moveCount: 1, endReason: 'resignation', seats: [seat(0, ME, 'You', 150), seat(1, 'rick', 'Rick', 212, true)], }, moves: [ play(0, 'H', [ [7, 6, 'С'], [7, 7, 'Л'], [7, 8, 'О'], [7, 9, 'В'], [7, 10, 'О'], ], ['СЛОВО'], 12, 12), ], rack: [], bagLen: 0, hintsRemaining: 0, chat: [], }; } export function seedGames(): Map { const m = new Map(); for (const g of [activeGame(), finishedG2(), finishedG3()]) m.set(g.view.id, g); return m; }