// What the server tells a viewer about a room. The game's own state is // whatever GameSpec.view returned for that viewer; nothing else leaves. import type { Outcome, SeatId, TableOptions } from '../game/spec'; /** One line of table talk: from a seat, or from the Peanut Gallery when the host allows it (id SPECTATOR, signed with `name`). */ export interface ChatLine { id: SeatId; text: string; at: number; name?: string; /** A private line: the seats it was said to. Absent, the whole table and the gallery heard it. */ to?: SeatId[]; /** The round the line was said in, counted from one; absent before the game begins. */ turn?: number; /** A bot's memory of the line (an offer made, an answer heard). Kept in the ledger; never sent. */ note?: unknown; } export interface RoomView { roomId: string; seq: number; /** The most seats the table will take. */ size: number; /** The viewer's seat, or SPECTATOR for the gallery. */ me: SeatId; /** The player who opened the table and may begin the game. */ host: SeatId; seats: { id: SeatId; name: string; bot: boolean }[]; /** Seats that still have to move before the round resolves. */ waitingOn: SeatId[]; /** Rounds played so far; a move is sent with the count it was made against. */ resolved: number; /** The round being written, from one; null before the game begins. */ turn: number | null; over: Outcome | null; state: State | null; /** This seat's ranking of the table's choices, at a table that asks for one; nobody sees another's. */ yourRanking: string[] | null; /** How many seats have ranked, and nothing more about them. */ ranked: number; /** This seat's input for the round in progress, as the server holds it (a draft, or a settled move); null for none, and for the gallery. */ yourInput: unknown; /** This seat's input in the last round it played, for telling it what became of its own choice; null for none, and for the gallery. */ yourLastInput: unknown; chat: ChatLine[]; /** The bots' last words to this seat once the game is over, for a game that gives them some. */ parting: { id: SeatId; text: string }[]; /** The bots are playing on by themselves, a round at a time, with no person owing a move. */ playingOn: boolean; /** How many watch from the Peanut Gallery. */ audience: number; /** The host lets the gallery talk. */ galleryTalk: boolean; /** The keeper of the site was called to a seat, and by whom. */ challenge: { by: SeatId; at: number } | null; /** Names with a seat held who have not yet sat: the last table's players, or the keeper. */ expected: string[]; /** A finished table's rematch: where it went, and who called. */ rematch: { to: string; by: SeatId } | null; /** The table this one is the rematch of. */ rematchOf: string | null; /** The host's choices for this table, every declared option filled. */ options: TableOptions; /** The keeper of the site, and where they live, for a table that calls them. */ keeper: string; keeperZone: string; } /** One line under a report: the keeper's reply, with its status, or the player's answer. */ export interface ReportLine { at: string; text: string; from: 'desk' | 'player'; status?: string; } /** A report to the keeper, with the exchange under it. */ export interface Report { id: string; at: string; roomId: string; /** The reporter's name, or "(gallery)" for a watcher. */ player: string; seat: SeatId | null; /** The round being written when the report was filed, and the ledger's length. */ turn: number | null; seq: number; happened: string; expected: string; /** The whole exchange in order: the keeper's replies and the player's answers. */ thread: ReportLine[]; /** A screenshot's file name under images/, when one was sent. */ image?: string; } /** What the ledgers add up to, for the hall's about panel. */ export interface Tally { tablesOpened: number; gamesBegun: number; gamesFinished: number; /** Distinct names of people who have taken a seat; a bot's name is not counted. */ namesSeated: number; turnsPlayed: number; /** Minutes at the table: gaps under ten minutes between one move and the next, summed. */ minutesAtTable: number; longestGameTurns: number; gamesWithBot: number; talkLines: number; firstGameAt: string | null; /** The game's own lines, summed over finished games. */ byGame: Record; }