export type PuzzleGridSize = 3 | 4; export interface PuzzleCellPosition { row: number; col: number; } export interface PuzzlePieceState { pieceId: string; correctRow: number; correctCol: number; currentRow: number; currentCol: number; mergedGroupId: string | null; } export interface PuzzleMergedGroupState { groupId: string; pieceIds: string[]; occupiedCells: PuzzleCellPosition[]; } export interface PuzzleLeaderboardEntry { rank: number; nickname: string; elapsedMs: number; isCurrentPlayer?: boolean; } export type PuzzleRuntimeLevelStatus = 'playing' | 'cleared' | 'failed'; export type PuzzleRuntimePropKind = 'hint' | 'reference' | 'freezeTime'; export interface PuzzleBoardSnapshot { rows: number; cols: number; pieces: PuzzlePieceState[]; mergedGroups: PuzzleMergedGroupState[]; selectedPieceId: string | null; allTilesResolved: boolean; } export interface PuzzleRuntimeLevelSnapshot { runId: string; levelIndex: number; gridSize: PuzzleGridSize; profileId: string; levelName: string; authorDisplayName: string; themeTags: string[]; coverImageSrc: string | null; board: PuzzleBoardSnapshot; status: PuzzleRuntimeLevelStatus; startedAtMs: number; clearedAtMs: number | null; elapsedMs: number | null; timeLimitMs: number; remainingMs: number; pausedAccumulatedMs: number; pauseStartedAtMs: number | null; freezeAccumulatedMs: number; freezeStartedAtMs: number | null; freezeUntilMs: number | null; leaderboardEntries: PuzzleLeaderboardEntry[]; } export interface PuzzleRunSnapshot { runId: string; entryProfileId: string; clearedLevelCount: number; currentLevelIndex: number; currentGridSize: PuzzleGridSize; playedProfileIds: string[]; previousLevelTags: string[]; currentLevel: PuzzleRuntimeLevelSnapshot | null; recommendedNextProfileId: string | null; leaderboardEntries: PuzzleLeaderboardEntry[]; } export interface StartPuzzleRunRequest { profileId: string; levelId?: string | null; } export interface AdvanceLocalPuzzleNextLevelRequest { run: PuzzleRunSnapshot; sourceSessionId?: string | null; } export interface PuzzleRunResponse { run: PuzzleRunSnapshot; } export interface SubmitPuzzleLeaderboardRequest { profileId: string; gridSize: PuzzleGridSize; elapsedMs: number; nickname: string; } export interface SwapPuzzlePiecesRequest { firstPieceId: string; secondPieceId: string; } export interface DragPuzzlePieceRequest { pieceId: string; targetRow: number; targetCol: number; } export interface UsePuzzleRuntimePropRequest { propKind: PuzzleRuntimePropKind; } export interface UpdatePuzzleRuntimePauseRequest { paused: boolean; }