/** * 方洞挑战运行态共享契约。 * 后端负责当前形状、洞口兼容、胜负和连击真相;前端只提交洞口选择并渲染快照。 */ export type SquareHoleRunStatus = | 'running' | 'won' | 'failed' | 'stopped' | string; export type SquareHoleShapeKind = | 'square' | 'circle' | 'triangle' | 'star' | 'arch' | 'diamond' | string; export type SquareHoleHoleKind = | 'square' | 'circle' | 'triangle' | 'star' | 'arch' | 'diamond' | string; export type SquareHoleDropRejectReason = | 'run_not_active' | 'snapshot_version_mismatch' | 'hole_not_found' | 'incompatible' | 'time_up' | string; export interface SquareHoleShapeSnapshot { shapeId: string; shapeKind: SquareHoleShapeKind; label: string; targetHoleId: string; color: string; imageSrc?: string | null; } export interface SquareHoleHoleSnapshot { holeId: string; holeKind: SquareHoleHoleKind; label: string; x: number; y: number; imageSrc?: string | null; } export interface SquareHoleRunSnapshot { runId: string; profileId: string; ownerUserId: string; status: SquareHoleRunStatus; snapshotVersion: number; startedAtMs: number; durationLimitMs: number; remainingMs: number; totalShapeCount: number; completedShapeCount: number; combo: number; bestCombo: number; score: number; ruleLabel: string; backgroundImageSrc?: string | null; currentShape?: SquareHoleShapeSnapshot | null; holes: SquareHoleHoleSnapshot[]; lastFeedback?: SquareHoleDropFeedback | null; } export interface StartSquareHoleRunRequest { profileId: string; } export interface DropSquareHoleShapeRequest { runId?: string; holeId: string; clientSnapshotVersion: number; clientEventId: string; droppedAtMs: number; } export interface StopSquareHoleRunRequest { clientActionId: string; } export interface SquareHoleDropFeedback { accepted: boolean; rejectReason?: SquareHoleDropRejectReason | null; message: string; } export interface SquareHoleDropResponse { feedback: SquareHoleDropFeedback; run: SquareHoleRunSnapshot; } export interface SquareHoleRunResponse { run: SquareHoleRunSnapshot; }