package server import ( "encoding/json" "html/template" "strings" "scrabble/backend/internal/adminconsole" "scrabble/backend/internal/engine" "scrabble/backend/internal/game" ) // The admin game-replay payload embedded in the game_detail page for its vanilla-JS stepper: // the premium board layout, the seats and one step per replay frame (the dealt racks, then // one per move) carrying the resulting racks, scores, turn cursor and bag size. Letters are // upper-cased for display and carry their tile value (0 renders without a subscript). type replayTileJSON struct { L string `json:"l"` V int `json:"v"` B bool `json:"b,omitempty"` } type replayPlaceJSON struct { R int `json:"r"` C int `json:"c"` L string `json:"l"` V int `json:"v"` B bool `json:"b,omitempty"` } type replayMoveJSON struct { Seat int `json:"seat"` Action string `json:"action"` Words []string `json:"words,omitempty"` Score int `json:"score"` Placements []replayPlaceJSON `json:"placements,omitempty"` Exchanged []replayTileJSON `json:"exchanged,omitempty"` } type replayStepJSON struct { Move *replayMoveJSON `json:"move"` Drawn []replayTileJSON `json:"drawn,omitempty"` Racks [][]replayTileJSON `json:"racks"` Scores []int `json:"scores"` ToMove int `json:"toMove"` BagLen int `json:"bagLen"` } type replaySeatJSON struct { Seat int `json:"seat"` Name string `json:"name"` AccountID string `json:"accountId"` } type replayDataJSON struct { Centre [2]int `json:"centre"` Premium [][]string `json:"premium"` Seats []replaySeatJSON `json:"seats"` Steps []replayStepJSON `json:"steps"` } // buildReplayJSON renders a game's replay timeline as the JSON the stepper consumes, resolving // each tile's value from the variant's alphabet. The result is safe to embed in a