jspsych-tangram 0.0.18 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/core/config/config.ts","../../src/core/domain/blueprints.ts","../../src/core/engine/state/BaseGameController.ts","../../src/core/engine/geometry/math.ts","../../src/core/engine/geometry/collision.ts","../../src/core/engine/geometry/bounds.ts","../../src/core/engine/geometry/pieces.ts","../../src/core/domain/solve.ts","../../src/core/domain/layout.ts","../../src/core/engine/validation/border-rendering.ts","../../src/assets/locked.png","../../src/assets/unlocked.png","../../src/core/components/board/BoardView.tsx","../../src/core/engine/validation/complete.ts","../../src/core/components/board/utils.ts","../../src/core/components/board/usePieceState.ts","../../src/core/engine/collision/grid-snapping.ts","../../src/core/components/board/useAnchorGrid.ts","../../src/core/engine/validation/face-to-face.ts","../../src/core/components/board/useDragController.ts","../../src/core/components/board/useClickController.ts","../../src/core/io/InteractionTracker.ts","../../src/core/components/board/GameBoard.tsx","../../src/core/domain/primitives.ts","../../src/core/io/quickstash.ts","../../src/plugins/tangram-construct/ConstructionApp.tsx","../../src/plugins/tangram-construct/index.ts"],"sourcesContent":["// src/core/config/config.ts\nexport type Config = {\n color: {\n background: string;\n bands: {\n silhouette: { fillEven: string; fillOdd: string; stroke: string };\n workspace: { fillEven: string; fillOdd: string; stroke: string };\n };\n completion: { fill: string; stroke: string };\n silhouetteMask: string;\n anchors: { invalid: string; valid: string };\n piece: { draggingFill: string; validFill: string; invalidFill: string; invalidStroke: string; selectedStroke: string; allGreenStroke: string; borderStroke: string };\n ui: { light: string; dark: string };\n blueprint: { fill: string; selectedStroke: string; badgeFill: string; labelFill: string };\n tangramDecomposition: { stroke: string };\n primitiveColors: string[];\n };\n opacity: {\n blueprint: number;\n silhouetteMask: number;\n anchors: { invalid: number; valid: number };\n piece: { invalid: number; dragging: number; locked: number; normal: number };\n };\n size: {\n stroke: { bandPx: number; pieceSelectedPx: number; allGreenStrokePx: number; pieceBorderPx: number; tangramDecompositionPx: number };\n anchorRadiusPx: { valid: number; invalid: number };\n badgeFontPx: number;\n centerBadge: { fractionOfOuterR: number; minPx: number; marginPx: number };\n invalidMarker: { sizePx: number; strokePx: number };\n };\n layout: {\n grid: { stepPx: number; unitPx: number };\n paddingPx: number;\n viewportScale: number;\n /** renamed from capacity → constraints */\n constraints: {\n workspaceDiamAnchors: number;\n quickstashDiamAnchors: number;\n primitiveDiamAnchors: number;\n };\n defaults: { maxQuickstashSlots: number };\n };\n game: {\n snapRadiusPx: number;\n showBorders: boolean;\n hideTouchingBorders: boolean;\n silhouettesBelowPieces: boolean;\n };\n};\n\nexport const CONFIG: Config = {\n color: {\n background: \"#fff7e0ff\",\n bands: {\n silhouette: { fillEven: \"#ffffff\", fillOdd: \"#ffffff\", stroke: \"#b1b1b1\" },\n workspace: { fillEven: \"#ffffff\", fillOdd: \"#ffffff\", stroke: \"#b1b1b1\" }\n },\n completion: { fill: \"#ccffcc\", stroke: \"#13da57\" },\n silhouetteMask: \"#374151\",\n anchors: { invalid: \"#7dd3fc\", valid: \"#475569\" },\n // validFill used here for placed composites\n piece: { draggingFill: \"#8e7cc3\", validFill: \"#8e7cc3\", invalidFill: \"#d55c00\", invalidStroke: \"#dc2626\", selectedStroke: \"#674ea7\", allGreenStroke: \"#86efac\", borderStroke: \"#674ea7\" },\n ui: { light: \"#60a5fa\", dark: \"#1d4ed8\" },\n blueprint: { fill: \"#374151\", selectedStroke: \"#111827\", badgeFill: \"#000000\", labelFill: \"#ffffff\" },\n tangramDecomposition: { stroke: \"#fef2cc\" },\n primitiveColors: [ // from seaborn \"colorblind\" palette, 6 colors, with red omitted\n '#0173b2',\n '#de8f05',\n '#029e73',\n '#cc78bc',\n '#ca9161'\n ]\n },\n opacity: {\n blueprint: 0.6,\n silhouetteMask: 0.25,\n //anchors: { valid: 0.80, invalid: 0.50 },\n anchors: { invalid: 0.0, valid: 0.0 },\n piece: { invalid: 1, dragging: 1, locked: 1, normal: 1 },\n },\n size: {\n stroke: { bandPx: 5, pieceSelectedPx: 5, allGreenStrokePx: 10, pieceBorderPx: 2, tangramDecompositionPx: 1 },\n anchorRadiusPx: { valid: 1.0, invalid: 1.0 },\n badgeFontPx: 16,\n centerBadge: { fractionOfOuterR: 0.15, minPx: 20, marginPx: 4 },\n invalidMarker: { sizePx: 10, strokePx: 4 }\n },\n layout: {\n grid: { stepPx: 20, unitPx: 40 },\n paddingPx: 1,\n viewportScale: 0.8,\n constraints: {\n workspaceDiamAnchors: 10, // num anchors req'd to be on diagonal\n quickstashDiamAnchors: 7, // num anchors req'd to be in single quickstash slot\n primitiveDiamAnchors: 5,\n },\n defaults: { maxQuickstashSlots: 1 }\n },\n game: {\n snapRadiusPx: 15,\n showBorders: false,\n hideTouchingBorders: true,\n silhouettesBelowPieces: true\n }\n};","import type {\n Blueprint, PrimitiveBlueprint, CompositeBlueprint, TanKind\n} from \"./types\";\n\nexport function isComposite(bp: Blueprint): bp is CompositeBlueprint {\n return (bp as CompositeBlueprint).parts !== undefined;\n}\nexport function isPrimitive(bp: Blueprint): bp is PrimitiveBlueprint {\n return !isComposite(bp);\n}\n\nexport class BlueprintRegistry {\n private byId = new Map<string, Blueprint>();\n private primitivesByKind = new Map<TanKind, PrimitiveBlueprint>();\n\n registerAll(bps: Blueprint[]) {\n for (const bp of bps) this.register(bp);\n }\n register(bp: Blueprint) {\n this.byId.set(bp.id, bp);\n if (isPrimitive(bp)) this.primitivesByKind.set(bp.kind, bp);\n }\n get(id: string) { return this.byId.get(id); }\n getPrimitive(kind: TanKind | string) { return this.primitivesByKind.get(kind as TanKind); }\n}\n","/**\n * BaseGameController with dependency injection - PHASE 2 MILESTONE\n * \n * Maintains compatibility with existing RoundController API while implementing\n * clean separation between configuration and data. All game content is injected\n * via constructor parameters, no hardcoded defaults.\n */\n\nimport type { \n Blueprint, \n Sector, \n LayoutMode,\n PlacementTarget,\n InputMode,\n RoundState,\n SectorState,\n TanKind,\n PrimitiveBlueprint\n} from '../../domain/types';\nimport { CONFIG } from '../../config/config';\nimport { BlueprintRegistry } from '../../domain/blueprints';\n\nexport interface GameConfig {\n n: number;\n layout: LayoutMode;\n target: PlacementTarget; // CRITICAL: \"workspace\" | \"silhouette\"\n input: InputMode; // CRITICAL: \"click\" | \"drag\"\n timeLimitMs: number;\n maxQuickstashSlots: number;\n maxCompositeSize?: number; // Optional - only used in prep mode\n mode: \"construction\" | \"prep\"; // NEW: Distinguishes prep vs construction behavior\n minPiecesPerMacro?: number; // NEW: Minimum pieces required per macro (prep mode)\n requireAllSlots?: boolean; // NEW: Whether all slots must be filled (prep mode)\n}\n\nlet PID = 0;\nconst newId = () => `p_${++PID}`;\nconst NOW = () => performance.now();\n\n// Event tracking callbacks (optional - set by InteractionTracker)\nexport interface TrackingCallbacks {\n onPiecePickup?: (pieceId: string, blueprintId: string, blueprintType: 'primitive' | 'composite', source: 'blueprint' | 'sector', position: { x: number; y: number }, vertices: number[][][], sectorId?: string) => void;\n onPiecePlacedown?: (outcome: 'placed' | 'deleted', sectorId?: string, position?: { x: number; y: number }, vertices?: number[][][], anchorId?: string, wasValid?: boolean, wasOverlapping?: boolean) => void;\n onClickEvent?: (location: { x: number; y: number }, anchorX: number, anchorY: number, clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt', metadata?: any) => void;\n onMouseMove?: (anchorX: number, anchorY: number, sectorId?: string) => void;\n onSectorCompleted?: (sectorId: string) => void;\n}\n\nexport class BaseGameController {\n // Core data - injected, not hardcoded\n private sectors: Sector[];\n private quickstash: Blueprint[];\n private primitives: PrimitiveBlueprint[];\n\n // Configuration\n private config: GameConfig;\n\n // State and registry\n public state: RoundState;\n private t0: number;\n private registry = new BlueprintRegistry();\n\n // React state update tracking\n private _updateCount = 0;\n public get updateCount() { return this._updateCount; }\n private notifyStateChange() { this._updateCount++; }\n\n // Event tracking (optional)\n private trackingCallbacks: TrackingCallbacks | null = null;\n \n constructor(\n sectors: Sector[],\n quickstash: Blueprint[],\n primitives: PrimitiveBlueprint[],\n config: GameConfig\n ) {\n // Validate required inputs - fail fast\n if (!sectors || sectors.length === 0) {\n throw new Error(\"BaseGameController: sectors array is required and cannot be empty\");\n }\n if (!primitives || primitives.length === 0) {\n throw new Error(\"BaseGameController: primitives array is required and cannot be empty\");\n }\n if (!config) {\n throw new Error(\"BaseGameController: config is required\");\n }\n\n // CRITICAL: All data is injected, no defaults\n this.sectors = sectors;\n this.quickstash = quickstash || [];\n this.primitives = primitives;\n this.config = config;\n \n // Initialize registry\n this.registry.registerAll(primitives);\n this.registry.registerAll(quickstash);\n \n // Initialize state\n this.t0 = NOW();\n this.state = this.initializeState();\n }\n \n private initializeState(): RoundState {\n // Create state that matches existing RoundController structure\n const sectors: Record<string, SectorState> = {};\n for (const s of this.sectors) {\n sectors[s.id] = { sectorId: s.id, pieces: [] };\n }\n\n return {\n cfg: {\n n: this.config.n,\n layout: this.config.layout,\n target: this.config.target,\n input: this.config.input,\n maxQuickstashSlots: this.config.maxQuickstashSlots,\n timeLimitMs: this.config.timeLimitMs,\n snapRadiusPx: CONFIG.game.snapRadiusPx,\n maxCompositeSize: this.config.maxCompositeSize ?? 0, // Default to 0 for legacy compatibility\n sectors: this.sectors,\n mode: this.config.mode\n },\n blueprintView: this.config.mode === \"prep\" ? \"primitives\" : \"quickstash\", // Start with primitives in prep mode\n primitives: this.primitives,\n quickstash: this.quickstash,\n sectors,\n startedAt: this.t0\n };\n }\n\n // ===== Event Tracking =====\n // Methods for InteractionTracker integration\n\n /**\n * Set tracking callbacks for data collection\n * Called by InteractionTracker to register itself\n */\n setTrackingCallbacks(callbacks: TrackingCallbacks | null): void {\n this.trackingCallbacks = callbacks;\n }\n\n // ===== RoundController Compatibility Interface =====\n // These methods maintain compatibility with Board.tsx expectations\n\n getState(): RoundState {\n return this.state;\n }\n\n getSnapRadius(): number {\n return CONFIG.game.snapRadiusPx;\n }\n\n // CRITICAL: Preserve target and input mode access\n getTarget(): PlacementTarget {\n return this.config.target;\n }\n\n getInputMode(): InputMode {\n return this.config.input;\n }\n\n // ===== Blueprint and Piece Management =====\n // Methods that Board.tsx expects\n\n getBlueprint(id: string): Blueprint | undefined {\n return this.registry.get(id);\n }\n\n getPrimitive(kind: TanKind | string): PrimitiveBlueprint | undefined {\n return this.registry.getPrimitive(kind);\n }\n\n getPiecesInSector(sectorId: string): any[] {\n const sectorState = this.state.sectors[sectorId];\n return sectorState ? sectorState.pieces : [];\n }\n\n // ===== Completion Management =====\n // Critical for Board.tsx validation\n\n isSectorCompleted(sectorId: string): boolean {\n return !!this.state.sectors[sectorId]?.completedAt;\n }\n\n markSectorCompleted(sectorId: string): void {\n const ss = this.state.sectors[sectorId];\n if (!ss || ss.completedAt) return;\n\n ss.completedAt = NOW();\n\n // Notify tracking system\n if (this.trackingCallbacks?.onSectorCompleted) {\n this.trackingCallbacks.onSectorCompleted(sectorId);\n }\n\n const allDone = Object.values(this.state.sectors).every((s: SectorState) => !!s.completedAt);\n if (allDone && !this.state.endedAt) {\n this.state.endedAt = NOW();\n }\n }\n\n // ===== Piece Operations =====\n // Methods that Board.tsx uses for drag/drop\n\n spawnFromBlueprint(bp: Blueprint, at: { x: number; y: number }): string {\n const id = newId();\n const piece = { id, blueprintId: bp.id, pos: { ...at } };\n this.getFloating().pieces.push(piece);\n this.notifyStateChange();\n return id;\n }\n\n move(id: string, to: { x: number; y: number }): void {\n const p = this.findPiece(id);\n if (!p) {\n return;\n }\n p.pos = { ...to };\n this.notifyStateChange();\n }\n\n drop(id: string, sectorId?: string): void {\n const p = this.findPiece(id);\n if (!p) {\n return;\n }\n\n // Remove from current location\n const where = this.findPieceLocation(id);\n this.removeFromCurrent(id);\n if (where?.sectorId) delete p.sectorId;\n\n // Inner-hole or no sector → float\n if (!sectorId) {\n this.getFloating().pieces.push(p);\n this.notifyStateChange();\n return;\n }\n\n // Completed sector → delete (already removed above)\n if (this.isSectorCompleted(sectorId)) {\n this.notifyStateChange();\n return;\n }\n\n // Place in sector\n const sector = this.state.sectors[sectorId];\n if (!sector) {\n return;\n }\n \n sector.pieces.push(p);\n p.sectorId = sectorId;\n this.notifyStateChange();\n }\n\n remove(id: string): void {\n const loc = this.findPieceLocation(id);\n if (!loc) return;\n loc.array.splice(loc.index, 1);\n this.notifyStateChange();\n }\n\n // ===== Helper Methods =====\n // Internal methods that support the public API\n\n findPiece(id: string): any {\n for (const s of Object.values(this.state.sectors)) {\n const sectorState = s as SectorState;\n const p = sectorState.pieces.find((pp) => pp.id === id);\n if (p) return p;\n }\n return this.getFloating().pieces.find((pp) => pp.id === id) ?? null;\n }\n\n private getFloating(): SectorState {\n if (!(this as any)._floating) {\n (this as any)._floating = { sectorId: \"-floating-\", pieces: [] } as SectorState;\n }\n return (this as any)._floating;\n }\n\n private findPieceLocation(id: string): \n | { sectorId?: string; array: SectorState[\"pieces\"]; index: number }\n | null {\n for (const s of Object.values(this.state.sectors)) {\n const sectorState = s as SectorState;\n const idx = sectorState.pieces.findIndex((pp) => pp.id === id);\n if (idx >= 0) return { sectorId: sectorState.sectorId, array: sectorState.pieces, index: idx };\n }\n const f = this.getFloating();\n const i = f.pieces.findIndex((pp) => pp.id === id);\n return i >= 0 ? { array: f.pieces, index: i } : null;\n }\n\n private removeFromCurrent(id: string): void {\n const loc = this.findPieceLocation(id);\n if (!loc) return;\n loc.array.splice(loc.index, 1);\n }\n\n // ===== Additional Compatibility Methods =====\n\n switchBlueprintView(): void {\n // Disable toggle in prep mode - keep primitives always visible\n if (this.config.mode === \"prep\") return;\n \n const to = this.state.blueprintView === \"primitives\" ? \"quickstash\" : \"primitives\";\n this.state.blueprintView = to;\n }\n\n /**\n * Check if submit button should be enabled in prep mode\n * Validates macro completion based on piece count and slot requirements\n */\n isSubmitEnabled(): boolean {\n if (this.config.mode !== \"prep\") return true; // Not applicable to construction mode\n \n const minPieces = this.config.minPiecesPerMacro ?? 2;\n const maxPieces = this.config.maxCompositeSize ?? Infinity; // No upper limit if not specified\n const requireAll = this.config.requireAllSlots ?? false;\n \n // Get all sectors (macro slots)\n const allSectors = Object.values(this.state.sectors);\n \n // Check each sector for valid piece count\n let validSectorCount = 0;\n for (const sector of allSectors) {\n const pieceCount = sector.pieces.length;\n \n // Valid if between min and max pieces (inclusive)\n if (pieceCount >= minPieces && pieceCount <= maxPieces) {\n validSectorCount++;\n }\n // Invalid if has pieces but not enough or too many\n else if (pieceCount > 0) {\n return false; // Has pieces but invalid count\n }\n // Empty sector (pieceCount === 0) is allowed, will be checked below\n }\n \n if (requireAll) {\n // All slots must have valid macros\n return validSectorCount === allSectors.length;\n } else {\n // At least 0 valid macros (can submit nothing)\n return true; // No invalid sectors found above, so can submit\n }\n }\n\n snapshot(): any {\n const perSector = Object.values(this.state.sectors).map((s) => {\n const sectorState = s as SectorState;\n const base = {\n sectorId: sectorState.sectorId,\n pieceCount: sectorState.pieces.length,\n };\n return sectorState.completedAt ? { ...base, completedAt: sectorState.completedAt } : base;\n });\n return {\n perSector,\n events: [], // TODO: Will be implemented in validation separation phase\n timeMs: NOW() - this.t0,\n completed: !!this.state.endedAt,\n };\n }\n}","/**\n * Pure vector and polygon mathematical operations\n * No game logic dependencies - just geometric math\n */\n\nimport type { Vec, Poly } from '@/core/domain/types';\n\n// ===== Constants =====\n\nexport const EPS = 1e-6;\n\n// ===== Vector Operations =====\n\nexport const vsub = (a: Vec, b: Vec): Vec => ({ x: a.x - b.x, y: a.y - b.y });\nexport const vlen = (v: Vec) => Math.hypot(v.x, v.y);\nexport const vscale = (v: Vec, s: number): Vec => ({ x: v.x * s, y: v.y * s });\nexport const vadd = (a: Vec, b: Vec): Vec => ({ x: a.x + b.x, y: a.y + b.y });\n\n/** Squared distance between two points (faster than full distance) */\nexport const dist2 = (a: Vec, b: Vec): number => {\n const dx = a.x - b.x, dy = a.y - b.y;\n return dx * dx + dy * dy;\n};\n\n/**\n * Check if point p lies on the line segment from a to b (within epsilon tolerance)\n */\nexport function pointOnSegment(p: Vec, a: Vec, b: Vec, eps = 1e-9): boolean {\n // collinear?\n const cross = (b.y - a.y) * (p.x - a.x) - (b.x - a.x) * (p.y - a.y);\n if (Math.abs(cross) > eps) return false;\n // within bounding box?\n const minX = Math.min(a.x, b.x) - eps, maxX = Math.max(a.x, b.x) + eps;\n const minY = Math.min(a.y, b.y) - eps, maxY = Math.max(a.y, b.y) + eps;\n return p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY;\n}\n\n/**\n * Return an array of points subdividing the segment [a,b] into `n` equal parts (excluding `a`).\n */\nexport function subdivideSegment(a: Vec, b: Vec, n: number): Vec[] {\n if (n <= 1) return [b];\n const ab = vsub(b, a);\n const step = 1 / n;\n const pts: Vec[] = [];\n for (let i = 1; i <= n; i++) pts.push(vadd(a, vscale(ab, step * i)));\n return pts;\n}\n\n// ===== Polygon Operations =====\n\n/** Boundary-inclusive even–odd point-in-polygon test */\nexport function pointInPolygon(pt: Vec, poly: Poly): boolean {\n // 1) On-edge / on-vertex counts as inside\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const vertexJ = poly[j];\n const vertexI = poly[i];\n if (!vertexJ || !vertexI) continue;\n if (pointOnSegment(pt, vertexJ, vertexI)) return true;\n }\n\n // 2) Standard even–odd ray casting (edges strictly above/below pivot)\n // Using the common (yi > y) !== (yj > y) test avoids counting horizontal edges twice.\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const vertexI = poly[i];\n const vertexJ = poly[j];\n if (!vertexI || !vertexJ) continue;\n const xi = vertexI.x, yi = vertexI.y;\n const xj = vertexJ.x, yj = vertexJ.y;\n\n const intersects = (yi > pt.y) !== (yj > pt.y)\n && pt.x < ((xj - xi) * (pt.y - yi)) / (yj - yi + 1e-12) + xi;\n\n if (intersects) inside = !inside;\n }\n return inside;\n}\n\n/** Project a polygon onto axis (nx, ny) and return min/max projection values */\nexport function project(poly: Poly, nx: number, ny: number) {\n let min = Infinity, max = -Infinity;\n for (const p of poly) {\n const s = p.x * nx + p.y * ny;\n if (s < min) min = s;\n if (s > max) max = s;\n }\n return { min, max };\n}\n\n/** Calculate axis-aligned bounding box for a polygon */\nexport function polygonAABB(poly: Poly) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of poly) {\n if (pt.x < minX) minX = pt.x;\n if (pt.y < minY) minY = pt.y;\n if (pt.x > maxX) maxX = pt.x;\n if (pt.y > maxY) maxY = pt.y;\n }\n return { minX, minY, maxX, maxY };\n}\n","/**\n * SAT (Separating Axis Theorem) collision detection for convex polygons\n * Extracted from polygon.ts for better organization\n */\n\nimport type { Poly } from '@/core/domain/types';\nimport { project } from './math';\n\nconst SEP_EPS = 1e-6; // allow touching within this tolerance\n\n/** SAT for convex polygons. Edges/vertices touching are allowed (non-overlap). */\nexport function convexIntersects(a: Poly, b: Poly): boolean {\n const polys = [a, b];\n for (const poly of polys) {\n for (let i = 0; i < poly.length; i++) {\n const p0 = poly[i], p1 = poly[(i + 1) % poly.length];\n if (!p0 || !p1) continue;\n const ex = p1.x - p0.x, ey = p1.y - p0.y;\n const nx = -ey, ny = ex; // outward normal\n const pa = project(a, nx, ny);\n const pb = project(b, nx, ny);\n // Treat touching (zero overlap) as separated: allow edges/vertices to touch.\n if (pa.max <= pb.min + SEP_EPS || pb.max <= pa.min + SEP_EPS) return false;\n }\n }\n return true;\n}\n\n/** True if any poly from A overlaps any poly from B (fast AABB short-circuit). */\nexport function polysOverlap(aPolys: Poly[], bPolys: Poly[]): boolean {\n // quick AABB test to skip obvious separations\n const aabbsA = aPolys.map(p => {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of p) {\n if (pt.x < minX) minX = pt.x;\n if (pt.y < minY) minY = pt.y;\n if (pt.x > maxX) maxX = pt.x;\n if (pt.y > maxY) maxY = pt.y;\n }\n return { minX, minY, maxX, maxY };\n });\n const aabbsB = bPolys.map(p => {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of p) {\n if (pt.x < minX) minX = pt.x;\n if (pt.y < minY) minY = pt.y;\n if (pt.x > maxX) maxX = pt.x;\n if (pt.y > maxY) maxY = pt.y;\n }\n return { minX, minY, maxX, maxY };\n });\n\n for (let i = 0; i < aPolys.length; i++) {\n for (let j = 0; j < bPolys.length; j++) {\n const A = aPolys[i], B = bPolys[j];\n const aa = aabbsA[i], bb = aabbsB[j];\n if (!A || !B || !aa || !bb) continue;\n if (aa.maxX <= bb.minX + SEP_EPS || bb.maxX <= aa.minX + SEP_EPS ||\n aa.maxY <= bb.minY + SEP_EPS || bb.maxY <= aa.minY + SEP_EPS) continue;\n if (convexIntersects(A, B)) return true;\n }\n }\n return false;\n}\n","import type { Poly, Vec, PrimitiveBlueprint, CompositeBlueprint, Blueprint } from \"@/core/domain/types\";\n\nexport type AABB = { min: Vec; max: Vec; width: number; height: number };\n\n/** AABB of a single polygon (numeric). */\nexport function aabbOf(poly: Poly): { minX: number; minY: number; maxX: number; maxY: number } {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { minX, minY, maxX, maxY };\n}\n\n/** AABB of one or more polygons with width/height and center. */\nexport function polysAABB(polys: Poly[]) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of polys) {\n for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n }\n const width = Math.max(1, maxX - minX);\n const height = Math.max(1, maxY - minY);\n return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY }, width, height, cx:(minX+maxX)/2, cy:(minY+maxY)/2 };\n}\n\n/** Bounds of multiple polygons at the origin. */\nexport function boundsOfShapes(shapes: Poly[]): AABB {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of shapes) {\n for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n }\n const width = Math.max(0, maxX - minX);\n const height = Math.max(0, maxY - minY);\n return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY }, width, height };\n}\n\n/** Bounds of a primitive blueprint (uses its canonical shape). */\nexport function boundsOfPrimitive(bp: PrimitiveBlueprint): AABB {\n return boundsOfShapes(bp.shape);\n}\n\n/**\n * Bounds of a composite blueprint.\n * If `shape` is provided as precomputed union polygons, we use that.\n * Otherwise we bound the parts’ primitives at their offsets (loose but safe).\n */\nexport function boundsOfComposite(\n bp: CompositeBlueprint,\n primitiveLookup: (kind: string) => PrimitiveBlueprint | undefined\n): AABB {\n if (bp.shape && bp.shape.length) return boundsOfShapes(bp.shape);\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const part of bp.parts) {\n const prim = primitiveLookup(part.kind);\n if (!prim) continue;\n const b = boundsOfPrimitive(prim);\n const pMinX = part.offset.x + b.min.x;\n const pMinY = part.offset.y + b.min.y;\n const pMaxX = part.offset.x + b.max.x;\n const pMaxY = part.offset.y + b.max.y;\n if (pMinX < minX) minX = pMinX;\n if (pMinY < minY) minY = pMinY;\n if (pMaxX > maxX) maxX = pMaxX;\n if (pMaxY > maxY) maxY = pMaxY;\n }\n const width = Math.max(0, maxX - minX);\n const height = Math.max(0, maxY - minY);\n return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY }, width, height };\n}\n\n/** Unified bounds helper. */\nexport function boundsOfBlueprint(\n bp: Blueprint,\n primitiveLookup: (kind: string) => PrimitiveBlueprint | undefined\n): AABB {\n if (\"parts\" in bp) return boundsOfComposite(bp, primitiveLookup);\n return boundsOfPrimitive(bp);\n}\n","/**\n * Game-specific piece geometry operations\n * Includes: piece positioning, placement, grid snapping, and anchor generation\n *\n * Consolidated from: piece.ts, placement.ts, grid.ts, anchors.ts\n */\n\nimport type { Blueprint, Vec, Poly, Anchor } from \"@/core/domain/types\";\nimport type { CircleLayout, SectorGeom } from \"@/core/domain/layout\";\nimport { polysAABB } from \"./bounds\";\nimport { pointInPolygon, dist2 } from \"./math\";\nimport { CONFIG } from \"@/core/config/config\";\n\nconst GRID_PX = CONFIG.layout.grid.stepPx;\n\n// ===== Piece Positioning (from piece.ts) =====\n\n/** Translate blueprint polys to world coords for a given top-left (TL). */\nexport function piecePolysAt(\n bp: Blueprint,\n bb: { min: { x: number; y: number } },\n tl: { x: number; y: number }\n) {\n const ox = tl.x - bb.min.x;\n const oy = tl.y - bb.min.y;\n const polys = (\"shape\" in bp && bp.shape) ? bp.shape : [];\n return polys.map(poly => poly.map(p => ({ x: p.x + ox, y: p.y + oy })));\n}\n\n/** Build support offsets: each vertex relative to the AABB center. */\nexport function computeSupportOffsets(\n bp: Blueprint,\n bb: { min: { x: number; y: number }; width: number; height: number }\n) {\n const cx = bb.min.x + bb.width / 2;\n const cy = bb.min.y + bb.height / 2;\n\n const polys = (\"shape\" in bp && bp.shape && bp.shape.length)\n ? bp.shape\n : [[\n { x: bb.min.x, y: bb.min.y },\n { x: bb.min.x + bb.width, y: bb.min.y },\n { x: bb.min.x + bb.width, y: bb.min.y + bb.height },\n { x: bb.min.x, y: bb.min.y + bb.height },\n ]];\n\n const offs: Vec[] = [];\n for (const poly of polys) for (const v of poly) offs.push({ x: v.x - cx, y: v.y - cy });\n return offs;\n}\n\n/** Clamp using directional vertex support → exact contact with the ring. */\nexport function clampTopLeftBySupport(\n tlx: number,\n tly: number,\n d: {\n aabb: { width: number; height: number };\n support: { x: number; y: number }[];\n },\n layout: CircleLayout,\n target: \"workspace\" | \"silhouette\",\n pointerInsideCenter: boolean\n) {\n const cx0 = tlx + d.aabb.width / 2;\n const cy0 = tly + d.aabb.height / 2;\n\n const vx = cx0 - layout.cx;\n const vy = cy0 - layout.cy;\n const r = Math.hypot(vx, vy);\n if (r === 0) return { x: tlx, y: tly };\n\n const ux = vx / r, uy = vy / r;\n\n let h_out = -Infinity, h_in = -Infinity;\n for (const o of d.support) {\n const outProj = o.x * ux + o.y * uy;\n if (outProj > h_out) h_out = outProj;\n const inProj = -(o.x * ux + o.y * uy);\n if (inProj > h_in) h_in = inProj;\n }\n\n if (target === \"workspace\") {\n const [rIn, rOut] = layout.bands.workspace;\n const minR = pointerInsideCenter ? 0 : (rIn + h_in);\n const maxR = rOut - h_out;\n const rClamped = Math.min(Math.max(r, minR), maxR);\n if (Math.abs(rClamped - r) < 1e-6) return { x: tlx, y: tly };\n const newCx = layout.cx + rClamped * ux;\n const newCy = layout.cy + rClamped * uy;\n return { x: newCx - d.aabb.width / 2, y: newCy - d.aabb.height / 2 };\n } else {\n const rOut = layout.bands.silhouette[1];\n const maxR = rOut - h_out;\n if (r <= maxR) return { x: tlx, y: tly };\n const newCx = layout.cx + maxR * ux;\n const newCy = layout.cy + maxR * uy;\n return { x: newCx - d.aabb.width / 2, y: newCy - d.aabb.height / 2 };\n }\n}\n\n// ===== Placement (from placement.ts) =====\n\n/** gcd for positive integers */\nfunction igcd(a: number, b: number) {\n a = Math.round(Math.abs(a)); b = Math.round(Math.abs(b));\n while (b) [a, b] = [b, a % b];\n return a || 1;\n}\n\n/** Infer the base lattice unit in raw silhouette coordinates. */\nexport function inferUnitFromPolys(polys: Poly[]): number {\n let g = 0;\n for (const poly of polys) {\n for (let i = 0; i < poly.length; i++) {\n const a = poly[i], b = poly[(i + 1) % poly.length];\n if (!a || !b) continue;\n const dx = Math.round(Math.abs(b.x - a.x));\n const dy = Math.round(Math.abs(b.y - a.y));\n if (dx) g = g ? igcd(g, dx) : dx;\n if (dy) g = g ? igcd(g, dy) : dy;\n }\n }\n return g || 1;\n}\n\n/**\n * Place polys using scale S, re-centered, and translation snapped to GRID_PX; returns polys.\n * The center is snapped to the grid so the lattice points under the silhouette stay invariant.\n */\nexport function placeSilhouetteGridAlignedAsPolys(\n polys: Poly[],\n S: number,\n rectCenter: { cx: number; cy: number }\n): Poly[] {\n if (!polys || polys.length === 0) return [];\n const a = polysAABB(polys);\n const cx0 = (a.min.x + a.max.x) / 2;\n const cy0 = (a.min.y + a.max.y) / 2;\n const cx = Math.round(rectCenter.cx / GRID_PX) * GRID_PX;\n const cy = Math.round(rectCenter.cy / GRID_PX) * GRID_PX;\n const tx = cx - S * cx0;\n const ty = cy - S * cy0;\n const stx = Math.round(tx / GRID_PX) * GRID_PX;\n const sty = Math.round(ty / GRID_PX) * GRID_PX;\n return polys.map(poly => poly.map(p => ({ x: S * p.x + stx, y: S * p.y + sty })));\n}\n\n// ===== Grid Operations (from grid.ts) =====\n\nexport function nearestGridNode(p: Vec): Vec {\n return { x: Math.round(p.x / GRID_PX) * GRID_PX, y: Math.round(p.y / GRID_PX) * GRID_PX };\n}\n\n/** Generate grid nodes inside an AABB. */\nexport function gridNodesInAABB(min: Vec, max: Vec): Vec[] {\n const out: Vec[] = [];\n const x0 = Math.ceil(min.x / GRID_PX) * GRID_PX;\n const y0 = Math.ceil(min.y / GRID_PX) * GRID_PX;\n for (let y = y0; y <= max.y; y += GRID_PX) {\n for (let x = x0; x <= max.x; x += GRID_PX) out.push({ x, y });\n }\n return out;\n}\n\n/** Keep nodes in a band (and optional sector wedge). */\nexport function filterNodesToBandAndSector(\n nodes: Vec[],\n layout: CircleLayout,\n band: \"workspace\" | \"silhouette\",\n sector?: SectorGeom\n): Vec[] {\n const [rIn, rOut] = layout.bands[band];\n const out: Vec[] = [];\n for (const n of nodes) {\n const dx = n.x - layout.cx, dy = n.y - layout.cy;\n const r = Math.hypot(dx, dy);\n if (r < rIn || r > rOut) continue;\n\n if (sector) {\n let theta = Math.atan2(dy, dx);\n if (layout.mode === \"circle\") {\n if (theta < -Math.PI / 2) theta += 2 * Math.PI;\n } else {\n if (theta < Math.PI) theta += 2 * Math.PI;\n }\n if (theta < sector.start || theta >= sector.end) continue;\n }\n out.push(n);\n }\n return out;\n}\n\n/** Keep nodes that lie inside any of the polygons. */\nexport function filterNodesInPolys(\n nodes: Vec[],\n polys: Poly[],\n pointInPolyFn: (pt: Vec, poly: Poly) => boolean = pointInPolygon\n): Vec[] {\n const out: Vec[] = [];\n node: for (const n of nodes) {\n for (const poly of polys) {\n if (pointInPolyFn(n, poly)) { out.push(n); continue node; }\n }\n }\n return out;\n}\n\n// ===== Anchor Operations (from anchors.ts) =====\n\n/**\n * Find the nearest anchor that \"accepts\" a piece signature (kind/compositeSignature).\n * Returns null if none within the optional radius.\n */\nexport function nearestAcceptingAnchor(\n anchors: Anchor[] | undefined,\n point: Vec,\n accepts: { kind?: string; compositeSignature?: string },\n withinPx: number = Infinity\n): { anchor: Anchor; d2: number } | null {\n if (!anchors || !anchors.length) return null;\n\n const { kind, compositeSignature } = accepts;\n const r2 = withinPx === Infinity ? Infinity : withinPx * withinPx;\n\n let best: { anchor: Anchor; d2: number } | null = null;\n for (const a of anchors) {\n const ok = a.accepts.some(acc =>\n (acc.kind === undefined || acc.kind === kind) &&\n (acc.compositeSignature === undefined || acc.compositeSignature === compositeSignature)\n );\n if (!ok) continue;\n\n const d2val = dist2(point, a.position);\n if (d2val <= r2 && (!best || d2val < best.d2)) {\n best = { anchor: a, d2: d2val };\n }\n }\n return best;\n}\n\n/** True if `point` is within `withinPx` of the given anchor. */\nexport function withinAnchor(anchor: Anchor, point: Vec, withinPx: number): boolean {\n const r2 = withinPx * withinPx;\n return dist2(point, anchor.position) <= r2;\n}\n\n// Node-grid helpers for anchor generation\nexport function workspaceNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"workspace\", sector);\n}\n\nexport function silhouetteNodes(layout: CircleLayout, sector: SectorGeom, fittedMask: Poly[]): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n const banded = filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n return filterNodesInPolys(banded, fittedMask);\n}\n\nexport function silhouetteBandNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n}\n\n/** Generate anchor grid nodes for the inner ring (radius < innerR) */\nexport function innerRingNodes(layout: CircleLayout): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.innerR, y: layout.cy - layout.innerR - pad };\n const max = { x: layout.cx + layout.innerR, y: layout.cy + layout.innerR + pad };\n const nodes = gridNodesInAABB(min, max);\n // Filter to nodes within the inner circle\n const out: Vec[] = [];\n for (const n of nodes) {\n const dx = n.x - layout.cx, dy = n.y - layout.cy;\n const r = Math.hypot(dx, dy);\n if (r < layout.innerR) out.push(n);\n }\n return out;\n}\n\nexport const anchorsDiameterToPx = (anchorsDiag: number, gridPx: number = GRID_PX) =>\n anchorsDiag * Math.SQRT2 * gridPx;\n","// src/core/domain/solve.ts\nimport type { LayoutMode, PlacementTarget, Poly } from \"@/core/domain/types\";\nimport { anchorsDiameterToPx } from \"@/core/engine/geometry\";\nimport { CONFIG } from \"@/core/config/config\";\n\n// --- helpers to infer lattice unit and silhouette radius -------------------\nfunction igcd(a: number, b: number) {\n a = Math.round(Math.abs(a)); b = Math.round(Math.abs(b));\n while (b) [a, b] = [b, a % b];\n return a || 1;\n}\nfunction inferUnitFromPolys(polys: Poly[]): number {\n let g = 0;\n for (const poly of polys) {\n for (let i = 0; i < poly.length; i++) {\n const a = poly[i], b = poly[(i + 1) % poly.length];\n if (!a || !b) continue;\n const dx = Math.round(Math.abs(b.x - a.x));\n const dy = Math.round(Math.abs(b.y - a.y));\n if (dx) g = g ? igcd(g, dx) : dx;\n if (dy) g = g ? igcd(g, dy) : dy;\n }\n }\n return g || 1;\n}\nfunction polysAABB(polys: Poly[]) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of polys) for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n const cx = (minX + maxX) / 2, cy = (minY + maxY) / 2;\n return { minX, minY, maxX, maxY, cx, cy };\n}\n\ntype RadiiParams = {\n n: number; // number of outer sectors\n layoutMode: LayoutMode; // \"circle\" | \"semicircle\"\n target: PlacementTarget; // \"workspace\" | \"silhouette\"\n qsMaxSlots: number; // number of quickstash slots on inner ring\n primitivesSlots: number; // number of primitive slots on inner ring\n gridPx?: number; // override GRID_PX (rare)\n reqWorkspaceDiamAnchors?: number; // override default capacity (rare)\n reqQuickstashDiamAnchors?: number; // override default capacity (rare)\n reqPrimitiveDiamAnchors?: number; // override defaults (rare)\n layoutPadPx?: number; // override outer pad (rare)\n masks?: Poly[][]; // raw silhouette polys per sector (for workspace fit calc)\n};\n\nexport type RadiiSolution = {\n innerR_min: number;\n dr_min: number;\n outerR_min: number;\n Tw_min: number; // minimal workspace-band thickness (px) (= required diagonal diameter)\n Tp_min: number; // minimal silhouette-plate thickness (px) (= 2*max silhouette radius or 0)\n Rshape_px_max: number; // max raw-shape radius after canonical unit scaling\n};\n\nexport function solveRadii(params: RadiiParams): RadiiSolution {\n const {\n n,\n layoutMode,\n target,\n qsMaxSlots,\n primitivesSlots,\n gridPx = CONFIG.layout.grid.stepPx,\n reqWorkspaceDiamAnchors = CONFIG.layout.constraints.workspaceDiamAnchors,\n reqQuickstashDiamAnchors = CONFIG.layout.constraints.quickstashDiamAnchors,\n reqPrimitiveDiamAnchors = CONFIG.layout.constraints.primitiveDiamAnchors,\n } = params;\n\n // Canonical lattice scale from raw masks (if provided)\n const allPolys: Poly[] = (params.masks ?? []).flat();\n const rawUnit = allPolys.length ? inferUnitFromPolys(allPolys) : 0;\n const unitScaleS = rawUnit ? (2 * gridPx) / rawUnit : 1;\n\n // Max silhouette radius (px) across all sectors, measured from each sector mask AABB center\n let Rshape_px_max = 0;\n if (params.masks && params.masks.length) {\n for (const sectorPolys of params.masks) {\n if (!sectorPolys?.length) continue;\n const a = polysAABB(sectorPolys);\n const { cx, cy } = a;\n for (const poly of sectorPolys) {\n for (const p of poly) {\n const rx = (p.x - cx) * unitScaleS;\n const ry = (p.y - cy) * unitScaleS;\n const r = Math.hypot(rx, ry);\n if (r > Rshape_px_max) Rshape_px_max = r;\n }\n }\n }\n }\n\n const sweep = layoutMode === \"circle\" ? Math.PI * 2 : Math.PI;\n const dOut = sweep / Math.max(1, n);\n const dIn = sweep / Math.max(1, qsMaxSlots);\n const dPrim = sweep / Math.max(1, primitivesSlots);\n const sinOut = Math.sin(dOut / 2);\n const sinIn = Math.sin(dIn / 2);\n const sinPrim = Math.sin(dPrim / 2);\n\n // Diagonal-based anchor diameters (so \"X anchors\" refers to the 45° lattice)\n const D_ws = anchorsDiameterToPx(reqWorkspaceDiamAnchors, gridPx);\n const D_bp = anchorsDiameterToPx(reqQuickstashDiamAnchors, gridPx);\n const D_prim = anchorsDiameterToPx(reqPrimitiveDiamAnchors, gridPx);\n\n // Inner-ring minimum from chord ≥ required diameter (blueprints + primitives)\n const innerR_min_bp = D_bp * (0.5 + 1 / (2 * Math.max(1e-9, sinIn)));\n const innerR_min_prim = D_prim * (0.5 + 1 / (2 * Math.max(1e-9, sinPrim)));\n const innerR_min_ws = D_ws / (2 * Math.max(1e-9, sinOut)) - D_ws / 2;\n\n const innerR_min = Math.max(innerR_min_bp, innerR_min_prim, innerR_min_ws);\n\n // Component minima: workspace band must be at least D_ws thick; silhouette plate\n // must be thick enough to contain the largest mask radius (both sides).\n const Tw_min = D_ws;\n const Tp_min = target === \"workspace\" ? (2 * Rshape_px_max) : 0;\n const dr_min = Tw_min + Tp_min;\n\n const outerR_min = innerR_min + dr_min;\n\n return { innerR_min, dr_min, outerR_min, Tw_min, Tp_min, Rshape_px_max };\n}\n\nexport function optimizeBandSplit(args: {\n outerRViewportBound: number;\n innerR_min: number;\n Tw_min: number;\n Tp_min: number;\n Rshape_px_max: number;\n D_ws_px: number; // anchorsDiameterToPx(REQ_WORKSPACE_DIAM_ANCHORS)\n}): { innerR: number; Tw: number; Tp: number; outerR: number } {\n const { outerRViewportBound, innerR_min, Tw_min, Tp_min, Rshape_px_max, D_ws_px } = args;\n\n const dr_min = Tw_min + Tp_min;\n\n // If the viewport can’t even accommodate the minima, clamp to the minimal feasible ring.\n if (outerRViewportBound < innerR_min + dr_min) {\n const outerR = innerR_min + dr_min;\n return { innerR: innerR_min, Tw: Tw_min, Tp: Tp_min, outerR };\n }\n\n // Maximize ring thickness by minimizing innerR (this maximizes anchor size everywhere).\n const outerR = outerRViewportBound;\n const innerR = innerR_min;\n const dr = outerR - innerR;\n\n // Distribute slack between bands with a gentle bias towards the silhouette plate\n // when masks have large radial extent (so they don’t look cramped).\n const slack = Math.max(0, dr - dr_min);\n const wWork = 1;\n const wSil = 1 + (Rshape_px_max / Math.max(1e-9, D_ws_px));\n const addWork = slack * (wWork / (wWork + wSil));\n const Tw = Tw_min + addWork;\n const Tp = dr - Tw;\n\n return { innerR, Tw, Tp, outerR };\n}\n\n/**\n * Compute the *logical* SVG viewBox (LOGICAL_W/H) from the minimal feasible\n * outer radius implied by the anchor-capacity constraints. The result ensures\n * lattice density is invariant across devices/zoom levels.\n *\n * NOTE: This should be called prior to computeCircleLayout and the returned\n * width/height must be passed as the viewport to computeCircleLayout so both\n * functions agree on the same bound.\n */\nexport function solveLogicalBox(params: RadiiParams & { layoutPadPx: number }): { LOGICAL_W: number; LOGICAL_H: number } {\n const { layoutMode, layoutPadPx } = params;\n const { outerR_min } = solveRadii(params);\n\n if (layoutMode === \"circle\") {\n const LOGICAL_W = 2 * (outerR_min + layoutPadPx);\n return { LOGICAL_W, LOGICAL_H: LOGICAL_W };\n } else {\n // semicircle: height is half the width; outerR computed against both axes ends up ~W/2\n const LOGICAL_W = 2 * (outerR_min + layoutPadPx);\n return { LOGICAL_W, LOGICAL_H: LOGICAL_W / 2 };\n }\n}","import type { LayoutMode, PlacementTarget, Poly } from \"./types\";\nimport { anchorsDiameterToPx } from \"@/core/engine/geometry\";\nimport { solveRadii, optimizeBandSplit } from \"@/core/domain/solve\";\nimport { CONFIG } from \"@/core/config/config\";\n\nexport type SectorGeom = { id: string; index: number; start: number; end: number; mid: number };\n\nexport type RingBands = {\n silhouette: [number, number];\n workspace: [number, number];\n};\n\nexport type CircleLayout = {\n mode: LayoutMode;\n cx: number; cy: number;\n innerR: number; outerR: number;\n sectors: SectorGeom[];\n bands: RingBands;\n sweepStart: number;\n sweepEnd: number;\n};\n\nexport function computeCircleLayout(\n viewport: { w: number; h: number },\n n: number,\n sectorIds: string[],\n mode: LayoutMode = \"circle\",\n target: PlacementTarget = \"workspace\",\n extras: { qsMaxSlots: number; primitivesSlots: number; masks?: Poly[][] }\n): CircleLayout {\n const pad = CONFIG.layout.paddingPx;\n\n // place the semicircle so its diameter sits on the bottom edge of the SVG\n const cx = viewport.w / 2;\n const cy = mode === \"semicircle\" ? viewport.h : viewport.h / 2;\n\n // The viewport bound must match the viewBox computed by solveLogicalBox so ring sizes stay consistent.\n // vertical radius must not cross the top padding\n const maxRVertical = mode === \"semicircle\" ? (viewport.h - pad) : cy;\n const outerRViewportBound = Math.min(cx, maxRVertical) - pad;\n\n // Solve *minimum* feasible radii and then optimize the band split within the viewport bound\n const sol = solveRadii({\n n,\n layoutMode: mode,\n target,\n qsMaxSlots: extras.qsMaxSlots,\n primitivesSlots: extras.primitivesSlots,\n masks: extras.masks ?? [],\n });\n\n let innerR: number, outerR: number, bands: RingBands;\n\n if (target === \"workspace\") {\n const D_ws_px = anchorsDiameterToPx(CONFIG.layout.constraints.workspaceDiamAnchors);\n const opt = optimizeBandSplit({\n outerRViewportBound,\n innerR_min: sol.innerR_min,\n Tw_min: sol.Tw_min,\n Tp_min: sol.Tp_min,\n Rshape_px_max: sol.Rshape_px_max,\n D_ws_px,\n });\n innerR = opt.innerR;\n outerR = opt.outerR;\n bands = {\n workspace: [opt.innerR, opt.innerR + opt.Tw],\n silhouette: [opt.innerR + opt.Tw, opt.outerR],\n };\n } else {\n // silhouette-only: maximize thickness; entire ring is silhouette\n outerR = Math.max(outerRViewportBound, sol.outerR_min);\n // minimize innerR to maximize thickness, but not below minimal requirement\n innerR = Math.min(sol.innerR_min, outerR);\n if (outerR < sol.outerR_min) { outerR = sol.outerR_min; innerR = sol.innerR_min; }\n bands = { silhouette: [innerR, outerR], workspace: [innerR, outerR] };\n }\n\n const sweep = mode === \"circle\" ? Math.PI * 2 : Math.PI;\n // semicircle: sweep the upper arc by anchoring the diameter on the bottom (π→2π)\n const sweepStart = mode === \"circle\" ? -Math.PI / 2 : Math.PI;\n const sweepEnd = sweepStart + sweep;\n const step = sweep / n;\n\n const sectors: SectorGeom[] = [];\n for (let i = 0; i < n; i++) {\n const id = sectorIds[i] ?? String(i);\n const start = sweepStart + i * step;\n const end = start + step;\n const mid = (start + end) / 2;\n sectors.push({ id, index: i, start, end, mid });\n }\n return { mode, cx, cy, innerR, outerR, sectors, bands, sweepStart, sweepEnd };\n}\n\n/** Ring wedge path helper */\nexport function wedgePath(\n cx: number, cy: number,\n innerR: number, outerR: number,\n start: number, end: number\n): string {\n const largeArc = end - start > Math.PI ? 1 : 0;\n const x0 = cx + innerR * Math.cos(start);\n const y0 = cy + innerR * Math.sin(start);\n const x1 = cx + outerR * Math.cos(start);\n const y1 = cy + outerR * Math.sin(start);\n const x2 = cx + outerR * Math.cos(end);\n const y2 = cy + outerR * Math.sin(end);\n const x3 = cx + innerR * Math.cos(end);\n const y3 = cy + innerR * Math.sin(end);\n return [\n `M ${x0} ${y0}`,\n `L ${x1} ${y1}`,\n `A ${outerR} ${outerR} 0 ${largeArc} 1 ${x2} ${y2}`,\n `L ${x3} ${y3}`,\n `A ${innerR} ${innerR} 0 ${largeArc} 0 ${x0} ${y0}`,\n \"Z\",\n ].join(\" \");\n}\n\n/** Sector hit-test (band optional) */\nexport function sectorAtPoint(\n x: number, y: number, layout: CircleLayout, band?: keyof RingBands\n): string | undefined {\n const dx = x - layout.cx;\n const dy = y - layout.cy;\n const r = Math.hypot(dx, dy);\n\n const [rIn, rOut] = band ? layout.bands[band] : [layout.innerR, layout.outerR];\n if (r < rIn || r > rOut) return undefined;\n\n let theta = Math.atan2(dy, dx); // [-π, +π]\n if (layout.mode === \"circle\") {\n if (theta < -Math.PI / 2) theta += 2 * Math.PI;\n } else {\n // semicircle covers [π, 2π]\n if (theta < Math.PI) theta += 2 * Math.PI;\n }\n\n for (const s of layout.sectors) {\n if (theta >= s.start && theta < s.end) return s.id;\n }\n return layout.sectors.at(-1)?.id;\n}\n\n/** Convenience: axis-aligned rect for fitting silhouettes in a band */\nexport function rectForBand(\n layout: CircleLayout, sector: SectorGeom, band: keyof RingBands, pad = 0.85\n) {\n const [rIn, rOut] = layout.bands[band];\n const rMid = (rIn + rOut) / 2;\n const dr = rOut - rIn;\n const arc = (sector.end - sector.start) * rMid * 0.9;\n const w = arc * pad;\n const h = dr * pad;\n const cx = layout.cx + rMid * Math.cos(sector.mid);\n const cy = layout.cy + rMid * Math.sin(sector.mid);\n return { cx, cy, w, h };\n}","/**\n * Border Rendering Utilities for Edge-Aware Piece Borders\n * \n * This module provides utilities for rendering piece borders with edge-aware logic.\n * Uses the same coordinate system and approach as face-to-face.ts for consistency.\n * Visual polish - hides borders between touching pieces\n */\n\nimport type { Vec, Piece, Blueprint } from \"../../domain/types\";\nimport { CONFIG } from \"../../config/config\";\nimport { boundsOfBlueprint } from \"../geometry\";\n\nexport interface UnitSegment {\n a: Vec;\n b: Vec;\n}\n\n/**\n * Generate SVG path data for individual edge strokes\n * Each edge becomes a separate path element for selective rendering\n */\nexport function generateEdgeStrokePaths(poly: Vec[]): string[] {\n const strokePaths: string[] = [];\n \n for (let i = 0; i < poly.length; i++) {\n const current = poly[i];\n const next = poly[(i + 1) % poly.length];\n \n if (current && next) {\n strokePaths.push(`M ${current.x} ${current.y} L ${next.x} ${next.y}`);\n }\n }\n \n return strokePaths;\n}\n\n/**\n * Convert a polygon edge into unit-length segments\n * Uses the same logic as face-to-face.ts for consistency\n */\nfunction edgeToUnitSegments(start: Vec, end: Vec, gridSize: number): UnitSegment[] {\n const segments: UnitSegment[] = [];\n \n // Convert to grid coordinates\n const startGrid = {\n x: Math.round(start.x / gridSize),\n y: Math.round(start.y / gridSize)\n };\n const endGrid = {\n x: Math.round(end.x / gridSize),\n y: Math.round(end.y / gridSize)\n };\n \n const dx = endGrid.x - startGrid.x;\n const dy = endGrid.y - startGrid.y;\n \n if (dx === 0 && dy === 0) return []; // Zero-length edge\n \n const steps = Math.max(Math.abs(dx), Math.abs(dy));\n const stepX = dx / steps;\n const stepY = dy / steps;\n \n for (let i = 0; i < steps; i++) {\n const aX = Math.round(startGrid.x + i * stepX);\n const aY = Math.round(startGrid.y + i * stepY);\n const bX = Math.round(startGrid.x + (i + 1) * stepX);\n const bY = Math.round(startGrid.y + (i + 1) * stepY);\n segments.push({ \n a: { x: aX, y: aY }, \n b: { x: bX, y: bY } \n });\n }\n \n return segments;\n}\n\n/**\n * Get all unit segments for a piece (same logic as face-to-face.ts)\n * Currently unused - kept for reference\n */\n/*\nfunction getPieceUnitSegments(\n piece: Piece, \n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any,\n gridSize: number\n): UnitSegment[] {\n // Defensive check: if getBlueprint fails, return empty segments\n let blueprint: Blueprint | undefined;\n try {\n blueprint = getBlueprint(piece.blueprintId);\n } catch (error) {\n console.warn('getBlueprint failed in getPieceUnitSegments:', error);\n return [];\n }\n\n if (!blueprint?.shape) return [];\n \n // Calculate offset using same logic as piecePolysAt\n const bb = boundsOfBlueprint(blueprint, getPrimitive);\n const ox = piece.pos.x - bb.min.x;\n const oy = piece.pos.y - bb.min.y;\n \n const allSegments: UnitSegment[] = [];\n \n // Translate polygons and convert edges to unit segments\n for (const poly of blueprint.shape) {\n const translatedPoly = poly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n \n for (let i = 0; i < translatedPoly.length; i++) {\n const current = translatedPoly[i];\n const next = translatedPoly[(i + 1) % translatedPoly.length];\n \n if (!current || !next) continue;\n \n allSegments.push(...edgeToUnitSegments(current, next, gridSize));\n }\n }\n \n return allSegments;\n}\n*/\n\n/**\n * Check which edges should be hidden for a specific polygon within a piece\n * Handles both internal composite edges and external touching between pieces\n */\nexport function getHiddenEdgesForPolygon(\n piece: Piece,\n polyIndex: number,\n allPiecesInSector: Piece[],\n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any\n): boolean[] {\n // Defensive check: if getBlueprint fails, return no hidden edges\n let blueprint: Blueprint | undefined;\n try {\n blueprint = getBlueprint(piece.blueprintId);\n } catch (error) {\n console.warn('getBlueprint failed in getHiddenEdgesForPolygon:', error);\n return [];\n }\n\n if (!blueprint?.shape) {\n return [];\n }\n\n const poly = blueprint.shape[polyIndex];\n if (!poly) return [];\n\n const gridSize = CONFIG.layout.grid.stepPx;\n const bb = boundsOfBlueprint(blueprint, getPrimitive);\n const ox = piece.pos.x - bb.min.x;\n const oy = piece.pos.y - bb.min.y;\n \n const translatedPoly = poly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n\n const hiddenEdges: boolean[] = [];\n\n // For each edge in this polygon\n for (let i = 0; i < translatedPoly.length; i++) {\n const current = translatedPoly[i];\n const next = translatedPoly[(i + 1) % translatedPoly.length];\n \n if (!current || !next) {\n hiddenEdges.push(false);\n continue;\n }\n\n // Get segments for this edge\n const edgeSegments = edgeToUnitSegments(current, next, gridSize);\n \n // Check if any of these segments are touching other pieces\n let isTouching = false;\n \n // 1. Check internal composite edges (if this is a composite)\n if (piece.blueprintId.startsWith('comp:')) {\n // Check against other polygons in the same composite\n for (let otherPolyIndex = 0; otherPolyIndex < blueprint.shape.length; otherPolyIndex++) {\n if (otherPolyIndex === polyIndex) continue; // Skip self\n \n const otherPoly = blueprint.shape[otherPolyIndex];\n if (!otherPoly) continue;\n \n const otherTranslatedPoly = otherPoly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n\n // Check if this edge touches any edge of the other polygon\n for (let j = 0; j < otherTranslatedPoly.length; j++) {\n const otherCurrent = otherTranslatedPoly[j];\n const otherNext = otherTranslatedPoly[(j + 1) % otherTranslatedPoly.length];\n \n if (!otherCurrent || !otherNext) continue;\n\n const otherEdgeSegments = edgeToUnitSegments(otherCurrent, otherNext, gridSize);\n \n // Check if any segments are shared\n for (const edgeSeg of edgeSegments) {\n const isShared = otherEdgeSegments.some(otherSeg => \n // Check if segments share the same endpoints (identical or reversed)\n (edgeSeg.a.x === otherSeg.a.x && edgeSeg.a.y === otherSeg.a.y &&\n edgeSeg.b.x === otherSeg.b.x && edgeSeg.b.y === otherSeg.b.y) ||\n (edgeSeg.a.x === otherSeg.b.x && edgeSeg.a.y === otherSeg.b.y &&\n edgeSeg.b.x === otherSeg.a.x && edgeSeg.b.y === otherSeg.a.y)\n );\n \n if (isShared) {\n isTouching = true;\n break;\n }\n }\n \n if (isTouching) break;\n }\n \n if (isTouching) break;\n }\n }\n \n // 2. Check external touching between different pieces (if not already touching internally)\n // Only check external touching when hideTouchingBorders is true\n if (!isTouching && CONFIG.game.hideTouchingBorders) {\n for (const otherPiece of allPiecesInSector) {\n if (otherPiece.id === piece.id) continue; // Skip self\n \n const otherBlueprint = getBlueprint(otherPiece.blueprintId);\n if (!otherBlueprint?.shape) continue;\n\n const otherBb = boundsOfBlueprint(otherBlueprint, getPrimitive);\n const otherOx = otherPiece.pos.x - otherBb.min.x;\n const otherOy = otherPiece.pos.y - otherBb.min.y;\n\n // Check if this edge touches any edge of the other piece\n for (const otherPoly of otherBlueprint.shape) {\n const otherTranslatedPoly = otherPoly.map((vertex: Vec) => ({\n x: vertex.x + otherOx,\n y: vertex.y + otherOy\n }));\n\n for (let j = 0; j < otherTranslatedPoly.length; j++) {\n const otherCurrent = otherTranslatedPoly[j];\n const otherNext = otherTranslatedPoly[(j + 1) % otherTranslatedPoly.length];\n \n if (!otherCurrent || !otherNext) continue;\n\n const otherEdgeSegments = edgeToUnitSegments(otherCurrent, otherNext, gridSize);\n \n // Check if any segments are shared\n for (const edgeSeg of edgeSegments) {\n const isShared = otherEdgeSegments.some(otherSeg => \n // Check if segments share the same endpoints (identical or reversed)\n (edgeSeg.a.x === otherSeg.a.x && edgeSeg.a.y === otherSeg.a.y &&\n edgeSeg.b.x === otherSeg.b.x && edgeSeg.b.y === otherSeg.b.y) ||\n (edgeSeg.a.x === otherSeg.b.x && edgeSeg.a.y === otherSeg.b.y &&\n edgeSeg.b.x === otherSeg.a.x && edgeSeg.b.y === otherSeg.a.y)\n );\n \n if (isShared) {\n isTouching = true;\n break;\n }\n }\n \n if (isTouching) break;\n }\n \n if (isTouching) break;\n }\n \n if (isTouching) break;\n }\n }\n\n hiddenEdges.push(isTouching);\n }\n\n return hiddenEdges;\n}\n\n/**\n * Check if borders should be shown at all\n * If false, neither primitives nor composites have borders\n */\nexport function shouldShowBorders(): boolean {\n return CONFIG.game.showBorders;\n}\n\n/**\n * Check if touching borders should be hidden\n * Only relevant when showBorders is true\n * - true: All pieces use selective border rendering\n * - false: Only composites use selective border rendering\n */\nexport function shouldHideTouchingBorders(): boolean {\n return CONFIG.game.hideTouchingBorders;\n}\n\n/**\n * Check if a piece should have selective border rendering\n * This determines whether to use edge-aware borders or full borders\n */\nexport function shouldUseSelectiveBorders(blueprintId: string): boolean {\n // Use selective borders if:\n // 1. Borders are enabled globally AND\n // 2. Either hideTouchingBorders is true (ALL pieces) OR this is a composite piece\n return CONFIG.game.showBorders && (\n CONFIG.game.hideTouchingBorders || // If true, ALL pieces use selective borders\n blueprintId.startsWith('comp:') // If false, only composites use selective borders\n );\n}","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsSAAALEgHS3X78AAAFY0lEQVR4nO2d7XXrNgyGH/r0f7zB9QbXnaDqBt6gvhM0I2SE3A2UDXwnqLKBPEHdDewJ0B+kYieWZEoiQfrjPQcnjqOI0GuYAAFQMiJCLjDGLIEFsHQyB/7w/Pd397MCamAnInVgFUfDpCTaGLMACmDlfj4FHuKAJX4DVCKyC3x+b6gTbYyZA2sn31UHhy1QAqWI7FVHFhEVwVpsCUgmUgKF2vUrEVxlQGyXVBqE3zPBqoTHIHhOXlPEUCmBedZEY6OHfQZkTZU9sMqO6Buw4ujWHYLkJXaBkJqUWFIDy6REYx3eLUwVl2TPREc5heR1BgRoy1qV6DsleRLZD5KVyH6QrET2UMeX+uJyE28H6UvykvuILobKHs/Qz4fkObcdJ0+VGo9FzcV8tDGmBP7qPSg+DtgLqrFWBLYSs8C/AhMTbyKy7j3igjWvSPu1LPH4ajo9y4S6ChdyI5emjFTz8isjcgxYC98kNIxOnfuUTmEhk5e6Tvd1IiMpBxFNmlDOy6kMIDtVpNRqKK3O0BhToetk/sPOxZ0FU1cxX2CNAGxFZCc9lW3XvlARvrreh3cRKc7ezcSaOx0e1tH1hZc1PY6INA79zKrbFKuUlXrpccZDdKnomHqwzlXzmqpeotG35l0PyWMWSa3zPGkiqKKP6FJZmXUH0VVIa0pk1WUr0e5T11REaLe+dYwPEOtIk13fqSLPykp0Wd4uwLm7piTtnM1zM/aMI9boovr6hgvHvgU49zdjTNHyvnZ36bp5MYOPGFW74bDtoouA52871y7g+X3w3XH7YdGFsgJwzMKdYh55zCry+dtQwJHoVQIF7gUrSGvR94ICYOYckGYu4N7wZIxZzLDx5QNxsZxh04kPxMUS9JNINfBChB7kS4KNal4JsygaIhtNooNUTwKS/oxeoqky7kVsbB3JujuhLkCzMKBF9O+S0ebKU7il+j+xx5ldPmQyfuZKMoCIVMCv2ONoEP2qMMZUlLEHiD11HEQkdv4iCIwxUafQ2Bad7ZShjd9SK+CLkz3kTQJsQ4o93RMQNX4MFPN2NcN4t816jBE1ltZwhpPgLLmiPdZ9Aip3TNbInmjsdNG3oHhCvww3GDOOd27JFT5FidwLF+8z2ktKD4TFfkb+Idgm0DEpUV8L0Yeevx94ED0dYttyC9rJPmCzgjtFlcagnjkl+ywmOVxSasHn5M8vYJFzwsrhICK7JryrUmriA7cCPCW1vpJVYQXHODr3Oe6asYEj0VU6PW4eFTii3Ty9TajMrWLbOOrTJXiZRJXbRtm8eBAdF2Xz4oNo58HfUmhzo3g7jYq+Zu9KXV0Go+54nSPKT7+1JMArwiW86wiNL2sm3ERKKfF/VvA42zkbus9BREyoc8WC68r/N+Ap/3RtDB84S/y7A4LlqI0xueeKIWx/+PtXkoHzqeOkRpdV3TCmELbpsbWG2Td4yA2QwefUgCS/BLzO185xehSYB/6ksyObsLeX2zHmxihOkdB3Biixqc3UBC8If6eaom9Mn5tXvQJ/9x40HFtsGKmd5pxjHV/oPZU/ReS57wCvp1YYY2r0N3xeC7YicnF7im9fx4rMqzCJcMCz1cGLaDnW7R74jEI865XenUpia3M/xmp0g/ghQ+qViUOia5XBoWoO8ee1yaj1QC7B/rXIKJK94ug+JLqvXAo0jTqjc+CT2nbdwEtuu7C7xSaKphUaAi1pm62/qb/aoWXUzWiDztEdhD8e4aRB9I1YdzArjkr0CeGNo0xNnK9UBNp4pEr0CeFF5oRXXPODIzsILzMgtpFSg+BGHg/3VcLjcdVKSEr0Vzjil4x/AHvTrF5jm3d2wZUcif8BqSLxz8FiAOgAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsSAAALEgHS3X78AAAFYklEQVR4nO1d0ZGjOBB9ct3/+iJYMlg2giODcwjeDCYEbwbeDNgMvBloIjgmAyYDHEHfh4SHsQUIaLVk7FfVNTblkZpHq1u0GqGICKlAKZUDyADkVrYA/vH891f7VwOoANREVDGrOBsqJtFKqQxAAWBn/35h7uIMQ/wJgCaimrl9b4gTrZTaAthb+SbaOfAGoARQElEj2jMRiQiMxZYAKBEpARRi5y9EsE6A2D7REoQ/MsGihIcgeIu0XMRUKQFskyYaZvbQJEDWUmkA7JIjegVWHNy6OUjOYW4QYpMSSioAeVSiYQLeGlzFmDRYGCiXkLxPgABp2YsS/aAkLyL7SbIQ2U+ShcieGvhin1xq4h0gvbJ3Nk+swZ/G9MEZZooFmKlkDB36cIYhezzv7WHJW8jOkxsAR5i7TOfNAszoOgKoBfXqk6pPz0muA3J3fDXmBBkTN2ITXi4i2lqVhKJHH6sYGXXHyGQP5kbGlJe465tsxSPWHYvoZshYYrsMNpITIbvXhfQpWwgo9eJB2AmfR1Vjjw1eoMhkF1OI1oGV0SNxofZoo8aAX7QXJAbRznOLZc1ZDzlzAtqxp60sEtEEh1XHsGanHwNwWNCm0w0h3mLEjVUnYc1M/d4k55GQVUtbQBUwJpx62q4jEV06iYaZN4fu/MafgtfqXKMlFtGEzrx6gw/sER6u5MuOsf1D94tS6gXAV8b2p2J/+dS58hKJo9tovCwIukTbNrXA+YxJ9cl1QC5ouIiONd+VkqzrOgrEQzI1zIFQALgQzeknh5AJ9ZMSdgDELTpzHDsJ9R0LRfshR4TgkNAUTMRPbyA7nL/ZxymuoQV1iIF8A2PRknDFg7W7j3wD+RnHTX9EdIJZUV4r8r8idPqvUmpLtw/rHBH+oscqV9gCskGhgblrY6+o9xWYmHSAfBWsWEenmAQ7CN9C9q5UpJMyNrEDhGsJDlTLdkC8wyTlZR+g9IR9wLRGYN+9Gf/JYhxSJRkArG7H0P1IWPTfKRMNXIo4/wvaB8IS/U5EWcD22aCUCmpwoV1HHbj9u4GEj2aBUmqnlKqUUmSlUkpJpXdZEHJao5mmYEOFNc4Cmhl9BJ9H65SJhl/NR5E40XoDcyuaMnzcwz60EgvRbJD+mp1PGjcLrcRCVPdAtM+IS31U3gXRPosCqS8cVG0gCJUy5Jp1DBX3ONchEwqGDdFHXYdmuGohUQD44zj+B3FrUnyggY8blqSHHhE1RLQD8LNz+CcR7VLPo8Byey8Wfc/QgCWazA6HbxGVWSveLLefch1lFFXWjbL98CQ6LMr2w4VoG1R+x9BmpfjdDdTXadJSVpdVo+x++UQ0EWl87MP8xHy8Wi4vcCX+DyKqzENbOnZG2nP/w/UB5w40SikN/53Ih8C+ZmgXUkHMu50zrhm+ElFx034P0Zyrwo+2Cv7dZQTONUP7w19MHd/Duh6Xjr96R9pANqut4FmavaqRUM1dz3lyZC8Hz7N3FdwO95cJV7MPXyFQCbQAJ/CUg+0HXaTHFefaq6hEQpYN3mrS0ZV4X6W4nqqtYRZS11Qf7bXw4LvBYGbJ5qy4fId8JRN3xf8ZplK2Hvuh93tYJAoB7xDOqZwL3iVhtsEfs1VaH374kgzAz0df+bg9eHzbPct+Mm8zA8ojkz2Z5NlEPzDZs0j2nnX0IfJ2x5Lw3764B4vqo23HOda9sPsGM4Vbli1kuglIYbfbELJoF2AWH91D+PMVThJEr8S62aw4KNEdwttAGZs4X9FgeFWTONEdwovECde45xdH9hBeJkBsK6UEwa08X+4rhOfrqoUQlehrWOJzzH8BewOTN69gEvI1u5Iz8T+TOcUtjzRRXwAAAABJRU5ErkJggg==\"","import React from \"react\";\nimport type { Poly, TanKind, Blueprint, PrimitiveBlueprint } from \"@/core/domain/types\";\nimport { wedgePath, rectForBand, type CircleLayout } from \"@/core/domain/layout\";\nimport { boundsOfBlueprint, placeSilhouetteGridAlignedAsPolys, polysAABB } from \"@/core/engine/geometry\";\nimport { CONFIG } from \"@/core/config/config\";\nimport { generateEdgeStrokePaths, shouldUseSelectiveBorders, shouldShowBorders, getHiddenEdgesForPolygon } from \"@/core/engine/validation/border-rendering\";\n\n// Import lock/unlock icons\nimport lockedIcon from \"@/assets/locked.png\";\nimport unlockedIcon from \"@/assets/unlocked.png\";\n\nexport type PieceView = { id: string; blueprintId: string; x: number; y: number; sectorId?: string };\nexport type AnchorDots = { sectorId: string; valid: {x:number;y:number}[]; invalid: {x:number;y:number}[] };\n\nexport type BoardViewProps = {\n controller: any; // RoundController (kept loose to avoid circular deps here)\n layout: CircleLayout;\n viewBox: { w: number; h: number };\n width?: number;\n height?: number;\n\n // derived visuals/geometry\n badgeR: number;\n badgeCenter: { x: number; y: number };\n placedSilBySector: Map<string, Poly[]>;\n anchorDots: AnchorDots[];\n pieces: PieceView[];\n scaleS: number; // scaling factor for silhouettes\n\n // UI state flags\n clickMode: boolean;\n draggingId: string | null;\n selectedPieceId: string | null;\n dragInvalid: boolean;\n lockedPieceId: string | null;\n showTangramDecomposition?: boolean; // whether to show tangram decomposed into primitives\n usePrimitiveColorsBlueprints?: boolean; // whether to use distinct colors for blueprints in dock\n usePrimitiveColorsTargets?: boolean; // whether to use distinct colors for target tangrams\n primitiveColorIndices?: number[]; // array of 5 integers mapping primitives to color indices\n\n // refs + handlers wired by the container\n svgRef: React.RefObject<SVGSVGElement>;\n setPieceRef: (id: string) => (el: SVGGElement | null) => void;\n onPiecePointerDown: (\n e: React.PointerEvent<SVGPathElement | SVGGElement>,\n p: PieceView\n ) => void;\n onBlueprintPointerDown: (\n e: React.PointerEvent,\n bp: Blueprint,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n ) => void;\n onRootPointerDown: (e: React.PointerEvent<SVGSVGElement>) => void;\n onPointerMove: (e: React.PointerEvent<SVGSVGElement>) => void;\n onPointerUp: () => void;\n onCenterBadgePointerDown: (e: React.PointerEvent) => void;\n};\n\nfunction pathD(poly: Poly) {\n return `M ${poly.map((pt) => `${pt.x} ${pt.y}`).join(\" L \")} Z`;\n}\n\n/**\n * Get the fill color for a piece or blueprint based on its type\n *\n * REQUIRES: blueprint is valid, primitiveColorIndices is an array of 5 valid indices\n * EFFECTS: Returns color based on primitive type if usePrimitiveColors is true,\n * otherwise returns the default color. Composites always use default color.\n */\nfunction getPieceColor(\n blueprint: Blueprint,\n usePrimitiveColors: boolean,\n defaultColor: string,\n primitiveColorIndices: number[]\n): string {\n if (!usePrimitiveColors) {\n return defaultColor;\n }\n\n // For primitive blueprints, use the mapped color from CONFIG\n if ('kind' in blueprint) {\n const kind = blueprint.kind as TanKind;\n // Map primitive kind to index: square=0, smalltriangle=1, parallelogram=2, medtriangle=3, largetriangle=4\n const kindToIndex: Record<TanKind, number> = {\n 'square': 0,\n 'smalltriangle': 1,\n 'parallelogram': 2,\n 'medtriangle': 3,\n 'largetriangle': 4\n };\n const primitiveIndex = kindToIndex[kind];\n if (primitiveIndex !== undefined && primitiveColorIndices[primitiveIndex] !== undefined) {\n const colorIndex = primitiveColorIndices[primitiveIndex];\n const color = CONFIG.color.primitiveColors[colorIndex];\n if (color) {\n return color;\n }\n }\n return defaultColor;\n }\n\n // For composite blueprints, always use the default color\n return defaultColor;\n}\n\nexport default function BoardView(props: BoardViewProps) {\n const {\n controller, layout, viewBox, width, height,\n badgeR, badgeCenter,\n placedSilBySector, anchorDots, pieces, scaleS,\n clickMode, draggingId, selectedPieceId, dragInvalid, lockedPieceId, showTangramDecomposition,\n usePrimitiveColorsBlueprints, usePrimitiveColorsTargets, primitiveColorIndices,\n svgRef, setPieceRef,\n onPiecePointerDown, onBlueprintPointerDown, onRootPointerDown, onPointerMove, onPointerUp, onCenterBadgePointerDown,\n } = props;\n\n const VW = viewBox.w, VH = viewBox.h;\n\n // Helper function to render silhouettes\n const renderSilhouettes = () => layout.sectors.map((s) => {\n const sectorCfg = controller.state.cfg.sectors.find((ss: any) => ss.id === s.id);\n\n // Check if we should render decomposed primitives\n if (showTangramDecomposition && sectorCfg?.silhouette.primitiveDecomposition) {\n const primitiveDecomposition = sectorCfg.silhouette.primitiveDecomposition;\n\n // Use same positioning logic as unified silhouette\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const rawPolys = primitiveDecomposition.map((primInfo: any) => primInfo.polygon);\n const placedPolys = placeSilhouetteGridAlignedAsPolys(rawPolys, scaleS, { cx: rect.cx, cy: rect.cy });\n\n return (\n <g key={`sil-decomposed-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((scaledPoly, i) => {\n // Get color for this primitive based on its kind\n const primInfo = primitiveDecomposition[i];\n let fillColor = CONFIG.color.silhouetteMask;\n\n if (usePrimitiveColorsTargets && primInfo?.kind && primitiveColorIndices) {\n // Map primitive kind to index\n const kindToIndex: Record<TanKind, number> = {\n 'square': 0,\n 'smalltriangle': 1,\n 'parallelogram': 2,\n 'medtriangle': 3,\n 'largetriangle': 4\n };\n const primitiveIndex = kindToIndex[primInfo.kind as TanKind];\n if (primitiveIndex !== undefined && primitiveColorIndices[primitiveIndex] !== undefined) {\n const colorIndex = primitiveColorIndices[primitiveIndex];\n const color = CONFIG.color.primitiveColors[colorIndex];\n if (color) {\n fillColor = color;\n }\n }\n }\n\n return (\n <path\n key={`prim-fill-${i}`}\n d={pathD(scaledPoly)}\n fill={fillColor}\n opacity={CONFIG.opacity.silhouetteMask}\n stroke=\"none\"\n />\n );\n })}\n </g>\n );\n } else {\n // Default: render unified silhouette\n const placedPolys = placedSilBySector.get(s.id) ?? [];\n if (!placedPolys.length) return null;\n return (\n <g key={`sil-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((poly, i) => (\n <path key={i} d={pathD(poly)} fill={CONFIG.color.silhouetteMask} opacity={CONFIG.opacity.silhouetteMask} />\n ))}\n </g>\n );\n }\n });\n\n // Helper function to render pieces (with optional filter)\n const renderPieces = (piecesFilter?: (p: PieceView) => boolean) => {\n const piecesToRender = piecesFilter ? pieces.filter(piecesFilter) : pieces;\n return piecesToRender\n .sort((a, b) => {\n // Sort so that dragged piece is rendered last (on top)\n if (draggingId === a.id) return 1;\n if (draggingId === b.id) return -1;\n return 0;\n })\n .map((p) => {\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, (k: string) => controller.getPrimitive(k as TanKind)!);\n const isDragging = draggingId === p.id;\n const locked = p.sectorId && controller.isSectorCompleted(p.sectorId);\n const isConnectivityLocked = lockedPieceId === p.id;\n const isSelected = selectedPieceId === p.id;\n const isCarriedInvalid = isDragging && dragInvalid;\n const translateX = p.x - bb.min.x;\n const translateY = p.y - bb.min.y;\n\n const validFillColor = getPieceColor(\n bp,\n usePrimitiveColorsBlueprints || false,\n CONFIG.color.piece.validFill,\n primitiveColorIndices || [0, 1, 2, 3, 4]\n );\n const draggingFillColor = getPieceColor(\n bp,\n usePrimitiveColorsBlueprints || false,\n CONFIG.color.piece.draggingFill,\n primitiveColorIndices || [0, 1, 2, 3, 4]\n );\n\n return (\n <g key={p.id} ref={setPieceRef(p.id)} transform={`translate(${translateX}, ${translateY})`} style={{ cursor: locked ? \"default\" : clickMode ? \"pointer\" : \"grab\" }} pointerEvents={clickMode && isDragging ? \"none\" : \"auto\"}>\n {(\"shape\" in bp ? bp.shape : []).map((poly: any, idx: number) => {\n const showBorders = shouldShowBorders();\n const useSelectiveBorders = shouldUseSelectiveBorders(p.blueprintId);\n return (\n <React.Fragment key={idx}>\n {/* Fill path - always rendered with no borders */}\n <path\n d={pathD(poly)}\n fill={isConnectivityLocked ? CONFIG.color.piece.invalidFill : (isCarriedInvalid ? CONFIG.color.piece.invalidFill : (isDragging ? draggingFillColor : validFillColor))}\n opacity={isConnectivityLocked ? CONFIG.opacity.piece.invalid : (isCarriedInvalid ? CONFIG.opacity.piece.invalid : (isDragging ? CONFIG.opacity.piece.dragging : (locked ? CONFIG.opacity.piece.locked : CONFIG.opacity.piece.normal)))}\n stroke=\"none\"\n onPointerDown={(e) => onPiecePointerDown(e, p)}\n />\n\n {/* Border paths - only rendered if borders are enabled */}\n {showBorders && (\n useSelectiveBorders ? (\n // For pieces with selective borders: render individual edge strokes with edge detection\n (() => {\n const allPiecesInSector = pieces.filter(piece => piece.sectorId === p.sectorId);\n const pieceAsPiece = { ...p, pos: { x: p.x, y: p.y } };\n const allPiecesAsPieces = allPiecesInSector.map(piece => ({ ...piece, pos: { x: piece.x, y: piece.y } }));\n const hiddenEdges = getHiddenEdgesForPolygon(pieceAsPiece, idx, allPiecesAsPieces, (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind));\n\n // Check if this piece's edges were hidden due to touching the dragged piece\n const draggedPiece = draggingId ? allPiecesInSector.find(piece => piece.id === draggingId) : null;\n\n // For composites, we need to distinguish between internal edges (always hidden) and external edges (shown when dragging)\n let wasTouchingDraggedPiece: boolean[];\n if (p.blueprintId.startsWith('comp:')) {\n // For composites, check internal edges separately from external edges\n const internalHiddenEdges = getHiddenEdgesForPolygon(pieceAsPiece, idx, [], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind));\n const externalHiddenEdges = draggedPiece ?\n getHiddenEdgesForPolygon(pieceAsPiece, idx, [{ ...draggedPiece, pos: { x: draggedPiece.x, y: draggedPiece.y } }], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind)) :\n new Array(hiddenEdges.length).fill(false);\n\n // Only consider external edges as \"touching dragged piece\"\n wasTouchingDraggedPiece = externalHiddenEdges.map((external, i) => external && !internalHiddenEdges[i]);\n } else {\n // For primitives, all hidden edges are external\n wasTouchingDraggedPiece = draggedPiece ?\n getHiddenEdgesForPolygon(pieceAsPiece, idx, [{ ...draggedPiece, pos: { x: draggedPiece.x, y: draggedPiece.y } }], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind)) :\n new Array(hiddenEdges.length).fill(false);\n }\n\n return generateEdgeStrokePaths(poly).map((strokePath, strokeIdx) => {\n // Show border if: 1) it wasn't hidden originally, OR 2) it was hidden due to touching the dragged piece\n const wasHiddenDueToDraggedPiece = wasTouchingDraggedPiece[strokeIdx] || false;\n\n // Special case: if this piece is being dragged and it's a composite, keep internal edges hidden\n let isHidden: boolean;\n if (isDragging && p.blueprintId.startsWith('comp:')) {\n // For dragged composites, only show external edges (not internal ones)\n const internalHiddenEdges = getHiddenEdgesForPolygon(pieceAsPiece, idx, [], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind));\n isHidden = internalHiddenEdges[strokeIdx] || false;\n } else {\n // Normal logic for non-dragged pieces or primitives\n isHidden = isDragging ? false : ((hiddenEdges[strokeIdx] || false) && !wasHiddenDueToDraggedPiece);\n }\n\n return (\n <path\n key={`stroke-${idx}-${strokeIdx}`}\n d={strokePath}\n fill=\"none\"\n stroke={isHidden ? \"none\" : (isConnectivityLocked ? CONFIG.color.piece.invalidStroke : (isCarriedInvalid ? CONFIG.color.piece.invalidStroke : (isSelected || isDragging ? CONFIG.color.piece.selectedStroke : CONFIG.color.piece.borderStroke)))}\n strokeWidth={isHidden ? 0 : ((isSelected || isDragging) ? CONFIG.size.stroke.pieceSelectedPx : CONFIG.size.stroke.pieceBorderPx)}\n onPointerDown={(e) => onPiecePointerDown(e, p)}\n />\n );\n });\n })()\n ) : (\n // For primitives or composites without selective borders: render full border\n <path\n d={pathD(poly)}\n fill=\"none\"\n stroke={isConnectivityLocked ? CONFIG.color.piece.invalidStroke : (isCarriedInvalid ? CONFIG.color.piece.invalidStroke : (isSelected || isDragging ? CONFIG.color.piece.selectedStroke : CONFIG.color.piece.borderStroke))}\n strokeWidth={(isSelected || isDragging) ? CONFIG.size.stroke.pieceSelectedPx : CONFIG.size.stroke.pieceBorderPx}\n onPointerDown={(e) => onPiecePointerDown(e, p)}\n />\n )\n )}\n </React.Fragment>\n );\n })}\n\n {/* Invalid marker 'X' - shown at piece center when dragging invalid piece */}\n {isDragging && isCarriedInvalid && \"shape\" in bp && bp.shape.length > 0 && (() => {\n const { cx, cy } = polysAABB(bp.shape);\n const size = CONFIG.size.invalidMarker.sizePx;\n const strokeWidth = CONFIG.size.invalidMarker.strokePx;\n const borderWidth = strokeWidth + 2;\n\n return (\n <g key=\"invalid-marker\">\n {/* White border for first line */}\n <line\n x1={cx - size}\n y1={cy - size}\n x2={cx + size}\n y2={cy + size}\n stroke=\"white\"\n strokeWidth={borderWidth}\n strokeLinecap=\"round\"\n />\n {/* Red interior for first line */}\n <line\n x1={cx - size}\n y1={cy - size}\n x2={cx + size}\n y2={cy + size}\n stroke={CONFIG.color.piece.invalidStroke}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n />\n {/* White border for second line */}\n <line\n x1={cx + size}\n y1={cy - size}\n x2={cx - size}\n y2={cy + size}\n stroke=\"white\"\n strokeWidth={borderWidth}\n strokeLinecap=\"round\"\n />\n {/* Red interior for second line */}\n <line\n x1={cx + size}\n y1={cy - size}\n x2={cx - size}\n y2={cy + size}\n stroke={CONFIG.color.piece.invalidStroke}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n />\n </g>\n );\n })()}\n </g>\n );\n });\n };\n\n // blueprint ring geometry\n const centerView = controller.state.blueprintView;\n const bps: Blueprint[] =\n centerView === \"primitives\"\n ? (controller.state.primitives as PrimitiveBlueprint[])\n : (controller.state.quickstash as Blueprint[]);\n\n const QS_SLOTS = controller.state.cfg.maxQuickstashSlots;\n const PRIM_SLOTS = controller.state.primitives.length;\n const slotsForView = centerView === \"primitives\" ? Math.max(1, PRIM_SLOTS) : Math.max(1, QS_SLOTS);\n const sweep = layout.mode === \"circle\" ? Math.PI * 2 : Math.PI;\n const delta = sweep / slotsForView;\n\n const start = layout.mode === \"circle\" ? -Math.PI / 2 : Math.PI;\n const blueprintTheta = (i: number) => start + (i + 0.5) * delta;\n\n // chord requirement (reuse same logic as container already used for radii)\n const anchorsDiameterToPx = (anchorsDiag: number, gridPx: number = CONFIG.layout.grid.stepPx) =>\n anchorsDiag * Math.SQRT2 * gridPx;\n const reqAnchors = centerView === \"primitives\"\n ? CONFIG.layout.constraints.primitiveDiamAnchors\n : CONFIG.layout.constraints.quickstashDiamAnchors;\n const D_slot = anchorsDiameterToPx(reqAnchors);\n const R_needed = D_slot / (2 * Math.max(1e-9, Math.sin(delta / 2)));\n\n // Minimum radius to avoid overlapping with badge\n // Badge takes up: badgeR + margin, plus we need half the slot diameter for clearance\n const R_min = badgeR + CONFIG.size.centerBadge.marginPx + D_slot / 2;\n const ringMax = layout.innerR - (badgeR + CONFIG.size.centerBadge.marginPx);\n\n // Clamp to [R_min, ringMax]\n const blueprintRingR = Math.min(Math.max(R_needed, R_min), ringMax);\n\n const renderBlueprintGlyph = (bp: Blueprint, bx: number, by: number) => {\n const bb = boundsOfBlueprint(bp, (k: string) => controller.getPrimitive(k as TanKind)!);\n const cx = bb.min.x + bb.width / 2;\n const cy = bb.min.y + bb.height / 2;\n const selected = false; // container highlights via pending state; optional\n\n const fillColor = getPieceColor(\n bp,\n usePrimitiveColorsBlueprints || false,\n CONFIG.color.blueprint.fill,\n primitiveColorIndices || [0, 1, 2, 3, 4]\n );\n\n return (\n <g\n key={bp.id}\n transform={`translate(${bx}, ${by}) scale(1) translate(${-cx}, ${-cy})`}\n >\n {(\"shape\" in bp ? bp.shape : []).map((poly, idx) => (\n <path\n key={idx}\n d={pathD(poly)}\n fill={fillColor}\n opacity={CONFIG.opacity.blueprint}\n stroke={selected ? CONFIG.color.blueprint.selectedStroke : \"none\"}\n strokeWidth={selected ? 2 : 0}\n pointerEvents=\"visiblePainted\"\n style={{ cursor: \"pointer\" }}\n onPointerDown={(e) => onBlueprintPointerDown(e as any, bp, { bx, by, cx, cy })}\n />\n ))}\n </g>\n );\n };\n\n return (\n <svg\n ref={svgRef}\n width={width}\n height={height}\n viewBox={`0 0 ${VW} ${VH}`}\n preserveAspectRatio=\"xMidYMid meet\"\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerDown={(e) => {\n onRootPointerDown(e);\n }}\n style={{ background: CONFIG.color.background, touchAction: \"none\", userSelect: \"none\" }}\n >\n {/* bands as wedges */}\n {layout.sectors.map((s, i) => {\n const done = !!controller.state.sectors[s.id].completedAt;\n const baseSil = i % 2 ? CONFIG.color.bands.silhouette.fillOdd : CONFIG.color.bands.silhouette.fillEven;\n const baseWork = i % 2 ? CONFIG.color.bands.workspace.fillOdd : CONFIG.color.bands.workspace.fillEven;\n const sil = layout.bands.silhouette;\n const work = layout.bands.workspace;\n return (\n <g key={`bands-${s.id}`}>\n {controller.state.cfg.target === \"workspace\" ? (\n <>\n <path d={wedgePath(layout.cx, layout.cy, sil[0], sil[1], s.start, s.end)} fill={baseSil} stroke={CONFIG.color.bands.silhouette.stroke} strokeWidth={CONFIG.size.stroke.bandPx} pointerEvents=\"none\" />\n <path d={wedgePath(layout.cx, layout.cy, work[0], work[1], s.start, s.end)} fill={done ? CONFIG.color.completion.fill : baseWork} stroke={done ? CONFIG.color.completion.stroke : CONFIG.color.bands.workspace.stroke} strokeWidth={CONFIG.size.stroke.bandPx} pointerEvents=\"none\" />\n </>\n ) : (\n <path d={wedgePath(layout.cx, layout.cy, sil[0], sil[1], s.start, s.end)} fill={done ? CONFIG.color.completion.fill : baseSil} stroke={done ? CONFIG.color.completion.stroke : CONFIG.color.bands.silhouette.stroke} strokeWidth={CONFIG.size.stroke.bandPx} pointerEvents=\"none\" />\n )}\n </g>\n );\n })}\n\n\n {/* Conditional rendering based on silhouettesBelowPieces config */}\n {CONFIG.game.silhouettesBelowPieces ? (\n <>\n {/* Render silhouettes first (below all pieces) */}\n {renderSilhouettes()}\n\n {/* Then all pieces */}\n {renderPieces()}\n </>\n ) : (\n <>\n {/* Render all pieces first */}\n {renderPieces()}\n\n {/* Then silhouettes (above all pieces) */}\n {renderSilhouettes()}\n </>\n )}\n\n {/* silhouettes (use pre-placed polys) - rendered first so pieces appear on top */}\n {layout.sectors.map((s) => {\n const sectorCfg = controller.state.cfg.sectors.find((ss: any) => ss.id === s.id);\n\n // Check if we should render decomposed primitives\n if (showTangramDecomposition && sectorCfg?.silhouette.primitiveDecomposition) {\n const primitiveDecomposition = sectorCfg.silhouette.primitiveDecomposition;\n\n // Use same positioning logic as unified silhouette\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const rawPolys = primitiveDecomposition.map((primInfo: any) => primInfo.polygon);\n const placedPolys = placeSilhouetteGridAlignedAsPolys(rawPolys, scaleS, { cx: rect.cx, cy: rect.cy });\n\n return (\n <g key={`sil-decomposed-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((scaledPoly, i) => {\n // Get color for this primitive based on its kind\n const primInfo = primitiveDecomposition[i];\n let fillColor = CONFIG.color.silhouetteMask;\n\n if (usePrimitiveColorsTargets && primInfo?.kind && primitiveColorIndices) {\n // Map primitive kind to index\n const kindToIndex: Record<TanKind, number> = {\n 'square': 0,\n 'smalltriangle': 1,\n 'parallelogram': 2,\n 'medtriangle': 3,\n 'largetriangle': 4\n };\n const primitiveIndex = kindToIndex[primInfo.kind as TanKind];\n if (primitiveIndex !== undefined && primitiveColorIndices[primitiveIndex] !== undefined) {\n const colorIndex = primitiveColorIndices[primitiveIndex];\n const color = CONFIG.color.primitiveColors[colorIndex];\n if (color) {\n fillColor = color;\n }\n }\n }\n\n return (\n <path\n key={`prim-fill-${i}`}\n d={pathD(scaledPoly)}\n fill=\"none\"\n opacity={0}\n stroke=\"none\"\n />\n );\n })}\n </g>\n );\n } else {\n // Default: render unified silhouette\n const placedPolys = placedSilBySector.get(s.id) ?? [];\n if (!placedPolys.length) return null;\n return (\n <g key={`sil-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((poly, i) => (\n <path key={i} d={pathD(poly)} fill={CONFIG.color.silhouetteMask} opacity={CONFIG.opacity.silhouetteMask} />\n ))}\n </g>\n );\n }\n })}\n\n {/* anchor grid */}\n {anchorDots.map(({ sectorId, valid, invalid }) => {\n const isInnerRing = sectorId === \"inner-ring\";\n return (\n <g key={`anchors-${sectorId}`} pointerEvents=\"none\">\n {invalid.map((p, i) => (\n <circle key={`inv-${i}`} cx={p.x} cy={p.y} r={CONFIG.size.anchorRadiusPx.invalid} fill={CONFIG.color.anchors.invalid} opacity={CONFIG.opacity.anchors.invalid} />\n ))}\n {valid.map((p, i) => (\n <circle\n key={`val-${i}`}\n cx={p.x}\n cy={p.y}\n r={isInnerRing ? CONFIG.size.anchorRadiusPx.invalid : CONFIG.size.anchorRadiusPx.valid}\n fill={isInnerRing ? CONFIG.color.anchors.invalid : CONFIG.color.anchors.valid}\n opacity={isInnerRing ? CONFIG.opacity.anchors.invalid : CONFIG.opacity.anchors.valid}\n />\n ))}\n </g>\n );\n })}\n\n {/* SVG filter for inverting icon colors to white */}\n <defs>\n <filter id=\"invert-to-white\">\n <feColorMatrix\n type=\"matrix\"\n values=\"-1 0 0 0 1\n 0 -1 0 0 1\n 0 0 -1 0 1\n 0 0 0 1 0\"\n />\n </filter>\n </defs>\n\n {/* center badge */}\n {(() => {\n const isPrep = controller.state.cfg.mode === \"prep\";\n const isSubmitEnabled = isPrep ? controller.isSubmitEnabled() : true;\n const isClickable = !draggingId && (!isPrep || isSubmitEnabled);\n const [imageError, setImageError] = React.useState(false);\n\n // Size the image to fill most of the badge (80% of diameter)\n const iconSize = badgeR * 1.6;\n const iconOffset = iconSize / 2;\n\n return (\n <g transform={`translate(${badgeCenter.x}, ${badgeCenter.y})`}\n style={{ cursor: isClickable ? \"pointer\" : \"default\" }}\n onPointerDown={isClickable ? onCenterBadgePointerDown : undefined}>\n <circle r={badgeR}\n fill={isSubmitEnabled ? CONFIG.color.blueprint.badgeFill : \"#ccc\"}\n opacity={isSubmitEnabled ? 1.0 : 0.5} />\n {isPrep ? (\n <text textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize={CONFIG.size.badgeFontPx}\n fill={isSubmitEnabled ? CONFIG.color.blueprint.labelFill : \"#888\"}\n pointerEvents=\"none\">\n Submit\n </text>\n ) : imageError ? (\n <text textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize={CONFIG.size.badgeFontPx}\n fill={CONFIG.color.blueprint.labelFill}\n pointerEvents=\"none\">\n inventory\n </text>\n ) : (\n <image\n href={controller.state.blueprintView === \"quickstash\" ? lockedIcon : unlockedIcon}\n x={-iconOffset}\n y={-iconOffset}\n width={iconSize}\n height={iconSize}\n pointerEvents=\"none\"\n onError={() => setImageError(true)}\n filter=\"url(#invert-to-white)\"\n />\n )}\n </g>\n );\n })()}\n\n {/* blueprint glyphs */}\n {bps.map((bp: any, i: number) => {\n const theta = blueprintTheta(i);\n const bx = layout.cx + blueprintRingR * Math.cos(theta);\n const by = layout.cy + blueprintRingR * Math.sin(theta);\n return renderBlueprintGlyph(bp, bx, by);\n })}\n\n\n {/* all green pulse */}\n {controller.state.endedAt && (\n <g pointerEvents=\"none\">\n <circle cx={layout.cx} cy={layout.cy} r={layout.outerR - 3} fill=\"none\" stroke={CONFIG.color.piece.allGreenStroke} strokeWidth={CONFIG.size.stroke.allGreenStrokePx} opacity={0}>\n <animate attributeName=\"opacity\" from=\"0\" to=\"1\" dur=\"160ms\" fill=\"freeze\" />\n <animate attributeName=\"opacity\" from=\"1\" to=\"0\" begin=\"560ms\" dur=\"520ms\" fill=\"freeze\" />\n </circle>\n </g>\n )}\n\n {/* tangram decomposition borders - rendered last so they appear on top of pieces */}\n {showTangramDecomposition && layout.sectors.map((s) => {\n const sectorCfg = controller.state.cfg.sectors.find((ss: any) => ss.id === s.id);\n if (!sectorCfg?.silhouette.primitiveDecomposition) return null;\n\n const primitiveDecomposition = sectorCfg.silhouette.primitiveDecomposition;\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const rawPolys = primitiveDecomposition.map((primInfo: any) => primInfo.polygon);\n const placedPolys = placeSilhouetteGridAlignedAsPolys(rawPolys, scaleS, { cx: rect.cx, cy: rect.cy });\n\n return (\n <g key={`sil-borders-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((scaledPoly, i) => (\n <path\n key={`prim-border-${i}`}\n d={pathD(scaledPoly)}\n fill=\"none\"\n stroke={CONFIG.color.tangramDecomposition.stroke}\n strokeWidth={CONFIG.size.stroke.tangramDecompositionPx}\n />\n ))}\n </g>\n );\n })}\n </svg>\n );\n}","// core/validate/complete.ts\nimport type { Poly, Vec } from \"@/core/domain/types\";\nimport { pointInPolygon } from \"@/core/engine/geometry\";\nimport { CONFIG } from \"@/core/config/config\";\n\n/** AABB of one or more polys */\nfunction aabb(polys: Poly[]) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of polys) for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { minX, minY, maxX, maxY };\n}\n\n/** Cell centers over an AABB, aligned to GRID_PX centers (k + GRID_PX/2). */\nfunction cellCentersInAABB(minX: number, minY: number, maxX: number, maxY: number): Vec[] {\n const GRID_PX = CONFIG.layout.grid.stepPx;\n const x0 = Math.floor((minX - GRID_PX/2) / GRID_PX) * GRID_PX + GRID_PX/2;\n const y0 = Math.floor((minY - GRID_PX/2) / GRID_PX) * GRID_PX + GRID_PX/2;\n const out: Vec[] = [];\n for (let y = y0; y <= maxY; y += GRID_PX) {\n for (let x = x0; x <= maxX; x += GRID_PX) out.push({ x, y });\n }\n return out;\n}\n\n/** Build a set of grid centers that lie inside ANY of the polygons. */\nexport function cellSetForPolys(polys: Poly[]): Set<string> {\n if (!polys.length) return new Set();\n const { minX, minY, maxX, maxY } = aabb(polys);\n const centers = cellCentersInAABB(minX, minY, maxX, maxY);\n const key = (p: Vec) => `${p.x},${p.y}`;\n const S = new Set<string>();\n center: for (const c of centers) {\n for (const poly of polys) {\n if (pointInPolygon(c, poly)) { S.add(key(c)); continue center; }\n }\n }\n return S;\n}\n\n/** Anchors | Silhouette: complete iff silhouette cell set ⊆ piece cell set. */\nexport function anchorsSilhouetteComplete(silPolys: Poly[], piecePolys: Poly[]): boolean {\n if (!silPolys.length) return false;\n const S = cellSetForPolys(silPolys);\n if (S.size === 0) return false;\n const P = cellSetForPolys(piecePolys);\n if (P.size === 0) return false;\n for (const k of S) if (!P.has(k)) return false;\n return true;\n}\n\n// --- helpers for translation-invariant equality on the grid -----------------\nfunction stringSetToVecs(S: Set<string>): Vec[] {\n const out: Vec[] = [];\n for (const k of S) {\n const [xs, ys] = k.split(\",\");\n out.push({ x: Number(xs), y: Number(ys) });\n }\n return out;\n}\n\nfunction normalizeCells(S: Set<string>): Set<string> {\n if (S.size === 0) return S;\n const pts = stringSetToVecs(S);\n let minX = Infinity,\n minY = Infinity;\n for (const p of pts) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n }\n const N = new Set<string>();\n for (const p of pts) N.add(`${p.x - minX},${p.y - minY}`);\n return N;\n}\n\nfunction setsEqual(a: Set<string>, b: Set<string>): boolean {\n if (a.size !== b.size) return false;\n for (const k of a) if (!b.has(k)) return false;\n return true;\n}\n\n/**\n * Anchors | Workspace:\n * complete iff the pieces form the sector's silhouette pattern up to a GRID_PX translation.\n * (No rotation/mirror; exact coverage — no extra cells.)\n */\nexport function anchorsWorkspaceComplete(\n silPolys: Poly[],\n piecePolys: Poly[]\n): boolean {\n if (!silPolys.length) return false;\n const Sraw = cellSetForPolys(silPolys);\n const Praw = cellSetForPolys(piecePolys);\n if (Sraw.size === 0 || Praw.size === 0) return false;\n const S = normalizeCells(Sraw);\n const P = normalizeCells(Praw);\n return setsEqual(S, P);\n}","import type { Poly } from \"@/core/domain/types\";\n\n/**\n * Board Component Utilities\n * \n * This module provides utility functions used by board interaction hooks.\n * These functions handle coordinate transformations and geometric operations\n * needed for blueprint interaction and polygon scaling.\n */\n\n/**\n * Convert world coordinates to blueprint local coordinates\n * \n * When a user clicks on a blueprint glyph in the blueprint ring, this function\n * converts the world click coordinates to local coordinates within the blueprint's\n * coordinate system. This is needed to maintain the clicked point under the cursor\n * when spawning and dragging new pieces.\n * \n * @param px - World X coordinate (SVG space)\n * @param py - World Y coordinate (SVG space) \n * @param bpGeom - Blueprint geometry information\n * @param bpGeom.bx - Blueprint center X in world space\n * @param bpGeom.by - Blueprint center Y in world space\n * @param bpGeom.cx - Blueprint local center X\n * @param bpGeom.cy - Blueprint local center Y\n * @returns Local coordinates within the blueprint's coordinate system\n * \n * @example\n * ```typescript\n * const localPoint = blueprintLocalFromWorld(100, 200, {\n * bx: 50, by: 50, // Blueprint is rendered at (50, 50) in world space\n * cx: 25, cy: 25 // Blueprint's local center is at (25, 25)\n * });\n * // Result: { x: 75, y: 175 } - point in blueprint's local coordinate system\n * ```\n */\nexport function blueprintLocalFromWorld(\n px: number,\n py: number,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n) {\n return { x: px - bpGeom.bx + bpGeom.cx, y: py - bpGeom.by + bpGeom.cy };\n}\n\n/**\n * Scale polygons by factor S about the origin (no translation/snapping)\n * \n * This function scales polygon coordinates by a factor S around the origin (0,0).\n * Used for scaling silhouette masks and other geometric shapes when computing\n * layouts with different scaling factors. The scaling is uniform (same factor\n * for both X and Y axes).\n * \n * @param polys - Array of polygons to scale\n * @param S - Scale factor (1.0 = no change, 0.5 = half size, 2.0 = double size)\n * @returns New array of scaled polygons (original polygons are not modified)\n * \n * @example\n * ```typescript\n * const originalPolys = [[\n * { x: 10, y: 10 },\n * { x: 20, y: 10 }, \n * { x: 15, y: 20 }\n * ]];\n * \n * const scaledPolys = scalePolys(originalPolys, 2.0);\n * // Result: [[\n * // { x: 20, y: 20 },\n * // { x: 40, y: 20 },\n * // { x: 30, y: 40 }\n * // ]]\n * ```\n */\nexport function scalePolys(polys: Poly[], S: number): Poly[] {\n if (!polys || polys.length === 0) return [];\n return polys.map(poly => poly.map(p => ({ x: S * p.x, y: S * p.y })));\n}","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { Poly } from \"@/core/domain/types\";\nimport { boundsOfBlueprint, piecePolysAt } from \"@/core/engine/geometry\";\n\n/**\n * Piece data interface used throughout the hook system\n * \n * Represents a tangram piece instance with position and blueprint information.\n * This is the normalized interface used across all board components.\n */\nexport interface PieceData {\n /** Unique identifier for this piece instance */\n id: string;\n \n /** ID of the blueprint that defines this piece's shape */\n blueprintId: string;\n \n /** X coordinate of the piece's top-left position in SVG space */\n x: number;\n \n /** Y coordinate of the piece's top-left position in SVG space */\n y: number;\n \n /** ID of the sector containing this piece (undefined if floating) */\n sectorId?: string;\n}\n\n/**\n * Return interface for usePieceState hook\n * \n * Provides normalized piece data and computed polygon functions for collision\n * detection and rendering. All functions are memoized for optimal performance.\n */\nexport interface PieceStateHook {\n /** Array of all pieces from all sectors plus floating pieces */\n pieces: PieceData[];\n \n /** \n * Lookup function to find a piece by its ID\n * @param id - Piece ID to lookup (null-safe)\n * @returns PieceData or null if not found\n */\n pieceById: (id: string | null) => PieceData | null;\n \n /** \n * Compute world polygons for all pieces in a sector (live/no cache)\n * @param sectorId - Target sector ID\n * @returns Array of world-space polygons\n */\n sectorPiecePolysLive: (sectorId: string) => Poly[];\n \n /** \n * Cached version of sectorPiecePolysLive with signature-based invalidation\n * @param sectorId - Target sector ID \n * @returns Cached array of world-space polygons\n */\n getSectorPiecePolysCached: (sectorId: string) => Poly[];\n}\n\n/**\n * Hook for managing piece data and computed polygon states\n * \n * This hook provides normalized access to piece data from the BaseGameController,\n * combining pieces from sectors and floating state into a unified interface.\n * It also provides optimized polygon computation functions for collision detection.\n * \n * ## Key Features\n * - **Unified piece access**: Combines sector and floating pieces\n * - **Polygon caching**: Optimized collision detection with signature-based cache\n * - **Live updates**: Reactively updates when controller state changes\n * - **Null-safe lookups**: Safe piece retrieval by ID\n * \n * ## Performance\n * - Pieces array is memoized based on controller.updateCount\n * - Polygon cache uses sector \"signature\" (piece positions) for invalidation\n * - Live polygon computation bypasses cache for real-time operations\n * \n * @param controller - BaseGameController instance managing game state\n * @returns Hook interface with piece data and polygon functions\n * \n * @example\n * ```typescript\n * const pieceState = usePieceState(controller);\n * const allPieces = pieceState.pieces;\n * const piece = pieceState.pieceById(\"piece_123\");\n * const sectorPolygons = pieceState.sectorPiecePolysLive(\"sector_1\");\n * ```\n */\nexport function usePieceState(controller: BaseGameController): PieceStateHook {\n // --- pieces ---------------------------------------------------------------\n const pieces = React.useMemo(() => {\n const out: PieceData[] = [];\n for (const s of Object.values(controller.state.sectors)) {\n for (const p of s.pieces) {\n out.push({\n id: p.id,\n blueprintId: p.blueprintId,\n x: p.pos.x,\n y: p.pos.y,\n sectorId: s.sectorId\n });\n }\n }\n const floating: any = (controller as any)._floating;\n if (floating?.pieces) {\n for (const p of floating.pieces) {\n out.push({\n id: p.id,\n blueprintId: p.blueprintId,\n x: p.pos.x,\n y: p.pos.y\n });\n }\n }\n return out;\n }, [controller.state.sectors, (controller as any)._floating, controller.updateCount]);\n\n const pieceById = React.useCallback(\n (id: string | null) => (id ? pieces.find(p => p.id === id) ?? null : null),\n [pieces]\n );\n\n // --- LIVE sector polys (reads controller.state directly) -----------------\n const sectorPiecePolysLive = React.useCallback(\n (sectorId: string): Poly[] => {\n const out: Poly[] = [];\n const ss = controller.state.sectors[sectorId];\n if (!ss) return out;\n for (const p of ss.pieces) {\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n out.push(...piecePolysAt(bp, bb, { x: p.pos.x, y: p.pos.y }));\n }\n return out;\n },\n [controller]\n );\n\n // --- OPTIONAL: cached variant keyed by a sector \"signature\" --------------\n // Sig = pieceId@x,y;... (order-insensitive)\n const polyCacheRef = React.useRef(\n new Map<string, { sig: string; polys: Poly[] }>()\n );\n\n const sectorSignature = React.useCallback(\n (sectorId: string): string => {\n const ss = controller.state.sectors[sectorId];\n if (!ss) return \"\";\n // stable order by id\n const parts = ss.pieces\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : 1))\n .map(p => `${p.id}@${p.pos.x},${p.pos.y}`);\n return parts.join(\"|\");\n },\n [controller.state.sectors]\n );\n\n const getSectorPiecePolysCached = React.useCallback(\n (sectorId: string): Poly[] => {\n const sig = sectorSignature(sectorId);\n const hit = polyCacheRef.current.get(sectorId);\n if (hit && hit.sig === sig) return hit.polys;\n const polys = sectorPiecePolysLive(sectorId);\n polyCacheRef.current.set(sectorId, { sig, polys });\n return polys;\n },\n [sectorSignature, sectorPiecePolysLive]\n );\n\n return {\n pieces,\n pieceById,\n sectorPiecePolysLive,\n getSectorPiecePolysCached\n };\n}","/**\n * Grid Snapping Engine - PHASE 2 MILESTONE\n * \n * Consolidates duplicate anchor functions from anchors.ts and anchors-mode.ts\n * into a single, parameterized grid snapping system.\n */\n\nimport type { Blueprint, Poly, Vec, PrimitiveBlueprint } from \"../../domain/types\";\nimport type { CircleLayout, SectorGeom } from \"../../domain/layout\";\nimport { \n boundsOfBlueprint, \n pointInPolygon, \n gridNodesInAABB, \n filterNodesToBandAndSector, \n filterNodesInPolys\n} from \"../geometry\";\nimport { CONFIG } from \"../../config/config\";\n\nexport interface GridConfig {\n stepPx: number;\n snapRadiusPx: number;\n densitySampleStepPx?: number; // For polyFullyInside sampling\n}\n\nexport interface SnapResult {\n tl: Vec;\n node: Vec | null;\n dist: number;\n accepted: boolean;\n}\n\n/**\n * GridSnapper handles all anchor-based snapping and node generation\n */\nexport class GridSnapper {\n private config: GridConfig;\n\n constructor(config: GridConfig) {\n this.config = config;\n }\n\n // ===== Reference Vertex Management =====\n \n /**\n * Choose a reference vertex (v0 of first poly) for snapping.\n * Consolidated from both anchors.ts and anchors-mode.ts\n */\n referenceVertex(bp: Blueprint): Vec {\n const poly = (\"shape\" in bp && bp.shape?.[0]) ? bp.shape[0] : [{x:0,y:0}];\n return poly[0] ?? { x: 0, y: 0 };\n }\n\n // ===== Snapping Operations =====\n\n /**\n * Perform nearest-node snapping with configurable snap radius\n * Consolidated from both files with enhanced configuration\n */\n nearestNodeSnap(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n ): SnapResult {\n if (!nodes.length) {\n return { tl, node: null, dist: Infinity, accepted: false };\n }\n\n const bb = boundsOfBlueprint(bp, primitiveLookup);\n const v0 = this.referenceVertex(bp);\n const v0World = { x: tl.x + (v0.x - bb.min.x), y: tl.y + (v0.y - bb.min.y) };\n\n let best: Vec | null = null;\n let bestD2 = Infinity;\n \n for (const n of nodes) {\n const dx = n.x - v0World.x;\n const dy = n.y - v0World.y;\n const d2 = dx * dx + dy * dy;\n if (d2 < bestD2) { \n bestD2 = d2; \n best = n; \n }\n }\n\n const distance = Math.sqrt(bestD2);\n const accepted = distance <= this.config.snapRadiusPx;\n \n const snapped = (best && accepted)\n ? { x: tl.x + (best.x - v0World.x), y: tl.y + (best.y - v0World.y) }\n : tl;\n\n return { \n tl: snapped, \n node: best, \n dist: distance, \n accepted \n };\n }\n\n /**\n * Back-compatibility shim for existing Board.tsx usage\n */\n snapTopLeftToNodes(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n ): { x: number; y: number } {\n const { tl: snapped } = this.nearestNodeSnap(tl, bp, primitiveLookup, nodes);\n return snapped;\n }\n\n // ===== Node Generation =====\n\n /**\n * Generate workspace-band grid nodes for a sector\n * Extracted from anchors-mode.ts\n */\n generateWorkspaceNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"workspace\", sector);\n }\n\n /**\n * Generate silhouette-mask nodes for a sector\n * Extracted from anchors-mode.ts\n */\n generateSilhouetteNodes(layout: CircleLayout, sector: SectorGeom, fittedMask: Poly[]): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n const banded = filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n return filterNodesInPolys(banded, fittedMask, pointInPolygon);\n }\n\n /**\n * Generate silhouette-band nodes for a sector (no mask filter)\n * Extracted from anchors-mode.ts\n */\n generateSilhouetteBandNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n }\n\n // ===== Validation Helpers =====\n\n /**\n * Check if point lies inside any silhouette polygon (union semantics)\n * Private helper used by polyFullyInside\n */\n private insideAnySilhouette(pt: Vec, silPolys: Poly[]): boolean {\n for (const sp of silPolys) {\n if (pointInPolygon(pt, sp)) return true;\n }\n return false;\n }\n\n /**\n * Robust \"fully inside\" check with configurable sampling density\n * Consolidated from both files with enhanced configuration\n */\n polyFullyInside(\n piecePolys: Poly[],\n silhouettePolys: Poly[],\n customStep?: number\n ): boolean {\n // Quick exits\n if (!piecePolys.length) return true;\n if (!silhouettePolys.length) return false;\n\n const step = customStep ?? \n this.config.densitySampleStepPx ?? \n Math.max(1, Math.round(CONFIG.layout.grid.stepPx / 3));\n\n for (const poly of piecePolys) {\n if (poly.length < 2) continue;\n\n for (let i = 0; i < poly.length; i++) {\n const a = poly[i];\n const b = poly[(i + 1) % poly.length];\n \n if (!a || !b) continue;\n \n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len = Math.hypot(dx, dy);\n const n = Math.max(1, Math.ceil(len / step));\n\n // Sample all points along the edge, including endpoints\n for (let k = 0; k <= n; k++) {\n const t = k / n;\n const p = { x: a.x + t * dx, y: a.y + t * dy };\n if (!this.insideAnySilhouette(p, silhouettePolys)) {\n return false; // One point outside → reject\n }\n }\n }\n }\n return true;\n }\n}\n\n// ===== Factory Functions =====\n\n/**\n * Create a GridSnapper with default configuration\n */\nexport function createDefaultGridSnapper(): GridSnapper {\n return new GridSnapper({\n stepPx: CONFIG.layout.grid.stepPx,\n snapRadiusPx: CONFIG.game.snapRadiusPx,\n densitySampleStepPx: Math.max(1, Math.round(CONFIG.layout.grid.stepPx / 3))\n });\n}\n\n/**\n * Create a GridSnapper with custom snap radius\n */\nexport function createGridSnapper(snapRadiusPx: number): GridSnapper {\n return new GridSnapper({\n stepPx: CONFIG.layout.grid.stepPx,\n snapRadiusPx,\n densitySampleStepPx: Math.max(1, Math.round(CONFIG.layout.grid.stepPx / 3))\n });\n}\n\n// ===== Legacy Compatibility Exports =====\n// These maintain compatibility with existing code while using the new system\n\nexport const defaultGridSnapper = createDefaultGridSnapper();\n\nexport function referenceVertex(bp: Blueprint): Vec {\n return defaultGridSnapper.referenceVertex(bp);\n}\n\nexport function nearestNodeSnap(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n): { tl: Vec; node: Vec | null; dist: number } {\n const result = defaultGridSnapper.nearestNodeSnap(tl, bp, primitiveLookup, nodes);\n return { tl: result.tl, node: result.node, dist: result.dist };\n}\n\nexport function snapTopLeftToNodes(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n): { x: number; y: number } {\n return defaultGridSnapper.snapTopLeftToNodes(tl, bp, primitiveLookup, nodes);\n}\n\nexport function polyFullyInside(\n piecePolys: Poly[],\n silhouettePolys: Poly[],\n step?: number\n): boolean {\n return defaultGridSnapper.polyFullyInside(piecePolys, silhouettePolys, step);\n}\n\nexport function workspaceNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n return defaultGridSnapper.generateWorkspaceNodes(layout, sector);\n}\n\nexport function silhouetteNodes(layout: CircleLayout, sector: SectorGeom, fittedMask: Poly[]): Vec[] {\n return defaultGridSnapper.generateSilhouetteNodes(layout, sector, fittedMask);\n}\n\nexport function silhouetteBandNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n return defaultGridSnapper.generateSilhouetteBandNodes(layout, sector);\n}\n\nexport { innerRingNodes } from \"../geometry\";","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { CircleLayout } from \"@/core/domain/layout\";\nimport { rectForBand } from \"@/core/domain/layout\";\nimport { placeSilhouetteGridAlignedAsPolys } from \"@/core/engine/geometry\";\nimport {\n workspaceNodes,\n silhouetteNodes,\n silhouetteBandNodes,\n innerRingNodes\n} from \"@/core/engine/collision/grid-snapping\";\n\n/**\n * Anchor dots data for a single sector\n * \n * Represents the valid and invalid snap points for piece placement within\n * a sector. Valid dots allow piece placement, invalid dots show grid structure\n * but don't allow snapping.\n */\nexport interface AnchorDots {\n /** Sector ID these anchor dots belong to */\n sectorId: string;\n \n /** Array of valid snap points where pieces can be placed */\n valid: { x: number; y: number }[];\n \n /** Array of invalid snap points (visual grid, no placement allowed) */\n invalid: { x: number; y: number }[];\n}\n\n/**\n * Return interface for useAnchorGrid hook\n * \n * Provides computed anchor grid data for all active sectors in the layout.\n * Used by rendering components to draw snap points and by interaction hooks\n * for piece placement validation.\n */\nexport interface AnchorGridHook {\n /** Array of anchor dot data for all sectors (excludes completed sectors) */\n anchorDots: AnchorDots[];\n}\n\n/**\n * Hook for computing anchor grid data for all sectors\n * \n * This hook computes the snap points (anchor dots) for piece placement validation\n * across all active sectors. It handles both workspace and silhouette target modes,\n * computing appropriate valid and invalid snap points for each.\n * \n * ## Key Features\n * - **Workspace mode**: All grid nodes within sector bounds are valid\n * - **Silhouette mode**: Only nodes within silhouette mask are valid\n * - **Completion hiding**: Completed sectors don't show anchor dots\n * - **Scale-aware**: Handles silhouette scaling for proper grid alignment\n * \n * ## Target Mode Behavior\n * - **Workspace**: `valid` contains all workspace nodes, `invalid` is empty\n * - **Silhouette**: `valid` contains nodes inside silhouette, `invalid` contains band nodes outside\n * \n * @param controller - BaseGameController instance for accessing game state\n * @param layout - Computed CircleLayout containing sector geometry\n * @param scaleS - Scaling factor for silhouette placement (from solveLogicalBox)\n * @returns Hook interface with anchor dots for all active sectors\n * \n * @example\n * ```typescript\n * const { anchorDots } = useAnchorGrid(controller, layout, scaleS);\n * const sectorAnchors = anchorDots.find(a => a.sectorId === \"sector_1\");\n * const snapPoints = sectorAnchors?.valid ?? [];\n * ```\n */\nexport function useAnchorGrid(\n controller: BaseGameController,\n layout: CircleLayout,\n scaleS: number\n): AnchorGridHook {\n const cfg = controller.state.cfg;\n\n const anchorDots: AnchorDots[] = React.useMemo(() => {\n const out: AnchorDots[] = [];\n\n // Add inner ring anchors (always valid, shown throughout)\n out.push({ sectorId: \"inner-ring\", valid: innerRingNodes(layout), invalid: [] });\n\n for (const s of layout.sectors) {\n // Show anchors for ALL sectors, including completed ones\n if (cfg.target === \"workspace\") {\n out.push({ sectorId: s.id, valid: workspaceNodes(layout, s), invalid: [] });\n } else {\n const mask = controller.state.cfg.sectors.find(ss => ss.id === s.id)?.silhouette.mask ?? [];\n if (!mask || mask.length === 0) continue;\n const rect = rectForBand(layout, s, \"silhouette\", 1.0); // center only; size was handled in global scale\n const placedPolys = placeSilhouetteGridAlignedAsPolys(mask, scaleS, { cx: rect.cx, cy: rect.cy });\n const bandAll = silhouetteBandNodes(layout, s);\n const valid = silhouetteNodes(layout, s, placedPolys);\n // invalid = bandAll \\ valid (by coordinate)\n const key = (p: { x: number; y: number }) => `${p.x},${p.y}`;\n const validSet = new Set(valid.map(key));\n const invalid = bandAll.filter(p => !validSet.has(key(p)));\n out.push({ sectorId: s.id, valid, invalid });\n }\n }\n return out;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [cfg.target, controller.state.sectors, layout, scaleS]);\n\n return {\n anchorDots\n };\n}","/**\n * Face-to-Face Attachment Validation for Prep Mode\n * \n * Validates that pieces in prep mode attach to existing pieces by sharing\n * at least 1 anchor unit of edge contact. Uses discrete unit segments\n * for precise edge detection.\n */\n\nimport type { Piece, Vec, Blueprint } from \"../../domain/types\";\nimport { CONFIG } from \"../../config/config\";\nimport { boundsOfBlueprint } from \"../geometry\";\n\nexport interface EdgeAttachmentResult {\n isAttached: boolean;\n attachedPieceIds: string[];\n sharedEdgeLength: number; // In anchor units\n}\n\nexport interface UnitSegment {\n a: Vec;\n b: Vec;\n}\n\n/**\n * Convert a polygon edge into unit-length segments\n * Each segment represents a discrete coordinate unit along the edge\n */\nfunction edgeToUnitSegments(start: Vec, end: Vec, gridSize: number): UnitSegment[] {\n const segments: UnitSegment[] = [];\n \n // Convert to grid coordinates\n const startGrid = {\n x: Math.round(start.x / gridSize),\n y: Math.round(start.y / gridSize)\n };\n const endGrid = {\n x: Math.round(end.x / gridSize),\n y: Math.round(end.y / gridSize)\n };\n \n const dx = endGrid.x - startGrid.x;\n const dy = endGrid.y - startGrid.y;\n \n if (dx === 0 && dy === 0) return []; // Zero-length edge\n \n const steps = Math.max(Math.abs(dx), Math.abs(dy));\n const stepX = dx / steps;\n const stepY = dy / steps;\n \n for (let i = 0; i < steps; i++) {\n const aX = Math.round(startGrid.x + i * stepX);\n const aY = Math.round(startGrid.y + i * stepY);\n const bX = Math.round(startGrid.x + (i + 1) * stepX);\n const bY = Math.round(startGrid.y + (i + 1) * stepY);\n segments.push({ \n a: { x: aX, y: aY }, \n b: { x: bX, y: bY } \n });\n }\n \n return segments;\n}\n\n\n\n/**\n * Get all unit segments for a piece (all edges broken down into unit-length segments)\n * Uses the same coordinate system as piecePolysAt for consistency with visual rendering\n */\nfunction getPieceUnitSegments(\n piece: Piece, \n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any,\n gridSize: number\n): UnitSegment[] {\n const blueprint = getBlueprint(piece.blueprintId);\n if (!blueprint?.shape) return [];\n \n // Calculate offset using same logic as piecePolysAt\n const bb = boundsOfBlueprint(blueprint, getPrimitive);\n const ox = piece.pos.x - bb.min.x;\n const oy = piece.pos.y - bb.min.y;\n \n const allSegments: UnitSegment[] = [];\n \n // Translate polygons and convert edges to unit segments\n for (const poly of blueprint.shape) {\n const translatedPoly = poly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n \n for (let i = 0; i < translatedPoly.length; i++) {\n const current = translatedPoly[i];\n const next = translatedPoly[(i + 1) % translatedPoly.length];\n \n if (!current || !next) continue;\n \n allSegments.push(...edgeToUnitSegments(current, next, gridSize));\n }\n }\n \n return allSegments;\n}\n\n/**\n * Main face-to-face attachment validation function\n */\nexport function checkFaceToFaceAttachment(\n piece: Piece,\n existingPieces: Piece[],\n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any\n): EdgeAttachmentResult {\n if (existingPieces.length === 0) {\n return { isAttached: true, attachedPieceIds: [], sharedEdgeLength: 0 };\n }\n \n const gridSize = CONFIG.layout.grid.stepPx;\n const newPieceSegments = getPieceUnitSegments(piece, getBlueprint, getPrimitive, gridSize);\n \n if (newPieceSegments.length === 0) {\n return { isAttached: false, attachedPieceIds: [], sharedEdgeLength: 0 };\n }\n \n let totalSharedLength = 0;\n const attachedPieceIds: string[] = [];\n \n // Check against each existing piece\n for (const existingPiece of existingPieces) {\n const existingSegments = getPieceUnitSegments(existingPiece, getBlueprint, getPrimitive, gridSize);\n \n // Find shared segments (undirected edge matching)\n const sharedSegments = newPieceSegments.filter(newSeg => \n existingSegments.some(existingSeg => \n // Check if segments share the same endpoints (identical or reversed)\n (newSeg.a.x === existingSeg.a.x && newSeg.a.y === existingSeg.a.y &&\n newSeg.b.x === existingSeg.b.x && newSeg.b.y === existingSeg.b.y) ||\n (newSeg.a.x === existingSeg.b.x && newSeg.a.y === existingSeg.b.y &&\n newSeg.b.x === existingSeg.a.x && newSeg.b.y === existingSeg.a.y)\n )\n );\n \n if (sharedSegments.length > 0) {\n totalSharedLength += sharedSegments.length;\n attachedPieceIds.push(existingPiece.id);\n }\n }\n \n return {\n isAttached: totalSharedLength >= 1,\n attachedPieceIds,\n sharedEdgeLength: totalSharedLength\n };\n}\n\n/**\n * Check if removing a piece would disconnect the remaining pieces in a sector\n * Uses graph connectivity to ensure all remaining pieces stay connected\n */\nexport function wouldRemovalDisconnectSector(\n pieceToRemove: Piece,\n allPiecesInSector: Piece[],\n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any\n): boolean {\n // If there are 0 or 1 pieces remaining, no disconnection possible\n if (allPiecesInSector.length <= 2) return false;\n \n const remainingPieces = allPiecesInSector.filter(p => p.id !== pieceToRemove.id);\n if (remainingPieces.length <= 1) return false;\n \n // Build adjacency graph of remaining pieces\n const adjacencyMap = new Map<string, string[]>();\n \n // Initialize adjacency map\n for (const piece of remainingPieces) {\n adjacencyMap.set(piece.id, []);\n }\n \n // Check all pairs of remaining pieces for connectivity\n for (let i = 0; i < remainingPieces.length; i++) {\n for (let j = i + 1; j < remainingPieces.length; j++) {\n const piece1 = remainingPieces[i];\n const piece2 = remainingPieces[j];\n \n if (!piece1 || !piece2) continue;\n \n const result = checkFaceToFaceAttachment(piece1, [piece2], getBlueprint, getPrimitive);\n if (result.isAttached) {\n adjacencyMap.get(piece1.id)!.push(piece2.id);\n adjacencyMap.get(piece2.id)!.push(piece1.id);\n }\n }\n }\n \n // Check if graph is connected using DFS\n const visited = new Set<string>();\n const startPiece = remainingPieces[0];\n \n if (!startPiece) return false;\n \n function dfs(pieceId: string) {\n if (visited.has(pieceId)) return;\n visited.add(pieceId);\n \n const neighbors = adjacencyMap.get(pieceId) || [];\n for (const neighborId of neighbors) {\n dfs(neighborId);\n }\n }\n \n dfs(startPiece.id);\n \n // If we visited all pieces, the graph is connected\n return visited.size !== remainingPieces.length;\n}","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { CircleLayout } from \"@/core/domain/layout\";\nimport type { Blueprint } from \"@/core/domain/types\";\nimport { sectorAtPoint } from \"@/core/domain/layout\";\nimport { \n boundsOfBlueprint, \n computeSupportOffsets, \n clampTopLeftBySupport, \n polysOverlap, \n piecePolysAt \n} from \"@/core/engine/geometry\";\nimport { nearestNodeSnap, polyFullyInside } from \"@/core/engine/collision/grid-snapping\";\nimport { checkFaceToFaceAttachment, wouldRemovalDisconnectSector } from \"@/core/engine/validation/face-to-face\";\nimport { blueprintLocalFromWorld } from \"./utils\";\nimport type { AnchorDots } from \"./useAnchorGrid\";\nimport type { PieceData } from \"./usePieceState\";\nimport { CONFIG } from \"@/core/config/config\";\n\ninterface DragState {\n id: string;\n dx: number;\n dy: number;\n tlx: number;\n tly: number;\n aabb: { width: number; height: number };\n minx: number;\n miny: number;\n support: { x: number; y: number }[];\n fromIcon?: boolean;\n validSnap?: boolean;\n prevValidSnap?: boolean;\n raf?: number | null;\n originalPos?: { x: number; y: number; sectorId: string | undefined } | undefined; // For prep mode: return to original position when invalid\n pointerAnchor?: { x: number; y: number } | null;\n pointerAnchorId?: string | null;\n pointerAnchorSectorId?: string | undefined;\n snapAnchor?: { x: number; y: number } | null;\n snapAnchorId?: string | null;\n snapAnchorSectorId?: string | undefined;\n snapAnchorDist?: number | null;\n overlaps?: boolean;\n maxExceeded?: boolean;\n}\n\n/**\n * Return interface for useDragController hook\n * \n * Provides complete drag interaction functionality for both click and drag input modes.\n * Handles piece spawning, dragging, collision detection, snapping, and placement validation.\n */\nexport interface DragControllerHook {\n // State\n /** ID of currently dragging piece (null if none) */\n draggingId: string | null;\n \n /** True if current drag position is invalid (for visual feedback) */\n dragInvalid: boolean;\n \n /** ID of piece that is locked due to connectivity constraints (for visual feedback) */\n lockedPieceId: string | null;\n \n /** Ref to SVG element for coordinate transformation and pointer capture */\n svgRef: React.RefObject<SVGSVGElement>;\n \n // Handlers\n /** \n * Handler for piece pointer down events (both click and drag modes)\n * @param e - Pointer event from SVG path or group element\n * @param p - Piece data including position and blueprint information\n */\n onPiecePointerDown: (\n e: React.PointerEvent<SVGPathElement | SVGGElement>,\n p: { id: string; x: number; y: number; blueprintId: string; sectorId?: string }\n ) => void;\n \n /** \n * Handler for blueprint icon pointer down events (spawning new pieces)\n * @param e - Pointer event from blueprint icon\n * @param bp - Blueprint definition for the new piece\n * @param bpGeom - Geometry information for the blueprint icon\n */\n onBlueprintPointerDown: (\n e: React.PointerEvent,\n bp: Blueprint,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n ) => void;\n \n /** \n * Handler for pointer move events during drag operations\n * @param e - Pointer event from SVG root element\n */\n onPointerMove: (e: React.PointerEvent<SVGSVGElement>) => void;\n \n /** Handler for pointer up events (completing drag operations) */\n onPointerUp: () => void;\n \n /** \n * Factory function for piece element refs (for direct DOM manipulation)\n * @param id - Piece ID\n * @returns Ref callback for SVG group element\n */\n setPieceRef: (id: string) => (el: SVGGElement | null) => void;\n \n // Click controller integration\n /** \n * Setter for dragging ID (used by click controller for carry state)\n * @param id - Piece ID or null to clear\n */\n setDraggingId: (id: string | null) => void;\n \n // TODO: Remove this once click mode is extracted - temporary for compatibility\n /** Internal drag state ref (temporary for click controller integration) */\n dragRef: React.RefObject<DragState | null>;\n}\n\n/**\n * Hook for managing drag interactions with RAF optimization and collision detection\n * \n * This is the most complex hook in the system, handling all aspects of piece interaction\n * for both click and drag input modes. It manages piece spawning, dragging, collision\n * detection, grid snapping, placement validation, and visual feedback.\n * \n * ## Key Features\n * - **Dual input mode support**: Handles both click and drag interaction patterns\n * - **RAF-optimized rendering**: Uses requestAnimationFrame for smooth drag performance\n * - **Collision detection**: Real-time overlap checking with existing pieces\n * - **Grid snapping**: Automatic snapping to anchor points with validation\n * - **Placement validation**: Comprehensive validation for workspace/silhouette modes\n * - **Visual feedback**: Real-time visual indicators for valid/invalid placement\n * \n * ## Input Mode Behavior\n * - **Click mode**: First click starts \"carry\" state, second click places/cancels\n * - **Drag mode**: Traditional drag-and-drop with immediate visual feedback\n * \n * ## Validation Rules\n * - **Workspace mode**: Pieces must not overlap, any grid position valid\n * - **Silhouette mode**: Pieces must be within silhouette mask, on valid anchors, no overlap\n * - **Completed sectors**: No placement allowed, pieces deleted if dropped\n * \n * @param controller - BaseGameController for state management\n * @param layout - Computed CircleLayout for sector geometry\n * @param pieces - Current piece data from usePieceState\n * @param pieceById - Lookup function for piece data\n * @param anchorDots - Anchor grid data from useAnchorGrid\n * @param placedSilBySector - Silhouette polygons for containment checking\n * @param isSectorLocked - Function to check if sector is completed\n * @param maybeCompleteSector - Callback to check sector completion after placement\n * @param force - Force React re-render function\n * @param clickController - Optional click controller integration\n * @returns Hook interface with drag state and event handlers\n * \n * @example\n * ```typescript\n * const dragController = useDragController(\n * controller, layout, pieces, pieceById, anchorDots,\n * placedSilBySector, isSectorLocked, maybeCompleteSector, force\n * );\n * \n * // Usage in JSX:\n * <svg ref={dragController.svgRef} onPointerMove={dragController.onPointerMove}>\n * <g onPointerDown={(e) => dragController.onPiecePointerDown(e, piece)}>\n * <path /> \n * </g>\n * </svg>\n * ```\n */\nexport function useDragController(\n controller: BaseGameController,\n layout: CircleLayout,\n pieces: PieceData[],\n pieceById: (id: string | null) => PieceData | null,\n anchorDots: AnchorDots[],\n placedSilBySector: Map<string, any[]>,\n isSectorLocked: (id: string) => boolean,\n maybeCompleteSector: (secId: string) => boolean,\n force: () => void,\n // Click controller integration\n clickController?: {\n setSelectedPiece: (id: string | null) => void;\n setPendingBp: (id: string | null) => void;\n },\n // Interaction tracking\n tracker?: {\n recordPickup: (\n pieceId: string,\n blueprintId: string,\n blueprintType: 'primitive' | 'composite',\n source: 'blueprint' | 'sector',\n position: { x: number; y: number },\n vertices: number[][][],\n sectorId?: string\n ) => void;\n recordPlacedown: (\n outcome: 'placed' | 'deleted',\n sectorId?: string,\n position?: { x: number; y: number },\n vertices?: number[][][],\n anchorId?: string,\n wasValid?: boolean,\n wasOverlapping?: boolean,\n completedSector?: boolean\n ) => void;\n recordMouseMove?: (anchorX: number, anchorY: number, sectorId?: string) => void;\n recordClickEvent?: (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => void;\n } | null\n): DragControllerHook {\n const cfg = controller.state.cfg;\n const clickMode = cfg.input === \"click\";\n \n // Core drag state\n const svgRef = React.useRef<SVGSVGElement | null>(null);\n const dragRef = React.useRef<DragState | null>(null);\n const [draggingId, setDraggingId] = React.useState<string | null>(null);\n const elMap = React.useRef(new Map<string, SVGGElement>());\n \n // Visual feedback for connectivity-locked pieces\n const [lockedPieceId, setLockedPieceId] = React.useState<string | null>(null);\n \n // Ensure dragRef is cleared when draggingId becomes null (for click controller integration)\n React.useEffect(() => {\n if (draggingId === null) {\n dragRef.current = null;\n }\n }, [draggingId]);\n\n const setPieceRef = (id: string) => (el: SVGGElement | null) => {\n const m = elMap.current;\n if (el) m.set(id, el); else m.delete(id);\n };\n\n const svgPoint = (clientX: number, clientY: number) => {\n const svg = svgRef.current!;\n const pt = svg.createSVGPoint();\n pt.x = clientX; pt.y = clientY;\n const ctm = svg.getScreenCTM();\n if (!ctm) return { x: 0, y: 0 };\n const sp = pt.matrixTransform(ctm.inverse());\n return { x: sp.x, y: sp.y };\n };\n\n const scheduleFrame = () => {\n if (!dragRef.current) return;\n const d = dragRef.current;\n if (d.raf != null) return;\n d.raf = requestAnimationFrame(() => {\n d.raf = null;\n const g = elMap.current.get(d.id);\n if (g) g.setAttribute(\"transform\", `translate(${d.tlx - d.minx}, ${d.tly - d.miny})`);\n });\n };\n\n const sectorIdAt = (x: number, y: number) => sectorAtPoint(x, y, layout, cfg.target);\n const GRID_STEP = CONFIG.layout.grid.stepPx;\n\n const anchorIdFromNode = (node: { x: number; y: number } | null | undefined): string | null => {\n if (!node) return null;\n const ax = Math.round(node.x / GRID_STEP);\n const ay = Math.round(node.y / GRID_STEP);\n return `${ax},${ay}`;\n };\n\n const anchorNodeFromPoint = (point: { x: number; y: number }) => ({\n x: Math.round(point.x / GRID_STEP) * GRID_STEP,\n y: Math.round(point.y / GRID_STEP) * GRID_STEP\n });\n\n const updatePointerAnchor = (point: { x: number; y: number }, sectorId: string | undefined) => {\n if (!dragRef.current) return;\n const d = dragRef.current;\n const anchorNode = anchorNodeFromPoint(point);\n const anchorId = anchorIdFromNode(anchorNode);\n\n if (tracker?.recordMouseMove && (anchorId !== d.pointerAnchorId || sectorId !== d.pointerAnchorSectorId)) {\n tracker.recordMouseMove(anchorNode.x, anchorNode.y, sectorId);\n }\n\n d.pointerAnchor = anchorNode;\n d.pointerAnchorId = anchorId;\n d.pointerAnchorSectorId = sectorId;\n };\n\n const updateSnapAnchor = (\n node: { x: number; y: number } | null,\n sectorId: string | undefined,\n dist?: number\n ) => {\n if (!dragRef.current) return;\n const d = dragRef.current;\n d.snapAnchor = node;\n d.snapAnchorId = anchorIdFromNode(node);\n d.snapAnchorSectorId = sectorId;\n d.snapAnchorDist = node && dist !== undefined ? dist : null;\n };\n\n const emitClickEvent = (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => {\n if (!tracker?.recordClickEvent) return;\n tracker.recordClickEvent(location, clickType, metadata);\n };\n\n // Helper: Compute piece vertices in world space\n const getPieceVertices = (pieceId: string): number[][][] => {\n const piece = controller.findPiece(pieceId);\n if (!piece) return [];\n const bp = controller.getBlueprint(piece.blueprintId);\n if (!bp) return [];\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const polys = piecePolysAt(bp, bb, piece.pos);\n // Convert from {x,y}[][] to number[][][]\n return polys.map(ring => ring.map(pt => [pt.x, pt.y]));\n };\n\n const onPiecePointerDown = (\n e: React.PointerEvent<SVGPathElement | SVGGElement>,\n p: { id: string; x: number; y: number; blueprintId: string; sectorId?: string }\n ) => {\n if (p.sectorId && isSectorLocked(p.sectorId)) return;\n if (clickMode && draggingId) return; // ignore if already carrying\n\n // Check connectivity in prep mode - prevent removal if it would disconnect remaining pieces\n if (cfg.mode === \"prep\" && p.sectorId) {\n const allPiecesInSector = controller.getPiecesInSector(p.sectorId);\n const pieceToRemove = controller.findPiece(p.id);\n \n if (pieceToRemove && wouldRemovalDisconnectSector(\n pieceToRemove,\n allPiecesInSector,\n (id) => controller.getBlueprint(id),\n (kind) => controller.getPrimitive(kind)\n )) {\n // Flash red briefly to indicate piece cannot be removed\n setLockedPieceId(p.id);\n setTimeout(() => setLockedPieceId(null), 500);\n return; // Prevent pickup\n }\n }\n\n if (clickMode) {\n // Start a \"carry\" in click mode: make the piece follow the cursor\n e.stopPropagation();\n clickController?.setSelectedPiece(p.id);\n clickController?.setPendingBp(null);\n\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, (k) => controller.getPrimitive(k));\n const support = computeSupportOffsets(bp, bb);\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n const pointerAnchorNode = anchorNodeFromPoint({ x, y });\n const pointerSector = p.sectorId;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n p.id,\n p.blueprintId,\n blueprintType,\n 'sector',\n { x: p.x, y: p.y },\n getPieceVertices(p.id),\n p.sectorId\n );\n }\n\n dragRef.current = {\n id: p.id,\n dx: x - p.x, dy: y - p.y,\n tlx: p.x, tly: p.y,\n aabb: { width: bb.width, height: bb.height },\n minx: bb.min.x, miny: bb.min.y,\n support,\n fromIcon: false,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: { x: p.x, y: p.y, sectorId: p.sectorId },\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n maxExceeded: false,\n };\n updateSnapAnchor(null, p.sectorId);\n setDraggingId(p.id);\n force();\n return;\n }\n\n // DRAG path\n svgRef.current?.setPointerCapture(e.pointerId);\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, (k) => controller.getPrimitive(k));\n const support = computeSupportOffsets(bp, bb);\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n const pointerAnchorNode = anchorNodeFromPoint({ x, y });\n const pointerSector = p.sectorId;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n p.id,\n p.blueprintId,\n blueprintType,\n 'sector',\n { x: p.x, y: p.y },\n getPieceVertices(p.id),\n p.sectorId\n );\n }\n\n dragRef.current = {\n id: p.id,\n dx: x - p.x, dy: y - p.y,\n tlx: p.x, tly: p.y,\n aabb: { width: bb.width, height: bb.height },\n minx: bb.min.x, miny: bb.min.y,\n support,\n fromIcon: false,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: { x: p.x, y: p.y, sectorId: p.sectorId },\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n maxExceeded: false,\n };\n updateSnapAnchor(null, p.sectorId);\n setDraggingId(p.id);\n force();\n };\n\n const onPointerMove = (e: React.PointerEvent<SVGSVGElement>) => {\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n // Always log pointer movement for mouse tracking, even before pickup\n const pointerAnchorNode = anchorNodeFromPoint({ x, y });\n const pointerR = Math.hypot(x - layout.cx, y - layout.cy);\n const pointerSectorId = pointerR < layout.innerR ? undefined : sectorIdAt(x, y) ?? undefined;\n if (!dragRef.current) {\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSectorId);\n }\n return;\n }\n\n const d = dragRef.current;\n const tlx = x - d.dx, tly = y - d.dy;\n\n updatePointerAnchor({ x, y }, pointerSectorId);\n\n const clamped = clampTopLeftBySupport(\n tlx, tly,\n { aabb: d.aabb, support: d.support },\n layout,\n controller.state.cfg.target,\n pointerR < layout.innerR\n );\n\n let tl = clamped;\n // Snap the *piece itself* to nearest nodes in the active sector (or inner ring),\n // and compute validity (silhouette: within snapRadius; workspace: always valid).\n const centerX = tl.x + d.aabb.width / 2;\n const centerY = tl.y + d.aabb.height / 2;\n const rFromCenter = Math.hypot(centerX - layout.cx, centerY - layout.cy);\n const inInnerRing = rFromCenter < layout.innerR;\n const secId = inInnerRing ? null : sectorIdAt(centerX, centerY);\n let snapNode: { x: number; y: number } | null = null;\n let snapDist: number | null = null;\n let snapSectorId: string | undefined = secId ?? undefined;\n let overlapsDetected = false;\n let maxExceededDetected = false;\n\n // Check for inner ring snapping first\n if (inInnerRing) {\n const innerEntry = anchorDots.find(a => a.sectorId === \"inner-ring\");\n if (innerEntry && innerEntry.valid.length) {\n const piece = pieceById(d.id);\n if (piece) {\n const bp = controller.getBlueprint(piece.blueprintId)!;\n const snap = nearestNodeSnap(tl, bp, controller.getPrimitive, innerEntry.valid);\n tl = snap.tl;\n snapNode = snap.node;\n snapDist = snap.dist;\n snapSectorId = undefined;\n }\n }\n // Inner ring shows RED (invalid) to indicate piece will be deleted\n d.validSnap = false;\n } else if (secId) {\n const isCompletedSector = isSectorLocked(secId);\n const entry = anchorDots.find(a => a.sectorId === secId);\n const allNodes =\n (cfg.target === \"workspace\" && cfg.mode !== \"prep\")\n ? (entry?.valid ?? []) // Construction workspace: only valid nodes\n : [ ...(entry?.valid ?? []), ...(entry?.invalid ?? []) ]; // Silhouette + Prep: all nodes\n\n // Snap to anchors even in completed sectors\n if (allNodes.length) {\n const piece = pieceById(d.id);\n if (piece) {\n const bp = controller.getBlueprint(piece.blueprintId)!;\n const snap = nearestNodeSnap(\n tl,\n bp,\n controller.getPrimitive,\n allNodes\n );\n tl = snap.tl;\n snapNode = snap.node;\n snapDist = snap.dist;\n snapSectorId = secId;\n\n // Completed sectors: always show red (invalid)\n if (isCompletedSector) {\n d.validSnap = false;\n } else {\n // Normal validation for incomplete sectors\n const radius = controller.state.cfg.snapRadiusPx;\n // Gather world polys for the carried piece at the *snapped* TL\n const carried = pieceById(d.id);\n let overlapsOk = true;\n if (carried) {\n const bpCar = controller.getBlueprint(carried.blueprintId)!;\n const bbCar = boundsOfBlueprint(\n bpCar,\n controller.getPrimitive\n );\n const carriedPolys = piecePolysAt(bpCar, bbCar, tl);\n\n // only compare against pieces in the same sector we're currently over\n const sameSector = pieces.filter(\n pp =>\n pp.id !== d.id &&\n sectorIdAt(\n pp.x +\n boundsOfBlueprint(\n controller.getBlueprint(pp.blueprintId)!,\n controller.getPrimitive\n ).width / 2,\n pp.y +\n boundsOfBlueprint(\n controller.getBlueprint(pp.blueprintId)!,\n controller.getPrimitive\n ).height / 2,\n ) === secId\n );\n\n for (const other of sameSector) {\n const bpO = controller.getBlueprint(other.blueprintId)!;\n const bbO = boundsOfBlueprint(\n bpO,\n controller.getPrimitive\n );\n const otherPolys = piecePolysAt(bpO, bbO, { x: other.x, y: other.y });\n if (polysOverlap(carriedPolys, otherPolys)) {\n overlapsOk = false;\n break;\n }\n }\n\n // workspace: validity depends on mode\n if (cfg.target === \"workspace\") {\n if (cfg.mode === \"prep\") {\n // Prep mode: ALWAYS allow movement (just show visual feedback)\n // Face-to-face validation only affects visual feedback, not movement\n const allPiecesInSector = controller.getPiecesInSector(secId);\n const otherPiecesInSector = allPiecesInSector.filter(piece => piece.id !== d.id);\n const isFirstPiece = otherPiecesInSector.length === 0;\n const storedPiece = controller.findPiece(d.id);\n const currentSectorId = storedPiece?.sectorId;\n const maxPieces = controller.state.cfg.maxCompositeSize ?? 0;\n const enforceMaxPieces = maxPieces > 0;\n const effectiveCount = allPiecesInSector.length - (currentSectorId === secId ? 1 : 0);\n const wouldExceedMax = enforceMaxPieces && (effectiveCount + 1 > maxPieces);\n\n if (isFirstPiece) {\n // First piece: visual feedback based on overlaps and max-piece limit\n d.validSnap = overlapsOk && !wouldExceedMax;\n maxExceededDetected = wouldExceedMax;\n } else if (storedPiece) {\n // Subsequent pieces: visual feedback based on face-to-face attachment\n const pieceAtDragPosition = {\n ...storedPiece,\n pos: { x: tl.x, y: tl.y }\n };\n\n const attachmentResult = checkFaceToFaceAttachment(\n pieceAtDragPosition,\n otherPiecesInSector,\n (id) => controller.getBlueprint(id),\n (kind) => controller.getPrimitive(kind)\n );\n\n d.validSnap = overlapsOk && attachmentResult.isAttached && !wouldExceedMax;\n maxExceededDetected = wouldExceedMax;\n } else {\n d.validSnap = overlapsOk && !wouldExceedMax;\n maxExceededDetected = wouldExceedMax;\n }\n\n // IMPORTANT: In prep mode, always allow movement regardless of validSnap\n // validSnap is only for visual feedback (red/blue coloring)\n } else {\n // Construction mode: original behavior (validSnap blocks movement)\n d.validSnap = overlapsOk;\n maxExceededDetected = false;\n }\n overlapsDetected = !overlapsOk;\n } else {\n // silhouette: node must be valid AND fully inside AND !overlap\n const key = (p: { x: number; y: number }) => `${p.x},${p.y}`;\n const validSet = new Set((entry?.valid ?? []).map(key));\n const nodeOk =\n !!snap.node && validSet.has(key(snap.node)) && snap.dist <= (radius ?? 0);\n let insideOk = false;\n if (nodeOk) {\n const silPolys = placedSilBySector.get(secId) ?? [];\n insideOk = polyFullyInside(carriedPolys, silPolys);\n }\n d.validSnap = nodeOk && insideOk && overlapsOk;\n overlapsDetected = !overlapsOk;\n }\n }\n }\n }\n }\n } else { \n // not over any sector band\n d.validSnap = (controller.state.cfg.target === \"workspace\");\n snapNode = null;\n snapDist = null;\n snapSectorId = undefined;\n maxExceededDetected = false;\n }\n d.overlaps = overlapsDetected;\n d.maxExceeded = maxExceededDetected;\n updateSnapAnchor(snapNode, snapSectorId, snapDist ?? undefined);\n d.tlx = tl.x; d.tly = tl.y;\n\n // If the validity state changed, force a React render so fill/stroke update immediately.\n if (d.prevValidSnap !== d.validSnap) {\n d.prevValidSnap = d.validSnap ?? false;\n force();\n }\n\n scheduleFrame();\n };\n\n const onPointerUp = () => {\n if (!dragRef.current) return;\n if (clickMode) return;\n\n const d = dragRef.current;\n // If the candidate is invalid for any reason (overlap/outside/bad node), handle based on mode\n if (d.validSnap === false) {\n const piece = controller.findPiece(d.id);\n const cfg = controller.state.cfg;\n const centerX = d.tlx + d.aabb.width / 2;\n const centerY = d.tly + d.aabb.height / 2;\n const attemptedSector = sectorIdAt(centerX, centerY);\n let invalidReason: 'overlapping' | 'outside_bounds' | 'no_valid_anchor' | 'sector_complete' = 'outside_bounds';\n if (d.maxExceeded) {\n invalidReason = 'no_valid_anchor';\n } else if (d.overlaps) {\n invalidReason = 'overlapping';\n } else if (attemptedSector) {\n invalidReason = 'no_valid_anchor';\n }\n emitClickEvent(\n { x: centerX, y: centerY },\n 'invalid_placement',\n { invalidPlacement: { reason: invalidReason, attemptedSectorId: attemptedSector ?? undefined } }\n );\n\n // In prep mode: return to original position (if exists) or delete (if from icon)\n if (cfg.mode === \"prep\" && d.originalPos) {\n // Return piece to its original position\n controller.move(d.id, { x: d.originalPos.x, y: d.originalPos.y });\n\n // Record placedown as \"placed\" back in original position\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n d.originalPos.sectorId,\n { x: d.originalPos.x, y: d.originalPos.y },\n getPieceVertices(d.id),\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n } else {\n // Construction mode or fromIcon in prep mode: delete piece\n const removedFromSector = piece?.sectorId;\n controller.remove(d.id);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n }\n\n dragRef.current = null;\n setDraggingId(null);\n force();\n return;\n }\n \n dragRef.current = null;\n if (d.raf) { cancelAnimationFrame(d.raf); d.raf = null; }\n\n const commitTL = { x: d.tlx, y: d.tly };\n const centerX = commitTL.x + d.aabb.width / 2;\n const centerY = commitTL.y + d.aabb.height / 2;\n\n // delete if inside the inner hole\n const rFromCenter = Math.hypot(centerX - layout.cx, centerY - layout.cy);\n if (rFromCenter < layout.innerR) {\n const piece = controller.findPiece(d.id);\n const removedFromSector = piece?.sectorId;\n controller.remove(d.id);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n\n setDraggingId(null);\n force();\n return;\n }\n\n const secId = sectorIdAt(centerX, centerY);\n\n // Completed sector: no-op (do nothing, same as clicking incomplete sector in silhouette mode)\n if (secId && isSectorLocked(secId)) {\n emitClickEvent(\n { x: centerX, y: centerY },\n 'sector_complete_attempt',\n { invalidPlacement: { reason: 'sector_complete', attemptedSectorId: secId } }\n );\n // Return piece to original position if it exists, otherwise delete (from icon spawn)\n if (d.originalPos) {\n controller.move(d.id, { x: d.originalPos.x, y: d.originalPos.y });\n if (d.originalPos.sectorId) {\n controller.drop(d.id, d.originalPos.sectorId);\n }\n\n // Record placedown as \"placed\" back in original position\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n d.originalPos.sectorId,\n { x: d.originalPos.x, y: d.originalPos.y },\n getPieceVertices(d.id),\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n } else {\n // Piece was spawned from icon and dropped in completed sector → delete\n controller.remove(d.id);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n undefined,\n undefined,\n undefined,\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n }\n setDraggingId(null);\n force();\n return;\n }\n\n controller.move(d.id, commitTL);\n controller.drop(d.id, secId);\n\n const justCompleted = secId ? maybeCompleteSector(secId) : false;\n\n // Record placedown as \"placed\" successfully\n const wasValid = d.validSnap === undefined ? true : d.validSnap;\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n secId,\n commitTL,\n getPieceVertices(d.id),\n d.snapAnchorId ?? undefined,\n wasValid,\n d.overlaps ?? false,\n justCompleted\n );\n }\n\n setDraggingId(null);\n\n // auto-revert AFTER completing a drag spawn from the center\n if (d.fromIcon && controller.state.blueprintView === \"primitives\") {\n controller.switchBlueprintView();\n }\n force();\n };\n\n const onBlueprintPointerDown = (\n e: React.PointerEvent,\n bp: Blueprint,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n ) => {\n if (clickMode && draggingId) return;\n e.stopPropagation();\n\n const { x: px, y: py } = svgPoint(e.clientX, e.clientY);\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const support = computeSupportOffsets(bp, bb);\n\n if (clickMode) {\n // Click mode: spawn then enter carry state\n \n // Compute the local point of the blueprint glyph that was clicked\n const q = blueprintLocalFromWorld(px, py, bpGeom);\n // Compute TL so that the clicked point stays under the cursor\n const tl0 = { x: px - (q.x - bb.min.x), y: py - (q.y - bb.min.y) };\n const pointerR = Math.hypot(px - layout.cx, py - layout.cy);\n const allowInside = pointerR < layout.innerR;\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: bb, support },\n layout,\n controller.state.cfg.target,\n allowInside\n );\n const pieceId = controller.spawnFromBlueprint(bp, clamped);\n const pointerAnchorNode = anchorNodeFromPoint({ x: px, y: py });\n const pointerSector = sectorIdAt(px, py) ?? undefined;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event for blueprint spawn\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n pieceId,\n bp.id,\n blueprintType,\n 'blueprint',\n clamped,\n getPieceVertices(pieceId),\n undefined\n );\n }\n\n const tl = clamped;\n // If anchors mode, immediately snap initial TL to the nearest nodes in the active sector\n let finalTl = tl;\n let snapInfo: { node: { x: number; y: number } | null; dist: number } | null = null;\n const centerX = tl.x + bb.width / 2;\n const centerY = tl.y + bb.height / 2;\n const secId = sectorIdAt(centerX, centerY);\n if (secId) {\n const entry = anchorDots.find(a => a.sectorId === secId);\n const nodes =\n controller.state.cfg.target === \"workspace\"\n ? (entry?.valid ?? [])\n : [ ...(entry?.valid ?? []), ...(entry?.invalid ?? []) ];\n if (nodes.length) {\n const snap = nearestNodeSnap(tl, bp, controller.getPrimitive, nodes);\n finalTl = snap.tl;\n snapInfo = { node: snap.node, dist: snap.dist };\n }\n }\n \n controller.move(pieceId, finalTl);\n dragRef.current = {\n id: pieceId,\n dx: px - finalTl.x,\n dy: py - finalTl.y,\n tlx: finalTl.x,\n tly: finalTl.y,\n aabb: bb,\n minx: bb.min.x,\n miny: bb.min.y,\n support,\n fromIcon: true,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: undefined, // No original position for fromIcon drags\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n maxExceeded: false,\n };\n updatePointerAnchor({ x: px, y: py }, pointerSector);\n const snappingSecId = sectorIdAt(finalTl.x + bb.width / 2, finalTl.y + bb.height / 2) ?? undefined;\n updateSnapAnchor(snapInfo?.node ?? null, snappingSecId, snapInfo?.dist);\n setDraggingId(pieceId); // now onPointerMove will keep it in sync\n force();\n scheduleFrame();\n return;\n }\n\n // Drag mode: spawn at pointer with immediate drag\n svgRef.current?.setPointerCapture(e.pointerId);\n\n // Compute the local point of the blueprint glyph that was clicked\n const q = blueprintLocalFromWorld(px, py, bpGeom);\n // Compute TL so that the clicked point stays under the cursor\n const tl0 = { x: px - (q.x - bb.min.x), y: py - (q.y - bb.min.y) };\n const pointerR = Math.hypot(px - layout.cx, py - layout.cy);\n const allowInside = pointerR < layout.innerR;\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: bb, support },\n layout,\n controller.state.cfg.target,\n allowInside\n );\n const pieceId = controller.spawnFromBlueprint(bp, clamped);\n const pointerAnchorNode = anchorNodeFromPoint({ x: px, y: py });\n const pointerSector = sectorIdAt(px, py) ?? undefined;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event for blueprint spawn\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n pieceId,\n bp.id,\n blueprintType,\n 'blueprint',\n clamped,\n getPieceVertices(pieceId),\n undefined\n );\n }\n\n dragRef.current = {\n id: pieceId,\n dx: px - clamped.x,\n dy: py - clamped.y,\n tlx: clamped.x,\n tly: clamped.y,\n aabb: bb,\n minx: bb.min.x,\n miny: bb.min.y,\n support,\n fromIcon: true,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: undefined, // No original position for fromIcon drags\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n };\n updatePointerAnchor({ x: px, y: py }, pointerSector);\n updateSnapAnchor(null, undefined);\n setDraggingId(pieceId);\n force();\n scheduleFrame();\n };\n\n return {\n // State\n draggingId,\n dragInvalid: !!(dragRef.current && dragRef.current.validSnap === false),\n lockedPieceId,\n svgRef,\n \n // Handlers\n onPiecePointerDown,\n onBlueprintPointerDown,\n onPointerMove,\n onPointerUp,\n setPieceRef,\n \n // Click controller integration\n setDraggingId,\n\n // TODO: Remove this once click mode is extracted - temporary for compatibility\n dragRef\n };\n}\n","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { CircleLayout } from \"@/core/domain/layout\";\nimport { sectorAtPoint } from \"@/core/domain/layout\";\nimport { boundsOfBlueprint, computeSupportOffsets, clampTopLeftBySupport, piecePolysAt } from \"@/core/engine/geometry\";\nimport type { PieceData } from \"./usePieceState\";\n\n// Click controller state is managed internally with React hooks\n\n/**\n * Return interface for useClickController hook\n * \n * Provides click-based interaction functionality that works alongside\n * useDragController to support click-and-place interaction patterns.\n */\nexport interface ClickControllerHook {\n // State\n /** ID of pending blueprint for placement (from blueprint ring clicks) */\n pendingBpId: string | null;\n \n /** ID of currently selected piece (for click-to-move functionality) */\n selectedPieceId: string | null;\n \n // Handlers \n /** \n * Handler for root SVG clicks (placement, movement, deletion)\n * @param e - Pointer event from SVG root element\n */\n onRootPointerDown: (e: React.PointerEvent<SVGSVGElement>) => void;\n \n // Helper methods for drag controller integration\n /** Clear all selection state */\n clearSelection: () => void;\n \n /** \n * Set pending blueprint ID for placement\n * @param id - Blueprint ID or null to clear\n */\n setPendingBp: (id: string | null) => void;\n \n /** \n * Set selected piece ID for movement\n * @param id - Piece ID or null to clear\n */\n setSelectedPiece: (id: string | null) => void;\n}\n\n/**\n * Hook for managing click-based interactions in click input mode\n * \n * This hook works in conjunction with useDragController to provide click-and-place\n * interaction patterns. It manages the selection state for both blueprint icons and\n * live pieces, handling placement, movement, and deletion through click interactions.\n * \n * ## Click Interaction Patterns\n * - **Blueprint click**: Selects blueprint for placement (pendingBpId)\n * - **Piece click**: Starts \"carry\" state via drag controller integration\n * - **Empty click**: Places pending blueprint or moves selected piece\n * - **Center badge click**: Deletes carried/selected piece\n * - **Completed sector click**: Deletes pieces (invalid placement)\n * \n * ## State Management\n * - **pendingBpId**: Blueprint selected from ring, awaiting placement\n * - **selectedPieceId**: Live piece selected for movement\n * - **Integration with drag controller**: Uses draggingId for \"carry\" state\n * \n * ## Dependencies\n * This hook requires tight integration with useDragController as it uses the\n * drag controller's carry mechanism for piece movement in click mode.\n * \n * @param controller - BaseGameController for state management\n * @param layout - Computed CircleLayout for sector geometry\n * @param pieces - Current piece data from usePieceState\n * @param clickMode - Whether click input mode is active\n * @param draggingId - Current dragging piece ID from drag controller\n * @param setDraggingId - Setter for dragging ID (drag controller integration)\n * @param dragRef - Drag state ref from drag controller\n * @param isInsideBadge - Function to check if point is inside center badge\n * @param isSectorLocked - Function to check if sector is completed\n * @param maybeCompleteSector - Callback to check sector completion\n * @param svgPoint - Function to convert screen to SVG coordinates\n * @param force - Force React re-render function\n * @returns Hook interface with click state and handlers\n * \n * @example\n * ```typescript\n * const clickController = useClickController(\n * controller, layout, pieces, clickMode, \n * draggingId, setDraggingId, dragRef,\n * isInsideBadge, isSectorLocked, maybeCompleteSector, svgPoint, force\n * );\n * \n * // Usage in JSX:\n * <svg onPointerDown={clickController.onRootPointerDown}>\n * Game content\n * </svg>\n * ```\n */\nexport function useClickController(\n controller: BaseGameController,\n layout: CircleLayout,\n pieces: PieceData[],\n clickMode: boolean,\n draggingId: string | null,\n setDraggingId: (id: string | null) => void,\n dragRef: React.RefObject<any>,\n isInsideBadge: (x: number, y: number) => boolean,\n isSectorLocked: (id: string) => boolean,\n maybeCompleteSector: (secId: string) => boolean,\n svgPoint: (clientX: number, clientY: number) => { x: number; y: number },\n force: () => void,\n // Interaction tracking\n tracker?: {\n recordPlacedown: (\n outcome: 'placed' | 'deleted',\n sectorId?: string,\n position?: { x: number; y: number },\n vertices?: number[][][],\n anchorId?: string,\n wasValid?: boolean,\n wasOverlapping?: boolean,\n completedSector?: boolean\n ) => void;\n recordClickEvent?: (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => void;\n } | null\n): ClickControllerHook {\n const cfg = controller.state.cfg;\n const sectorIdAt = (x: number, y: number) => sectorAtPoint(x, y, layout, cfg.target);\n\n // Helper: Compute piece vertices in world space\n const getPieceVertices = (pieceId: string): number[][][] => {\n const piece = controller.findPiece(pieceId);\n if (!piece) return [];\n const bp = controller.getBlueprint(piece.blueprintId);\n if (!bp) return [];\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const polys = piecePolysAt(bp, bb, piece.pos);\n // Convert from {x,y}[][] to number[][][]\n return polys.map(ring => ring.map(pt => [pt.x, pt.y]));\n };\n\n const getCurrentAnchorInfo = () => {\n const d = dragRef.current;\n return {\n anchorId: d?.snapAnchorId ?? d?.pointerAnchorId ?? undefined,\n wasValid: d?.validSnap !== false,\n wasOverlapping: d?.overlaps ?? false,\n anchorX: d?.pointerAnchor?.x,\n anchorY: d?.pointerAnchor?.y,\n sectorId: d?.snapAnchorSectorId ?? d?.pointerAnchorSectorId\n };\n };\n\n const emitClickEvent = (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => {\n if (!tracker?.recordClickEvent) return;\n tracker.recordClickEvent(location, clickType, metadata);\n };\n\n // Click mode state\n const [pendingBpId, setPendingBpId] = React.useState<string | null>(null); // selected icon\n const [selectedPieceId, setSelectedPieceId] = React.useState<string | null>(null); // selected live piece\n\n const onRootPointerDown = (e: React.PointerEvent<SVGSVGElement>) => {\n const { x: px, y: py } = svgPoint(e.clientX, e.clientY);\n\n // --- CLICK MODE: second-click behaviors (move/delete/place)\n if (clickMode) {\n const secId = sectorIdAt(px, py);\n\n // If we're currently carrying a piece (draggingId set via click), this click commits (or deletes)\n if (draggingId && dragRef.current) {\n const d = dragRef.current;\n const centerX2 = d.tlx + d.aabb.width / 2;\n const centerY2 = d.tly + d.aabb.height / 2;\n\n // delete/cancel if clicked center (carry piece is already under pointer)\n if (isInsideBadge(px, py)) {\n const piece = controller.findPiece(d.id);\n const removedFromSector = piece?.sectorId;\n const anchorInfo = getCurrentAnchorInfo();\n controller.remove(d.id);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n anchorInfo.anchorId,\n anchorInfo.wasValid,\n anchorInfo.wasOverlapping\n );\n }\n\n // TODO: Remove dragRef manipulation once drag controller provides proper interface\n // dragRef.current = null; // Cannot assign to readonly property - drag controller should handle this\n setDraggingId(null);\n setSelectedPieceId(null);\n setPendingBpId(null);\n force();\n return; // don't toggle view\n }\n\n // Check if piece is in inner ring - if so, delete it\n const rFromCenter = Math.hypot(centerX2 - layout.cx, centerY2 - layout.cy);\n if (rFromCenter < layout.innerR) {\n const piece = controller.findPiece(d.id);\n const removedFromSector = piece?.sectorId;\n const anchorInfo = getCurrentAnchorInfo();\n controller.remove(d.id);\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n anchorInfo.anchorId,\n anchorInfo.wasValid,\n anchorInfo.wasOverlapping\n );\n }\n\n setDraggingId(null);\n setSelectedPieceId(null);\n setPendingBpId(null);\n force();\n return;\n }\n\n const secId2 = sectorIdAt(centerX2, centerY2);\n\n if (!secId2) {\n emitClickEvent(\n { x: centerX2, y: centerY2 },\n 'invalid_placement',\n { invalidPlacement: { reason: 'outside_bounds' } }\n );\n force();\n return;\n }\n\n if (isSectorLocked(secId2)) {\n emitClickEvent(\n { x: centerX2, y: centerY2 },\n 'sector_complete_attempt',\n { invalidPlacement: { reason: 'sector_complete', attemptedSectorId: secId2 } }\n );\n force();\n return;\n }\n\n // If the candidate is invalid for any reason (overlap / outside / bad node), keep carrying\n if (d.validSnap === false) {\n const anchorInfo = getCurrentAnchorInfo();\n const invalidReason = anchorInfo.wasOverlapping ? 'overlapping' : 'no_valid_anchor';\n emitClickEvent(\n { x: centerX2, y: centerY2 },\n 'invalid_placement',\n { invalidPlacement: { reason: invalidReason, attemptedSectorId: secId2 } }\n );\n force();\n return;\n }\n \n controller.move(d.id, { x: d.tlx, y: d.tly }); // TL already snapped (valid)\n controller.drop(d.id, secId2);\n\n const anchorInfo = getCurrentAnchorInfo();\n const justCompleted = maybeCompleteSector(secId2);\n\n // Record placedown as \"placed\" successfully\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n secId2,\n { x: d.tlx, y: d.tly },\n getPieceVertices(d.id),\n anchorInfo.anchorId,\n anchorInfo.wasValid,\n anchorInfo.wasOverlapping,\n justCompleted\n );\n }\n // TODO: Remove dragRef manipulation once drag controller provides proper interface\n // dragRef.current = null; // Cannot assign to readonly property - drag controller should handle this\n setDraggingId(null);\n setSelectedPieceId(null);\n setPendingBpId(null);\n // auto-revert AFTER placement completes (click mode)\n if (controller.state.blueprintView === \"primitives\") {\n controller.switchBlueprintView();\n }\n force();\n return;\n }\n\n // Selected piece → delete / move / deselect\n if (selectedPieceId) {\n if (isInsideBadge(px, py)) {\n const piece = controller.findPiece(selectedPieceId);\n const removedFromSector = piece?.sectorId;\n controller.remove(selectedPieceId);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown('deleted');\n }\n\n setSelectedPieceId(null);\n force();\n return; // DO NOT toggle view after delete\n }\n // Completed sector: no-op (do nothing, same as incomplete sector in silhouette mode)\n if (secId && isSectorLocked(secId)) {\n setSelectedPieceId(null);\n force();\n return;\n }\n if (secId) {\n const p = pieces.find(pp => pp.id === selectedPieceId);\n setSelectedPieceId(null);\n if (p) {\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const support = computeSupportOffsets(bp, bb);\n const tl0 = { x: px - bb.width / 2, y: py - bb.height / 2 };\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: { width: bb.width, height: bb.height }, support },\n layout,\n controller.state.cfg.target,\n false\n );\n\n const maxPieces = controller.state.cfg.maxCompositeSize ?? 0;\n if (controller.state.cfg.mode === \"prep\" && maxPieces > 0) {\n const sectorPieces = controller.getPiecesInSector(secId);\n const effectiveCount = sectorPieces.length - (p.sectorId === secId ? 1 : 0);\n if (effectiveCount + 1 > maxPieces) {\n force();\n return;\n }\n }\n\n controller.move(p.id, { x: clamped.x, y: clamped.y });\n controller.drop(p.id, secId);\n maybeCompleteSector(secId);\n force();\n }\n return;\n }\n // click outside → deselect only\n setSelectedPieceId(null);\n force();\n return;\n }\n\n // Pending icon → place\n if (pendingBpId) {\n const secId2 = sectorIdAt(px, py);\n\n if (isInsideBadge(px, py) || !secId2 || isSectorLocked(secId2)) {\n setPendingBpId(null); // cancel\n force();\n return;\n }\n\n const bp = controller.getBlueprint(pendingBpId)!;\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const support = computeSupportOffsets(bp, bb);\n const tl0 = { x: px - bb.width / 2, y: py - bb.height / 2 };\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: { width: bb.width, height: bb.height }, support },\n layout,\n controller.state.cfg.target,\n false\n );\n const id = controller.spawnFromBlueprint(bp, clamped);\n\n const maxPieces = controller.state.cfg.maxCompositeSize ?? 0;\n if (controller.state.cfg.mode === \"prep\" && maxPieces > 0) {\n const sectorPieces = controller.getPiecesInSector(secId2);\n if (sectorPieces.length + 1 > maxPieces) {\n controller.remove(id);\n setPendingBpId(null);\n force();\n return;\n }\n }\n\n controller.drop(id, secId2);\n setPendingBpId(null);\n maybeCompleteSector(secId2);\n\n // auto-revert AFTER placement completes (click mode)\n if (controller.state.blueprintView === \"primitives\") controller.switchBlueprintView();\n force();\n return;\n }\n }\n };\n\n return {\n // State\n pendingBpId,\n selectedPieceId,\n \n // Handlers\n onRootPointerDown,\n \n // Helper methods for integration\n clearSelection: () => {\n setSelectedPieceId(null);\n setPendingBpId(null);\n },\n setPendingBp: setPendingBpId,\n setSelectedPiece: setSelectedPieceId,\n };\n}\n","/**\n * InteractionTracker - Event accumulation and data tracking for experiments\n *\n * This class listens to game controller events and builds structured data\n * according to the data-tracking.ts schema. It generates InteractionEvent\n * objects and accumulates TrialEndData for export.\n *\n * ## Key Responsibilities\n * - Track interaction lifecycle (pickup → placedown)\n * - Accumulate click events and mouse tracking between interactions\n * - Generate InteractionEvent objects with state snapshots\n * - Build TrialEndData on trial completion\n * - Call onInteraction/onTrialEnd callbacks for data export\n *\n * ## Architecture\n * ```\n * User Interaction\n * ↓\n * UI Controllers (drag/click)\n * ↓\n * BaseGameController Events\n * ↓\n * InteractionTracker\n * ↓\n * onInteraction(event) → socket.emit()\n * onTrialEnd(data) → socket.emit()\n * ```\n */\n\nimport { v4 as uuidv4 } from 'uuid';\nimport type { BaseGameController } from '../engine/state/BaseGameController';\nimport { boundsOfBlueprint, piecePolysAt } from '../engine/geometry';\nimport { CONFIG } from '../config/config';\nimport type {\n InteractionEvent,\n StateSnapshot,\n ConstructionTrialData,\n PrepTrialData,\n DataTrackingCallbacks,\n SectorSnapshot,\n PieceSnapshot,\n MacroSnapshot\n} from './data-tracking';\n\n/**\n * Pickup event data (temporary storage until placedown)\n */\ninterface PickupData {\n pieceId: string;\n blueprintId: string;\n blueprintType: 'primitive' | 'composite';\n timestamp: number;\n source: 'blueprint' | 'sector';\n sectorId: string | undefined;\n position: { x: number; y: number };\n vertices: number[][][];\n}\n\n/**\n * Click event data (accumulated until interaction completes)\n */\ninterface ClickEventData {\n timestamp: number;\n location: { x: number; y: number };\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt';\n blueprintViewSwitch?: {\n from: 'quickstash' | 'primitives';\n to: 'quickstash' | 'primitives';\n };\n invalidPlacement?: {\n reason: 'overlapping' | 'outside_bounds' | 'no_valid_anchor' | 'sector_complete';\n attemptedSectorId?: string;\n };\n}\n\n/**\n * Mouse tracking event data (accumulated until interaction completes)\n */\ninterface MouseTrackingData {\n timestamp: number;\n anchorX: number;\n anchorY: number;\n sectorId: string | undefined;\n phase: 'before_pickup' | 'while_holding';\n}\n\n/**\n * InteractionTracker - Main tracking class\n */\nexport class InteractionTracker {\n // Callbacks\n private callbacks: DataTrackingCallbacks;\n\n // Controller reference\n private controller: BaseGameController;\n\n // Trial parameters\n private trialParams: any;\n\n // Trial timing\n private trialStartTime: number;\n private completionTimes: Array<{ sectorId: string; completedAt: number }> = [];\n\n // Sector centers (set by GameBoard after layout computation)\n private sectorCenters: { [sectorId: string]: { x: number; y: number } } = {};\n\n // Interaction state\n private interactionIndex: number = 0;\n private currentPickup: PickupData | null = null;\n private previousSnapshotId: string | undefined = undefined;\n\n // Event accumulation (reset after each interaction)\n private clickEvents: ClickEventData[] = [];\n private mouseTracking: MouseTrackingData[] = [];\n\n // Interaction history (for TrialEndData)\n private interactions: InteractionEvent[] = [];\n\n // Prep-specific tracking\n private createdMacros: MacroSnapshot[] = [];\n\n // Grid step for coordinate conversion\n private gridStep: number;\n\n constructor(\n controller: BaseGameController,\n callbacks: DataTrackingCallbacks,\n trialParams: any\n ) {\n this.controller = controller;\n this.callbacks = callbacks;\n this.trialParams = trialParams;\n this.trialStartTime = Date.now();\n this.gridStep = CONFIG.layout.grid.stepPx;\n\n // Register tracking callbacks with controller\n this.controller.setTrackingCallbacks({\n onSectorCompleted: (sectorId) => this.recordSectorCompletion(sectorId)\n });\n }\n\n /**\n * Cleanup method to unregister from controller\n */\n dispose(): void {\n this.controller.setTrackingCallbacks(null);\n }\n\n // ===== Event Recording Methods =====\n // Called by UI controllers to record events\n\n /**\n * Record piece pickup event\n */\n recordPickup(\n pieceId: string,\n blueprintId: string,\n blueprintType: 'primitive' | 'composite',\n source: 'blueprint' | 'sector',\n position: { x: number; y: number },\n vertices: number[][][],\n sectorId?: string\n ): void {\n const anchorPosition = this.toAnchorPoint(position);\n const anchorVertices = this.toAnchorVertices(vertices);\n\n this.currentPickup = {\n pieceId,\n blueprintId,\n blueprintType,\n timestamp: Date.now(),\n source,\n sectorId,\n position: anchorPosition,\n vertices: anchorVertices\n };\n\n // Mark all subsequent mouse tracking as \"while_holding\"\n // (UI controllers should call recordMouseMove after this)\n }\n\n /**\n * Record piece placedown event\n */\n recordPlacedown(\n outcome: 'placed' | 'deleted',\n sectorId?: string,\n position?: { x: number; y: number },\n vertices?: number[][][],\n anchorId?: string,\n wasValid?: boolean,\n wasOverlapping?: boolean,\n completedSector?: boolean\n ): void {\n if (!this.currentPickup) {\n console.warn('[InteractionTracker] recordPlacedown called without pickup');\n return;\n }\n\n const interactionType = this.determineInteractionType(this.currentPickup.source, outcome);\n const placedownTimestamp = Date.now();\n const holdDuration = placedownTimestamp - this.currentPickup.timestamp;\n\n // Build post-interaction snapshot\n // If this placement completes a sector, mark it in the snapshot\n const postSnapshot = this.buildStateSnapshot(completedSector ? sectorId : undefined);\n\n const anchorPosition = position ? this.toAnchorPoint(position) : undefined;\n const anchorVertices = vertices ? this.toAnchorVertices(vertices) : undefined;\n\n // Create interaction event - build incrementally to satisfy exactOptionalPropertyTypes\n const event: InteractionEvent = {\n // Metadata\n interactionId: uuidv4(),\n interactionIndex: this.interactionIndex++,\n\n // Interaction type\n interactionType,\n\n // Piece information\n pieceId: this.currentPickup.pieceId,\n blueprintId: this.currentPickup.blueprintId,\n blueprintType: this.currentPickup.blueprintType,\n\n // Pickup event\n pickupTimestamp: this.currentPickup.timestamp,\n pickupSource: this.currentPickup.source,\n pickupSectorId: this.currentPickup.sectorId,\n pickupPosition: this.currentPickup.position,\n pickupVertices: this.currentPickup.vertices,\n\n // Placedown event\n placedownTimestamp,\n placedownOutcome: outcome,\n\n // Validation context\n wasValid: outcome === 'placed' && wasValid === true,\n wasOverlapping: outcome === 'placed' && wasOverlapping === true,\n\n // Timing\n holdDuration,\n\n // Events\n clickEvents: [...this.clickEvents],\n mouseTracking: [...this.mouseTracking],\n\n // Snapshots\n postSnapshot\n };\n\n // Add optional placedown properties based on outcome\n if (outcome === 'placed' && sectorId) {\n event.placedownSectorId = sectorId;\n }\n if (outcome === 'placed' && anchorPosition) {\n event.placedownPosition = anchorPosition;\n }\n if (outcome === 'placed' && anchorVertices) {\n event.placedownVertices = anchorVertices;\n }\n if (anchorId) {\n event.placedownAnchorId = anchorId;\n }\n if (this.previousSnapshotId !== undefined) {\n event.preSnapshotId = this.previousSnapshotId;\n }\n\n // Store for trial end data\n this.interactions.push(event);\n this.previousSnapshotId = postSnapshot.snapshotId;\n\n // Call interaction callback\n if (this.callbacks.onInteraction) {\n this.callbacks.onInteraction(event);\n }\n\n // Reset interaction state\n this.currentPickup = null;\n this.clickEvents = [];\n this.mouseTracking = [];\n }\n\n /**\n * Record click event\n */\n recordClickEvent(\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: {\n blueprintViewSwitch?: { from: 'quickstash' | 'primitives'; to: 'quickstash' | 'primitives' };\n invalidPlacement?: { reason: 'overlapping' | 'outside_bounds' | 'no_valid_anchor' | 'sector_complete'; attemptedSectorId?: string };\n }\n ): void {\n const anchorLocation = this.toAnchorPoint(location);\n\n this.clickEvents.push({\n timestamp: Date.now(),\n location: anchorLocation,\n clickType,\n ...metadata\n });\n }\n\n /**\n * Record mouse movement to different anchor\n */\n recordMouseMove(\n anchorX: number,\n anchorY: number,\n sectorId?: string\n ): void {\n const phase: 'before_pickup' | 'while_holding' = this.currentPickup ? 'while_holding' : 'before_pickup';\n const anchorCoordX = this.toAnchorValue(anchorX);\n const anchorCoordY = this.toAnchorValue(anchorY);\n\n // Only record if anchor position changed\n const lastTracking = this.mouseTracking[this.mouseTracking.length - 1];\n if (lastTracking && lastTracking.anchorX === anchorCoordX && lastTracking.anchorY === anchorCoordY) {\n return; // Same position, skip\n }\n\n this.mouseTracking.push({\n timestamp: Date.now(),\n anchorX: anchorCoordX,\n anchorY: anchorCoordY,\n sectorId,\n phase\n });\n }\n\n /**\n * Set sector centers (for anchor alignment)\n */\n setSectorCenters(centers: { [sectorId: string]: { x: number; y: number } }): void {\n this.sectorCenters = centers;\n }\n\n /**\n * Record a sector completion event\n */\n recordSectorCompletion(sectorId: string): void {\n this.completionTimes.push({\n sectorId,\n completedAt: Date.now()\n });\n }\n\n /**\n * Record macro creation (prep mode only)\n */\n recordMacroCreation(macro: MacroSnapshot): void {\n this.createdMacros.push(macro);\n }\n\n // ===== Trial Completion =====\n\n /**\n * Finalize trial and call onTrialEnd callback\n */\n finalizeTrial(endReason: 'timeout' | 'auto_complete' | 'submit'): void {\n const trialEndTime = Date.now();\n const totalDuration = trialEndTime - this.trialStartTime;\n const finalSnapshot = this.buildStateSnapshot();\n\n // Calculate anchor to stimuli ratio (grid step in stimuli units)\n // CONFIG.layout.grid.stepPx is the pixel size of one anchor unit\n // CONFIG.layout.grid.unitPx is the pixel size of one stimuli unit (UNIT in tangram.py)\n // So the ratio is stepPx / unitPx (typically 20 / 40 = 0.5)\n const anchorToStimuliRatio = CONFIG.layout.grid.stepPx / CONFIG.layout.grid.unitPx;\n\n const mode = this.controller.state.cfg.mode;\n\n if (mode === 'construction') {\n const finalBlueprintState = this.buildFinalBlueprintState(finalSnapshot);\n\n // Extract composites as quickstash macros (ready for next trial input)\n const quickstashMacros = finalBlueprintState\n .filter(bp => bp.blueprintType === 'composite')\n .map(bp => ({\n id: bp.blueprintId,\n parts: bp.parts!, // Composites always have parts\n ...(bp.label && { label: bp.label })\n }));\n\n const data: ConstructionTrialData = {\n trialType: 'construction',\n trialStartTime: this.trialStartTime,\n trialEndTime,\n totalDuration,\n anchorToStimuliRatio,\n trialParams: this.trialParams,\n endReason: endReason as 'timeout' | 'auto_complete',\n completionTimes: this.completionTimes,\n finalBlueprintState,\n quickstashMacros,\n finalSnapshot\n };\n\n if (this.callbacks.onTrialEnd) {\n this.callbacks.onTrialEnd(data);\n }\n } else {\n const finalMacros = this.createdMacros.length\n ? this.createdMacros\n : this.buildMacrosFromSnapshot(finalSnapshot);\n\n // Convert MacroSnapshot to quickstash input format\n // Ensure IDs start with \"comp:\" for proper border rendering\n const quickstashMacros = finalMacros.map(macro => ({\n id: macro.macroId.startsWith('comp:') ? macro.macroId : `comp:${macro.macroId}`,\n parts: macro.parts\n // Note: label not included in prep macros\n }));\n\n const data: PrepTrialData = {\n trialType: 'prep',\n trialStartTime: this.trialStartTime,\n trialEndTime,\n totalDuration,\n anchorToStimuliRatio,\n trialParams: this.trialParams,\n endReason: 'submit',\n createdMacros: finalMacros,\n quickstashMacros,\n finalSnapshot\n };\n\n if (this.callbacks.onTrialEnd) {\n this.callbacks.onTrialEnd(data);\n }\n }\n }\n\n // ===== Helper Methods =====\n\n /**\n * Determine interaction type from source and outcome\n */\n private determineInteractionType(\n source: 'blueprint' | 'sector',\n outcome: 'placed' | 'deleted'\n ): 'spawn' | 'move' | 'delete' {\n if (outcome === 'deleted') return 'delete';\n if (source === 'blueprint') return 'spawn';\n return 'move';\n }\n\n private toAnchorValue(value: number): number {\n return Math.round(value / this.gridStep);\n }\n\n private toAnchorPoint(point: { x: number; y: number }): { x: number; y: number } {\n return { x: this.toAnchorValue(point.x), y: this.toAnchorValue(point.y) };\n }\n\n private toAnchorVertices(vertices: number[][][]): number[][][] {\n return vertices.map(ring =>\n ring.map(vertex => [\n this.toAnchorValue(vertex[0]!),\n this.toAnchorValue(vertex[1]!)\n ])\n );\n }\n\n private buildMacrosFromSnapshot(snapshot: StateSnapshot): MacroSnapshot[] {\n return snapshot.sectors.map(sec => {\n // STEP 1: Convert bbox positions to shape origin positions in anchor coordinates\n const shapeOriginPositions = sec.pieces.map(piece => {\n const bp = this.controller.getBlueprint(piece.blueprintId);\n const kind = bp && 'kind' in bp ? bp.kind : piece.blueprintId;\n\n // Get the piece's actual position in pixels from controller state\n const actualPiece = this.controller.findPiece(piece.pieceId);\n if (!actualPiece || !bp) {\n return {\n kind,\n position: piece.position // Fallback to bbox position\n };\n }\n\n // Get bounding box of the blueprint using the geometry helper\n const bb = boundsOfBlueprint(bp, this.controller.getPrimitive);\n\n // Convert bbox position to shape origin position\n // In pixels: shapeOriginPos = piece.pos - bb.min\n // Then convert to anchor coordinates\n const shapeOriginPixels = {\n x: actualPiece.pos.x - bb.min.x,\n y: actualPiece.pos.y - bb.min.y\n };\n const shapeOriginAnchor = this.toAnchorPoint(shapeOriginPixels);\n\n return {\n kind,\n position: shapeOriginAnchor // Shape origin in anchor coordinates\n };\n });\n\n // STEP 2: Calculate centroid and convert to relative offsets\n if (shapeOriginPositions.length === 0) {\n return {\n macroId: sec.sectorId,\n parts: [],\n shape: [],\n pieceCount: 0\n };\n }\n\n // Calculate centroid of all pieces (in anchor coordinates)\n let sumX = 0, sumY = 0;\n for (const item of shapeOriginPositions) {\n sumX += item.position.x;\n sumY += item.position.y;\n }\n const centroidX = Math.round(sumX / shapeOriginPositions.length);\n const centroidY = Math.round(sumY / shapeOriginPositions.length);\n\n // Convert absolute positions to relative offsets (like ANCHOR_COMPOSITES format)\n const parts = shapeOriginPositions.map(item => ({\n kind: item.kind,\n anchorOffset: {\n x: Math.round(item.position.x - centroidX),\n y: Math.round(item.position.y - centroidY)\n }\n }));\n\n const shape = sec.pieces.flatMap(piece => piece.vertices || []);\n\n return {\n macroId: sec.sectorId,\n parts,\n shape,\n pieceCount: sec.pieceCount\n };\n });\n }\n\n /**\n * Build state snapshot from current controller state\n * @param justCompletedSectorId - Sector ID that was just completed (but controller state hasn't updated yet)\n */\n private buildStateSnapshot(justCompletedSectorId?: string): StateSnapshot {\n const snapshotId = uuidv4();\n const timestamp = Date.now();\n\n // Build sector snapshots\n const sectors: SectorSnapshot[] = [];\n const completedSectorIds: string[] = [];\n\n for (const sector of this.controller.state.cfg.sectors) {\n const sectorState = this.controller.state.sectors[sector.id];\n // Check if this sector was just completed OR is already completed\n const completed = sector.id === justCompletedSectorId || !!sectorState?.completedAt;\n\n if (completed) {\n completedSectorIds.push(sector.id);\n }\n\n const pieces: PieceSnapshot[] = (sectorState?.pieces || []).map(p => ({\n pieceId: p.id,\n blueprintId: p.blueprintId,\n blueprintType: this.getBlueprintType(p.blueprintId),\n position: this.toAnchorPoint(p.pos),\n vertices: this.getPieceVertices(p.id)\n }));\n\n const snapshot: SectorSnapshot = {\n sectorId: sector.id,\n completed,\n pieceCount: pieces.length,\n pieces,\n center: this.sectorCenters[sector.id] ? this.toAnchorPoint(this.sectorCenters[sector.id]) : undefined\n };\n\n if (sectorState?.completedAt !== undefined) {\n snapshot.completedAt = sectorState.completedAt;\n }\n\n sectors.push(snapshot);\n }\n\n // Build sector-tangram map\n const sectorTangramMap = this.controller.state.cfg.sectors.map(s => ({\n sectorId: s.id,\n tangramId: s.tangramId\n }));\n\n // Build blueprint order\n const blueprintOrder = {\n primitives: this.controller.state.primitives.map(bp => bp.id),\n quickstash: this.controller.state.quickstash.map(bp => bp.id)\n };\n\n return {\n snapshotId,\n timestamp,\n sectors,\n completedSectorIds,\n sectorTangramMap,\n blueprintOrder\n };\n }\n\n /**\n * Get blueprint type from blueprint ID\n */\n private getBlueprintType(blueprintId: string): 'primitive' | 'composite' {\n const bp = this.controller.getBlueprint(blueprintId);\n if (!bp) return 'primitive'; // Fallback\n return 'kind' in bp ? 'primitive' : 'composite';\n }\n\n /**\n * Get piece vertices in world space\n */\n private getPieceVertices(pieceId: string): number[][][] {\n const piece = this.controller.findPiece(pieceId);\n if (!piece) return [];\n\n const bp = this.controller.getBlueprint(piece.blueprintId);\n if (!bp) return [];\n\n const bb = boundsOfBlueprint(bp, (k) => this.controller.getPrimitive(k));\n const polys = piecePolysAt(bp, bb, piece.pos) ?? [];\n const asNumbers = polys.map(ring => ring.map(pt => [pt.x, pt.y] as [number, number]));\n return this.toAnchorVertices(asNumbers);\n }\n\n /**\n * Build final blueprint state (usage counts + definitions)\n */\n private buildFinalBlueprintState(snapshot: StateSnapshot): Array<{\n blueprintId: string;\n blueprintType: 'primitive' | 'composite';\n totalPieces: number;\n bySector: Array<{ sectorId: string; count: number }>;\n parts?: Array<{ kind: string; anchorOffset: { x: number; y: number } }>;\n shape?: Array<Array<{ x: number; y: number }>>;\n label?: string;\n }> {\n const counts = new Map<string, {\n blueprintType: 'primitive' | 'composite';\n totalPieces: number;\n bySector: Map<string, number>;\n }>();\n\n // Accumulate counts\n for (const sector of snapshot.sectors) {\n for (const piece of sector.pieces) {\n if (!counts.has(piece.blueprintId)) {\n counts.set(piece.blueprintId, {\n blueprintType: piece.blueprintType,\n totalPieces: 0,\n bySector: new Map()\n });\n }\n\n const entry = counts.get(piece.blueprintId)!;\n entry.totalPieces++;\n entry.bySector.set(sector.sectorId, (entry.bySector.get(sector.sectorId) || 0) + 1);\n }\n }\n\n // Ensure all primitives are represented, even if count is zero\n for (const primitive of this.controller.state.primitives) {\n if (!counts.has(primitive.id)) {\n counts.set(primitive.id, {\n blueprintType: 'primitive',\n totalPieces: 0,\n bySector: new Map()\n });\n }\n }\n\n // Ensure all composites are represented, even if count is zero\n for (const composite of this.controller.state.quickstash) {\n if (!counts.has(composite.id)) {\n counts.set(composite.id, {\n blueprintType: 'composite',\n totalPieces: 0,\n bySector: new Map()\n });\n }\n }\n\n // Convert to array format with blueprint definitions\n return Array.from(counts.entries()).map(([blueprintId, data]) => {\n const blueprint = this.controller.getBlueprint(blueprintId);\n\n const result: {\n blueprintId: string;\n blueprintType: 'primitive' | 'composite';\n totalPieces: number;\n bySector: Array<{ sectorId: string; count: number }>;\n parts?: Array<{ kind: string; anchorOffset: { x: number; y: number } }>;\n shape?: Array<Array<{ x: number; y: number }>>;\n label?: string;\n } = {\n blueprintId,\n blueprintType: data.blueprintType,\n totalPieces: data.totalPieces,\n bySector: Array.from(data.bySector.entries()).map(([sectorId, count]) => ({\n sectorId,\n count\n }))\n };\n\n // Add blueprint definition for both primitives and composites\n if (blueprint) {\n if (data.blueprintType === 'composite' && 'parts' in blueprint) {\n // Composite blueprint: convert pixel-based parts to anchor-based parts\n result.parts = blueprint.parts.map(part => ({\n kind: part.kind,\n anchorOffset: {\n x: Math.round(part.offset.x / this.gridStep),\n y: Math.round(part.offset.y / this.gridStep)\n }\n }));\n\n // Convert pixel-based shape to anchor-based shape\n if (blueprint.shape) {\n result.shape = blueprint.shape.map(poly =>\n poly.map(vertex => ({\n x: Math.round(vertex.x / this.gridStep),\n y: Math.round(vertex.y / this.gridStep)\n }))\n );\n }\n\n // Add label if available\n if (blueprint.label) {\n result.label = blueprint.label;\n }\n } else if (data.blueprintType === 'primitive' && 'kind' in blueprint) {\n // Primitive blueprint: convert pixel-based shape to anchor-based shape\n if (blueprint.shape) {\n result.shape = blueprint.shape.map(poly =>\n poly.map(vertex => ({\n x: Math.round(vertex.x / this.gridStep),\n y: Math.round(vertex.y / this.gridStep)\n }))\n );\n }\n\n // Primitives don't have labels, but we could add a default one based on kind\n result.label = blueprint.kind;\n }\n }\n\n return result;\n });\n }\n}\n","/**\n * GameBoard - Core reusable tangram game board component\n *\n * This component provides the complete tangram game functionality that can be\n * shared between jsPsych plugins. It handles both construction and preparation\n * game modes with full interaction support.\n *\n * ## Key Features\n * - **Dependency Injection**: All game content provided via props (no hardcoded data)\n * - **Multiple Input Modes**: Supports both click and drag interactions\n * - **Layout Flexibility**: Circle and semicircle layout modes\n * - **Event Tracking**: Comprehensive data collection for research\n * - **State Management**: Uses BaseGameController for robust state handling\n *\n * ## Architecture\n * - Uses modern React patterns with hooks\n * - Integrates with BaseGameController for state management\n * - Renders via Board component with computed layout\n * - Handles completion events and data collection\n *\n * ## Usage in Plugins\n * ```typescript\n * // In jsPsych plugin trial method:\n * const root = createRoot(display_element);\n * root.render(React.createElement(GameBoard, {\n * sectors: convertedSectors,\n * quickstash: convertedMacros,\n * primitives: PRIMITIVE_BLUEPRINTS,\n * layout: \"semicircle\",\n * target: \"silhouette\",\n * input: \"drag\",\n * onComplete: handleTrialComplete\n * }));\n * ```\n *\n * @see {@link BaseGameController} For state management details\n * @see {@link Board} For rendering implementation\n * @since Phase 3.3 - Extracted from monolithic Board component\n * @author Claude Code Assistant\n */\n\nimport React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type {\n Sector,\n Blueprint,\n PrimitiveBlueprint,\n LayoutMode,\n PlacementTarget,\n InputMode\n} from \"@/core/domain/types\";\nimport { computeCircleLayout, rectForBand } from \"@/core/domain/layout\";\nimport { solveLogicalBox } from \"@/core/domain/solve\";\nimport type { Poly } from \"@/core/domain/types\";\nimport { CONFIG } from \"@/core/config/config\";\nimport BoardView, { type AnchorDots as DotsType } from \"./BoardView\";\nimport {\n inferUnitFromPolys,\n placeSilhouetteGridAlignedAsPolys } from \"@/core/engine/geometry\";\nimport { anchorsSilhouetteComplete, anchorsWorkspaceComplete } from \"@/core/engine/validation/complete\";\nimport { scalePolys } from \"@/core/components/board/utils\";\nimport { usePieceState } from \"@/core/components/board/usePieceState\";\nimport { useAnchorGrid } from \"@/core/components/board/useAnchorGrid\";\nimport { useDragController } from \"@/core/components/board/useDragController\";\nimport { useClickController } from \"@/core/components/board/useClickController\";\nimport { InteractionTracker } from \"@/core/io/InteractionTracker\";\n\n/**\n * Configuration interface for GameBoard component\n *\n * This interface defines all the required game content and behavior settings\n * that must be provided to the GameBoard component. All properties use\n * dependency injection - no defaults are provided.\n */\nexport interface GameBoardConfig {\n /**\n * Array of sector definitions containing target silhouettes to construct\n * Each sector represents one puzzle to solve\n */\n sectors: Sector[];\n\n /**\n * Array of pre-made composite piece blueprints (macros)\n * Usually created in prep trials and passed to construction trials\n */\n quickstash: Blueprint[];\n\n /**\n * Array of primitive tangram piece definitions\n * These are the basic 7 tangram shapes that never change\n */\n primitives: PrimitiveBlueprint[];\n\n /**\n * Layout mode for the game board\n * - \"circle\": Full circular layout with pieces arranged in complete circle\n * - \"semicircle\": Half-circle layout with pieces in arc above workspace\n */\n layout: LayoutMode;\n\n /**\n * Target placement mode for piece validation\n * - \"workspace\": Pieces can be placed freely in workspace area\n * - \"silhouette\": Pieces must be placed within target silhouette bounds\n */\n target: PlacementTarget;\n\n /**\n * Input interaction mode\n * - \"click\": Click to select pieces, click to place (better for touch)\n * - \"drag\": Drag pieces directly with mouse/touch\n */\n input: InputMode;\n\n /**\n * Time limit for the trial in milliseconds\n * Set to 0 for no time limit\n */\n timeLimitMs: number;\n\n /**\n * Maximum number of quickstash/macro slots to display\n * Controls size of the macro selection ring\n */\n maxQuickstashSlots: number;\n\n /**\n * Maximum number of primitive pieces allowed in a composite\n * Used for validation when creating macros (prep mode only)\n */\n maxCompositeSize?: number;\n\n /**\n * Game mode to determine behavior differences\n * - \"construction\": Standard puzzle-solving mode with toggle\n * - \"prep\": Macro creation mode with primitives-only center\n */\n mode?: \"construction\" | \"prep\";\n\n /**\n * Minimum pieces required per macro (prep mode only)\n * Used for submit button validation\n */\n minPiecesPerMacro?: number;\n\n /**\n * Whether all slots must be filled to complete trial (prep mode only)\n * Used for submit button validation\n */\n requireAllSlots?: boolean;\n\n /**\n * Whether to show tangram target shapes decomposed into individual primitives with borders\n * Independent from showBorders/hideTouchingBorders (which control spawned pieces)\n */\n showTangramDecomposition?: boolean;\n\n /**\n * HTML content to display above the gameboard as instructions\n * Allows rich formatting via HTML\n */\n instructions?: string;\n\n /**\n * Cleaned jsPsych plugin parameters (excluding callbacks)\n * Saved to trial data for analysis\n */\n trialParams?: any;\n\n /** Optional CSS width for the game board SVG */\n width?: number;\n\n /** Optional CSS height for the game board SVG */\n height?: number;\n}\n\n/**\n * Props interface for GameBoard component, extending configuration with event callbacks\n *\n * This interface includes all configuration options plus optional event handlers\n * that plugins can use to respond to game events and collect data.\n */\nexport interface GameBoardProps extends GameBoardConfig {\n /**\n * Called when an individual sector is completed\n * Useful for tracking progress through multi-sector trials\n */\n onSectorComplete?: (sectorId: string, snapshot: any) => void;\n\n /**\n * Called when a piece is successfully placed in a sector\n * Useful for real-time interaction tracking\n */\n onPiecePlace?: (pieceId: string, sectorId: string) => void;\n\n /**\n * Called when a piece is removed from a sector\n * Useful for tracking piece manipulation patterns\n */\n onPieceRemove?: (pieceId: string) => void;\n\n /**\n * Called immediately after each complete interaction (piece pickup + placedown)\n * Use for incremental data saving (e.g., socket.emit())\n */\n onInteraction?: (event: any) => void;\n\n /**\n * Called once when trial ends\n * Contains complete interaction history + final state\n * This is the primary mechanism for trial completion - plugins should handle\n * React cleanup and jsPsych.finishTrial() in their wrapper for this callback\n */\n onTrialEnd?: (data: any) => void;\n\n /**\n * Called when the game controller is ready\n * Useful for spawning initial pieces or setting up state\n */\n onControllerReady?: (controller: BaseGameController, layout?: any, force?: () => void) => void;\n\n /**\n * Whether to use distinct colors for each primitive shape type in blueprints\n * When true, each primitive type (square, triangle, etc.) gets its own color in dock area\n */\n usePrimitiveColorsBlueprints?: boolean;\n\n /**\n * Whether to use distinct colors for each primitive shape type in target tangrams\n * When true, each primitive type gets its own color in target silhouettes\n */\n usePrimitiveColorsTargets?: boolean;\n\n /**\n * Array of 5 integers mapping primitives to colors from CONFIG.color.primitiveColors\n * Maps [square, smalltriangle, parallelogram, medtriangle, largetriangle] to color indices\n */\n primitiveColorIndices?: number[];\n}\n\n/**\n * Core GameBoard component that encapsulates all tangram game functionality\n *\n * This is the main reusable component that provides complete tangram game\n * functionality for jsPsych plugins. It handles all aspects of the game\n * including piece interaction, collision detection, completion validation,\n * and data collection.\n *\n * ## Key Responsibilities\n * - Creates and manages BaseGameController for state management\n * - Computes layout geometry for board rendering\n * - Handles event callbacks for plugin integration\n * - Manages CSS sizing for responsive display\n *\n * ## State Management\n * Uses BaseGameController internally which provides:\n * - Piece placement and validation\n * - Sector completion tracking\n * - Event logging for data collection\n * - Collision detection and snapping\n *\n * @param props - Configuration and event callbacks for the game\n * @returns React component rendering the complete tangram game interface\n */\nexport default function GameBoard(props: GameBoardProps) {\n const {\n sectors,\n quickstash,\n primitives,\n layout: layoutMode,\n target,\n input,\n timeLimitMs,\n maxQuickstashSlots,\n maxCompositeSize,\n mode,\n showTangramDecomposition,\n instructions,\n trialParams,\n width: _width,\n height: _height,\n onSectorComplete,\n onPiecePlace,\n onPieceRemove,\n onInteraction,\n onTrialEnd,\n onControllerReady,\n usePrimitiveColorsBlueprints,\n usePrimitiveColorsTargets,\n primitiveColorIndices,\n } = props;\n\n // Timer state for countdown\n const [timeRemaining, setTimeRemaining] = React.useState(timeLimitMs > 0 ? Math.floor(timeLimitMs / 1000) : 0);\n\n // Initialize game controller with injected data\n const controller = React.useMemo(() => {\n const gameConfig = {\n n: sectors.length,\n layout: layoutMode,\n target,\n input,\n timeLimitMs,\n maxQuickstashSlots,\n ...(maxCompositeSize !== undefined && { maxCompositeSize }),\n mode: mode || \"construction\", // Default to construction mode for backwards compatibility\n ...(props.minPiecesPerMacro !== undefined && { minPiecesPerMacro: props.minPiecesPerMacro }),\n ...(props.requireAllSlots !== undefined && { requireAllSlots: props.requireAllSlots })\n };\n\n return new BaseGameController(\n sectors,\n quickstash,\n primitives,\n gameConfig\n );\n }, [sectors, quickstash, primitives, layoutMode, target, input, timeLimitMs, maxQuickstashSlots, maxCompositeSize, mode, props.minPiecesPerMacro, props.requireAllSlots]);\n\n // Initialize interaction tracker for data collection (if callbacks provided)\n const tracker = React.useMemo(() => {\n if (!onInteraction && !onTrialEnd) return null;\n\n const callbacks: { onInteraction?: (event: any) => void; onTrialEnd?: (data: any) => void } = {};\n if (onInteraction) callbacks.onInteraction = onInteraction;\n if (onTrialEnd) callbacks.onTrialEnd = onTrialEnd;\n\n return new InteractionTracker(controller, callbacks, trialParams);\n }, [controller, onInteraction, onTrialEnd, trialParams]);\n\n // Call onControllerReady when controller is ready\n React.useEffect(() => {\n if (onControllerReady) {\n onControllerReady(controller);\n }\n }, [controller, onControllerReady]);\n\n // Cleanup tracker on unmount\n React.useEffect(() => {\n return () => {\n if (tracker) {\n tracker.dispose();\n }\n };\n }, [tracker]);\n\n // Compute layout geometry\n const { layout, viewBox } = React.useMemo(() => {\n const nSectors = sectors.length;\n const sectorIds = sectors.map(s => s.id);\n const masksPerSector: Poly[][] = sectors.map(s => s.silhouette.mask ?? []);\n\n const logicalBox = solveLogicalBox({\n n: nSectors,\n layoutMode,\n target,\n qsMaxSlots: maxQuickstashSlots,\n primitivesSlots: primitives.length,\n layoutPadPx: CONFIG.layout.paddingPx,\n masks: masksPerSector,\n });\n\n const layout = computeCircleLayout(\n { w: logicalBox.LOGICAL_W, h: logicalBox.LOGICAL_H },\n nSectors,\n sectorIds,\n layoutMode,\n target,\n {\n qsMaxSlots: maxQuickstashSlots,\n primitivesSlots: primitives.length,\n masks: masksPerSector,\n }\n );\n\n return {\n layout,\n viewBox: { w: logicalBox.LOGICAL_W, h: logicalBox.LOGICAL_H }\n };\n }, [sectors, layoutMode, target, maxQuickstashSlots, primitives.length]);\n\n // Update tracker with sector centers whenever layout changes\n React.useEffect(() => {\n if (tracker && layout) {\n const centers: { [sectorId: string]: { x: number; y: number } } = {};\n layout.sectors.forEach(s => {\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n centers[s.id] = { x: rect.cx, y: rect.cy };\n });\n tracker.setSectorCenters(centers);\n }\n }, [tracker, layout]);\n\n // Force re-render utility\n const [, force] = React.useReducer((x) => x + 1, 0);\n\n // Call onControllerReady when controller and layout are ready\n React.useEffect(() => {\n if (onControllerReady) {\n onControllerReady(controller, layout, force);\n }\n }, [controller, layout, onControllerReady, force]);\n\n // Game completion tracking\n const [gameCompleted, setGameCompleted] = React.useState(false);\n\n // Watch for game completion\n React.useEffect(() => {\n const checkGameCompletion = () => {\n const allSectorsComplete = sectors.every(s =>\n controller.isSectorCompleted(s.id)\n );\n\n if (allSectorsComplete && !gameCompleted) {\n setGameCompleted(true);\n\n // Finalize trial data tracking (which calls onTrialEnd)\n // Defer to avoid unmounting React while still in commit phase\n if (tracker) {\n setTimeout(() => {\n tracker.finalizeTrial('auto_complete');\n }, 0);\n }\n }\n };\n\n // Check completion whenever controller state updates\n checkGameCompletion();\n }, [controller.updateCount, sectors, gameCompleted, controller, tracker]);\n\n // Sector completion callback\n const handleSectorComplete = React.useCallback((sectorId: string) => {\n if (onSectorComplete) {\n onSectorComplete(sectorId, controller.snapshot());\n }\n }, [onSectorComplete, controller]);\n\n // Event callbacks for plugin integration\n const eventCallbacks = React.useMemo(() => ({\n onSectorComplete: handleSectorComplete,\n onPiecePlace: onPiecePlace || (() => {}),\n onPieceRemove: onPieceRemove || (() => {})\n }), [handleSectorComplete, onPiecePlace, onPieceRemove]);\n\n // Calculate sizing based on layout mode\n const getGameboardStyle = () => {\n const baseStyle = {\n margin: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n position: 'relative' as const,\n };\n\n if (layoutMode === 'circle') {\n // Circle mode: square aspect ratio (height == width)\n const size = Math.min(window.innerWidth * CONFIG.layout.viewportScale, window.innerHeight * CONFIG.layout.viewportScale);\n return {\n ...baseStyle,\n width: `${size}px`,\n height: `${size}px`,\n };\n } else {\n // Semicircle mode: width is 2x height\n const maxWidth = Math.min(window.innerWidth * CONFIG.layout.viewportScale, window.innerHeight * CONFIG.layout.viewportScale * 2);\n const maxHeight = Math.min(window.innerWidth * CONFIG.layout.viewportScale / 2, window.innerHeight * CONFIG.layout.viewportScale);\n return {\n ...baseStyle,\n width: `${maxWidth}px`,\n height: `${maxHeight}px`,\n };\n }\n };\n\n // Calculate SVG dimensions to pass to Board component\n const getSvgDimensions = () => {\n if (layoutMode === 'circle') {\n // Circle mode: square aspect ratio (height == width)\n const size = Math.min(window.innerWidth * 0.96, window.innerHeight * 0.96);\n return { width: size, height: size };\n } else {\n // Semicircle mode: width is 2x height\n const maxWidth = Math.min(window.innerWidth * 0.96, window.innerHeight * 0.96 * 2);\n const maxHeight = Math.min(window.innerWidth * 0.96 / 2, window.innerHeight * 0.96);\n return { width: maxWidth, height: maxHeight };\n }\n };\n\n const svgDimensions = getSvgDimensions();\n\n React.useEffect(() => {\n if (controller.state.cfg.mode !== \"construction\") return;\n if (!timeLimitMs || timeLimitMs <= 0) return;\n if (gameCompleted) return;\n\n const timeoutId = window.setTimeout(() => {\n if (gameCompleted) return;\n\n if (!controller.state.endedAt) {\n controller.state.endedAt = performance.now();\n force();\n }\n\n tracker?.finalizeTrial('timeout');\n setGameCompleted(true);\n }, timeLimitMs);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [controller, timeLimitMs, gameCompleted, tracker, force]);\n\n const isSectorLocked = (id: string) => controller.isSectorCompleted(id);\n\n // Extract piece management to custom hook\n const { pieces, pieceById, getSectorPiecePolysCached } = usePieceState(controller);\n\n const clickMode = controller.state.cfg.input === \"click\";\n\n // Center badge geometry (visual + click target are identical)\n const badgeR = Math.max(CONFIG.size.centerBadge.minPx, layout.innerR * CONFIG.size.centerBadge.fractionOfOuterR);\n const badgeCenter = (controller.state.cfg.layout === \"semicircle\")\n ? { x: layout.cx, y: layout.cy - badgeR - CONFIG.size.centerBadge.marginPx }\n : { x: layout.cx, y: layout.cy };\n const isInsideBadge = (px: number, py: number) =>\n Math.hypot(px - badgeCenter.x, py - badgeCenter.y) <= badgeR;\n\n // All sector masks (raw)\n const allMasks: Poly[][] = React.useMemo(() => {\n return controller.state.cfg.sectors.map(sec => (sec.silhouette.mask ?? []));\n }, [controller.state.cfg.sectors]);\n\n // Canonical lattice scale: 1 raw UNIT → CONFIG.layout.grid.unitPx (so a unit edge = 2 grid nodes)\n // Keep a single scale so lattice density stays invariant across devices/zoom levels.\n const scaleS = React.useMemo(() => {\n const u = inferUnitFromPolys(allMasks.flat());\n return u ? (CONFIG.layout.grid.unitPx / u) : 1;\n }, [allMasks]);\n\n // Extract anchor grid logic to custom hook\n const { anchorDots } = useAnchorGrid(controller, layout, scaleS);\n\n // Placed silhouettes per sector (grid-aligned polys used for inclusion tests)\n const placedSilBySector = React.useMemo(() => {\n const m = new Map<string, Poly[]>();\n for (const s of layout.sectors) {\n const mask = controller.state.cfg.sectors.find(ss => ss.id === s.id)?.silhouette.mask ?? [];\n if (!mask?.length) continue;\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const placed = placeSilhouetteGridAlignedAsPolys(mask, scaleS, { cx: rect.cx, cy: rect.cy });\n m.set(s.id, placed);\n }\n return m;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [layout, scaleS, controller.state.cfg.sectors]);\n\n const maybeCompleteSector = (secId: string): boolean => {\n if (!secId) return false;\n if (isSectorLocked(secId)) return false;\n\n if (controller.state.cfg.target === \"silhouette\") {\n const sil = placedSilBySector.get(secId) ?? [];\n if (!sil.length) return false;\n const piecePolys = getSectorPiecePolysCached(secId);\n if (anchorsSilhouetteComplete(sil, piecePolys)) {\n controller.markSectorCompleted(secId);\n return true;\n }\n } else {\n const raw = controller.state.cfg.sectors.find(ss => ss.id === secId)?.silhouette.mask ?? [];\n if (!raw.length) return false;\n const scaledSil = scalePolys(raw, scaleS);\n const piecePolys = getSectorPiecePolysCached(secId);\n if (anchorsWorkspaceComplete(scaledSil, piecePolys)) {\n controller.markSectorCompleted(secId);\n return true;\n }\n }\n return false;\n };\n\n // ---- drag (RAF) - Extracted to useDragController hook ---\n const dragController = useDragController(\n controller,\n layout,\n pieces,\n pieceById,\n anchorDots,\n placedSilBySector,\n isSectorLocked,\n maybeCompleteSector,\n force,\n undefined, // clickController - will be set later\n tracker // Pass tracker for data collection\n );\n\n const {\n draggingId,\n dragInvalid,\n svgRef,\n onPiecePointerDown,\n onBlueprintPointerDown,\n onPointerMove,\n onPointerUp,\n setPieceRef,\n setDraggingId,\n lockedPieceId,\n dragRef // TODO: Remove once click mode is extracted\n } = dragController;\n\n // ---- CLICK controller - Extracted click mode logic ---\n const svgPoint = (clientX: number, clientY: number) => {\n const svg = svgRef.current!;\n const pt = svg.createSVGPoint();\n pt.x = clientX; pt.y = clientY;\n const ctm = svg.getScreenCTM();\n if (!ctm) return { x: 0, y: 0 };\n const sp = pt.matrixTransform(ctm.inverse());\n return { x: sp.x, y: sp.y };\n };\n\n const clickController = useClickController(\n controller,\n layout,\n pieces,\n clickMode,\n draggingId,\n setDraggingId,\n dragRef,\n isInsideBadge,\n isSectorLocked,\n maybeCompleteSector,\n svgPoint,\n force,\n tracker // Pass tracker for data collection\n );\n\n const {\n selectedPieceId,\n onRootPointerDown\n } = clickController;\n\n const onCenterBadgePointerDown = (e: React.PointerEvent) => {\n if (draggingId) return;\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n if (controller.state.cfg.mode === \"prep\") {\n if (!controller.isSubmitEnabled() || gameCompleted) {\n e.stopPropagation();\n return;\n }\n\n setGameCompleted(true);\n if (tracker) {\n tracker.finalizeTrial('submit');\n }\n e.stopPropagation();\n return;\n }\n\n // Construction mode: toggle blueprint view\n if (tracker?.recordClickEvent) {\n const from = controller.state.blueprintView;\n const to = from === \"primitives\" ? \"quickstash\" : \"primitives\";\n tracker.recordClickEvent({ x, y }, 'blueprint_view_switch', {\n blueprintViewSwitch: { from, to }\n });\n }\n controller.switchBlueprintView();\n force();\n e.stopPropagation();\n };\n\n // Timer effect\n React.useEffect(() => {\n if (timeLimitMs === 0) return;\n\n const interval = setInterval(() => {\n setTimeRemaining(prev => {\n if (prev <= 1) {\n clearInterval(interval);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(interval);\n }, [timeLimitMs]);\n\n // Format time helper\n const formatTime = (seconds: number): string => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n };\n\n // Container style\n const containerStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n // minHeight: '100vh'\n };\n\n // Header style (constrained to gameboard width)\n const headerStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n alignItems: 'center',\n padding: '20px',\n background: CONFIG.color.background,\n flex: '0 0 auto'\n };\n\n // Header content wrapper (matches gameboard width)\n const headerContentStyle: React.CSSProperties = {\n position: 'relative',\n width: `${svgDimensions.width}px`,\n maxWidth: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center'\n };\n\n // Instructions style (always centered)\n const instructionsStyle: React.CSSProperties = {\n fontSize: '20px',\n lineHeight: 1.5,\n textAlign: 'center'\n };\n\n // Timer style - positioned absolutely to align right edge with semicircle's right edge\n // Independent of instructions content\n const scaleX = svgDimensions.width / viewBox.w;\n const rightEdgeOfSemicircleLogical = viewBox.w / 2 + layout.outerR;\n const distanceFromRightEdgeLogical = viewBox.w - rightEdgeOfSemicircleLogical;\n const distanceFromRightEdgePx = distanceFromRightEdgeLogical * scaleX;\n\n // Shift left by 5 monospaced characters (monospace is typically 0.6em wide per char)\n const charWidth = 24 * 0.6; // fontSize * typical monospace char width ratio\n const offsetLeft = charWidth * 5;\n\n const timerStyle: React.CSSProperties = {\n position: 'absolute',\n right: `${distanceFromRightEdgePx + offsetLeft}px`,\n fontSize: '24px',\n fontWeight: 'bold',\n fontFamily: 'monospace',\n color: '#333',\n whiteSpace: 'nowrap',\n textAlign: 'right'\n };\n\n // Gameboard wrapper style (to center the gameboard in remaining space)\n const gameboardWrapperStyle: React.CSSProperties = {\n flex: '1 1 auto',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden'\n };\n\n return (\n <div className=\"tangram-trial-container\" style={containerStyle}>\n {(instructions || timeLimitMs > 0) && (\n <div className=\"tangram-header\" style={headerStyle}>\n <div className=\"tangram-header-content\" style={headerContentStyle}>\n {instructions && (\n <div\n className=\"tangram-instructions\"\n style={instructionsStyle}\n dangerouslySetInnerHTML={{ __html: instructions }}\n />\n )}\n {timeLimitMs > 0 && (\n <div className=\"tangram-timer\" style={timerStyle}>\n {formatTime(timeRemaining)}\n </div>\n )}\n </div>\n </div>\n )}\n <div className=\"tangram-gameboard-wrapper\" style={gameboardWrapperStyle}>\n <div className=\"tangram-gameboard\" style={getGameboardStyle()}>\n <BoardView\n controller={controller}\n layout={layout}\n viewBox={viewBox}\n width={svgDimensions.width}\n height={svgDimensions.height}\n badgeR={badgeR}\n badgeCenter={badgeCenter}\n placedSilBySector={placedSilBySector}\n anchorDots={anchorDots as DotsType[]}\n pieces={pieces}\n clickMode={clickMode}\n draggingId={draggingId}\n selectedPieceId={selectedPieceId}\n dragInvalid={dragInvalid}\n lockedPieceId={lockedPieceId}\n svgRef={svgRef}\n setPieceRef={setPieceRef}\n onPiecePointerDown={onPiecePointerDown}\n onBlueprintPointerDown={onBlueprintPointerDown}\n onRootPointerDown={onRootPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onCenterBadgePointerDown={onCenterBadgePointerDown}\n showTangramDecomposition={showTangramDecomposition ?? false}\n scaleS={scaleS}\n usePrimitiveColorsBlueprints={usePrimitiveColorsBlueprints ?? false}\n usePrimitiveColorsTargets={usePrimitiveColorsTargets ?? false}\n primitiveColorIndices={primitiveColorIndices ?? [0, 1, 2, 3, 4]}\n {...eventCallbacks}\n />\n </div>\n </div>\n </div>\n );\n}\n","import type { PrimitiveBlueprint, Poly, Vec, TanKind } from \"@/core/domain/types\";\n\n// ===== numeric units (match Python SideLength scaling) ======================\nconst U = 40; // 1 UNIT in pixels\nconst HALFUNIT = U / 2;\nconst DIAGONAL = U * Math.SQRT2;\nconst HALFDIAGONAL = DIAGONAL / 2;\n\n// ===== small vec helpers ====================================================\nconst P = (x: number, y: number): Vec => ({ x, y });\n\n/** rotate array left by k (Python deque.rotate(-k)) */\nfunction rotLeft<T>(arr: T[], k: number): T[] {\n const n = arr.length; if (n === 0) return [];\n const s = ((k % n) + n) % n;\n return arr.slice(s).concat(arr.slice(0, s));\n}\n\n/**\n * Mirrors your Python `next_point`:\n * interior angle is CLOCKWISE at the vertex; we walk the boundary clockwise.\n */\nfunction nextPoint(\n x0: number, y0: number, // previous vertex\n x1: number, y1: number, // current vertex\n interiorDeg: number,\n dist: number\n): Vec {\n const phi = Math.atan2(y0 - y1, x0 - x1); // incoming edge (x0->x1)\n const theta = phi - (interiorDeg * Math.PI) / 180; // rotate clockwise by interior angle\n return P(x1 + dist * Math.cos(theta), y1 + dist * Math.sin(theta));\n}\n\n/**\n * Build polygon from side lengths & clockwise interior angles.\n * If `firstEdgeUnits` is provided ([(x0,y0),(x1,y1)] in **unit** coords with +y up),\n * we use that exact first edge. Otherwise we default to +X of length sideLens[0].\n * Returns vertices without repeating the start (close is implied).\n */\nfunction constructFromSpec(\n sideLens: number[],\n angles: number[],\n firstEdgeUnits?: [Vec, Vec]\n): Poly {\n let pts: Vec[];\n if (firstEdgeUnits) {\n // map unit coords (up +y) -> canvas coords (down +y): invert y and scale by U\n const a = firstEdgeUnits[0]; // typically (0,0)\n const b = firstEdgeUnits[1];\n const A = P(-a.x * U, a.y * U);\n const B = P(-b.x * U, b.y * U);\n pts = [A, B];\n } else {\n // default: first edge along +X\n const firstSideLen = sideLens[0];\n if (firstSideLen === undefined) throw new Error(\"No side lengths provided\");\n pts = [P(0, 0), P(firstSideLen, 0)];\n }\n\n // Python logic: rotate side lengths by -1 (since first edge already placed), angles unchanged\n const sidesRot = rotLeft(sideLens, 1);\n const angRot = angles;\n\n // add all but the final closing edge\n for (let i = 1; i < sideLens.length - 1; i++) {\n const last = pts[i - 1];\n const curr = pts[i];\n if (!last || !curr) continue;\n const sLen = sidesRot[i - 1];\n const aDeg = angRot[i - 1];\n if (sLen === undefined || aDeg === undefined) continue;\n pts.push(nextPoint(last.x, last.y, curr.x, curr.y, aDeg, sLen));\n }\n return pts;\n}\n\n// ===== default first edges in UNIT coords ( +y is UP here ) =================\n// Copied from your `default_pilot_rotations`. We invert y above for canvas.\nconst FIRST_EDGES_UNITS: Record<TanKind, [Vec, Vec]> = {\n \"smalltriangle\": [P(0, 0), P(0.5, 0.5)],\n \"parallelogram\": [P(0, 0), P(0.5, 0)],\n \"largetriangle\": [P(0, 0), P(0.5, -0.5)],\n \"medtriangle\": [P(0, 0), P(0.5, 0)],\n \"square\": [P(0, 0), P(0.5, 0)],\n};\n\n// ===== canonical half-edge primitives ===================\n// Unchanging primitive tangram pieces - these are constants, not configurable\nconst PRIMITIVE_BLUEPRINTS_CACHE = (() => {\n // Sequences copied verbatim from your Python tanprimitives_halfedges()\n const specs: Array<{\n id: string;\n kind: TanKind;\n sideLens: number[];\n angles: number[];\n color: string;\n }> = [\n {\n id: \"prim:square\",\n kind: \"square\",\n sideLens: [HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT],\n angles: [180, 90, 180, 90, 180, 90, 180, 90],\n color: \"#f43f5e\",\n },\n {\n id: \"prim:smalltriangle\",\n kind: \"smalltriangle\",\n sideLens: [HALFDIAGONAL, HALFDIAGONAL, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT],\n angles: [180, 45, 180, 90, 180, 45],\n color: \"#f59e0b\",\n },\n {\n id: \"prim:parallelogram\",\n kind: \"parallelogram\",\n sideLens: [HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL, HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL],\n angles: [180, 135, 180, 45, 180, 135, 180, 45],\n color: \"#10b981\",\n },\n {\n id: \"prim:medtriangle\",\n kind: \"medtriangle\",\n sideLens: [HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL],\n angles: [180, 180, 180, 45, 180, 90, 180, 45],\n color: \"#3b82f6\",\n },\n {\n id: \"prim:largetriangle\",\n kind: \"largetriangle\",\n sideLens: [\n HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL,\n HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT\n ],\n angles: [\n 180, 180, 180, 45,\n 180, 180, 180, 90, 180, 180, 180, 45\n ],\n color: \"#8b5cf6\",\n },\n ];\n\n return specs.map(({ id, kind, sideLens, angles, color }) => {\n const firstEdge = FIRST_EDGES_UNITS[kind]; // always present for these 5\n const verts = constructFromSpec(sideLens, angles, firstEdge);\n return {\n id,\n kind,\n shape: [verts],\n colorHint: color,\n } as PrimitiveBlueprint;\n });\n})();\n\nexport function primitiveBlueprintsHalfEdge(): PrimitiveBlueprint[] {\n return PRIMITIVE_BLUEPRINTS_CACHE;\n}\n\n// Direct access to primitives constant (for dependency injection)\nexport const PRIMITIVE_BLUEPRINTS: PrimitiveBlueprint[] = PRIMITIVE_BLUEPRINTS_CACHE;\n","// src/core/io/quickstash.ts\nimport { CONFIG } from \"@/core/config/config\";\nimport type { Blueprint, CompositeBlueprint, PrimitiveBlueprint, TanKind, Vec } from \"@/core/domain/types\";\nimport { primitiveBlueprintsHalfEdge } from \"@/core/domain/primitives\";\n\n/**\n * Convert anchor-based composite definition to pixel-based composite with custom grid step\n * @param anchorComposite - Composite defined with anchor coordinates\n * @param primsByKind - Map of primitive blueprints by kind\n * @param gridStepPx - Grid step in pixels (defaults to current CONFIG)\n * @returns CompositeBlueprint with pixel coordinates\n */\nexport function convertAnchorCompositeToPixels(\n anchorComposite: { id: string; parts: Array<{ kind: TanKind; anchorOffset: { x: number; y: number } }>; label?: string },\n primsByKind: Map<TanKind, PrimitiveBlueprint>,\n gridStepPx: number = CONFIG.layout.grid.stepPx\n): CompositeBlueprint {\n const { id, parts, label } = anchorComposite;\n \n // Convert anchor offsets to pixel offsets using custom grid step\n const pixelParts: Array<{ kind: TanKind; offset: Vec }> = parts.map(p => ({\n kind: p.kind,\n offset: { \n x: p.anchorOffset.x * gridStepPx, \n y: p.anchorOffset.y * gridStepPx \n }\n }));\n \n // Compute shape using custom grid step\n const shape: Vec[][] = [];\n for (const p of parts) {\n const prim = primsByKind.get(p.kind);\n if (!prim) continue;\n \n const pixelOffset = { \n x: p.anchorOffset.x * gridStepPx, \n y: p.anchorOffset.y * gridStepPx \n };\n for (const poly of prim.shape) {\n shape.push(poly.map(v => ({ x: v.x + pixelOffset.x, y: v.y + pixelOffset.y })));\n }\n }\n \n return { id, parts: pixelParts, shape, label: label ?? `Composite-${id}` };\n}\n\n/**\n * Anchor-based composite definitions (configuration-independent)\n * These are converted to pixel coordinates at render time\n */\nconst ANCHOR_COMPOSITES = [\n {\n id: \"comp:parallelogram+parallelogram\",\n parts: [\n { kind: \"parallelogram\" as TanKind, anchorOffset: { x: 0, y: 0 } },\n { kind: \"parallelogram\" as TanKind, anchorOffset: { x: 2, y: 2 } }, // Diagonal contact\n ],\n label: \"Parallelogram+Parallelogram\"\n },\n {\n id: \"comp:smalltriangle+medtriangle\",\n parts: [\n { kind: \"smalltriangle\" as TanKind, anchorOffset: { x: -2, y: -2 } },\n { kind: \"medtriangle\" as TanKind, anchorOffset: { x: 0, y: 0 } },\n ],\n label: \"SmallTriangle+MedTriangle\"\n },\n {\n id: \"comp:square\",\n parts: [\n { kind: \"square\" as TanKind, anchorOffset: { x: 0, y: 0 } },\n ],\n label: \"Square\"\n }\n];\n\n/**\n * Create quickstash with custom grid step (useful for testing different configurations)\n * @param gridStepPx - Grid step in pixels\n * @returns Array of blueprints with pixel coordinates based on custom grid step\n */\nexport function createQuickstashWithGridStep(gridStepPx: number): Blueprint[] {\n const prims = primitiveBlueprintsHalfEdge();\n const byKind = new Map<TanKind, PrimitiveBlueprint>();\n prims.forEach(p => byKind.set(p.kind, p));\n\n // Convert anchor-based definitions to pixel-based composites with custom grid step\n const list: Blueprint[] = ANCHOR_COMPOSITES.map(anchorComposite => \n convertAnchorCompositeToPixels(anchorComposite, byKind, gridStepPx)\n );\n\n const maxSlots = CONFIG.layout.defaults.maxQuickstashSlots;\n if (list.length > maxSlots) {\n throw new Error(\n `Quickstash has ${list.length} items but max is ${maxSlots}. Trim defaultQuickstash() or raise CONFIG.layout.defaults.maxQuickstashSlots.`\n );\n }\n return list;\n}\n\n/**\n * Get anchor-based composite definitions (for debugging/testing)\n * @returns Array of anchor-based composite definitions\n */\nexport function getAnchorComposites() {\n return ANCHOR_COMPOSITES;\n}\n\n/**\n * Default Quickstash using anchor coordinates\n * Conversion to pixels happens at render time using current CONFIG\n */\nexport function defaultQuickstash(): Blueprint[] {\n return createQuickstashWithGridStep(CONFIG.layout.grid.stepPx);\n}","/**\n * ConstructionApp.tsx - React wrapper for tangram construction trials\n * \n * This component handles the React rendering logic for construction trials,\n * separating it from the pure jsPsych plugin class.\n */\n\nimport React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { JsPsych } from \"jspsych\";\nimport { GameBoard } from \"../../core/components\";\nimport { PRIMITIVE_BLUEPRINTS } from \"../../core/domain/primitives\";\nimport { convertAnchorCompositeToPixels } from \"../../core/io/quickstash\";\nimport type { \n Sector, \n Blueprint, \n PlacementTarget, \n InputMode, \n LayoutMode,\n TanKind,\n PrimitiveBlueprint\n} from \"../../core/domain/types\";\nimport { CONFIG } from \"../../core/config/config\";\n\nexport interface StartConstructionTrialParams {\n tangrams: any[];\n quickstash_macros?: Blueprint[] | AnchorComposite[];\n primitiveOrder: string[];\n target?: PlacementTarget;\n input?: InputMode;\n layout?: LayoutMode;\n time_limit_ms: number;\n show_tangram_decomposition?: boolean;\n instructions?: string;\n onInteraction?: (event: any) => void;\n onTrialEnd?: (data: any) => void;\n usePrimitiveColorsBlueprints?: boolean;\n usePrimitiveColorsTargets?: boolean;\n primitiveColorIndices?: number[];\n}\n\n// Type for anchor-based composite definitions\ntype AnchorComposite = {\n id: string;\n parts: Array<{ kind: TanKind; anchorOffset: { x: number; y: number } }>;\n label?: string;\n};\n\n/**\n * Start a construction trial by rendering the GameBoard component\n */\nexport function startConstructionTrial(\n display_element: HTMLElement,\n params: StartConstructionTrialParams,\n _jsPsych: JsPsych\n) {\n // Canonical piece names we accept\n const CANON = new Set([\n \"square\",\n \"smalltriangle\",\n \"parallelogram\",\n \"medtriangle\",\n \"largetriangle\",\n ]);\n\n // make copy of PRIMITIVE_BLUEPRINTS sorted by primitiveOrder\n const PRIMITIVE_BLUEPRINTS_ORDERED = [...PRIMITIVE_BLUEPRINTS].sort((a, b) => params.primitiveOrder.indexOf(a.kind) - params.primitiveOrder.indexOf(b.kind));\n\n // Convert JSON plugin parameters to internal Sector[] format\n const sectors: Sector[] = params.tangrams.map((tangramSpec, index) => {\n \n // Filter to canonical pieces only and convert vertices to polygon format\n const filteredTans = tangramSpec.solutionTans.filter((tan: any) => {\n // Support both \"name\" and \"kind\" fields (different JSON formats)\n const tanName = tan.name ?? tan.kind;\n const isCanonical = CANON.has(tanName);\n return isCanonical;\n });\n\n const mask = filteredTans.map((tan: any) => {\n const polygon = tan.vertices.map(([x, y]: number[]) => ({ x: x ?? 0, y: -(y ?? 0) }));\n return polygon;\n });\n\n // Store primitive decomposition for optional decomposition view\n const primitiveDecomposition = filteredTans.map((tan: any) => ({\n kind: (tan.name ?? tan.kind) as TanKind,\n polygon: tan.vertices.map(([x, y]: number[]) => ({ x: x ?? 0, y: -(y ?? 0) }))\n }));\n\n // Assign sector ID from alphabetical sequence\n const sectorId = `sector${index}`;\n \n const sector = {\n id: sectorId,\n tangramId: tangramSpec.tangramID,\n silhouette: {\n id: sectorId,\n mask,\n primitiveDecomposition,\n },\n };\n\n return sector;\n });\n\n // Convert quickstash_macros to Blueprint[] format\n // Handle both anchor-based composites and pre-converted blueprints\n let quickstash: Blueprint[] = [];\n\n if (params.quickstash_macros && params.quickstash_macros.length > 0) {\n // Check if the first item has anchorOffset (anchor-based) or offset (pixel-based)\n const firstMacro = params.quickstash_macros[0];\n if (firstMacro && 'parts' in firstMacro && firstMacro.parts && firstMacro.parts[0] && 'anchorOffset' in firstMacro.parts[0]) {\n\n // Create primitive map for conversion\n const primsByKind = new Map<TanKind, PrimitiveBlueprint>();\n PRIMITIVE_BLUEPRINTS_ORDERED.forEach(p => primsByKind.set(p.kind, p));\n\n // Convert each anchor composite to pixel-based blueprint\n quickstash = (params.quickstash_macros as AnchorComposite[]).map(anchorComposite =>\n convertAnchorCompositeToPixels(anchorComposite, primsByKind, CONFIG.layout.grid.stepPx) // Use current CONFIG grid step\n );\n } else {\n // Already pixel-based blueprints\n quickstash = params.quickstash_macros as Blueprint[];\n }\n } else {\n }\n\n // Extract non-callback params for trial data\n const { onInteraction, onTrialEnd, ...trialParams } = params;\n\n // Create React root and render GameBoard\n const gameBoardProps = {\n sectors,\n quickstash,\n primitives: PRIMITIVE_BLUEPRINTS_ORDERED,\n layout: params.layout as LayoutMode,\n target: params.target as PlacementTarget,\n input: params.input as InputMode,\n timeLimitMs: params.time_limit_ms,\n maxQuickstashSlots: CONFIG.layout.defaults.maxQuickstashSlots,\n mode: 'construction' as const,\n showTangramDecomposition: params.show_tangram_decomposition ?? false,\n trialParams,\n ...(params.instructions && { instructions: params.instructions }),\n ...(params.onInteraction && { onInteraction: params.onInteraction }),\n ...(params.onTrialEnd && { onTrialEnd: params.onTrialEnd }),\n ...(params.usePrimitiveColorsBlueprints !== undefined && { usePrimitiveColorsBlueprints: params.usePrimitiveColorsBlueprints }),\n ...(params.usePrimitiveColorsTargets !== undefined && { usePrimitiveColorsTargets: params.usePrimitiveColorsTargets }),\n ...(params.primitiveColorIndices !== undefined && { primitiveColorIndices: params.primitiveColorIndices })\n };\n\n const root = createRoot(display_element);\n root.render(React.createElement(GameBoard, gameBoardProps));\n\n return { root, display_element, jsPsych: _jsPsych };\n}","import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\nimport { startConstructionTrial, StartConstructionTrialParams } from \"./ConstructionApp\";\n\nconst info = {\n name: \"tangram-construct\",\n version: \"1.0.0\",\n parameters: {\n /** Array of tangram specifications defining the puzzles to solve */\n tangrams: {\n type: ParameterType.COMPLEX,\n default: undefined,\n description: \"Array of TangramSpec objects defining target shapes to construct\"\n },\n /** Array of pre-made macro pieces from prep plugin */\n quickstash_macros: {\n type: ParameterType.COMPLEX,\n default: [],\n description: \"Array of MacroSpec objects created in prep trial\"\n },\n /** Array of primitive names in the order they should be displayed */\n primitive_order: {\n type: ParameterType.OBJECT,\n default: [\"square\", \"smalltriangle\", \"parallelogram\", \"medtriangle\", \"largetriangle\"],\n description: \"Array of primitive names in the order they should be displayed\"\n },\n /** Whether to place pieces in workspace or directly on silhouette */\n target: {\n type: ParameterType.SELECT,\n options: [\"workspace\", \"silhouette\"],\n default: \"silhouette\",\n description: \"Placement target: workspace (free placement) or silhouette (onto target shape)\"\n },\n /** Input method for piece manipulation */\n input: {\n type: ParameterType.SELECT, \n options: [\"click\", \"drag\"],\n default: \"drag\",\n description: \"Input mode: drag (mouse/touch drag) or click (click to select/place)\"\n },\n /** Layout style for piece arrangement */\n layout: {\n type: ParameterType.SELECT,\n options: [\"circle\", \"semicircle\"], \n default: \"semicircle\",\n description: \"Layout mode: full circle or semicircle piece arrangement\"\n },\n /** Maximum time allowed for trial in milliseconds */\n time_limit_ms: {\n type: ParameterType.INT,\n default: 0,\n description: \"Time limit in milliseconds (0 = no limit)\"\n },\n /** Snap radius for piece placement in pixels */\n snap_radius_px: {\n type: ParameterType.INT,\n default: 18,\n description: \"Snap radius for anchor-based piece placement\"\n },\n /** Whether to show tangram target shapes decomposed into individual primitives with borders */\n show_tangram_decomposition: {\n type: ParameterType.BOOL,\n default: false,\n description: \"Whether to show tangram target shapes decomposed into individual primitives with borders\"\n },\n /** HTML content to display above the gameboard as instructions */\n instructions: {\n type: ParameterType.STRING,\n default: \"\",\n description: \"HTML content to display above the gameboard as instructions\"\n },\n /** Callback fired after each interaction (piece pickup + placedown) */\n onInteraction: {\n type: ParameterType.FUNCTION,\n default: undefined,\n description: \"Callback for each interaction event (e.g., socket.emit)\"\n },\n /** Callback fired when trial ends */\n onTrialEnd: {\n type: ParameterType.FUNCTION,\n default: undefined,\n description: \"Callback when trial completes with full data\"\n },\n /** Whether to use distinct colors for each primitive shape type in blueprints */\n use_primitive_colors_blueprints: {\n type: ParameterType.BOOL,\n default: false,\n description: \"Whether each primitive shape type should have its own distinct color in the blueprint dock area\"\n },\n /** Whether to use distinct colors for each primitive shape type in target tangrams */\n use_primitive_colors_targets: {\n type: ParameterType.BOOL,\n default: false,\n description: \"Whether each primitive shape type should have its own distinct color in target tangram silhouettes\"\n },\n /** Indices mapping primitives to colors from the color palette */\n primitive_color_indices: {\n type: ParameterType.OBJECT,\n default: [0, 1, 2, 3, 4],\n description: \"Array of 5 integers indexing into primitiveColors array, mapping [square, smalltriangle, parallelogram, medtriangle, largetriangle] to colors\"\n }\n },\n data: {\n /** Array of all interaction events during trial */\n events: {\n type: ParameterType.COMPLEX,\n description: \"Chronological log of all user interactions and game events\"\n },\n /** Completion time for each sector/tangram */\n completion_times: {\n type: ParameterType.COMPLEX,\n description: \"Array of completion times in milliseconds for each tangram\"\n },\n /** Final completion state of each sector */\n final_state: {\n type: ParameterType.COMPLEX,\n description: \"Array describing completion status of each tangram sector\"\n },\n /** Usage statistics for macro pieces */\n macros_used: {\n type: ParameterType.COMPLEX,\n description: \"Array tracking which macros were used and when\"\n },\n /** Total trial duration in milliseconds */\n trial_duration_ms: {\n type: ParameterType.INT,\n description: \"Total time from trial start to completion\"\n }\n },\n citations: \"\"\n};\n\ntype Info = typeof info;\n\n/**\n * **tangram-construct**\n *\n * A jsPsych wrapper around the React-based construction interface.\n *\n * @author Justin Yang & Sean Paul Anderson\n * @see {@link https://github.com/cogtoolslab/tangram_construction.git/tree/main/experiments/jspsych-tangram-prep}\n */\nclass TangramConstructPlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n /**\n * Launches the trial by invoking startConstructionTrial\n * with the display element, parameters, and jsPsych instance.\n */\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n // Wrap onTrialEnd to handle React cleanup and jsPsych trial completion\n const wrappedOnTrialEnd = (data: any) => {\n // Call user-provided callback if exists\n if (trial.onTrialEnd) {\n trial.onTrialEnd(data);\n }\n\n // Clean up React first (before clearing DOM)\n const reactContext = (display_element as any).__reactContext;\n if (reactContext?.root) {\n reactContext.root.unmount();\n }\n\n // Clear display after React cleanup\n display_element.innerHTML = '';\n\n // Finish jsPsych trial with data\n this.jsPsych.finishTrial(data);\n };\n\n // Create parameter object for wrapper\n const params: StartConstructionTrialParams = {\n tangrams: trial.tangrams,\n quickstash_macros: trial.quickstash_macros,\n primitiveOrder: trial.primitive_order,\n target: trial.target,\n input: trial.input,\n layout: trial.layout,\n time_limit_ms: trial.time_limit_ms,\n show_tangram_decomposition: trial.show_tangram_decomposition,\n instructions: trial.instructions,\n onInteraction: trial.onInteraction,\n onTrialEnd: wrappedOnTrialEnd,\n usePrimitiveColorsBlueprints: trial.use_primitive_colors_blueprints,\n usePrimitiveColorsTargets: trial.use_primitive_colors_targets,\n primitiveColorIndices: trial.primitive_color_indices\n };\n\n // Use React wrapper to start the trial\n const { root, display_element: element, jsPsych } = startConstructionTrial(display_element, params, this.jsPsych);\n \n // Store React context for cleanup\n (element as any).__reactContext = { root, jsPsych };\n }\n}\n\nexport default TangramConstructPlugin;"],"names":["polysAABB","igcd","inferUnitFromPolys","outerR","bp","bb","support","x","y","pointerAnchorNode","pointerSector","piece","cfg","centerX","centerY","q","tl0","pointerR","allowInside","clamped","pieceId","anchorInfo","uuidv4","layout","createRoot","ParameterType"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/core/config/config.ts","../../src/core/domain/blueprints.ts","../../src/core/engine/state/BaseGameController.ts","../../src/core/engine/geometry/math.ts","../../src/core/engine/geometry/collision.ts","../../src/core/engine/geometry/bounds.ts","../../src/core/engine/geometry/pieces.ts","../../src/core/domain/solve.ts","../../src/core/domain/layout.ts","../../src/core/engine/validation/border-rendering.ts","../../src/assets/locked.png","../../src/assets/unlocked.png","../../src/core/components/board/BoardView.tsx","../../src/core/engine/validation/complete.ts","../../src/core/components/board/utils.ts","../../src/core/components/board/usePieceState.ts","../../src/core/engine/collision/grid-snapping.ts","../../src/core/components/board/useAnchorGrid.ts","../../src/core/engine/validation/face-to-face.ts","../../src/core/components/board/useDragController.ts","../../src/core/components/board/useClickController.ts","../../src/core/io/InteractionTracker.ts","../../src/core/components/board/GameBoard.tsx","../../src/core/domain/primitives.ts","../../src/core/io/quickstash.ts","../../src/plugins/tangram-construct/ConstructionApp.tsx","../../src/plugins/tangram-construct/index.ts"],"sourcesContent":["// src/core/config/config.ts\nexport type Config = {\n color: {\n background: string;\n bands: {\n silhouette: { fillEven: string; fillOdd: string; stroke: string };\n workspace: { fillEven: string; fillOdd: string; stroke: string };\n };\n completion: { fill: string; stroke: string };\n silhouetteMask: string;\n anchors: { invalid: string; valid: string };\n piece: { draggingFill: string; validFill: string; invalidFill: string; invalidStroke: string; selectedStroke: string; allGreenStroke: string; borderStroke: string };\n ui: { light: string; dark: string };\n blueprint: { fill: string; selectedStroke: string; badgeFill: string; labelFill: string };\n tangramDecomposition: { stroke: string };\n primitiveColors: string[];\n };\n opacity: {\n blueprint: number;\n silhouetteMask: number;\n anchors: { invalid: number; valid: number };\n piece: { invalid: number; dragging: number; locked: number; normal: number };\n };\n size: {\n stroke: { bandPx: number; pieceSelectedPx: number; allGreenStrokePx: number; pieceBorderPx: number; tangramDecompositionPx: number };\n anchorRadiusPx: { valid: number; invalid: number };\n badgeFontPx: number;\n centerBadge: { fractionOfOuterR: number; minPx: number; marginPx: number };\n invalidMarker: { sizePx: number; strokePx: number };\n };\n layout: {\n grid: { stepPx: number; unitPx: number };\n paddingPx: number;\n viewportScale: number;\n /** renamed from capacity → constraints */\n constraints: {\n workspaceDiamAnchors: number;\n quickstashDiamAnchors: number;\n primitiveDiamAnchors: number;\n };\n defaults: { maxQuickstashSlots: number };\n };\n game: {\n snapRadiusPx: number;\n showBorders: boolean;\n hideTouchingBorders: boolean;\n silhouettesBelowPieces: boolean;\n };\n};\n\nexport const CONFIG: Config = {\n color: {\n background: \"#fff7e0ff\",\n bands: {\n silhouette: { fillEven: \"#ffffff\", fillOdd: \"#ffffff\", stroke: \"#b1b1b1\" },\n workspace: { fillEven: \"#ffffff\", fillOdd: \"#ffffff\", stroke: \"#b1b1b1\" }\n },\n completion: { fill: \"#ccffcc\", stroke: \"#13da57\" },\n silhouetteMask: \"#374151\",\n anchors: { invalid: \"#7dd3fc\", valid: \"#475569\" },\n // validFill used here for placed composites\n piece: { draggingFill: \"#8e7cc3\", validFill: \"#8e7cc3\", invalidFill: \"#d55c00\", invalidStroke: \"#dc2626\", selectedStroke: \"#674ea7\", allGreenStroke: \"#86efac\", borderStroke: \"#674ea7\" },\n ui: { light: \"#60a5fa\", dark: \"#1d4ed8\" },\n blueprint: { fill: \"#374151\", selectedStroke: \"#111827\", badgeFill: \"#000000\", labelFill: \"#ffffff\" },\n tangramDecomposition: { stroke: \"#fef2cc\" },\n primitiveColors: [ // from seaborn \"colorblind\" palette, 6 colors, with red omitted\n '#0173b2',\n '#de8f05',\n '#029e73',\n '#cc78bc',\n '#ca9161'\n ]\n },\n opacity: {\n blueprint: 0.6,\n silhouetteMask: 0.25,\n //anchors: { valid: 0.80, invalid: 0.50 },\n anchors: { invalid: 0.0, valid: 0.0 },\n piece: { invalid: 1, dragging: 1, locked: 1, normal: 1 },\n },\n size: {\n stroke: { bandPx: 5, pieceSelectedPx: 5, allGreenStrokePx: 10, pieceBorderPx: 2, tangramDecompositionPx: 1 },\n anchorRadiusPx: { valid: 1.0, invalid: 1.0 },\n badgeFontPx: 16,\n centerBadge: { fractionOfOuterR: 0.15, minPx: 20, marginPx: 4 },\n invalidMarker: { sizePx: 10, strokePx: 4 }\n },\n layout: {\n grid: { stepPx: 20, unitPx: 40 },\n paddingPx: 1,\n viewportScale: 0.8,\n constraints: {\n workspaceDiamAnchors: 10, // num anchors req'd to be on diagonal\n quickstashDiamAnchors: 7, // num anchors req'd to be in single quickstash slot\n primitiveDiamAnchors: 5,\n },\n defaults: { maxQuickstashSlots: 1 }\n },\n game: {\n snapRadiusPx: 15,\n showBorders: false,\n hideTouchingBorders: true,\n silhouettesBelowPieces: true\n }\n};","import type {\n Blueprint, PrimitiveBlueprint, CompositeBlueprint, TanKind\n} from \"./types\";\n\nexport function isComposite(bp: Blueprint): bp is CompositeBlueprint {\n return (bp as CompositeBlueprint).parts !== undefined;\n}\nexport function isPrimitive(bp: Blueprint): bp is PrimitiveBlueprint {\n return !isComposite(bp);\n}\n\nexport class BlueprintRegistry {\n private byId = new Map<string, Blueprint>();\n private primitivesByKind = new Map<TanKind, PrimitiveBlueprint>();\n\n registerAll(bps: Blueprint[]) {\n for (const bp of bps) this.register(bp);\n }\n register(bp: Blueprint) {\n this.byId.set(bp.id, bp);\n if (isPrimitive(bp)) this.primitivesByKind.set(bp.kind, bp);\n }\n get(id: string) { return this.byId.get(id); }\n getPrimitive(kind: TanKind | string) { return this.primitivesByKind.get(kind as TanKind); }\n}\n","/**\n * BaseGameController with dependency injection - PHASE 2 MILESTONE\n * \n * Maintains compatibility with existing RoundController API while implementing\n * clean separation between configuration and data. All game content is injected\n * via constructor parameters, no hardcoded defaults.\n */\n\nimport type { \n Blueprint, \n Sector, \n LayoutMode,\n PlacementTarget,\n InputMode,\n RoundState,\n SectorState,\n TanKind,\n PrimitiveBlueprint\n} from '../../domain/types';\nimport { CONFIG } from '../../config/config';\nimport { BlueprintRegistry } from '../../domain/blueprints';\n\nexport interface GameConfig {\n n: number;\n layout: LayoutMode;\n target: PlacementTarget; // CRITICAL: \"workspace\" | \"silhouette\"\n input: InputMode; // CRITICAL: \"click\" | \"drag\"\n timeLimitMs: number;\n maxQuickstashSlots: number;\n maxCompositeSize?: number; // Optional - only used in prep mode\n mode: \"construction\" | \"prep\"; // NEW: Distinguishes prep vs construction behavior\n minPiecesPerMacro?: number; // NEW: Minimum pieces required per macro (prep mode)\n requireAllSlots?: boolean; // NEW: Whether all slots must be filled (prep mode)\n}\n\nlet PID = 0;\nconst newId = () => `p_${++PID}`;\nconst NOW = () => performance.now();\n\n// Event tracking callbacks (optional - set by InteractionTracker)\nexport interface TrackingCallbacks {\n onPiecePickup?: (pieceId: string, blueprintId: string, blueprintType: 'primitive' | 'composite', source: 'blueprint' | 'sector', position: { x: number; y: number }, vertices: number[][][], sectorId?: string) => void;\n onPiecePlacedown?: (outcome: 'placed' | 'deleted', sectorId?: string, position?: { x: number; y: number }, vertices?: number[][][], anchorId?: string, wasValid?: boolean, wasOverlapping?: boolean) => void;\n onClickEvent?: (location: { x: number; y: number }, anchorX: number, anchorY: number, clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt', metadata?: any) => void;\n onMouseMove?: (anchorX: number, anchorY: number, sectorId?: string) => void;\n onSectorCompleted?: (sectorId: string) => void;\n}\n\nexport class BaseGameController {\n // Core data - injected, not hardcoded\n private sectors: Sector[];\n private quickstash: Blueprint[];\n private primitives: PrimitiveBlueprint[];\n\n // Configuration\n private config: GameConfig;\n\n // State and registry\n public state: RoundState;\n private t0: number;\n private registry = new BlueprintRegistry();\n\n // React state update tracking\n private _updateCount = 0;\n public get updateCount() { return this._updateCount; }\n private notifyStateChange() { this._updateCount++; }\n\n // Event tracking (optional)\n private trackingCallbacks: TrackingCallbacks | null = null;\n \n constructor(\n sectors: Sector[],\n quickstash: Blueprint[],\n primitives: PrimitiveBlueprint[],\n config: GameConfig\n ) {\n // Validate required inputs - fail fast\n if (!sectors || sectors.length === 0) {\n throw new Error(\"BaseGameController: sectors array is required and cannot be empty\");\n }\n if (!primitives || primitives.length === 0) {\n throw new Error(\"BaseGameController: primitives array is required and cannot be empty\");\n }\n if (!config) {\n throw new Error(\"BaseGameController: config is required\");\n }\n\n // CRITICAL: All data is injected, no defaults\n this.sectors = sectors;\n this.quickstash = quickstash || [];\n this.primitives = primitives;\n this.config = config;\n \n // Initialize registry\n this.registry.registerAll(primitives);\n this.registry.registerAll(quickstash);\n \n // Initialize state\n this.t0 = NOW();\n this.state = this.initializeState();\n }\n \n private initializeState(): RoundState {\n // Create state that matches existing RoundController structure\n const sectors: Record<string, SectorState> = {};\n for (const s of this.sectors) {\n sectors[s.id] = { sectorId: s.id, pieces: [] };\n }\n\n return {\n cfg: {\n n: this.config.n,\n layout: this.config.layout,\n target: this.config.target,\n input: this.config.input,\n maxQuickstashSlots: this.config.maxQuickstashSlots,\n timeLimitMs: this.config.timeLimitMs,\n snapRadiusPx: CONFIG.game.snapRadiusPx,\n maxCompositeSize: this.config.maxCompositeSize ?? 0, // Default to 0 for legacy compatibility\n sectors: this.sectors,\n mode: this.config.mode\n },\n blueprintView: this.config.mode === \"prep\" ? \"primitives\" : \"quickstash\", // Start with primitives in prep mode\n primitives: this.primitives,\n quickstash: this.quickstash,\n sectors,\n startedAt: this.t0\n };\n }\n\n // ===== Event Tracking =====\n // Methods for InteractionTracker integration\n\n /**\n * Set tracking callbacks for data collection\n * Called by InteractionTracker to register itself\n */\n setTrackingCallbacks(callbacks: TrackingCallbacks | null): void {\n this.trackingCallbacks = callbacks;\n }\n\n // ===== RoundController Compatibility Interface =====\n // These methods maintain compatibility with Board.tsx expectations\n\n getState(): RoundState {\n return this.state;\n }\n\n getSnapRadius(): number {\n return CONFIG.game.snapRadiusPx;\n }\n\n // CRITICAL: Preserve target and input mode access\n getTarget(): PlacementTarget {\n return this.config.target;\n }\n\n getInputMode(): InputMode {\n return this.config.input;\n }\n\n // ===== Blueprint and Piece Management =====\n // Methods that Board.tsx expects\n\n getBlueprint(id: string): Blueprint | undefined {\n return this.registry.get(id);\n }\n\n getPrimitive(kind: TanKind | string): PrimitiveBlueprint | undefined {\n return this.registry.getPrimitive(kind);\n }\n\n getPiecesInSector(sectorId: string): any[] {\n const sectorState = this.state.sectors[sectorId];\n return sectorState ? sectorState.pieces : [];\n }\n\n // ===== Completion Management =====\n // Critical for Board.tsx validation\n\n isSectorCompleted(sectorId: string): boolean {\n return !!this.state.sectors[sectorId]?.completedAt;\n }\n\n markSectorCompleted(sectorId: string): void {\n const ss = this.state.sectors[sectorId];\n if (!ss || ss.completedAt) return;\n\n ss.completedAt = NOW();\n\n // Notify tracking system\n if (this.trackingCallbacks?.onSectorCompleted) {\n this.trackingCallbacks.onSectorCompleted(sectorId);\n }\n\n const allDone = Object.values(this.state.sectors).every((s: SectorState) => !!s.completedAt);\n if (allDone && !this.state.endedAt) {\n this.state.endedAt = NOW();\n }\n }\n\n // ===== Piece Operations =====\n // Methods that Board.tsx uses for drag/drop\n\n spawnFromBlueprint(bp: Blueprint, at: { x: number; y: number }): string {\n const id = newId();\n const piece = { id, blueprintId: bp.id, pos: { ...at } };\n this.getFloating().pieces.push(piece);\n this.notifyStateChange();\n return id;\n }\n\n move(id: string, to: { x: number; y: number }): void {\n const p = this.findPiece(id);\n if (!p) {\n return;\n }\n p.pos = { ...to };\n this.notifyStateChange();\n }\n\n drop(id: string, sectorId?: string): void {\n const p = this.findPiece(id);\n if (!p) {\n return;\n }\n\n // Remove from current location\n const where = this.findPieceLocation(id);\n this.removeFromCurrent(id);\n if (where?.sectorId) delete p.sectorId;\n\n // Inner-hole or no sector → float\n if (!sectorId) {\n this.getFloating().pieces.push(p);\n this.notifyStateChange();\n return;\n }\n\n // Completed sector → delete (already removed above)\n if (this.isSectorCompleted(sectorId)) {\n this.notifyStateChange();\n return;\n }\n\n // Place in sector\n const sector = this.state.sectors[sectorId];\n if (!sector) {\n return;\n }\n \n sector.pieces.push(p);\n p.sectorId = sectorId;\n this.notifyStateChange();\n }\n\n remove(id: string): void {\n const loc = this.findPieceLocation(id);\n if (!loc) return;\n loc.array.splice(loc.index, 1);\n this.notifyStateChange();\n }\n\n // ===== Helper Methods =====\n // Internal methods that support the public API\n\n findPiece(id: string): any {\n for (const s of Object.values(this.state.sectors)) {\n const sectorState = s as SectorState;\n const p = sectorState.pieces.find((pp) => pp.id === id);\n if (p) return p;\n }\n return this.getFloating().pieces.find((pp) => pp.id === id) ?? null;\n }\n\n private getFloating(): SectorState {\n if (!(this as any)._floating) {\n (this as any)._floating = { sectorId: \"-floating-\", pieces: [] } as SectorState;\n }\n return (this as any)._floating;\n }\n\n private findPieceLocation(id: string): \n | { sectorId?: string; array: SectorState[\"pieces\"]; index: number }\n | null {\n for (const s of Object.values(this.state.sectors)) {\n const sectorState = s as SectorState;\n const idx = sectorState.pieces.findIndex((pp) => pp.id === id);\n if (idx >= 0) return { sectorId: sectorState.sectorId, array: sectorState.pieces, index: idx };\n }\n const f = this.getFloating();\n const i = f.pieces.findIndex((pp) => pp.id === id);\n return i >= 0 ? { array: f.pieces, index: i } : null;\n }\n\n private removeFromCurrent(id: string): void {\n const loc = this.findPieceLocation(id);\n if (!loc) return;\n loc.array.splice(loc.index, 1);\n }\n\n // ===== Additional Compatibility Methods =====\n\n switchBlueprintView(): void {\n // Disable toggle in prep mode - keep primitives always visible\n if (this.config.mode === \"prep\") return;\n \n const to = this.state.blueprintView === \"primitives\" ? \"quickstash\" : \"primitives\";\n this.state.blueprintView = to;\n }\n\n /**\n * Check if submit button should be enabled in prep mode\n * Validates macro completion based on piece count and slot requirements\n */\n isSubmitEnabled(): boolean {\n if (this.config.mode !== \"prep\") return true; // Not applicable to construction mode\n \n const minPieces = this.config.minPiecesPerMacro ?? 2;\n const maxPieces = this.config.maxCompositeSize ?? Infinity; // No upper limit if not specified\n const requireAll = this.config.requireAllSlots ?? false;\n \n // Get all sectors (macro slots)\n const allSectors = Object.values(this.state.sectors);\n \n // Check each sector for valid piece count\n let validSectorCount = 0;\n for (const sector of allSectors) {\n const pieceCount = sector.pieces.length;\n \n // Valid if between min and max pieces (inclusive)\n if (pieceCount >= minPieces && pieceCount <= maxPieces) {\n validSectorCount++;\n }\n // Invalid if has pieces but not enough or too many\n else if (pieceCount > 0) {\n return false; // Has pieces but invalid count\n }\n // Empty sector (pieceCount === 0) is allowed, will be checked below\n }\n \n if (requireAll) {\n // All slots must have valid macros\n return validSectorCount === allSectors.length;\n } else {\n // At least 0 valid macros (can submit nothing)\n return true; // No invalid sectors found above, so can submit\n }\n }\n\n snapshot(): any {\n const perSector = Object.values(this.state.sectors).map((s) => {\n const sectorState = s as SectorState;\n const base = {\n sectorId: sectorState.sectorId,\n pieceCount: sectorState.pieces.length,\n };\n return sectorState.completedAt ? { ...base, completedAt: sectorState.completedAt } : base;\n });\n return {\n perSector,\n events: [], // TODO: Will be implemented in validation separation phase\n timeMs: NOW() - this.t0,\n completed: !!this.state.endedAt,\n };\n }\n}","/**\n * Pure vector and polygon mathematical operations\n * No game logic dependencies - just geometric math\n */\n\nimport type { Vec, Poly } from '@/core/domain/types';\n\n// ===== Constants =====\n\nexport const EPS = 1e-6;\n\n// ===== Vector Operations =====\n\nexport const vsub = (a: Vec, b: Vec): Vec => ({ x: a.x - b.x, y: a.y - b.y });\nexport const vlen = (v: Vec) => Math.hypot(v.x, v.y);\nexport const vscale = (v: Vec, s: number): Vec => ({ x: v.x * s, y: v.y * s });\nexport const vadd = (a: Vec, b: Vec): Vec => ({ x: a.x + b.x, y: a.y + b.y });\n\n/** Squared distance between two points (faster than full distance) */\nexport const dist2 = (a: Vec, b: Vec): number => {\n const dx = a.x - b.x, dy = a.y - b.y;\n return dx * dx + dy * dy;\n};\n\n/**\n * Check if point p lies on the line segment from a to b (within epsilon tolerance)\n */\nexport function pointOnSegment(p: Vec, a: Vec, b: Vec, eps = 1e-9): boolean {\n // collinear?\n const cross = (b.y - a.y) * (p.x - a.x) - (b.x - a.x) * (p.y - a.y);\n if (Math.abs(cross) > eps) return false;\n // within bounding box?\n const minX = Math.min(a.x, b.x) - eps, maxX = Math.max(a.x, b.x) + eps;\n const minY = Math.min(a.y, b.y) - eps, maxY = Math.max(a.y, b.y) + eps;\n return p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY;\n}\n\n/**\n * Return an array of points subdividing the segment [a,b] into `n` equal parts (excluding `a`).\n */\nexport function subdivideSegment(a: Vec, b: Vec, n: number): Vec[] {\n if (n <= 1) return [b];\n const ab = vsub(b, a);\n const step = 1 / n;\n const pts: Vec[] = [];\n for (let i = 1; i <= n; i++) pts.push(vadd(a, vscale(ab, step * i)));\n return pts;\n}\n\n// ===== Polygon Operations =====\n\n/** Boundary-inclusive even–odd point-in-polygon test */\nexport function pointInPolygon(pt: Vec, poly: Poly): boolean {\n // 1) On-edge / on-vertex counts as inside\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const vertexJ = poly[j];\n const vertexI = poly[i];\n if (!vertexJ || !vertexI) continue;\n if (pointOnSegment(pt, vertexJ, vertexI)) return true;\n }\n\n // 2) Standard even–odd ray casting (edges strictly above/below pivot)\n // Using the common (yi > y) !== (yj > y) test avoids counting horizontal edges twice.\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const vertexI = poly[i];\n const vertexJ = poly[j];\n if (!vertexI || !vertexJ) continue;\n const xi = vertexI.x, yi = vertexI.y;\n const xj = vertexJ.x, yj = vertexJ.y;\n\n const intersects = (yi > pt.y) !== (yj > pt.y)\n && pt.x < ((xj - xi) * (pt.y - yi)) / (yj - yi + 1e-12) + xi;\n\n if (intersects) inside = !inside;\n }\n return inside;\n}\n\n/** Project a polygon onto axis (nx, ny) and return min/max projection values */\nexport function project(poly: Poly, nx: number, ny: number) {\n let min = Infinity, max = -Infinity;\n for (const p of poly) {\n const s = p.x * nx + p.y * ny;\n if (s < min) min = s;\n if (s > max) max = s;\n }\n return { min, max };\n}\n\n/** Calculate axis-aligned bounding box for a polygon */\nexport function polygonAABB(poly: Poly) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of poly) {\n if (pt.x < minX) minX = pt.x;\n if (pt.y < minY) minY = pt.y;\n if (pt.x > maxX) maxX = pt.x;\n if (pt.y > maxY) maxY = pt.y;\n }\n return { minX, minY, maxX, maxY };\n}\n","/**\n * SAT (Separating Axis Theorem) collision detection for convex polygons\n * Extracted from polygon.ts for better organization\n */\n\nimport type { Poly } from '@/core/domain/types';\nimport { project } from './math';\n\nconst SEP_EPS = 1e-6; // allow touching within this tolerance\n\n/** SAT for convex polygons. Edges/vertices touching are allowed (non-overlap). */\nexport function convexIntersects(a: Poly, b: Poly): boolean {\n const polys = [a, b];\n for (const poly of polys) {\n for (let i = 0; i < poly.length; i++) {\n const p0 = poly[i], p1 = poly[(i + 1) % poly.length];\n if (!p0 || !p1) continue;\n const ex = p1.x - p0.x, ey = p1.y - p0.y;\n const nx = -ey, ny = ex; // outward normal\n const pa = project(a, nx, ny);\n const pb = project(b, nx, ny);\n // Treat touching (zero overlap) as separated: allow edges/vertices to touch.\n if (pa.max <= pb.min + SEP_EPS || pb.max <= pa.min + SEP_EPS) return false;\n }\n }\n return true;\n}\n\n/** True if any poly from A overlaps any poly from B (fast AABB short-circuit). */\nexport function polysOverlap(aPolys: Poly[], bPolys: Poly[]): boolean {\n // quick AABB test to skip obvious separations\n const aabbsA = aPolys.map(p => {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of p) {\n if (pt.x < minX) minX = pt.x;\n if (pt.y < minY) minY = pt.y;\n if (pt.x > maxX) maxX = pt.x;\n if (pt.y > maxY) maxY = pt.y;\n }\n return { minX, minY, maxX, maxY };\n });\n const aabbsB = bPolys.map(p => {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of p) {\n if (pt.x < minX) minX = pt.x;\n if (pt.y < minY) minY = pt.y;\n if (pt.x > maxX) maxX = pt.x;\n if (pt.y > maxY) maxY = pt.y;\n }\n return { minX, minY, maxX, maxY };\n });\n\n for (let i = 0; i < aPolys.length; i++) {\n for (let j = 0; j < bPolys.length; j++) {\n const A = aPolys[i], B = bPolys[j];\n const aa = aabbsA[i], bb = aabbsB[j];\n if (!A || !B || !aa || !bb) continue;\n if (aa.maxX <= bb.minX + SEP_EPS || bb.maxX <= aa.minX + SEP_EPS ||\n aa.maxY <= bb.minY + SEP_EPS || bb.maxY <= aa.minY + SEP_EPS) continue;\n if (convexIntersects(A, B)) return true;\n }\n }\n return false;\n}\n","import type { Poly, Vec, PrimitiveBlueprint, CompositeBlueprint, Blueprint } from \"@/core/domain/types\";\n\nexport type AABB = { min: Vec; max: Vec; width: number; height: number };\n\n/** AABB of a single polygon (numeric). */\nexport function aabbOf(poly: Poly): { minX: number; minY: number; maxX: number; maxY: number } {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { minX, minY, maxX, maxY };\n}\n\n/** AABB of one or more polygons with width/height and center. */\nexport function polysAABB(polys: Poly[]) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of polys) {\n for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n }\n const width = Math.max(1, maxX - minX);\n const height = Math.max(1, maxY - minY);\n return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY }, width, height, cx:(minX+maxX)/2, cy:(minY+maxY)/2 };\n}\n\n/** Bounds of multiple polygons at the origin. */\nexport function boundsOfShapes(shapes: Poly[]): AABB {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of shapes) {\n for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n }\n const width = Math.max(0, maxX - minX);\n const height = Math.max(0, maxY - minY);\n return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY }, width, height };\n}\n\n/** Bounds of a primitive blueprint (uses its canonical shape). */\nexport function boundsOfPrimitive(bp: PrimitiveBlueprint): AABB {\n return boundsOfShapes(bp.shape);\n}\n\n/**\n * Bounds of a composite blueprint.\n * If `shape` is provided as precomputed union polygons, we use that.\n * Otherwise we bound the parts’ primitives at their offsets (loose but safe).\n */\nexport function boundsOfComposite(\n bp: CompositeBlueprint,\n primitiveLookup: (kind: string) => PrimitiveBlueprint | undefined\n): AABB {\n if (bp.shape && bp.shape.length) return boundsOfShapes(bp.shape);\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const part of bp.parts) {\n const prim = primitiveLookup(part.kind);\n if (!prim) continue;\n const b = boundsOfPrimitive(prim);\n const pMinX = part.offset.x + b.min.x;\n const pMinY = part.offset.y + b.min.y;\n const pMaxX = part.offset.x + b.max.x;\n const pMaxY = part.offset.y + b.max.y;\n if (pMinX < minX) minX = pMinX;\n if (pMinY < minY) minY = pMinY;\n if (pMaxX > maxX) maxX = pMaxX;\n if (pMaxY > maxY) maxY = pMaxY;\n }\n const width = Math.max(0, maxX - minX);\n const height = Math.max(0, maxY - minY);\n return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY }, width, height };\n}\n\n/** Unified bounds helper. */\nexport function boundsOfBlueprint(\n bp: Blueprint,\n primitiveLookup: (kind: string) => PrimitiveBlueprint | undefined\n): AABB {\n if (\"parts\" in bp) return boundsOfComposite(bp, primitiveLookup);\n return boundsOfPrimitive(bp);\n}\n","/**\n * Game-specific piece geometry operations\n * Includes: piece positioning, placement, grid snapping, and anchor generation\n *\n * Consolidated from: piece.ts, placement.ts, grid.ts, anchors.ts\n */\n\nimport type { Blueprint, Vec, Poly, Anchor } from \"@/core/domain/types\";\nimport type { CircleLayout, SectorGeom } from \"@/core/domain/layout\";\nimport { polysAABB } from \"./bounds\";\nimport { pointInPolygon, dist2 } from \"./math\";\nimport { CONFIG } from \"@/core/config/config\";\n\nconst GRID_PX = CONFIG.layout.grid.stepPx;\n\n// ===== Piece Positioning (from piece.ts) =====\n\n/** Translate blueprint polys to world coords for a given top-left (TL). */\nexport function piecePolysAt(\n bp: Blueprint,\n bb: { min: { x: number; y: number } },\n tl: { x: number; y: number }\n) {\n const ox = tl.x - bb.min.x;\n const oy = tl.y - bb.min.y;\n const polys = (\"shape\" in bp && bp.shape) ? bp.shape : [];\n return polys.map(poly => poly.map(p => ({ x: p.x + ox, y: p.y + oy })));\n}\n\n/** Build support offsets: each vertex relative to the AABB center. */\nexport function computeSupportOffsets(\n bp: Blueprint,\n bb: { min: { x: number; y: number }; width: number; height: number }\n) {\n const cx = bb.min.x + bb.width / 2;\n const cy = bb.min.y + bb.height / 2;\n\n const polys = (\"shape\" in bp && bp.shape && bp.shape.length)\n ? bp.shape\n : [[\n { x: bb.min.x, y: bb.min.y },\n { x: bb.min.x + bb.width, y: bb.min.y },\n { x: bb.min.x + bb.width, y: bb.min.y + bb.height },\n { x: bb.min.x, y: bb.min.y + bb.height },\n ]];\n\n const offs: Vec[] = [];\n for (const poly of polys) for (const v of poly) offs.push({ x: v.x - cx, y: v.y - cy });\n return offs;\n}\n\n/** Clamp using directional vertex support → exact contact with the ring. */\nexport function clampTopLeftBySupport(\n tlx: number,\n tly: number,\n d: {\n aabb: { width: number; height: number };\n support: { x: number; y: number }[];\n },\n layout: CircleLayout,\n target: \"workspace\" | \"silhouette\",\n pointerInsideCenter: boolean\n) {\n const cx0 = tlx + d.aabb.width / 2;\n const cy0 = tly + d.aabb.height / 2;\n\n const vx = cx0 - layout.cx;\n const vy = cy0 - layout.cy;\n const r = Math.hypot(vx, vy);\n if (r === 0) return { x: tlx, y: tly };\n\n const ux = vx / r, uy = vy / r;\n\n let h_out = -Infinity, h_in = -Infinity;\n for (const o of d.support) {\n const outProj = o.x * ux + o.y * uy;\n if (outProj > h_out) h_out = outProj;\n const inProj = -(o.x * ux + o.y * uy);\n if (inProj > h_in) h_in = inProj;\n }\n\n if (target === \"workspace\") {\n const [rIn, rOut] = layout.bands.workspace;\n const minR = pointerInsideCenter ? 0 : (rIn + h_in);\n const maxR = rOut - h_out;\n const rClamped = Math.min(Math.max(r, minR), maxR);\n if (Math.abs(rClamped - r) < 1e-6) return { x: tlx, y: tly };\n const newCx = layout.cx + rClamped * ux;\n const newCy = layout.cy + rClamped * uy;\n return { x: newCx - d.aabb.width / 2, y: newCy - d.aabb.height / 2 };\n } else {\n const rOut = layout.bands.silhouette[1];\n const maxR = rOut - h_out;\n if (r <= maxR) return { x: tlx, y: tly };\n const newCx = layout.cx + maxR * ux;\n const newCy = layout.cy + maxR * uy;\n return { x: newCx - d.aabb.width / 2, y: newCy - d.aabb.height / 2 };\n }\n}\n\n// ===== Placement (from placement.ts) =====\n\n/** gcd for positive integers */\nfunction igcd(a: number, b: number) {\n a = Math.round(Math.abs(a)); b = Math.round(Math.abs(b));\n while (b) [a, b] = [b, a % b];\n return a || 1;\n}\n\n/** Infer the base lattice unit in raw silhouette coordinates. */\nexport function inferUnitFromPolys(polys: Poly[]): number {\n let g = 0;\n for (const poly of polys) {\n for (let i = 0; i < poly.length; i++) {\n const a = poly[i], b = poly[(i + 1) % poly.length];\n if (!a || !b) continue;\n const dx = Math.round(Math.abs(b.x - a.x));\n const dy = Math.round(Math.abs(b.y - a.y));\n if (dx) g = g ? igcd(g, dx) : dx;\n if (dy) g = g ? igcd(g, dy) : dy;\n }\n }\n return g || 1;\n}\n\n/**\n * Place polys using scale S, re-centered, and translation snapped to GRID_PX; returns polys.\n * The center is snapped to the grid so the lattice points under the silhouette stay invariant.\n */\nexport function placeSilhouetteGridAlignedAsPolys(\n polys: Poly[],\n S: number,\n rectCenter: { cx: number; cy: number }\n): Poly[] {\n if (!polys || polys.length === 0) return [];\n const a = polysAABB(polys);\n const cx0 = (a.min.x + a.max.x) / 2;\n const cy0 = (a.min.y + a.max.y) / 2;\n const cx = Math.round(rectCenter.cx / GRID_PX) * GRID_PX;\n const cy = Math.round(rectCenter.cy / GRID_PX) * GRID_PX;\n const tx = cx - S * cx0;\n const ty = cy - S * cy0;\n const stx = Math.round(tx / GRID_PX) * GRID_PX;\n const sty = Math.round(ty / GRID_PX) * GRID_PX;\n return polys.map(poly => poly.map(p => ({ x: S * p.x + stx, y: S * p.y + sty })));\n}\n\n// ===== Grid Operations (from grid.ts) =====\n\nexport function nearestGridNode(p: Vec): Vec {\n return { x: Math.round(p.x / GRID_PX) * GRID_PX, y: Math.round(p.y / GRID_PX) * GRID_PX };\n}\n\n/** Generate grid nodes inside an AABB. */\nexport function gridNodesInAABB(min: Vec, max: Vec): Vec[] {\n const out: Vec[] = [];\n const x0 = Math.ceil(min.x / GRID_PX) * GRID_PX;\n const y0 = Math.ceil(min.y / GRID_PX) * GRID_PX;\n for (let y = y0; y <= max.y; y += GRID_PX) {\n for (let x = x0; x <= max.x; x += GRID_PX) out.push({ x, y });\n }\n return out;\n}\n\n/** Keep nodes in a band (and optional sector wedge). */\nexport function filterNodesToBandAndSector(\n nodes: Vec[],\n layout: CircleLayout,\n band: \"workspace\" | \"silhouette\",\n sector?: SectorGeom\n): Vec[] {\n const [rIn, rOut] = layout.bands[band];\n const out: Vec[] = [];\n for (const n of nodes) {\n const dx = n.x - layout.cx, dy = n.y - layout.cy;\n const r = Math.hypot(dx, dy);\n if (r < rIn || r > rOut) continue;\n\n if (sector) {\n let theta = Math.atan2(dy, dx);\n if (layout.mode === \"circle\") {\n if (theta < -Math.PI / 2) theta += 2 * Math.PI;\n } else {\n if (theta < Math.PI) theta += 2 * Math.PI;\n }\n if (theta < sector.start || theta >= sector.end) continue;\n }\n out.push(n);\n }\n return out;\n}\n\n/** Keep nodes that lie inside any of the polygons. */\nexport function filterNodesInPolys(\n nodes: Vec[],\n polys: Poly[],\n pointInPolyFn: (pt: Vec, poly: Poly) => boolean = pointInPolygon\n): Vec[] {\n const out: Vec[] = [];\n node: for (const n of nodes) {\n for (const poly of polys) {\n if (pointInPolyFn(n, poly)) { out.push(n); continue node; }\n }\n }\n return out;\n}\n\n// ===== Anchor Operations (from anchors.ts) =====\n\n/**\n * Find the nearest anchor that \"accepts\" a piece signature (kind/compositeSignature).\n * Returns null if none within the optional radius.\n */\nexport function nearestAcceptingAnchor(\n anchors: Anchor[] | undefined,\n point: Vec,\n accepts: { kind?: string; compositeSignature?: string },\n withinPx: number = Infinity\n): { anchor: Anchor; d2: number } | null {\n if (!anchors || !anchors.length) return null;\n\n const { kind, compositeSignature } = accepts;\n const r2 = withinPx === Infinity ? Infinity : withinPx * withinPx;\n\n let best: { anchor: Anchor; d2: number } | null = null;\n for (const a of anchors) {\n const ok = a.accepts.some(acc =>\n (acc.kind === undefined || acc.kind === kind) &&\n (acc.compositeSignature === undefined || acc.compositeSignature === compositeSignature)\n );\n if (!ok) continue;\n\n const d2val = dist2(point, a.position);\n if (d2val <= r2 && (!best || d2val < best.d2)) {\n best = { anchor: a, d2: d2val };\n }\n }\n return best;\n}\n\n/** True if `point` is within `withinPx` of the given anchor. */\nexport function withinAnchor(anchor: Anchor, point: Vec, withinPx: number): boolean {\n const r2 = withinPx * withinPx;\n return dist2(point, anchor.position) <= r2;\n}\n\n// Node-grid helpers for anchor generation\nexport function workspaceNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"workspace\", sector);\n}\n\nexport function silhouetteNodes(layout: CircleLayout, sector: SectorGeom, fittedMask: Poly[]): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n const banded = filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n return filterNodesInPolys(banded, fittedMask);\n}\n\nexport function silhouetteBandNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n}\n\n/** Generate anchor grid nodes for the inner ring (radius < innerR) */\nexport function innerRingNodes(layout: CircleLayout): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.innerR, y: layout.cy - layout.innerR - pad };\n const max = { x: layout.cx + layout.innerR, y: layout.cy + layout.innerR + pad };\n const nodes = gridNodesInAABB(min, max);\n // Filter to nodes within the inner circle\n const out: Vec[] = [];\n for (const n of nodes) {\n const dx = n.x - layout.cx, dy = n.y - layout.cy;\n const r = Math.hypot(dx, dy);\n if (r < layout.innerR) out.push(n);\n }\n return out;\n}\n\nexport const anchorsDiameterToPx = (anchorsDiag: number, gridPx: number = GRID_PX) =>\n anchorsDiag * Math.SQRT2 * gridPx;\n","// src/core/domain/solve.ts\nimport type { LayoutMode, PlacementTarget, Poly } from \"@/core/domain/types\";\nimport { anchorsDiameterToPx } from \"@/core/engine/geometry\";\nimport { CONFIG } from \"@/core/config/config\";\n\n// --- helpers to infer lattice unit and silhouette radius -------------------\nfunction igcd(a: number, b: number) {\n a = Math.round(Math.abs(a)); b = Math.round(Math.abs(b));\n while (b) [a, b] = [b, a % b];\n return a || 1;\n}\nfunction inferUnitFromPolys(polys: Poly[]): number {\n let g = 0;\n for (const poly of polys) {\n for (let i = 0; i < poly.length; i++) {\n const a = poly[i], b = poly[(i + 1) % poly.length];\n if (!a || !b) continue;\n const dx = Math.round(Math.abs(b.x - a.x));\n const dy = Math.round(Math.abs(b.y - a.y));\n if (dx) g = g ? igcd(g, dx) : dx;\n if (dy) g = g ? igcd(g, dy) : dy;\n }\n }\n return g || 1;\n}\nfunction polysAABB(polys: Poly[]) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of polys) for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n const cx = (minX + maxX) / 2, cy = (minY + maxY) / 2;\n return { minX, minY, maxX, maxY, cx, cy };\n}\n\ntype RadiiParams = {\n n: number; // number of outer sectors\n layoutMode: LayoutMode; // \"circle\" | \"semicircle\"\n target: PlacementTarget; // \"workspace\" | \"silhouette\"\n qsMaxSlots: number; // number of quickstash slots on inner ring\n primitivesSlots: number; // number of primitive slots on inner ring\n gridPx?: number; // override GRID_PX (rare)\n reqWorkspaceDiamAnchors?: number; // override default capacity (rare)\n reqQuickstashDiamAnchors?: number; // override default capacity (rare)\n reqPrimitiveDiamAnchors?: number; // override defaults (rare)\n layoutPadPx?: number; // override outer pad (rare)\n masks?: Poly[][]; // raw silhouette polys per sector (for workspace fit calc)\n};\n\nexport type RadiiSolution = {\n innerR_min: number;\n dr_min: number;\n outerR_min: number;\n Tw_min: number; // minimal workspace-band thickness (px) (= required diagonal diameter)\n Tp_min: number; // minimal silhouette-plate thickness (px) (= 2*max silhouette radius or 0)\n Rshape_px_max: number; // max raw-shape radius after canonical unit scaling\n};\n\nexport function solveRadii(params: RadiiParams): RadiiSolution {\n const {\n n,\n layoutMode,\n target,\n qsMaxSlots,\n primitivesSlots,\n gridPx = CONFIG.layout.grid.stepPx,\n reqWorkspaceDiamAnchors = CONFIG.layout.constraints.workspaceDiamAnchors,\n reqQuickstashDiamAnchors = CONFIG.layout.constraints.quickstashDiamAnchors,\n reqPrimitiveDiamAnchors = CONFIG.layout.constraints.primitiveDiamAnchors,\n } = params;\n\n // Canonical lattice scale from raw masks (if provided)\n const allPolys: Poly[] = (params.masks ?? []).flat();\n const rawUnit = allPolys.length ? inferUnitFromPolys(allPolys) : 0;\n const unitScaleS = rawUnit ? (2 * gridPx) / rawUnit : 1;\n\n // Max silhouette radius (px) across all sectors, measured from each sector mask AABB center\n let Rshape_px_max = 0;\n if (params.masks && params.masks.length) {\n for (const sectorPolys of params.masks) {\n if (!sectorPolys?.length) continue;\n const a = polysAABB(sectorPolys);\n const { cx, cy } = a;\n for (const poly of sectorPolys) {\n for (const p of poly) {\n const rx = (p.x - cx) * unitScaleS;\n const ry = (p.y - cy) * unitScaleS;\n const r = Math.hypot(rx, ry);\n if (r > Rshape_px_max) Rshape_px_max = r;\n }\n }\n }\n }\n\n const sweep = layoutMode === \"circle\" ? Math.PI * 2 : Math.PI;\n const dOut = sweep / Math.max(1, n);\n const dIn = sweep / Math.max(1, qsMaxSlots);\n const dPrim = sweep / Math.max(1, primitivesSlots);\n const sinOut = Math.sin(dOut / 2);\n const sinIn = Math.sin(dIn / 2);\n const sinPrim = Math.sin(dPrim / 2);\n\n // Diagonal-based anchor diameters (so \"X anchors\" refers to the 45° lattice)\n const D_ws = anchorsDiameterToPx(reqWorkspaceDiamAnchors, gridPx);\n const D_bp = anchorsDiameterToPx(reqQuickstashDiamAnchors, gridPx);\n const D_prim = anchorsDiameterToPx(reqPrimitiveDiamAnchors, gridPx);\n\n // Inner-ring minimum from chord ≥ required diameter (blueprints + primitives)\n const innerR_min_bp = D_bp * (0.5 + 1 / (2 * Math.max(1e-9, sinIn)));\n const innerR_min_prim = D_prim * (0.5 + 1 / (2 * Math.max(1e-9, sinPrim)));\n const innerR_min_ws = D_ws / (2 * Math.max(1e-9, sinOut)) - D_ws / 2;\n\n const innerR_min = Math.max(innerR_min_bp, innerR_min_prim, innerR_min_ws);\n\n // Component minima: workspace band must be at least D_ws thick; silhouette plate\n // must be thick enough to contain the largest mask radius (both sides).\n const Tw_min = D_ws;\n const Tp_min = target === \"workspace\" ? (2 * Rshape_px_max) : 0;\n const dr_min = Tw_min + Tp_min;\n\n const outerR_min = innerR_min + dr_min;\n\n return { innerR_min, dr_min, outerR_min, Tw_min, Tp_min, Rshape_px_max };\n}\n\nexport function optimizeBandSplit(args: {\n outerRViewportBound: number;\n innerR_min: number;\n Tw_min: number;\n Tp_min: number;\n Rshape_px_max: number;\n D_ws_px: number; // anchorsDiameterToPx(REQ_WORKSPACE_DIAM_ANCHORS)\n}): { innerR: number; Tw: number; Tp: number; outerR: number } {\n const { outerRViewportBound, innerR_min, Tw_min, Tp_min, Rshape_px_max, D_ws_px } = args;\n\n const dr_min = Tw_min + Tp_min;\n\n // If the viewport can’t even accommodate the minima, clamp to the minimal feasible ring.\n if (outerRViewportBound < innerR_min + dr_min) {\n const outerR = innerR_min + dr_min;\n return { innerR: innerR_min, Tw: Tw_min, Tp: Tp_min, outerR };\n }\n\n // Maximize ring thickness by minimizing innerR (this maximizes anchor size everywhere).\n const outerR = outerRViewportBound;\n const innerR = innerR_min;\n const dr = outerR - innerR;\n\n // Distribute slack between bands with a gentle bias towards the silhouette plate\n // when masks have large radial extent (so they don’t look cramped).\n const slack = Math.max(0, dr - dr_min);\n const wWork = 1;\n const wSil = 1 + (Rshape_px_max / Math.max(1e-9, D_ws_px));\n const addWork = slack * (wWork / (wWork + wSil));\n const Tw = Tw_min + addWork;\n const Tp = dr - Tw;\n\n return { innerR, Tw, Tp, outerR };\n}\n\n/**\n * Compute the *logical* SVG viewBox (LOGICAL_W/H) from the minimal feasible\n * outer radius implied by the anchor-capacity constraints. The result ensures\n * lattice density is invariant across devices/zoom levels.\n *\n * NOTE: This should be called prior to computeCircleLayout and the returned\n * width/height must be passed as the viewport to computeCircleLayout so both\n * functions agree on the same bound.\n */\nexport function solveLogicalBox(params: RadiiParams & { layoutPadPx: number }): { LOGICAL_W: number; LOGICAL_H: number } {\n const { layoutMode, layoutPadPx } = params;\n const { outerR_min } = solveRadii(params);\n\n if (layoutMode === \"circle\") {\n const LOGICAL_W = 2 * (outerR_min + layoutPadPx);\n return { LOGICAL_W, LOGICAL_H: LOGICAL_W };\n } else {\n // semicircle: height is half the width; outerR computed against both axes ends up ~W/2\n const LOGICAL_W = 2 * (outerR_min + layoutPadPx);\n return { LOGICAL_W, LOGICAL_H: LOGICAL_W / 2 };\n }\n}","import type { LayoutMode, PlacementTarget, Poly } from \"./types\";\nimport { anchorsDiameterToPx } from \"@/core/engine/geometry\";\nimport { solveRadii, optimizeBandSplit } from \"@/core/domain/solve\";\nimport { CONFIG } from \"@/core/config/config\";\n\nexport type SectorGeom = { id: string; index: number; start: number; end: number; mid: number };\n\nexport type RingBands = {\n silhouette: [number, number];\n workspace: [number, number];\n};\n\nexport type CircleLayout = {\n mode: LayoutMode;\n cx: number; cy: number;\n innerR: number; outerR: number;\n sectors: SectorGeom[];\n bands: RingBands;\n sweepStart: number;\n sweepEnd: number;\n};\n\nexport function computeCircleLayout(\n viewport: { w: number; h: number },\n n: number,\n sectorIds: string[],\n mode: LayoutMode = \"circle\",\n target: PlacementTarget = \"workspace\",\n extras: { qsMaxSlots: number; primitivesSlots: number; masks?: Poly[][] }\n): CircleLayout {\n const pad = CONFIG.layout.paddingPx;\n\n // place the semicircle so its diameter sits on the bottom edge of the SVG\n const cx = viewport.w / 2;\n const cy = mode === \"semicircle\" ? viewport.h : viewport.h / 2;\n\n // The viewport bound must match the viewBox computed by solveLogicalBox so ring sizes stay consistent.\n // vertical radius must not cross the top padding\n const maxRVertical = mode === \"semicircle\" ? (viewport.h - pad) : cy;\n const outerRViewportBound = Math.min(cx, maxRVertical) - pad;\n\n // Solve *minimum* feasible radii and then optimize the band split within the viewport bound\n const sol = solveRadii({\n n,\n layoutMode: mode,\n target,\n qsMaxSlots: extras.qsMaxSlots,\n primitivesSlots: extras.primitivesSlots,\n masks: extras.masks ?? [],\n });\n\n let innerR: number, outerR: number, bands: RingBands;\n\n if (target === \"workspace\") {\n const D_ws_px = anchorsDiameterToPx(CONFIG.layout.constraints.workspaceDiamAnchors);\n const opt = optimizeBandSplit({\n outerRViewportBound,\n innerR_min: sol.innerR_min,\n Tw_min: sol.Tw_min,\n Tp_min: sol.Tp_min,\n Rshape_px_max: sol.Rshape_px_max,\n D_ws_px,\n });\n innerR = opt.innerR;\n outerR = opt.outerR;\n bands = {\n workspace: [opt.innerR, opt.innerR + opt.Tw],\n silhouette: [opt.innerR + opt.Tw, opt.outerR],\n };\n } else {\n // silhouette-only: maximize thickness; entire ring is silhouette\n outerR = Math.max(outerRViewportBound, sol.outerR_min);\n // minimize innerR to maximize thickness, but not below minimal requirement\n innerR = Math.min(sol.innerR_min, outerR);\n if (outerR < sol.outerR_min) { outerR = sol.outerR_min; innerR = sol.innerR_min; }\n bands = { silhouette: [innerR, outerR], workspace: [innerR, outerR] };\n }\n\n const sweep = mode === \"circle\" ? Math.PI * 2 : Math.PI;\n // semicircle: sweep the upper arc by anchoring the diameter on the bottom (π→2π)\n const sweepStart = mode === \"circle\" ? -Math.PI / 2 : Math.PI;\n const sweepEnd = sweepStart + sweep;\n const step = sweep / n;\n\n const sectors: SectorGeom[] = [];\n for (let i = 0; i < n; i++) {\n const id = sectorIds[i] ?? String(i);\n const start = sweepStart + i * step;\n const end = start + step;\n const mid = (start + end) / 2;\n sectors.push({ id, index: i, start, end, mid });\n }\n return { mode, cx, cy, innerR, outerR, sectors, bands, sweepStart, sweepEnd };\n}\n\n/** Ring wedge path helper */\nexport function wedgePath(\n cx: number, cy: number,\n innerR: number, outerR: number,\n start: number, end: number\n): string {\n const largeArc = end - start > Math.PI ? 1 : 0;\n const x0 = cx + innerR * Math.cos(start);\n const y0 = cy + innerR * Math.sin(start);\n const x1 = cx + outerR * Math.cos(start);\n const y1 = cy + outerR * Math.sin(start);\n const x2 = cx + outerR * Math.cos(end);\n const y2 = cy + outerR * Math.sin(end);\n const x3 = cx + innerR * Math.cos(end);\n const y3 = cy + innerR * Math.sin(end);\n return [\n `M ${x0} ${y0}`,\n `L ${x1} ${y1}`,\n `A ${outerR} ${outerR} 0 ${largeArc} 1 ${x2} ${y2}`,\n `L ${x3} ${y3}`,\n `A ${innerR} ${innerR} 0 ${largeArc} 0 ${x0} ${y0}`,\n \"Z\",\n ].join(\" \");\n}\n\n/** Sector hit-test (band optional) */\nexport function sectorAtPoint(\n x: number, y: number, layout: CircleLayout, band?: keyof RingBands\n): string | undefined {\n const dx = x - layout.cx;\n const dy = y - layout.cy;\n const r = Math.hypot(dx, dy);\n\n const [rIn, rOut] = band ? layout.bands[band] : [layout.innerR, layout.outerR];\n if (r < rIn || r > rOut) return undefined;\n\n let theta = Math.atan2(dy, dx); // [-π, +π]\n if (layout.mode === \"circle\") {\n if (theta < -Math.PI / 2) theta += 2 * Math.PI;\n } else {\n // semicircle covers [π, 2π]\n if (theta < Math.PI) theta += 2 * Math.PI;\n }\n\n for (const s of layout.sectors) {\n if (theta >= s.start && theta < s.end) return s.id;\n }\n return layout.sectors.at(-1)?.id;\n}\n\n/** Convenience: axis-aligned rect for fitting silhouettes in a band */\nexport function rectForBand(\n layout: CircleLayout, sector: SectorGeom, band: keyof RingBands, pad = 0.85\n) {\n const [rIn, rOut] = layout.bands[band];\n const rMid = (rIn + rOut) / 2;\n const dr = rOut - rIn;\n const arc = (sector.end - sector.start) * rMid * 0.9;\n const w = arc * pad;\n const h = dr * pad;\n const cx = layout.cx + rMid * Math.cos(sector.mid);\n const cy = layout.cy + rMid * Math.sin(sector.mid);\n return { cx, cy, w, h };\n}","/**\n * Border Rendering Utilities for Edge-Aware Piece Borders\n * \n * This module provides utilities for rendering piece borders with edge-aware logic.\n * Uses the same coordinate system and approach as face-to-face.ts for consistency.\n * Visual polish - hides borders between touching pieces\n */\n\nimport type { Vec, Piece, Blueprint } from \"../../domain/types\";\nimport { CONFIG } from \"../../config/config\";\nimport { boundsOfBlueprint } from \"../geometry\";\n\nexport interface UnitSegment {\n a: Vec;\n b: Vec;\n}\n\n/**\n * Generate SVG path data for individual edge strokes\n * Each edge becomes a separate path element for selective rendering\n */\nexport function generateEdgeStrokePaths(poly: Vec[]): string[] {\n const strokePaths: string[] = [];\n \n for (let i = 0; i < poly.length; i++) {\n const current = poly[i];\n const next = poly[(i + 1) % poly.length];\n \n if (current && next) {\n strokePaths.push(`M ${current.x} ${current.y} L ${next.x} ${next.y}`);\n }\n }\n \n return strokePaths;\n}\n\n/**\n * Convert a polygon edge into unit-length segments\n * Uses the same logic as face-to-face.ts for consistency\n */\nfunction edgeToUnitSegments(start: Vec, end: Vec, gridSize: number): UnitSegment[] {\n const segments: UnitSegment[] = [];\n \n // Convert to grid coordinates\n const startGrid = {\n x: Math.round(start.x / gridSize),\n y: Math.round(start.y / gridSize)\n };\n const endGrid = {\n x: Math.round(end.x / gridSize),\n y: Math.round(end.y / gridSize)\n };\n \n const dx = endGrid.x - startGrid.x;\n const dy = endGrid.y - startGrid.y;\n \n if (dx === 0 && dy === 0) return []; // Zero-length edge\n \n const steps = Math.max(Math.abs(dx), Math.abs(dy));\n const stepX = dx / steps;\n const stepY = dy / steps;\n \n for (let i = 0; i < steps; i++) {\n const aX = Math.round(startGrid.x + i * stepX);\n const aY = Math.round(startGrid.y + i * stepY);\n const bX = Math.round(startGrid.x + (i + 1) * stepX);\n const bY = Math.round(startGrid.y + (i + 1) * stepY);\n segments.push({ \n a: { x: aX, y: aY }, \n b: { x: bX, y: bY } \n });\n }\n \n return segments;\n}\n\n/**\n * Get all unit segments for a piece (same logic as face-to-face.ts)\n * Currently unused - kept for reference\n */\n/*\nfunction getPieceUnitSegments(\n piece: Piece, \n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any,\n gridSize: number\n): UnitSegment[] {\n // Defensive check: if getBlueprint fails, return empty segments\n let blueprint: Blueprint | undefined;\n try {\n blueprint = getBlueprint(piece.blueprintId);\n } catch (error) {\n console.warn('getBlueprint failed in getPieceUnitSegments:', error);\n return [];\n }\n\n if (!blueprint?.shape) return [];\n \n // Calculate offset using same logic as piecePolysAt\n const bb = boundsOfBlueprint(blueprint, getPrimitive);\n const ox = piece.pos.x - bb.min.x;\n const oy = piece.pos.y - bb.min.y;\n \n const allSegments: UnitSegment[] = [];\n \n // Translate polygons and convert edges to unit segments\n for (const poly of blueprint.shape) {\n const translatedPoly = poly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n \n for (let i = 0; i < translatedPoly.length; i++) {\n const current = translatedPoly[i];\n const next = translatedPoly[(i + 1) % translatedPoly.length];\n \n if (!current || !next) continue;\n \n allSegments.push(...edgeToUnitSegments(current, next, gridSize));\n }\n }\n \n return allSegments;\n}\n*/\n\n/**\n * Check which edges should be hidden for a specific polygon within a piece\n * Handles both internal composite edges and external touching between pieces\n */\nexport function getHiddenEdgesForPolygon(\n piece: Piece,\n polyIndex: number,\n allPiecesInSector: Piece[],\n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any\n): boolean[] {\n // Defensive check: if getBlueprint fails, return no hidden edges\n let blueprint: Blueprint | undefined;\n try {\n blueprint = getBlueprint(piece.blueprintId);\n } catch (error) {\n console.warn('getBlueprint failed in getHiddenEdgesForPolygon:', error);\n return [];\n }\n\n if (!blueprint?.shape) {\n return [];\n }\n\n const poly = blueprint.shape[polyIndex];\n if (!poly) return [];\n\n const gridSize = CONFIG.layout.grid.stepPx;\n const bb = boundsOfBlueprint(blueprint, getPrimitive);\n const ox = piece.pos.x - bb.min.x;\n const oy = piece.pos.y - bb.min.y;\n \n const translatedPoly = poly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n\n const hiddenEdges: boolean[] = [];\n\n // For each edge in this polygon\n for (let i = 0; i < translatedPoly.length; i++) {\n const current = translatedPoly[i];\n const next = translatedPoly[(i + 1) % translatedPoly.length];\n \n if (!current || !next) {\n hiddenEdges.push(false);\n continue;\n }\n\n // Get segments for this edge\n const edgeSegments = edgeToUnitSegments(current, next, gridSize);\n \n // Check if any of these segments are touching other pieces\n let isTouching = false;\n \n // 1. Check internal composite edges (if this is a composite)\n if (piece.blueprintId.startsWith('comp:')) {\n // Check against other polygons in the same composite\n for (let otherPolyIndex = 0; otherPolyIndex < blueprint.shape.length; otherPolyIndex++) {\n if (otherPolyIndex === polyIndex) continue; // Skip self\n \n const otherPoly = blueprint.shape[otherPolyIndex];\n if (!otherPoly) continue;\n \n const otherTranslatedPoly = otherPoly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n\n // Check if this edge touches any edge of the other polygon\n for (let j = 0; j < otherTranslatedPoly.length; j++) {\n const otherCurrent = otherTranslatedPoly[j];\n const otherNext = otherTranslatedPoly[(j + 1) % otherTranslatedPoly.length];\n \n if (!otherCurrent || !otherNext) continue;\n\n const otherEdgeSegments = edgeToUnitSegments(otherCurrent, otherNext, gridSize);\n \n // Check if any segments are shared\n for (const edgeSeg of edgeSegments) {\n const isShared = otherEdgeSegments.some(otherSeg => \n // Check if segments share the same endpoints (identical or reversed)\n (edgeSeg.a.x === otherSeg.a.x && edgeSeg.a.y === otherSeg.a.y &&\n edgeSeg.b.x === otherSeg.b.x && edgeSeg.b.y === otherSeg.b.y) ||\n (edgeSeg.a.x === otherSeg.b.x && edgeSeg.a.y === otherSeg.b.y &&\n edgeSeg.b.x === otherSeg.a.x && edgeSeg.b.y === otherSeg.a.y)\n );\n \n if (isShared) {\n isTouching = true;\n break;\n }\n }\n \n if (isTouching) break;\n }\n \n if (isTouching) break;\n }\n }\n \n // 2. Check external touching between different pieces (if not already touching internally)\n // Only check external touching when hideTouchingBorders is true\n if (!isTouching && CONFIG.game.hideTouchingBorders) {\n for (const otherPiece of allPiecesInSector) {\n if (otherPiece.id === piece.id) continue; // Skip self\n \n const otherBlueprint = getBlueprint(otherPiece.blueprintId);\n if (!otherBlueprint?.shape) continue;\n\n const otherBb = boundsOfBlueprint(otherBlueprint, getPrimitive);\n const otherOx = otherPiece.pos.x - otherBb.min.x;\n const otherOy = otherPiece.pos.y - otherBb.min.y;\n\n // Check if this edge touches any edge of the other piece\n for (const otherPoly of otherBlueprint.shape) {\n const otherTranslatedPoly = otherPoly.map((vertex: Vec) => ({\n x: vertex.x + otherOx,\n y: vertex.y + otherOy\n }));\n\n for (let j = 0; j < otherTranslatedPoly.length; j++) {\n const otherCurrent = otherTranslatedPoly[j];\n const otherNext = otherTranslatedPoly[(j + 1) % otherTranslatedPoly.length];\n \n if (!otherCurrent || !otherNext) continue;\n\n const otherEdgeSegments = edgeToUnitSegments(otherCurrent, otherNext, gridSize);\n \n // Check if any segments are shared\n for (const edgeSeg of edgeSegments) {\n const isShared = otherEdgeSegments.some(otherSeg => \n // Check if segments share the same endpoints (identical or reversed)\n (edgeSeg.a.x === otherSeg.a.x && edgeSeg.a.y === otherSeg.a.y &&\n edgeSeg.b.x === otherSeg.b.x && edgeSeg.b.y === otherSeg.b.y) ||\n (edgeSeg.a.x === otherSeg.b.x && edgeSeg.a.y === otherSeg.b.y &&\n edgeSeg.b.x === otherSeg.a.x && edgeSeg.b.y === otherSeg.a.y)\n );\n \n if (isShared) {\n isTouching = true;\n break;\n }\n }\n \n if (isTouching) break;\n }\n \n if (isTouching) break;\n }\n \n if (isTouching) break;\n }\n }\n\n hiddenEdges.push(isTouching);\n }\n\n return hiddenEdges;\n}\n\n/**\n * Check if borders should be shown at all\n * If false, neither primitives nor composites have borders\n */\nexport function shouldShowBorders(): boolean {\n return CONFIG.game.showBorders;\n}\n\n/**\n * Check if touching borders should be hidden\n * Only relevant when showBorders is true\n * - true: All pieces use selective border rendering\n * - false: Only composites use selective border rendering\n */\nexport function shouldHideTouchingBorders(): boolean {\n return CONFIG.game.hideTouchingBorders;\n}\n\n/**\n * Check if a piece should have selective border rendering\n * This determines whether to use edge-aware borders or full borders\n */\nexport function shouldUseSelectiveBorders(blueprintId: string): boolean {\n // Use selective borders if:\n // 1. Borders are enabled globally AND\n // 2. Either hideTouchingBorders is true (ALL pieces) OR this is a composite piece\n return CONFIG.game.showBorders && (\n CONFIG.game.hideTouchingBorders || // If true, ALL pieces use selective borders\n blueprintId.startsWith('comp:') // If false, only composites use selective borders\n );\n}","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsSAAALEgHS3X78AAAFY0lEQVR4nO2d7XXrNgyGH/r0f7zB9QbXnaDqBt6gvhM0I2SE3A2UDXwnqLKBPEHdDewJ0B+kYieWZEoiQfrjPQcnjqOI0GuYAAFQMiJCLjDGLIEFsHQyB/7w/Pd397MCamAnInVgFUfDpCTaGLMACmDlfj4FHuKAJX4DVCKyC3x+b6gTbYyZA2sn31UHhy1QAqWI7FVHFhEVwVpsCUgmUgKF2vUrEVxlQGyXVBqE3zPBqoTHIHhOXlPEUCmBedZEY6OHfQZkTZU9sMqO6Buw4ujWHYLkJXaBkJqUWFIDy6REYx3eLUwVl2TPREc5heR1BgRoy1qV6DsleRLZD5KVyH6QrET2UMeX+uJyE28H6UvykvuILobKHs/Qz4fkObcdJ0+VGo9FzcV8tDGmBP7qPSg+DtgLqrFWBLYSs8C/AhMTbyKy7j3igjWvSPu1LPH4ajo9y4S6ChdyI5emjFTz8isjcgxYC98kNIxOnfuUTmEhk5e6Tvd1IiMpBxFNmlDOy6kMIDtVpNRqKK3O0BhToetk/sPOxZ0FU1cxX2CNAGxFZCc9lW3XvlARvrreh3cRKc7ezcSaOx0e1tH1hZc1PY6INA79zKrbFKuUlXrpccZDdKnomHqwzlXzmqpeotG35l0PyWMWSa3zPGkiqKKP6FJZmXUH0VVIa0pk1WUr0e5T11REaLe+dYwPEOtIk13fqSLPykp0Wd4uwLm7piTtnM1zM/aMI9boovr6hgvHvgU49zdjTNHyvnZ36bp5MYOPGFW74bDtoouA52871y7g+X3w3XH7YdGFsgJwzMKdYh55zCry+dtQwJHoVQIF7gUrSGvR94ICYOYckGYu4N7wZIxZzLDx5QNxsZxh04kPxMUS9JNINfBChB7kS4KNal4JsygaIhtNooNUTwKS/oxeoqky7kVsbB3JujuhLkCzMKBF9O+S0ebKU7il+j+xx5ldPmQyfuZKMoCIVMCv2ONoEP2qMMZUlLEHiD11HEQkdv4iCIwxUafQ2Bad7ZShjd9SK+CLkz3kTQJsQ4o93RMQNX4MFPN2NcN4t816jBE1ltZwhpPgLLmiPdZ9Aip3TNbInmjsdNG3oHhCvww3GDOOd27JFT5FidwLF+8z2ktKD4TFfkb+Idgm0DEpUV8L0Yeevx94ED0dYttyC9rJPmCzgjtFlcagnjkl+ywmOVxSasHn5M8vYJFzwsrhICK7JryrUmriA7cCPCW1vpJVYQXHODr3Oe6asYEj0VU6PW4eFTii3Ty9TajMrWLbOOrTJXiZRJXbRtm8eBAdF2Xz4oNo58HfUmhzo3g7jYq+Zu9KXV0Go+54nSPKT7+1JMArwiW86wiNL2sm3ERKKfF/VvA42zkbus9BREyoc8WC68r/N+Ap/3RtDB84S/y7A4LlqI0xueeKIWx/+PtXkoHzqeOkRpdV3TCmELbpsbWG2Td4yA2QwefUgCS/BLzO185xehSYB/6ksyObsLeX2zHmxihOkdB3Biixqc3UBC8If6eaom9Mn5tXvQJ/9x40HFtsGKmd5pxjHV/oPZU/ReS57wCvp1YYY2r0N3xeC7YicnF7im9fx4rMqzCJcMCz1cGLaDnW7R74jEI865XenUpia3M/xmp0g/ghQ+qViUOia5XBoWoO8ee1yaj1QC7B/rXIKJK94ug+JLqvXAo0jTqjc+CT2nbdwEtuu7C7xSaKphUaAi1pm62/qb/aoWXUzWiDztEdhD8e4aRB9I1YdzArjkr0CeGNo0xNnK9UBNp4pEr0CeFF5oRXXPODIzsILzMgtpFSg+BGHg/3VcLjcdVKSEr0Vzjil4x/AHvTrF5jm3d2wZUcif8BqSLxz8FiAOgAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAYAAAA4qEECAAAACXBIWXMAAAsSAAALEgHS3X78AAAFYklEQVR4nO1d0ZGjOBB9ct3/+iJYMlg2giODcwjeDCYEbwbeDNgMvBloIjgmAyYDHEHfh4SHsQUIaLVk7FfVNTblkZpHq1u0GqGICKlAKZUDyADkVrYA/vH891f7VwOoANREVDGrOBsqJtFKqQxAAWBn/35h7uIMQ/wJgCaimrl9b4gTrZTaAthb+SbaOfAGoARQElEj2jMRiQiMxZYAKBEpARRi5y9EsE6A2D7REoQ/MsGihIcgeIu0XMRUKQFskyYaZvbQJEDWUmkA7JIjegVWHNy6OUjOYW4QYpMSSioAeVSiYQLeGlzFmDRYGCiXkLxPgABp2YsS/aAkLyL7SbIQ2U+ShcieGvhin1xq4h0gvbJ3Nk+swZ/G9MEZZooFmKlkDB36cIYhezzv7WHJW8jOkxsAR5i7TOfNAszoOgKoBfXqk6pPz0muA3J3fDXmBBkTN2ITXi4i2lqVhKJHH6sYGXXHyGQP5kbGlJe465tsxSPWHYvoZshYYrsMNpITIbvXhfQpWwgo9eJB2AmfR1Vjjw1eoMhkF1OI1oGV0SNxofZoo8aAX7QXJAbRznOLZc1ZDzlzAtqxp60sEtEEh1XHsGanHwNwWNCm0w0h3mLEjVUnYc1M/d4k55GQVUtbQBUwJpx62q4jEV06iYaZN4fu/MafgtfqXKMlFtGEzrx6gw/sER6u5MuOsf1D94tS6gXAV8b2p2J/+dS58hKJo9tovCwIukTbNrXA+YxJ9cl1QC5ouIiONd+VkqzrOgrEQzI1zIFQALgQzeknh5AJ9ZMSdgDELTpzHDsJ9R0LRfshR4TgkNAUTMRPbyA7nL/ZxymuoQV1iIF8A2PRknDFg7W7j3wD+RnHTX9EdIJZUV4r8r8idPqvUmpLtw/rHBH+oscqV9gCskGhgblrY6+o9xWYmHSAfBWsWEenmAQ7CN9C9q5UpJMyNrEDhGsJDlTLdkC8wyTlZR+g9IR9wLRGYN+9Gf/JYhxSJRkArG7H0P1IWPTfKRMNXIo4/wvaB8IS/U5EWcD22aCUCmpwoV1HHbj9u4GEj2aBUmqnlKqUUmSlUkpJpXdZEHJao5mmYEOFNc4Cmhl9BJ9H65SJhl/NR5E40XoDcyuaMnzcwz60EgvRbJD+mp1PGjcLrcRCVPdAtM+IS31U3gXRPosCqS8cVG0gCJUy5Jp1DBX3ONchEwqGDdFHXYdmuGohUQD44zj+B3FrUnyggY8blqSHHhE1RLQD8LNz+CcR7VLPo8Byey8Wfc/QgCWazA6HbxGVWSveLLefch1lFFXWjbL98CQ6LMr2w4VoG1R+x9BmpfjdDdTXadJSVpdVo+x++UQ0EWl87MP8xHy8Wi4vcCX+DyKqzENbOnZG2nP/w/UB5w40SikN/53Ih8C+ZmgXUkHMu50zrhm+ElFx034P0Zyrwo+2Cv7dZQTONUP7w19MHd/Duh6Xjr96R9pANqut4FmavaqRUM1dz3lyZC8Hz7N3FdwO95cJV7MPXyFQCbQAJ/CUg+0HXaTHFefaq6hEQpYN3mrS0ZV4X6W4nqqtYRZS11Qf7bXw4LvBYGbJ5qy4fId8JRN3xf8ZplK2Hvuh93tYJAoB7xDOqZwL3iVhtsEfs1VaH374kgzAz0df+bg9eHzbPct+Mm8zA8ojkz2Z5NlEPzDZs0j2nnX0IfJ2x5Lw3764B4vqo23HOda9sPsGM4Vbli1kuglIYbfbELJoF2AWH91D+PMVThJEr8S62aw4KNEdwttAGZs4X9FgeFWTONEdwovECde45xdH9hBeJkBsK6UEwa08X+4rhOfrqoUQlehrWOJzzH8BewOTN69gEvI1u5Iz8T+TOcUtjzRRXwAAAABJRU5ErkJggg==\"","import React from \"react\";\nimport type { Poly, TanKind, Blueprint, PrimitiveBlueprint } from \"@/core/domain/types\";\nimport { wedgePath, rectForBand, type CircleLayout } from \"@/core/domain/layout\";\nimport { boundsOfBlueprint, placeSilhouetteGridAlignedAsPolys, polysAABB } from \"@/core/engine/geometry\";\nimport { CONFIG } from \"@/core/config/config\";\nimport { generateEdgeStrokePaths, shouldUseSelectiveBorders, shouldShowBorders, getHiddenEdgesForPolygon } from \"@/core/engine/validation/border-rendering\";\n\n// Import lock/unlock icons\nimport lockedIcon from \"@/assets/locked.png\";\nimport unlockedIcon from \"@/assets/unlocked.png\";\n\nexport type PieceView = { id: string; blueprintId: string; x: number; y: number; sectorId?: string };\nexport type AnchorDots = { sectorId: string; valid: {x:number;y:number}[]; invalid: {x:number;y:number}[] };\n\nexport type BoardViewProps = {\n controller: any; // RoundController (kept loose to avoid circular deps here)\n layout: CircleLayout;\n viewBox: { w: number; h: number };\n width?: number;\n height?: number;\n\n // derived visuals/geometry\n badgeR: number;\n badgeCenter: { x: number; y: number };\n placedSilBySector: Map<string, Poly[]>;\n anchorDots: AnchorDots[];\n pieces: PieceView[];\n scaleS: number; // scaling factor for silhouettes\n\n // UI state flags\n clickMode: boolean;\n draggingId: string | null;\n selectedPieceId: string | null;\n dragInvalid: boolean;\n lockedPieceId: string | null;\n showTangramDecomposition?: boolean; // whether to show tangram decomposed into primitives\n usePrimitiveColorsBlueprints?: boolean; // whether to use distinct colors for blueprints in dock\n usePrimitiveColorsTargets?: boolean; // whether to use distinct colors for target tangrams\n primitiveColorIndices?: number[]; // array of 5 integers mapping primitives to color indices\n\n // refs + handlers wired by the container\n svgRef: React.RefObject<SVGSVGElement>;\n setPieceRef: (id: string) => (el: SVGGElement | null) => void;\n onPiecePointerDown: (\n e: React.PointerEvent<SVGPathElement | SVGGElement>,\n p: PieceView\n ) => void;\n onBlueprintPointerDown: (\n e: React.PointerEvent,\n bp: Blueprint,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n ) => void;\n onRootPointerDown: (e: React.PointerEvent<SVGSVGElement>) => void;\n onPointerMove: (e: React.PointerEvent<SVGSVGElement>) => void;\n onPointerUp: () => void;\n onCenterBadgePointerDown: (e: React.PointerEvent) => void;\n};\n\nfunction pathD(poly: Poly) {\n return `M ${poly.map((pt) => `${pt.x} ${pt.y}`).join(\" L \")} Z`;\n}\n\n/**\n * Get the fill color for a piece or blueprint based on its type\n *\n * REQUIRES: blueprint is valid, primitiveColorIndices is an array of 5 valid indices\n * EFFECTS: Returns color based on primitive type if usePrimitiveColors is true,\n * otherwise returns the default color. Composites always use default color.\n */\nfunction getPieceColor(\n blueprint: Blueprint,\n usePrimitiveColors: boolean,\n defaultColor: string,\n primitiveColorIndices: number[]\n): string {\n if (!usePrimitiveColors) {\n return defaultColor;\n }\n\n // For primitive blueprints, use the mapped color from CONFIG\n if ('kind' in blueprint) {\n const kind = blueprint.kind as TanKind;\n // Map primitive kind to index: square=0, smalltriangle=1, parallelogram=2, medtriangle=3, largetriangle=4\n const kindToIndex: Record<TanKind, number> = {\n 'square': 0,\n 'smalltriangle': 1,\n 'parallelogram': 2,\n 'medtriangle': 3,\n 'largetriangle': 4\n };\n const primitiveIndex = kindToIndex[kind];\n if (primitiveIndex !== undefined && primitiveColorIndices[primitiveIndex] !== undefined) {\n const colorIndex = primitiveColorIndices[primitiveIndex];\n const color = CONFIG.color.primitiveColors[colorIndex];\n if (color) {\n return color;\n }\n }\n return defaultColor;\n }\n\n // For composite blueprints, always use the default color\n return defaultColor;\n}\n\nexport default function BoardView(props: BoardViewProps) {\n const {\n controller, layout, viewBox, width, height,\n badgeR, badgeCenter,\n placedSilBySector, anchorDots, pieces, scaleS,\n clickMode, draggingId, selectedPieceId, dragInvalid, lockedPieceId, showTangramDecomposition,\n usePrimitiveColorsBlueprints, usePrimitiveColorsTargets, primitiveColorIndices,\n svgRef, setPieceRef,\n onPiecePointerDown, onBlueprintPointerDown, onRootPointerDown, onPointerMove, onPointerUp, onCenterBadgePointerDown,\n } = props;\n\n const VW = viewBox.w, VH = viewBox.h;\n\n // Helper function to render silhouettes\n const renderSilhouettes = () => layout.sectors.map((s) => {\n const sectorCfg = controller.state.cfg.sectors.find((ss: any) => ss.id === s.id);\n\n // Check if we should render decomposed primitives\n if (showTangramDecomposition && sectorCfg?.silhouette.primitiveDecomposition) {\n const primitiveDecomposition = sectorCfg.silhouette.primitiveDecomposition;\n\n // Use same positioning logic as unified silhouette\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const rawPolys = primitiveDecomposition.map((primInfo: any) => primInfo.polygon);\n const placedPolys = placeSilhouetteGridAlignedAsPolys(rawPolys, scaleS, { cx: rect.cx, cy: rect.cy });\n\n return (\n <g key={`sil-decomposed-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((scaledPoly, i) => {\n // Get color for this primitive based on its kind\n const primInfo = primitiveDecomposition[i];\n let fillColor = CONFIG.color.silhouetteMask;\n\n if (usePrimitiveColorsTargets && primInfo?.kind && primitiveColorIndices) {\n // Map primitive kind to index\n const kindToIndex: Record<TanKind, number> = {\n 'square': 0,\n 'smalltriangle': 1,\n 'parallelogram': 2,\n 'medtriangle': 3,\n 'largetriangle': 4\n };\n const primitiveIndex = kindToIndex[primInfo.kind as TanKind];\n if (primitiveIndex !== undefined && primitiveColorIndices[primitiveIndex] !== undefined) {\n const colorIndex = primitiveColorIndices[primitiveIndex];\n const color = CONFIG.color.primitiveColors[colorIndex];\n if (color) {\n fillColor = color;\n }\n }\n }\n\n return (\n <path\n key={`prim-fill-${i}`}\n d={pathD(scaledPoly)}\n fill={fillColor}\n opacity={CONFIG.opacity.silhouetteMask}\n stroke=\"none\"\n />\n );\n })}\n </g>\n );\n } else {\n // Default: render unified silhouette\n const placedPolys = placedSilBySector.get(s.id) ?? [];\n if (!placedPolys.length) return null;\n return (\n <g key={`sil-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((poly, i) => (\n <path key={i} d={pathD(poly)} fill={CONFIG.color.silhouetteMask} opacity={CONFIG.opacity.silhouetteMask} />\n ))}\n </g>\n );\n }\n });\n\n // Helper function to render pieces (with optional filter)\n const renderPieces = (piecesFilter?: (p: PieceView) => boolean) => {\n const piecesToRender = piecesFilter ? pieces.filter(piecesFilter) : pieces;\n return piecesToRender\n .sort((a, b) => {\n // Sort so that dragged piece is rendered last (on top)\n if (draggingId === a.id) return 1;\n if (draggingId === b.id) return -1;\n return 0;\n })\n .map((p) => {\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, (k: string) => controller.getPrimitive(k as TanKind)!);\n const isDragging = draggingId === p.id;\n const locked = p.sectorId && controller.isSectorCompleted(p.sectorId);\n const isConnectivityLocked = lockedPieceId === p.id;\n const isSelected = selectedPieceId === p.id;\n const isCarriedInvalid = isDragging && dragInvalid;\n const translateX = p.x - bb.min.x;\n const translateY = p.y - bb.min.y;\n\n const validFillColor = getPieceColor(\n bp,\n usePrimitiveColorsBlueprints || false,\n CONFIG.color.piece.validFill,\n primitiveColorIndices || [0, 1, 2, 3, 4]\n );\n const draggingFillColor = getPieceColor(\n bp,\n usePrimitiveColorsBlueprints || false,\n CONFIG.color.piece.draggingFill,\n primitiveColorIndices || [0, 1, 2, 3, 4]\n );\n\n return (\n <g key={p.id} ref={setPieceRef(p.id)} transform={`translate(${translateX}, ${translateY})`} style={{ cursor: locked ? \"default\" : clickMode ? \"pointer\" : \"grab\" }} pointerEvents={clickMode && isDragging ? \"none\" : \"auto\"}>\n {(\"shape\" in bp ? bp.shape : []).map((poly: any, idx: number) => {\n const showBorders = shouldShowBorders();\n const useSelectiveBorders = shouldUseSelectiveBorders(p.blueprintId);\n return (\n <React.Fragment key={idx}>\n {/* Fill path - always rendered with no borders */}\n <path\n d={pathD(poly)}\n fill={isConnectivityLocked ? CONFIG.color.piece.invalidFill : (isCarriedInvalid ? CONFIG.color.piece.invalidFill : (isDragging ? draggingFillColor : validFillColor))}\n opacity={isConnectivityLocked ? CONFIG.opacity.piece.invalid : (isCarriedInvalid ? CONFIG.opacity.piece.invalid : (isDragging ? CONFIG.opacity.piece.dragging : (locked ? CONFIG.opacity.piece.locked : CONFIG.opacity.piece.normal)))}\n stroke=\"none\"\n onPointerDown={(e) => onPiecePointerDown(e, p)}\n />\n\n {/* Border paths - only rendered if borders are enabled */}\n {showBorders && (\n useSelectiveBorders ? (\n // For pieces with selective borders: render individual edge strokes with edge detection\n (() => {\n const allPiecesInSector = pieces.filter(piece => piece.sectorId === p.sectorId);\n const pieceAsPiece = { ...p, pos: { x: p.x, y: p.y } };\n const allPiecesAsPieces = allPiecesInSector.map(piece => ({ ...piece, pos: { x: piece.x, y: piece.y } }));\n const hiddenEdges = getHiddenEdgesForPolygon(pieceAsPiece, idx, allPiecesAsPieces, (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind));\n\n // Check if this piece's edges were hidden due to touching the dragged piece\n const draggedPiece = draggingId ? allPiecesInSector.find(piece => piece.id === draggingId) : null;\n\n // For composites, we need to distinguish between internal edges (always hidden) and external edges (shown when dragging)\n let wasTouchingDraggedPiece: boolean[];\n if (p.blueprintId.startsWith('comp:')) {\n // For composites, check internal edges separately from external edges\n const internalHiddenEdges = getHiddenEdgesForPolygon(pieceAsPiece, idx, [], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind));\n const externalHiddenEdges = draggedPiece ?\n getHiddenEdgesForPolygon(pieceAsPiece, idx, [{ ...draggedPiece, pos: { x: draggedPiece.x, y: draggedPiece.y } }], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind)) :\n new Array(hiddenEdges.length).fill(false);\n\n // Only consider external edges as \"touching dragged piece\"\n wasTouchingDraggedPiece = externalHiddenEdges.map((external, i) => external && !internalHiddenEdges[i]);\n } else {\n // For primitives, all hidden edges are external\n wasTouchingDraggedPiece = draggedPiece ?\n getHiddenEdgesForPolygon(pieceAsPiece, idx, [{ ...draggedPiece, pos: { x: draggedPiece.x, y: draggedPiece.y } }], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind)) :\n new Array(hiddenEdges.length).fill(false);\n }\n\n return generateEdgeStrokePaths(poly).map((strokePath, strokeIdx) => {\n // Show border if: 1) it wasn't hidden originally, OR 2) it was hidden due to touching the dragged piece\n const wasHiddenDueToDraggedPiece = wasTouchingDraggedPiece[strokeIdx] || false;\n\n // Special case: if this piece is being dragged and it's a composite, keep internal edges hidden\n let isHidden: boolean;\n if (isDragging && p.blueprintId.startsWith('comp:')) {\n // For dragged composites, only show external edges (not internal ones)\n const internalHiddenEdges = getHiddenEdgesForPolygon(pieceAsPiece, idx, [], (id) => controller.getBlueprint(id), (kind) => controller.getPrimitive(kind));\n isHidden = internalHiddenEdges[strokeIdx] || false;\n } else {\n // Normal logic for non-dragged pieces or primitives\n isHidden = isDragging ? false : ((hiddenEdges[strokeIdx] || false) && !wasHiddenDueToDraggedPiece);\n }\n\n return (\n <path\n key={`stroke-${idx}-${strokeIdx}`}\n d={strokePath}\n fill=\"none\"\n stroke={isHidden ? \"none\" : (isConnectivityLocked ? CONFIG.color.piece.invalidStroke : (isCarriedInvalid ? CONFIG.color.piece.invalidStroke : (isSelected || isDragging ? CONFIG.color.piece.selectedStroke : CONFIG.color.piece.borderStroke)))}\n strokeWidth={isHidden ? 0 : ((isSelected || isDragging) ? CONFIG.size.stroke.pieceSelectedPx : CONFIG.size.stroke.pieceBorderPx)}\n onPointerDown={(e) => onPiecePointerDown(e, p)}\n />\n );\n });\n })()\n ) : (\n // For primitives or composites without selective borders: render full border\n <path\n d={pathD(poly)}\n fill=\"none\"\n stroke={isConnectivityLocked ? CONFIG.color.piece.invalidStroke : (isCarriedInvalid ? CONFIG.color.piece.invalidStroke : (isSelected || isDragging ? CONFIG.color.piece.selectedStroke : CONFIG.color.piece.borderStroke))}\n strokeWidth={(isSelected || isDragging) ? CONFIG.size.stroke.pieceSelectedPx : CONFIG.size.stroke.pieceBorderPx}\n onPointerDown={(e) => onPiecePointerDown(e, p)}\n />\n )\n )}\n </React.Fragment>\n );\n })}\n\n {/* Invalid marker 'X' - shown at piece center when dragging invalid piece */}\n {isDragging && isCarriedInvalid && \"shape\" in bp && bp.shape.length > 0 && (() => {\n const { cx, cy } = polysAABB(bp.shape);\n const size = CONFIG.size.invalidMarker.sizePx;\n const strokeWidth = CONFIG.size.invalidMarker.strokePx;\n const borderWidth = strokeWidth + 2;\n\n return (\n <g key=\"invalid-marker\">\n {/* White border for first line */}\n <line\n x1={cx - size}\n y1={cy - size}\n x2={cx + size}\n y2={cy + size}\n stroke=\"white\"\n strokeWidth={borderWidth}\n strokeLinecap=\"round\"\n />\n {/* Red interior for first line */}\n <line\n x1={cx - size}\n y1={cy - size}\n x2={cx + size}\n y2={cy + size}\n stroke={CONFIG.color.piece.invalidStroke}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n />\n {/* White border for second line */}\n <line\n x1={cx + size}\n y1={cy - size}\n x2={cx - size}\n y2={cy + size}\n stroke=\"white\"\n strokeWidth={borderWidth}\n strokeLinecap=\"round\"\n />\n {/* Red interior for second line */}\n <line\n x1={cx + size}\n y1={cy - size}\n x2={cx - size}\n y2={cy + size}\n stroke={CONFIG.color.piece.invalidStroke}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n />\n </g>\n );\n })()}\n </g>\n );\n });\n };\n\n // blueprint ring geometry\n const centerView = controller.state.blueprintView;\n const bps: Blueprint[] =\n centerView === \"primitives\"\n ? (controller.state.primitives as PrimitiveBlueprint[])\n : (controller.state.quickstash as Blueprint[]);\n\n const QS_SLOTS = controller.state.cfg.maxQuickstashSlots;\n const PRIM_SLOTS = controller.state.primitives.length;\n const slotsForView = centerView === \"primitives\" ? Math.max(1, PRIM_SLOTS) : Math.max(1, QS_SLOTS);\n const sweep = layout.mode === \"circle\" ? Math.PI * 2 : Math.PI;\n const delta = sweep / slotsForView;\n\n const start = layout.mode === \"circle\" ? -Math.PI / 2 : Math.PI;\n const blueprintTheta = (i: number) => start + (i + 0.5) * delta;\n\n // chord requirement (reuse same logic as container already used for radii)\n const anchorsDiameterToPx = (anchorsDiag: number, gridPx: number = CONFIG.layout.grid.stepPx) =>\n anchorsDiag * Math.SQRT2 * gridPx;\n const reqAnchors = centerView === \"primitives\"\n ? CONFIG.layout.constraints.primitiveDiamAnchors\n : CONFIG.layout.constraints.quickstashDiamAnchors;\n const D_slot = anchorsDiameterToPx(reqAnchors);\n const R_needed = D_slot / (2 * Math.max(1e-9, Math.sin(delta / 2)));\n\n // Minimum radius to avoid overlapping with badge\n // Badge takes up: badgeR + margin, plus we need half the slot diameter for clearance\n const R_min = badgeR + CONFIG.size.centerBadge.marginPx + D_slot / 2;\n const ringMax = layout.innerR - (badgeR + CONFIG.size.centerBadge.marginPx);\n\n // Clamp to [R_min, ringMax]\n const blueprintRingR = Math.min(Math.max(R_needed, R_min), ringMax);\n\n const renderBlueprintGlyph = (bp: Blueprint, bx: number, by: number) => {\n const bb = boundsOfBlueprint(bp, (k: string) => controller.getPrimitive(k as TanKind)!);\n const cx = bb.min.x + bb.width / 2;\n const cy = bb.min.y + bb.height / 2;\n const selected = false; // container highlights via pending state; optional\n\n const fillColor = getPieceColor(\n bp,\n usePrimitiveColorsBlueprints || false,\n CONFIG.color.blueprint.fill,\n primitiveColorIndices || [0, 1, 2, 3, 4]\n );\n\n return (\n <g\n key={bp.id}\n transform={`translate(${bx}, ${by}) scale(1) translate(${-cx}, ${-cy})`}\n >\n {(\"shape\" in bp ? bp.shape : []).map((poly, idx) => (\n <path\n key={idx}\n d={pathD(poly)}\n fill={fillColor}\n opacity={CONFIG.opacity.blueprint}\n stroke={selected ? CONFIG.color.blueprint.selectedStroke : \"none\"}\n strokeWidth={selected ? 2 : 0}\n pointerEvents=\"visiblePainted\"\n style={{ cursor: \"pointer\" }}\n onPointerDown={(e) => onBlueprintPointerDown(e as any, bp, { bx, by, cx, cy })}\n />\n ))}\n </g>\n );\n };\n\n return (\n <svg\n ref={svgRef}\n width={width}\n height={height}\n viewBox={`0 0 ${VW} ${VH}`}\n preserveAspectRatio=\"xMidYMid meet\"\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerDown={(e) => {\n onRootPointerDown(e);\n }}\n style={{ background: CONFIG.color.background, touchAction: \"none\", userSelect: \"none\" }}\n >\n {/* bands as wedges */}\n {layout.sectors.map((s, i) => {\n const done = !!controller.state.sectors[s.id].completedAt;\n const baseSil = i % 2 ? CONFIG.color.bands.silhouette.fillOdd : CONFIG.color.bands.silhouette.fillEven;\n const baseWork = i % 2 ? CONFIG.color.bands.workspace.fillOdd : CONFIG.color.bands.workspace.fillEven;\n const sil = layout.bands.silhouette;\n const work = layout.bands.workspace;\n return (\n <g key={`bands-${s.id}`}>\n {controller.state.cfg.target === \"workspace\" ? (\n <>\n <path d={wedgePath(layout.cx, layout.cy, sil[0], sil[1], s.start, s.end)} fill={baseSil} stroke={CONFIG.color.bands.silhouette.stroke} strokeWidth={CONFIG.size.stroke.bandPx} pointerEvents=\"none\" />\n <path d={wedgePath(layout.cx, layout.cy, work[0], work[1], s.start, s.end)} fill={done ? CONFIG.color.completion.fill : baseWork} stroke={done ? CONFIG.color.completion.stroke : CONFIG.color.bands.workspace.stroke} strokeWidth={CONFIG.size.stroke.bandPx} pointerEvents=\"none\" />\n </>\n ) : (\n <path d={wedgePath(layout.cx, layout.cy, sil[0], sil[1], s.start, s.end)} fill={done ? CONFIG.color.completion.fill : baseSil} stroke={done ? CONFIG.color.completion.stroke : CONFIG.color.bands.silhouette.stroke} strokeWidth={CONFIG.size.stroke.bandPx} pointerEvents=\"none\" />\n )}\n </g>\n );\n })}\n\n\n {/* Conditional rendering based on silhouettesBelowPieces config */}\n {CONFIG.game.silhouettesBelowPieces ? (\n <>\n {/* Render silhouettes first (below all pieces) */}\n {renderSilhouettes()}\n\n {/* Then all pieces */}\n {renderPieces()}\n </>\n ) : (\n <>\n {/* Render all pieces first */}\n {renderPieces()}\n\n {/* Then silhouettes (above all pieces) */}\n {renderSilhouettes()}\n </>\n )}\n\n {/* silhouettes (use pre-placed polys) - rendered first so pieces appear on top */}\n {layout.sectors.map((s) => {\n const sectorCfg = controller.state.cfg.sectors.find((ss: any) => ss.id === s.id);\n\n // Check if we should render decomposed primitives\n if (showTangramDecomposition && sectorCfg?.silhouette.primitiveDecomposition) {\n const primitiveDecomposition = sectorCfg.silhouette.primitiveDecomposition;\n\n // Use same positioning logic as unified silhouette\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const rawPolys = primitiveDecomposition.map((primInfo: any) => primInfo.polygon);\n const placedPolys = placeSilhouetteGridAlignedAsPolys(rawPolys, scaleS, { cx: rect.cx, cy: rect.cy });\n\n return (\n <g key={`sil-decomposed-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((scaledPoly, i) => {\n // Get color for this primitive based on its kind\n const primInfo = primitiveDecomposition[i];\n let fillColor = CONFIG.color.silhouetteMask;\n\n if (usePrimitiveColorsTargets && primInfo?.kind && primitiveColorIndices) {\n // Map primitive kind to index\n const kindToIndex: Record<TanKind, number> = {\n 'square': 0,\n 'smalltriangle': 1,\n 'parallelogram': 2,\n 'medtriangle': 3,\n 'largetriangle': 4\n };\n const primitiveIndex = kindToIndex[primInfo.kind as TanKind];\n if (primitiveIndex !== undefined && primitiveColorIndices[primitiveIndex] !== undefined) {\n const colorIndex = primitiveColorIndices[primitiveIndex];\n const color = CONFIG.color.primitiveColors[colorIndex];\n if (color) {\n fillColor = color;\n }\n }\n }\n\n return (\n <path\n key={`prim-fill-${i}`}\n d={pathD(scaledPoly)}\n fill=\"none\"\n opacity={0}\n stroke=\"none\"\n />\n );\n })}\n </g>\n );\n } else {\n // Default: render unified silhouette\n const placedPolys = placedSilBySector.get(s.id) ?? [];\n if (!placedPolys.length) return null;\n return (\n <g key={`sil-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((poly, i) => (\n <path key={i} d={pathD(poly)} fill={CONFIG.color.silhouetteMask} opacity={CONFIG.opacity.silhouetteMask} />\n ))}\n </g>\n );\n }\n })}\n\n {/* anchor grid */}\n {anchorDots.map(({ sectorId, valid, invalid }) => {\n const isInnerRing = sectorId === \"inner-ring\";\n return (\n <g key={`anchors-${sectorId}`} pointerEvents=\"none\">\n {invalid.map((p, i) => (\n <circle key={`inv-${i}`} cx={p.x} cy={p.y} r={CONFIG.size.anchorRadiusPx.invalid} fill={CONFIG.color.anchors.invalid} opacity={CONFIG.opacity.anchors.invalid} />\n ))}\n {valid.map((p, i) => (\n <circle\n key={`val-${i}`}\n cx={p.x}\n cy={p.y}\n r={isInnerRing ? CONFIG.size.anchorRadiusPx.invalid : CONFIG.size.anchorRadiusPx.valid}\n fill={isInnerRing ? CONFIG.color.anchors.invalid : CONFIG.color.anchors.valid}\n opacity={isInnerRing ? CONFIG.opacity.anchors.invalid : CONFIG.opacity.anchors.valid}\n />\n ))}\n </g>\n );\n })}\n\n {/* SVG filter for inverting icon colors to white */}\n <defs>\n <filter id=\"invert-to-white\">\n <feColorMatrix\n type=\"matrix\"\n values=\"-1 0 0 0 1\n 0 -1 0 0 1\n 0 0 -1 0 1\n 0 0 0 1 0\"\n />\n </filter>\n </defs>\n\n {/* center badge */}\n {(() => {\n const isPrep = controller.state.cfg.mode === \"prep\";\n const isSubmitEnabled = isPrep ? controller.isSubmitEnabled() : true;\n const isClickable = !draggingId && (!isPrep || isSubmitEnabled);\n const [imageError, setImageError] = React.useState(false);\n\n // Size the image to fill most of the badge (80% of diameter)\n const iconSize = badgeR * 1.6;\n const iconOffset = iconSize / 2;\n\n return (\n <g transform={`translate(${badgeCenter.x}, ${badgeCenter.y})`}\n style={{ cursor: isClickable ? \"pointer\" : \"default\" }}\n onPointerDown={isClickable ? onCenterBadgePointerDown : undefined}>\n <circle r={badgeR}\n fill={isSubmitEnabled ? CONFIG.color.blueprint.badgeFill : \"#ccc\"}\n opacity={isSubmitEnabled ? 1.0 : 0.5} />\n {isPrep ? (\n <text textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize={CONFIG.size.badgeFontPx}\n fill={isSubmitEnabled ? CONFIG.color.blueprint.labelFill : \"#888\"}\n pointerEvents=\"none\">\n Submit\n </text>\n ) : imageError ? (\n <text textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fontSize={CONFIG.size.badgeFontPx}\n fill={CONFIG.color.blueprint.labelFill}\n pointerEvents=\"none\">\n inventory\n </text>\n ) : (\n <image\n href={controller.state.blueprintView === \"quickstash\" ? lockedIcon : unlockedIcon}\n x={-iconOffset}\n y={-iconOffset}\n width={iconSize}\n height={iconSize}\n pointerEvents=\"none\"\n onError={() => setImageError(true)}\n filter=\"url(#invert-to-white)\"\n />\n )}\n </g>\n );\n })()}\n\n {/* blueprint glyphs */}\n {bps.map((bp: any, i: number) => {\n const theta = blueprintTheta(i);\n const bx = layout.cx + blueprintRingR * Math.cos(theta);\n const by = layout.cy + blueprintRingR * Math.sin(theta);\n return renderBlueprintGlyph(bp, bx, by);\n })}\n\n\n {/* all green pulse */}\n {controller.state.endedAt && (\n <g pointerEvents=\"none\">\n <circle cx={layout.cx} cy={layout.cy} r={layout.outerR - 3} fill=\"none\" stroke={CONFIG.color.piece.allGreenStroke} strokeWidth={CONFIG.size.stroke.allGreenStrokePx} opacity={0}>\n <animate attributeName=\"opacity\" from=\"0\" to=\"1\" dur=\"160ms\" fill=\"freeze\" />\n <animate attributeName=\"opacity\" from=\"1\" to=\"0\" begin=\"560ms\" dur=\"520ms\" fill=\"freeze\" />\n </circle>\n </g>\n )}\n\n {/* tangram decomposition borders - rendered last so they appear on top of pieces */}\n {showTangramDecomposition && layout.sectors.map((s) => {\n const sectorCfg = controller.state.cfg.sectors.find((ss: any) => ss.id === s.id);\n if (!sectorCfg?.silhouette.primitiveDecomposition) return null;\n\n const primitiveDecomposition = sectorCfg.silhouette.primitiveDecomposition;\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const rawPolys = primitiveDecomposition.map((primInfo: any) => primInfo.polygon);\n const placedPolys = placeSilhouetteGridAlignedAsPolys(rawPolys, scaleS, { cx: rect.cx, cy: rect.cy });\n\n return (\n <g key={`sil-borders-${s.id}`} pointerEvents=\"none\">\n {placedPolys.map((scaledPoly, i) => (\n <path\n key={`prim-border-${i}`}\n d={pathD(scaledPoly)}\n fill=\"none\"\n stroke={CONFIG.color.tangramDecomposition.stroke}\n strokeWidth={CONFIG.size.stroke.tangramDecompositionPx}\n />\n ))}\n </g>\n );\n })}\n </svg>\n );\n}","// core/validate/complete.ts\nimport type { Poly, Vec } from \"@/core/domain/types\";\nimport { pointInPolygon } from \"@/core/engine/geometry\";\nimport { CONFIG } from \"@/core/config/config\";\n\n/** AABB of one or more polys */\nfunction aabb(polys: Poly[]) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const poly of polys) for (const p of poly) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { minX, minY, maxX, maxY };\n}\n\n/** Cell centers over an AABB, aligned to GRID_PX centers (k + GRID_PX/2). */\nfunction cellCentersInAABB(minX: number, minY: number, maxX: number, maxY: number): Vec[] {\n const GRID_PX = CONFIG.layout.grid.stepPx;\n const x0 = Math.floor((minX - GRID_PX/2) / GRID_PX) * GRID_PX + GRID_PX/2;\n const y0 = Math.floor((minY - GRID_PX/2) / GRID_PX) * GRID_PX + GRID_PX/2;\n const out: Vec[] = [];\n for (let y = y0; y <= maxY; y += GRID_PX) {\n for (let x = x0; x <= maxX; x += GRID_PX) out.push({ x, y });\n }\n return out;\n}\n\n/** Build a set of grid centers that lie inside ANY of the polygons. */\nexport function cellSetForPolys(polys: Poly[]): Set<string> {\n if (!polys.length) return new Set();\n const { minX, minY, maxX, maxY } = aabb(polys);\n const centers = cellCentersInAABB(minX, minY, maxX, maxY);\n const key = (p: Vec) => `${p.x},${p.y}`;\n const S = new Set<string>();\n center: for (const c of centers) {\n for (const poly of polys) {\n if (pointInPolygon(c, poly)) { S.add(key(c)); continue center; }\n }\n }\n return S;\n}\n\n/** Anchors | Silhouette: complete iff silhouette cell set ⊆ piece cell set. */\nexport function anchorsSilhouetteComplete(silPolys: Poly[], piecePolys: Poly[]): boolean {\n if (!silPolys.length) return false;\n const S = cellSetForPolys(silPolys);\n if (S.size === 0) return false;\n const P = cellSetForPolys(piecePolys);\n if (P.size === 0) return false;\n for (const k of S) if (!P.has(k)) return false;\n return true;\n}\n\n// --- helpers for translation-invariant equality on the grid -----------------\nfunction stringSetToVecs(S: Set<string>): Vec[] {\n const out: Vec[] = [];\n for (const k of S) {\n const [xs, ys] = k.split(\",\");\n out.push({ x: Number(xs), y: Number(ys) });\n }\n return out;\n}\n\nfunction normalizeCells(S: Set<string>): Set<string> {\n if (S.size === 0) return S;\n const pts = stringSetToVecs(S);\n let minX = Infinity,\n minY = Infinity;\n for (const p of pts) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n }\n const N = new Set<string>();\n for (const p of pts) N.add(`${p.x - minX},${p.y - minY}`);\n return N;\n}\n\nfunction setsEqual(a: Set<string>, b: Set<string>): boolean {\n if (a.size !== b.size) return false;\n for (const k of a) if (!b.has(k)) return false;\n return true;\n}\n\n/**\n * Anchors | Workspace:\n * complete iff the pieces form the sector's silhouette pattern up to a GRID_PX translation.\n * (No rotation/mirror; exact coverage — no extra cells.)\n */\nexport function anchorsWorkspaceComplete(\n silPolys: Poly[],\n piecePolys: Poly[]\n): boolean {\n if (!silPolys.length) return false;\n const Sraw = cellSetForPolys(silPolys);\n const Praw = cellSetForPolys(piecePolys);\n if (Sraw.size === 0 || Praw.size === 0) return false;\n const S = normalizeCells(Sraw);\n const P = normalizeCells(Praw);\n return setsEqual(S, P);\n}","import type { Poly } from \"@/core/domain/types\";\n\n/**\n * Board Component Utilities\n * \n * This module provides utility functions used by board interaction hooks.\n * These functions handle coordinate transformations and geometric operations\n * needed for blueprint interaction and polygon scaling.\n */\n\n/**\n * Convert world coordinates to blueprint local coordinates\n * \n * When a user clicks on a blueprint glyph in the blueprint ring, this function\n * converts the world click coordinates to local coordinates within the blueprint's\n * coordinate system. This is needed to maintain the clicked point under the cursor\n * when spawning and dragging new pieces.\n * \n * @param px - World X coordinate (SVG space)\n * @param py - World Y coordinate (SVG space) \n * @param bpGeom - Blueprint geometry information\n * @param bpGeom.bx - Blueprint center X in world space\n * @param bpGeom.by - Blueprint center Y in world space\n * @param bpGeom.cx - Blueprint local center X\n * @param bpGeom.cy - Blueprint local center Y\n * @returns Local coordinates within the blueprint's coordinate system\n * \n * @example\n * ```typescript\n * const localPoint = blueprintLocalFromWorld(100, 200, {\n * bx: 50, by: 50, // Blueprint is rendered at (50, 50) in world space\n * cx: 25, cy: 25 // Blueprint's local center is at (25, 25)\n * });\n * // Result: { x: 75, y: 175 } - point in blueprint's local coordinate system\n * ```\n */\nexport function blueprintLocalFromWorld(\n px: number,\n py: number,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n) {\n return { x: px - bpGeom.bx + bpGeom.cx, y: py - bpGeom.by + bpGeom.cy };\n}\n\n/**\n * Scale polygons by factor S about the origin (no translation/snapping)\n * \n * This function scales polygon coordinates by a factor S around the origin (0,0).\n * Used for scaling silhouette masks and other geometric shapes when computing\n * layouts with different scaling factors. The scaling is uniform (same factor\n * for both X and Y axes).\n * \n * @param polys - Array of polygons to scale\n * @param S - Scale factor (1.0 = no change, 0.5 = half size, 2.0 = double size)\n * @returns New array of scaled polygons (original polygons are not modified)\n * \n * @example\n * ```typescript\n * const originalPolys = [[\n * { x: 10, y: 10 },\n * { x: 20, y: 10 }, \n * { x: 15, y: 20 }\n * ]];\n * \n * const scaledPolys = scalePolys(originalPolys, 2.0);\n * // Result: [[\n * // { x: 20, y: 20 },\n * // { x: 40, y: 20 },\n * // { x: 30, y: 40 }\n * // ]]\n * ```\n */\nexport function scalePolys(polys: Poly[], S: number): Poly[] {\n if (!polys || polys.length === 0) return [];\n return polys.map(poly => poly.map(p => ({ x: S * p.x, y: S * p.y })));\n}","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { Poly } from \"@/core/domain/types\";\nimport { boundsOfBlueprint, piecePolysAt } from \"@/core/engine/geometry\";\n\n/**\n * Piece data interface used throughout the hook system\n * \n * Represents a tangram piece instance with position and blueprint information.\n * This is the normalized interface used across all board components.\n */\nexport interface PieceData {\n /** Unique identifier for this piece instance */\n id: string;\n \n /** ID of the blueprint that defines this piece's shape */\n blueprintId: string;\n \n /** X coordinate of the piece's top-left position in SVG space */\n x: number;\n \n /** Y coordinate of the piece's top-left position in SVG space */\n y: number;\n \n /** ID of the sector containing this piece (undefined if floating) */\n sectorId?: string;\n}\n\n/**\n * Return interface for usePieceState hook\n * \n * Provides normalized piece data and computed polygon functions for collision\n * detection and rendering. All functions are memoized for optimal performance.\n */\nexport interface PieceStateHook {\n /** Array of all pieces from all sectors plus floating pieces */\n pieces: PieceData[];\n \n /** \n * Lookup function to find a piece by its ID\n * @param id - Piece ID to lookup (null-safe)\n * @returns PieceData or null if not found\n */\n pieceById: (id: string | null) => PieceData | null;\n \n /** \n * Compute world polygons for all pieces in a sector (live/no cache)\n * @param sectorId - Target sector ID\n * @returns Array of world-space polygons\n */\n sectorPiecePolysLive: (sectorId: string) => Poly[];\n \n /** \n * Cached version of sectorPiecePolysLive with signature-based invalidation\n * @param sectorId - Target sector ID \n * @returns Cached array of world-space polygons\n */\n getSectorPiecePolysCached: (sectorId: string) => Poly[];\n}\n\n/**\n * Hook for managing piece data and computed polygon states\n * \n * This hook provides normalized access to piece data from the BaseGameController,\n * combining pieces from sectors and floating state into a unified interface.\n * It also provides optimized polygon computation functions for collision detection.\n * \n * ## Key Features\n * - **Unified piece access**: Combines sector and floating pieces\n * - **Polygon caching**: Optimized collision detection with signature-based cache\n * - **Live updates**: Reactively updates when controller state changes\n * - **Null-safe lookups**: Safe piece retrieval by ID\n * \n * ## Performance\n * - Pieces array is memoized based on controller.updateCount\n * - Polygon cache uses sector \"signature\" (piece positions) for invalidation\n * - Live polygon computation bypasses cache for real-time operations\n * \n * @param controller - BaseGameController instance managing game state\n * @returns Hook interface with piece data and polygon functions\n * \n * @example\n * ```typescript\n * const pieceState = usePieceState(controller);\n * const allPieces = pieceState.pieces;\n * const piece = pieceState.pieceById(\"piece_123\");\n * const sectorPolygons = pieceState.sectorPiecePolysLive(\"sector_1\");\n * ```\n */\nexport function usePieceState(controller: BaseGameController): PieceStateHook {\n // --- pieces ---------------------------------------------------------------\n const pieces = React.useMemo(() => {\n const out: PieceData[] = [];\n for (const s of Object.values(controller.state.sectors)) {\n for (const p of s.pieces) {\n out.push({\n id: p.id,\n blueprintId: p.blueprintId,\n x: p.pos.x,\n y: p.pos.y,\n sectorId: s.sectorId\n });\n }\n }\n const floating: any = (controller as any)._floating;\n if (floating?.pieces) {\n for (const p of floating.pieces) {\n out.push({\n id: p.id,\n blueprintId: p.blueprintId,\n x: p.pos.x,\n y: p.pos.y\n });\n }\n }\n return out;\n }, [controller.state.sectors, (controller as any)._floating, controller.updateCount]);\n\n const pieceById = React.useCallback(\n (id: string | null) => (id ? pieces.find(p => p.id === id) ?? null : null),\n [pieces]\n );\n\n // --- LIVE sector polys (reads controller.state directly) -----------------\n const sectorPiecePolysLive = React.useCallback(\n (sectorId: string): Poly[] => {\n const out: Poly[] = [];\n const ss = controller.state.sectors[sectorId];\n if (!ss) return out;\n for (const p of ss.pieces) {\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n out.push(...piecePolysAt(bp, bb, { x: p.pos.x, y: p.pos.y }));\n }\n return out;\n },\n [controller]\n );\n\n // --- OPTIONAL: cached variant keyed by a sector \"signature\" --------------\n // Sig = pieceId@x,y;... (order-insensitive)\n const polyCacheRef = React.useRef(\n new Map<string, { sig: string; polys: Poly[] }>()\n );\n\n const sectorSignature = React.useCallback(\n (sectorId: string): string => {\n const ss = controller.state.sectors[sectorId];\n if (!ss) return \"\";\n // stable order by id\n const parts = ss.pieces\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : 1))\n .map(p => `${p.id}@${p.pos.x},${p.pos.y}`);\n return parts.join(\"|\");\n },\n [controller.state.sectors]\n );\n\n const getSectorPiecePolysCached = React.useCallback(\n (sectorId: string): Poly[] => {\n const sig = sectorSignature(sectorId);\n const hit = polyCacheRef.current.get(sectorId);\n if (hit && hit.sig === sig) return hit.polys;\n const polys = sectorPiecePolysLive(sectorId);\n polyCacheRef.current.set(sectorId, { sig, polys });\n return polys;\n },\n [sectorSignature, sectorPiecePolysLive]\n );\n\n return {\n pieces,\n pieceById,\n sectorPiecePolysLive,\n getSectorPiecePolysCached\n };\n}","/**\n * Grid Snapping Engine - PHASE 2 MILESTONE\n * \n * Consolidates duplicate anchor functions from anchors.ts and anchors-mode.ts\n * into a single, parameterized grid snapping system.\n */\n\nimport type { Blueprint, Poly, Vec, PrimitiveBlueprint } from \"../../domain/types\";\nimport type { CircleLayout, SectorGeom } from \"../../domain/layout\";\nimport { \n boundsOfBlueprint, \n pointInPolygon, \n gridNodesInAABB, \n filterNodesToBandAndSector, \n filterNodesInPolys\n} from \"../geometry\";\nimport { CONFIG } from \"../../config/config\";\n\nexport interface GridConfig {\n stepPx: number;\n snapRadiusPx: number;\n densitySampleStepPx?: number; // For polyFullyInside sampling\n}\n\nexport interface SnapResult {\n tl: Vec;\n node: Vec | null;\n dist: number;\n accepted: boolean;\n}\n\n/**\n * GridSnapper handles all anchor-based snapping and node generation\n */\nexport class GridSnapper {\n private config: GridConfig;\n\n constructor(config: GridConfig) {\n this.config = config;\n }\n\n // ===== Reference Vertex Management =====\n \n /**\n * Choose a reference vertex (v0 of first poly) for snapping.\n * Consolidated from both anchors.ts and anchors-mode.ts\n */\n referenceVertex(bp: Blueprint): Vec {\n const poly = (\"shape\" in bp && bp.shape?.[0]) ? bp.shape[0] : [{x:0,y:0}];\n return poly[0] ?? { x: 0, y: 0 };\n }\n\n // ===== Snapping Operations =====\n\n /**\n * Perform nearest-node snapping with configurable snap radius\n * Consolidated from both files with enhanced configuration\n */\n nearestNodeSnap(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n ): SnapResult {\n if (!nodes.length) {\n return { tl, node: null, dist: Infinity, accepted: false };\n }\n\n const bb = boundsOfBlueprint(bp, primitiveLookup);\n const v0 = this.referenceVertex(bp);\n const v0World = { x: tl.x + (v0.x - bb.min.x), y: tl.y + (v0.y - bb.min.y) };\n\n let best: Vec | null = null;\n let bestD2 = Infinity;\n \n for (const n of nodes) {\n const dx = n.x - v0World.x;\n const dy = n.y - v0World.y;\n const d2 = dx * dx + dy * dy;\n if (d2 < bestD2) { \n bestD2 = d2; \n best = n; \n }\n }\n\n const distance = Math.sqrt(bestD2);\n const accepted = distance <= this.config.snapRadiusPx;\n \n const snapped = (best && accepted)\n ? { x: tl.x + (best.x - v0World.x), y: tl.y + (best.y - v0World.y) }\n : tl;\n\n return { \n tl: snapped, \n node: best, \n dist: distance, \n accepted \n };\n }\n\n /**\n * Back-compatibility shim for existing Board.tsx usage\n */\n snapTopLeftToNodes(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n ): { x: number; y: number } {\n const { tl: snapped } = this.nearestNodeSnap(tl, bp, primitiveLookup, nodes);\n return snapped;\n }\n\n // ===== Node Generation =====\n\n /**\n * Generate workspace-band grid nodes for a sector\n * Extracted from anchors-mode.ts\n */\n generateWorkspaceNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"workspace\", sector);\n }\n\n /**\n * Generate silhouette-mask nodes for a sector\n * Extracted from anchors-mode.ts\n */\n generateSilhouetteNodes(layout: CircleLayout, sector: SectorGeom, fittedMask: Poly[]): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n const banded = filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n return filterNodesInPolys(banded, fittedMask, pointInPolygon);\n }\n\n /**\n * Generate silhouette-band nodes for a sector (no mask filter)\n * Extracted from anchors-mode.ts\n */\n generateSilhouetteBandNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n const pad = 6;\n const min = { x: layout.cx - layout.outerR, y: layout.cy - layout.outerR - pad };\n const max = { x: layout.cx + layout.outerR, y: layout.cy + layout.outerR + pad };\n const nodes = gridNodesInAABB(min, max);\n return filterNodesToBandAndSector(nodes, layout, \"silhouette\", sector);\n }\n\n // ===== Validation Helpers =====\n\n /**\n * Check if point lies inside any silhouette polygon (union semantics)\n * Private helper used by polyFullyInside\n */\n private insideAnySilhouette(pt: Vec, silPolys: Poly[]): boolean {\n for (const sp of silPolys) {\n if (pointInPolygon(pt, sp)) return true;\n }\n return false;\n }\n\n /**\n * Robust \"fully inside\" check with configurable sampling density\n * Consolidated from both files with enhanced configuration\n */\n polyFullyInside(\n piecePolys: Poly[],\n silhouettePolys: Poly[],\n customStep?: number\n ): boolean {\n // Quick exits\n if (!piecePolys.length) return true;\n if (!silhouettePolys.length) return false;\n\n const step = customStep ?? \n this.config.densitySampleStepPx ?? \n Math.max(1, Math.round(CONFIG.layout.grid.stepPx / 3));\n\n for (const poly of piecePolys) {\n if (poly.length < 2) continue;\n\n for (let i = 0; i < poly.length; i++) {\n const a = poly[i];\n const b = poly[(i + 1) % poly.length];\n \n if (!a || !b) continue;\n \n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len = Math.hypot(dx, dy);\n const n = Math.max(1, Math.ceil(len / step));\n\n // Sample all points along the edge, including endpoints\n for (let k = 0; k <= n; k++) {\n const t = k / n;\n const p = { x: a.x + t * dx, y: a.y + t * dy };\n if (!this.insideAnySilhouette(p, silhouettePolys)) {\n return false; // One point outside → reject\n }\n }\n }\n }\n return true;\n }\n}\n\n// ===== Factory Functions =====\n\n/**\n * Create a GridSnapper with default configuration\n */\nexport function createDefaultGridSnapper(): GridSnapper {\n return new GridSnapper({\n stepPx: CONFIG.layout.grid.stepPx,\n snapRadiusPx: CONFIG.game.snapRadiusPx,\n densitySampleStepPx: Math.max(1, Math.round(CONFIG.layout.grid.stepPx / 3))\n });\n}\n\n/**\n * Create a GridSnapper with custom snap radius\n */\nexport function createGridSnapper(snapRadiusPx: number): GridSnapper {\n return new GridSnapper({\n stepPx: CONFIG.layout.grid.stepPx,\n snapRadiusPx,\n densitySampleStepPx: Math.max(1, Math.round(CONFIG.layout.grid.stepPx / 3))\n });\n}\n\n// ===== Legacy Compatibility Exports =====\n// These maintain compatibility with existing code while using the new system\n\nexport const defaultGridSnapper = createDefaultGridSnapper();\n\nexport function referenceVertex(bp: Blueprint): Vec {\n return defaultGridSnapper.referenceVertex(bp);\n}\n\nexport function nearestNodeSnap(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n): { tl: Vec; node: Vec | null; dist: number } {\n const result = defaultGridSnapper.nearestNodeSnap(tl, bp, primitiveLookup, nodes);\n return { tl: result.tl, node: result.node, dist: result.dist };\n}\n\nexport function snapTopLeftToNodes(\n tl: Vec,\n bp: Blueprint,\n primitiveLookup: (k: string) => PrimitiveBlueprint | undefined,\n nodes: Vec[]\n): { x: number; y: number } {\n return defaultGridSnapper.snapTopLeftToNodes(tl, bp, primitiveLookup, nodes);\n}\n\nexport function polyFullyInside(\n piecePolys: Poly[],\n silhouettePolys: Poly[],\n step?: number\n): boolean {\n return defaultGridSnapper.polyFullyInside(piecePolys, silhouettePolys, step);\n}\n\nexport function workspaceNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n return defaultGridSnapper.generateWorkspaceNodes(layout, sector);\n}\n\nexport function silhouetteNodes(layout: CircleLayout, sector: SectorGeom, fittedMask: Poly[]): Vec[] {\n return defaultGridSnapper.generateSilhouetteNodes(layout, sector, fittedMask);\n}\n\nexport function silhouetteBandNodes(layout: CircleLayout, sector: SectorGeom): Vec[] {\n return defaultGridSnapper.generateSilhouetteBandNodes(layout, sector);\n}\n\nexport { innerRingNodes } from \"../geometry\";","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { CircleLayout } from \"@/core/domain/layout\";\nimport { rectForBand } from \"@/core/domain/layout\";\nimport { placeSilhouetteGridAlignedAsPolys } from \"@/core/engine/geometry\";\nimport {\n workspaceNodes,\n silhouetteNodes,\n silhouetteBandNodes,\n innerRingNodes\n} from \"@/core/engine/collision/grid-snapping\";\n\n/**\n * Anchor dots data for a single sector\n * \n * Represents the valid and invalid snap points for piece placement within\n * a sector. Valid dots allow piece placement, invalid dots show grid structure\n * but don't allow snapping.\n */\nexport interface AnchorDots {\n /** Sector ID these anchor dots belong to */\n sectorId: string;\n \n /** Array of valid snap points where pieces can be placed */\n valid: { x: number; y: number }[];\n \n /** Array of invalid snap points (visual grid, no placement allowed) */\n invalid: { x: number; y: number }[];\n}\n\n/**\n * Return interface for useAnchorGrid hook\n * \n * Provides computed anchor grid data for all active sectors in the layout.\n * Used by rendering components to draw snap points and by interaction hooks\n * for piece placement validation.\n */\nexport interface AnchorGridHook {\n /** Array of anchor dot data for all sectors (excludes completed sectors) */\n anchorDots: AnchorDots[];\n}\n\n/**\n * Hook for computing anchor grid data for all sectors\n * \n * This hook computes the snap points (anchor dots) for piece placement validation\n * across all active sectors. It handles both workspace and silhouette target modes,\n * computing appropriate valid and invalid snap points for each.\n * \n * ## Key Features\n * - **Workspace mode**: All grid nodes within sector bounds are valid\n * - **Silhouette mode**: Only nodes within silhouette mask are valid\n * - **Completion hiding**: Completed sectors don't show anchor dots\n * - **Scale-aware**: Handles silhouette scaling for proper grid alignment\n * \n * ## Target Mode Behavior\n * - **Workspace**: `valid` contains all workspace nodes, `invalid` is empty\n * - **Silhouette**: `valid` contains nodes inside silhouette, `invalid` contains band nodes outside\n * \n * @param controller - BaseGameController instance for accessing game state\n * @param layout - Computed CircleLayout containing sector geometry\n * @param scaleS - Scaling factor for silhouette placement (from solveLogicalBox)\n * @returns Hook interface with anchor dots for all active sectors\n * \n * @example\n * ```typescript\n * const { anchorDots } = useAnchorGrid(controller, layout, scaleS);\n * const sectorAnchors = anchorDots.find(a => a.sectorId === \"sector_1\");\n * const snapPoints = sectorAnchors?.valid ?? [];\n * ```\n */\nexport function useAnchorGrid(\n controller: BaseGameController,\n layout: CircleLayout,\n scaleS: number\n): AnchorGridHook {\n const cfg = controller.state.cfg;\n\n const anchorDots: AnchorDots[] = React.useMemo(() => {\n const out: AnchorDots[] = [];\n\n // Add inner ring anchors (always valid, shown throughout)\n out.push({ sectorId: \"inner-ring\", valid: innerRingNodes(layout), invalid: [] });\n\n for (const s of layout.sectors) {\n // Show anchors for ALL sectors, including completed ones\n if (cfg.target === \"workspace\") {\n out.push({ sectorId: s.id, valid: workspaceNodes(layout, s), invalid: [] });\n } else {\n const mask = controller.state.cfg.sectors.find(ss => ss.id === s.id)?.silhouette.mask ?? [];\n if (!mask || mask.length === 0) continue;\n const rect = rectForBand(layout, s, \"silhouette\", 1.0); // center only; size was handled in global scale\n const placedPolys = placeSilhouetteGridAlignedAsPolys(mask, scaleS, { cx: rect.cx, cy: rect.cy });\n const bandAll = silhouetteBandNodes(layout, s);\n const valid = silhouetteNodes(layout, s, placedPolys);\n // invalid = bandAll \\ valid (by coordinate)\n const key = (p: { x: number; y: number }) => `${p.x},${p.y}`;\n const validSet = new Set(valid.map(key));\n const invalid = bandAll.filter(p => !validSet.has(key(p)));\n out.push({ sectorId: s.id, valid, invalid });\n }\n }\n return out;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [cfg.target, controller.state.sectors, layout, scaleS]);\n\n return {\n anchorDots\n };\n}","/**\n * Face-to-Face Attachment Validation for Prep Mode\n * \n * Validates that pieces in prep mode attach to existing pieces by sharing\n * at least 1 anchor unit of edge contact. Uses discrete unit segments\n * for precise edge detection.\n */\n\nimport type { Piece, Vec, Blueprint } from \"../../domain/types\";\nimport { CONFIG } from \"../../config/config\";\nimport { boundsOfBlueprint } from \"../geometry\";\n\nexport interface EdgeAttachmentResult {\n isAttached: boolean;\n attachedPieceIds: string[];\n sharedEdgeLength: number; // In anchor units\n}\n\nexport interface UnitSegment {\n a: Vec;\n b: Vec;\n}\n\n/**\n * Convert a polygon edge into unit-length segments\n * Each segment represents a discrete coordinate unit along the edge\n */\nfunction edgeToUnitSegments(start: Vec, end: Vec, gridSize: number): UnitSegment[] {\n const segments: UnitSegment[] = [];\n \n // Convert to grid coordinates\n const startGrid = {\n x: Math.round(start.x / gridSize),\n y: Math.round(start.y / gridSize)\n };\n const endGrid = {\n x: Math.round(end.x / gridSize),\n y: Math.round(end.y / gridSize)\n };\n \n const dx = endGrid.x - startGrid.x;\n const dy = endGrid.y - startGrid.y;\n \n if (dx === 0 && dy === 0) return []; // Zero-length edge\n \n const steps = Math.max(Math.abs(dx), Math.abs(dy));\n const stepX = dx / steps;\n const stepY = dy / steps;\n \n for (let i = 0; i < steps; i++) {\n const aX = Math.round(startGrid.x + i * stepX);\n const aY = Math.round(startGrid.y + i * stepY);\n const bX = Math.round(startGrid.x + (i + 1) * stepX);\n const bY = Math.round(startGrid.y + (i + 1) * stepY);\n segments.push({ \n a: { x: aX, y: aY }, \n b: { x: bX, y: bY } \n });\n }\n \n return segments;\n}\n\n\n\n/**\n * Get all unit segments for a piece (all edges broken down into unit-length segments)\n * Uses the same coordinate system as piecePolysAt for consistency with visual rendering\n */\nfunction getPieceUnitSegments(\n piece: Piece, \n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any,\n gridSize: number\n): UnitSegment[] {\n const blueprint = getBlueprint(piece.blueprintId);\n if (!blueprint?.shape) return [];\n \n // Calculate offset using same logic as piecePolysAt\n const bb = boundsOfBlueprint(blueprint, getPrimitive);\n const ox = piece.pos.x - bb.min.x;\n const oy = piece.pos.y - bb.min.y;\n \n const allSegments: UnitSegment[] = [];\n \n // Translate polygons and convert edges to unit segments\n for (const poly of blueprint.shape) {\n const translatedPoly = poly.map((vertex: Vec) => ({\n x: vertex.x + ox,\n y: vertex.y + oy\n }));\n \n for (let i = 0; i < translatedPoly.length; i++) {\n const current = translatedPoly[i];\n const next = translatedPoly[(i + 1) % translatedPoly.length];\n \n if (!current || !next) continue;\n \n allSegments.push(...edgeToUnitSegments(current, next, gridSize));\n }\n }\n \n return allSegments;\n}\n\n/**\n * Main face-to-face attachment validation function\n */\nexport function checkFaceToFaceAttachment(\n piece: Piece,\n existingPieces: Piece[],\n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any\n): EdgeAttachmentResult {\n if (existingPieces.length === 0) {\n return { isAttached: true, attachedPieceIds: [], sharedEdgeLength: 0 };\n }\n \n const gridSize = CONFIG.layout.grid.stepPx;\n const newPieceSegments = getPieceUnitSegments(piece, getBlueprint, getPrimitive, gridSize);\n \n if (newPieceSegments.length === 0) {\n return { isAttached: false, attachedPieceIds: [], sharedEdgeLength: 0 };\n }\n \n let totalSharedLength = 0;\n const attachedPieceIds: string[] = [];\n \n // Check against each existing piece\n for (const existingPiece of existingPieces) {\n const existingSegments = getPieceUnitSegments(existingPiece, getBlueprint, getPrimitive, gridSize);\n \n // Find shared segments (undirected edge matching)\n const sharedSegments = newPieceSegments.filter(newSeg => \n existingSegments.some(existingSeg => \n // Check if segments share the same endpoints (identical or reversed)\n (newSeg.a.x === existingSeg.a.x && newSeg.a.y === existingSeg.a.y &&\n newSeg.b.x === existingSeg.b.x && newSeg.b.y === existingSeg.b.y) ||\n (newSeg.a.x === existingSeg.b.x && newSeg.a.y === existingSeg.b.y &&\n newSeg.b.x === existingSeg.a.x && newSeg.b.y === existingSeg.a.y)\n )\n );\n \n if (sharedSegments.length > 0) {\n totalSharedLength += sharedSegments.length;\n attachedPieceIds.push(existingPiece.id);\n }\n }\n \n return {\n isAttached: totalSharedLength >= 1,\n attachedPieceIds,\n sharedEdgeLength: totalSharedLength\n };\n}\n\n/**\n * Check if removing a piece would disconnect the remaining pieces in a sector\n * Uses graph connectivity to ensure all remaining pieces stay connected\n */\nexport function wouldRemovalDisconnectSector(\n pieceToRemove: Piece,\n allPiecesInSector: Piece[],\n getBlueprint: (id: string) => Blueprint | undefined,\n getPrimitive: (kind: string) => any\n): boolean {\n // If there are 0 or 1 pieces remaining, no disconnection possible\n if (allPiecesInSector.length <= 2) return false;\n \n const remainingPieces = allPiecesInSector.filter(p => p.id !== pieceToRemove.id);\n if (remainingPieces.length <= 1) return false;\n \n // Build adjacency graph of remaining pieces\n const adjacencyMap = new Map<string, string[]>();\n \n // Initialize adjacency map\n for (const piece of remainingPieces) {\n adjacencyMap.set(piece.id, []);\n }\n \n // Check all pairs of remaining pieces for connectivity\n for (let i = 0; i < remainingPieces.length; i++) {\n for (let j = i + 1; j < remainingPieces.length; j++) {\n const piece1 = remainingPieces[i];\n const piece2 = remainingPieces[j];\n \n if (!piece1 || !piece2) continue;\n \n const result = checkFaceToFaceAttachment(piece1, [piece2], getBlueprint, getPrimitive);\n if (result.isAttached) {\n adjacencyMap.get(piece1.id)!.push(piece2.id);\n adjacencyMap.get(piece2.id)!.push(piece1.id);\n }\n }\n }\n \n // Check if graph is connected using DFS\n const visited = new Set<string>();\n const startPiece = remainingPieces[0];\n \n if (!startPiece) return false;\n \n function dfs(pieceId: string) {\n if (visited.has(pieceId)) return;\n visited.add(pieceId);\n \n const neighbors = adjacencyMap.get(pieceId) || [];\n for (const neighborId of neighbors) {\n dfs(neighborId);\n }\n }\n \n dfs(startPiece.id);\n \n // If we visited all pieces, the graph is connected\n return visited.size !== remainingPieces.length;\n}","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { CircleLayout } from \"@/core/domain/layout\";\nimport type { Blueprint } from \"@/core/domain/types\";\nimport { sectorAtPoint } from \"@/core/domain/layout\";\nimport { \n boundsOfBlueprint, \n computeSupportOffsets, \n clampTopLeftBySupport, \n polysOverlap, \n piecePolysAt \n} from \"@/core/engine/geometry\";\nimport { nearestNodeSnap, polyFullyInside } from \"@/core/engine/collision/grid-snapping\";\nimport { checkFaceToFaceAttachment, wouldRemovalDisconnectSector } from \"@/core/engine/validation/face-to-face\";\nimport { blueprintLocalFromWorld } from \"./utils\";\nimport type { AnchorDots } from \"./useAnchorGrid\";\nimport type { PieceData } from \"./usePieceState\";\nimport { CONFIG } from \"@/core/config/config\";\n\ninterface DragState {\n id: string;\n dx: number;\n dy: number;\n tlx: number;\n tly: number;\n aabb: { width: number; height: number };\n minx: number;\n miny: number;\n support: { x: number; y: number }[];\n fromIcon?: boolean;\n validSnap?: boolean;\n prevValidSnap?: boolean;\n raf?: number | null;\n originalPos?: { x: number; y: number; sectorId: string | undefined } | undefined; // For prep mode: return to original position when invalid\n pointerAnchor?: { x: number; y: number } | null;\n pointerAnchorId?: string | null;\n pointerAnchorSectorId?: string | undefined;\n snapAnchor?: { x: number; y: number } | null;\n snapAnchorId?: string | null;\n snapAnchorSectorId?: string | undefined;\n snapAnchorDist?: number | null;\n overlaps?: boolean;\n maxExceeded?: boolean;\n}\n\n/**\n * Return interface for useDragController hook\n * \n * Provides complete drag interaction functionality for both click and drag input modes.\n * Handles piece spawning, dragging, collision detection, snapping, and placement validation.\n */\nexport interface DragControllerHook {\n // State\n /** ID of currently dragging piece (null if none) */\n draggingId: string | null;\n \n /** True if current drag position is invalid (for visual feedback) */\n dragInvalid: boolean;\n \n /** ID of piece that is locked due to connectivity constraints (for visual feedback) */\n lockedPieceId: string | null;\n \n /** Ref to SVG element for coordinate transformation and pointer capture */\n svgRef: React.RefObject<SVGSVGElement>;\n \n // Handlers\n /** \n * Handler for piece pointer down events (both click and drag modes)\n * @param e - Pointer event from SVG path or group element\n * @param p - Piece data including position and blueprint information\n */\n onPiecePointerDown: (\n e: React.PointerEvent<SVGPathElement | SVGGElement>,\n p: { id: string; x: number; y: number; blueprintId: string; sectorId?: string }\n ) => void;\n \n /** \n * Handler for blueprint icon pointer down events (spawning new pieces)\n * @param e - Pointer event from blueprint icon\n * @param bp - Blueprint definition for the new piece\n * @param bpGeom - Geometry information for the blueprint icon\n */\n onBlueprintPointerDown: (\n e: React.PointerEvent,\n bp: Blueprint,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n ) => void;\n \n /** \n * Handler for pointer move events during drag operations\n * @param e - Pointer event from SVG root element\n */\n onPointerMove: (e: React.PointerEvent<SVGSVGElement>) => void;\n \n /** Handler for pointer up events (completing drag operations) */\n onPointerUp: () => void;\n \n /** \n * Factory function for piece element refs (for direct DOM manipulation)\n * @param id - Piece ID\n * @returns Ref callback for SVG group element\n */\n setPieceRef: (id: string) => (el: SVGGElement | null) => void;\n \n // Click controller integration\n /** \n * Setter for dragging ID (used by click controller for carry state)\n * @param id - Piece ID or null to clear\n */\n setDraggingId: (id: string | null) => void;\n \n // TODO: Remove this once click mode is extracted - temporary for compatibility\n /** Internal drag state ref (temporary for click controller integration) */\n dragRef: React.RefObject<DragState | null>;\n}\n\n/**\n * Hook for managing drag interactions with RAF optimization and collision detection\n * \n * This is the most complex hook in the system, handling all aspects of piece interaction\n * for both click and drag input modes. It manages piece spawning, dragging, collision\n * detection, grid snapping, placement validation, and visual feedback.\n * \n * ## Key Features\n * - **Dual input mode support**: Handles both click and drag interaction patterns\n * - **RAF-optimized rendering**: Uses requestAnimationFrame for smooth drag performance\n * - **Collision detection**: Real-time overlap checking with existing pieces\n * - **Grid snapping**: Automatic snapping to anchor points with validation\n * - **Placement validation**: Comprehensive validation for workspace/silhouette modes\n * - **Visual feedback**: Real-time visual indicators for valid/invalid placement\n * \n * ## Input Mode Behavior\n * - **Click mode**: First click starts \"carry\" state, second click places/cancels\n * - **Drag mode**: Traditional drag-and-drop with immediate visual feedback\n * \n * ## Validation Rules\n * - **Workspace mode**: Pieces must not overlap, any grid position valid\n * - **Silhouette mode**: Pieces must be within silhouette mask, on valid anchors, no overlap\n * - **Completed sectors**: No placement allowed, pieces deleted if dropped\n * \n * @param controller - BaseGameController for state management\n * @param layout - Computed CircleLayout for sector geometry\n * @param pieces - Current piece data from usePieceState\n * @param pieceById - Lookup function for piece data\n * @param anchorDots - Anchor grid data from useAnchorGrid\n * @param placedSilBySector - Silhouette polygons for containment checking\n * @param isSectorLocked - Function to check if sector is completed\n * @param maybeCompleteSector - Callback to check sector completion after placement\n * @param force - Force React re-render function\n * @param clickController - Optional click controller integration\n * @returns Hook interface with drag state and event handlers\n * \n * @example\n * ```typescript\n * const dragController = useDragController(\n * controller, layout, pieces, pieceById, anchorDots,\n * placedSilBySector, isSectorLocked, maybeCompleteSector, force\n * );\n * \n * // Usage in JSX:\n * <svg ref={dragController.svgRef} onPointerMove={dragController.onPointerMove}>\n * <g onPointerDown={(e) => dragController.onPiecePointerDown(e, piece)}>\n * <path /> \n * </g>\n * </svg>\n * ```\n */\nexport function useDragController(\n controller: BaseGameController,\n layout: CircleLayout,\n pieces: PieceData[],\n pieceById: (id: string | null) => PieceData | null,\n anchorDots: AnchorDots[],\n placedSilBySector: Map<string, any[]>,\n isSectorLocked: (id: string) => boolean,\n maybeCompleteSector: (secId: string) => boolean,\n force: () => void,\n // Click controller integration\n clickController?: {\n setSelectedPiece: (id: string | null) => void;\n setPendingBp: (id: string | null) => void;\n },\n // Interaction tracking\n tracker?: {\n recordPickup: (\n pieceId: string,\n blueprintId: string,\n blueprintType: 'primitive' | 'composite',\n source: 'blueprint' | 'sector',\n position: { x: number; y: number },\n vertices: number[][][],\n sectorId?: string\n ) => void;\n recordPlacedown: (\n outcome: 'placed' | 'deleted',\n sectorId?: string,\n position?: { x: number; y: number },\n vertices?: number[][][],\n anchorId?: string,\n wasValid?: boolean,\n wasOverlapping?: boolean,\n completedSector?: boolean\n ) => void;\n recordMouseMove?: (anchorX: number, anchorY: number, sectorId?: string) => void;\n recordClickEvent?: (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => void;\n } | null\n): DragControllerHook {\n const cfg = controller.state.cfg;\n const clickMode = cfg.input === \"click\";\n \n // Core drag state\n const svgRef = React.useRef<SVGSVGElement | null>(null);\n const dragRef = React.useRef<DragState | null>(null);\n const [draggingId, setDraggingId] = React.useState<string | null>(null);\n const elMap = React.useRef(new Map<string, SVGGElement>());\n \n // Visual feedback for connectivity-locked pieces\n const [lockedPieceId, setLockedPieceId] = React.useState<string | null>(null);\n \n // Ensure dragRef is cleared when draggingId becomes null (for click controller integration)\n React.useEffect(() => {\n if (draggingId === null) {\n dragRef.current = null;\n }\n }, [draggingId]);\n\n const setPieceRef = (id: string) => (el: SVGGElement | null) => {\n const m = elMap.current;\n if (el) m.set(id, el); else m.delete(id);\n };\n\n const svgPoint = (clientX: number, clientY: number) => {\n const svg = svgRef.current!;\n const pt = svg.createSVGPoint();\n pt.x = clientX; pt.y = clientY;\n const ctm = svg.getScreenCTM();\n if (!ctm) return { x: 0, y: 0 };\n const sp = pt.matrixTransform(ctm.inverse());\n return { x: sp.x, y: sp.y };\n };\n\n const scheduleFrame = () => {\n if (!dragRef.current) return;\n const d = dragRef.current;\n if (d.raf != null) return;\n d.raf = requestAnimationFrame(() => {\n d.raf = null;\n const g = elMap.current.get(d.id);\n if (g) g.setAttribute(\"transform\", `translate(${d.tlx - d.minx}, ${d.tly - d.miny})`);\n });\n };\n\n const sectorIdAt = (x: number, y: number) => sectorAtPoint(x, y, layout, cfg.target);\n const GRID_STEP = CONFIG.layout.grid.stepPx;\n\n const anchorIdFromNode = (node: { x: number; y: number } | null | undefined): string | null => {\n if (!node) return null;\n const ax = Math.round(node.x / GRID_STEP);\n const ay = Math.round(node.y / GRID_STEP);\n return `${ax},${ay}`;\n };\n\n const anchorNodeFromPoint = (point: { x: number; y: number }) => ({\n x: Math.round(point.x / GRID_STEP) * GRID_STEP,\n y: Math.round(point.y / GRID_STEP) * GRID_STEP\n });\n\n const updatePointerAnchor = (point: { x: number; y: number }, sectorId: string | undefined) => {\n if (!dragRef.current) return;\n const d = dragRef.current;\n const anchorNode = anchorNodeFromPoint(point);\n const anchorId = anchorIdFromNode(anchorNode);\n\n if (tracker?.recordMouseMove && (anchorId !== d.pointerAnchorId || sectorId !== d.pointerAnchorSectorId)) {\n tracker.recordMouseMove(anchorNode.x, anchorNode.y, sectorId);\n }\n\n d.pointerAnchor = anchorNode;\n d.pointerAnchorId = anchorId;\n d.pointerAnchorSectorId = sectorId;\n };\n\n const updateSnapAnchor = (\n node: { x: number; y: number } | null,\n sectorId: string | undefined,\n dist?: number\n ) => {\n if (!dragRef.current) return;\n const d = dragRef.current;\n d.snapAnchor = node;\n d.snapAnchorId = anchorIdFromNode(node);\n d.snapAnchorSectorId = sectorId;\n d.snapAnchorDist = node && dist !== undefined ? dist : null;\n };\n\n const emitClickEvent = (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => {\n if (!tracker?.recordClickEvent) return;\n tracker.recordClickEvent(location, clickType, metadata);\n };\n\n // Helper: Compute piece vertices in world space\n const getPieceVertices = (pieceId: string): number[][][] => {\n const piece = controller.findPiece(pieceId);\n if (!piece) return [];\n const bp = controller.getBlueprint(piece.blueprintId);\n if (!bp) return [];\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const polys = piecePolysAt(bp, bb, piece.pos);\n // Convert from {x,y}[][] to number[][][]\n return polys.map(ring => ring.map(pt => [pt.x, pt.y]));\n };\n\n const onPiecePointerDown = (\n e: React.PointerEvent<SVGPathElement | SVGGElement>,\n p: { id: string; x: number; y: number; blueprintId: string; sectorId?: string }\n ) => {\n if (p.sectorId && isSectorLocked(p.sectorId)) return;\n if (clickMode && draggingId) return; // ignore if already carrying\n\n // Check connectivity in prep mode - prevent removal if it would disconnect remaining pieces\n if (cfg.mode === \"prep\" && p.sectorId) {\n const allPiecesInSector = controller.getPiecesInSector(p.sectorId);\n const pieceToRemove = controller.findPiece(p.id);\n \n if (pieceToRemove && wouldRemovalDisconnectSector(\n pieceToRemove,\n allPiecesInSector,\n (id) => controller.getBlueprint(id),\n (kind) => controller.getPrimitive(kind)\n )) {\n // Flash red briefly to indicate piece cannot be removed\n setLockedPieceId(p.id);\n setTimeout(() => setLockedPieceId(null), 500);\n return; // Prevent pickup\n }\n }\n\n if (clickMode) {\n // Start a \"carry\" in click mode: make the piece follow the cursor\n e.stopPropagation();\n clickController?.setSelectedPiece(p.id);\n clickController?.setPendingBp(null);\n\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, (k) => controller.getPrimitive(k));\n const support = computeSupportOffsets(bp, bb);\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n const pointerAnchorNode = anchorNodeFromPoint({ x, y });\n const pointerSector = p.sectorId;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n p.id,\n p.blueprintId,\n blueprintType,\n 'sector',\n { x: p.x, y: p.y },\n getPieceVertices(p.id),\n p.sectorId\n );\n }\n\n dragRef.current = {\n id: p.id,\n dx: x - p.x, dy: y - p.y,\n tlx: p.x, tly: p.y,\n aabb: { width: bb.width, height: bb.height },\n minx: bb.min.x, miny: bb.min.y,\n support,\n fromIcon: false,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: { x: p.x, y: p.y, sectorId: p.sectorId },\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n maxExceeded: false,\n };\n updateSnapAnchor(null, p.sectorId);\n setDraggingId(p.id);\n force();\n return;\n }\n\n // DRAG path\n svgRef.current?.setPointerCapture(e.pointerId);\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, (k) => controller.getPrimitive(k));\n const support = computeSupportOffsets(bp, bb);\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n const pointerAnchorNode = anchorNodeFromPoint({ x, y });\n const pointerSector = p.sectorId;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n p.id,\n p.blueprintId,\n blueprintType,\n 'sector',\n { x: p.x, y: p.y },\n getPieceVertices(p.id),\n p.sectorId\n );\n }\n\n dragRef.current = {\n id: p.id,\n dx: x - p.x, dy: y - p.y,\n tlx: p.x, tly: p.y,\n aabb: { width: bb.width, height: bb.height },\n minx: bb.min.x, miny: bb.min.y,\n support,\n fromIcon: false,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: { x: p.x, y: p.y, sectorId: p.sectorId },\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n maxExceeded: false,\n };\n updateSnapAnchor(null, p.sectorId);\n setDraggingId(p.id);\n force();\n };\n\n const onPointerMove = (e: React.PointerEvent<SVGSVGElement>) => {\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n // Always log pointer movement for mouse tracking, even before pickup\n const pointerAnchorNode = anchorNodeFromPoint({ x, y });\n const pointerR = Math.hypot(x - layout.cx, y - layout.cy);\n const pointerSectorId = pointerR < layout.innerR ? undefined : sectorIdAt(x, y) ?? undefined;\n if (!dragRef.current) {\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSectorId);\n }\n return;\n }\n\n const d = dragRef.current;\n const tlx = x - d.dx, tly = y - d.dy;\n\n updatePointerAnchor({ x, y }, pointerSectorId);\n\n const clamped = clampTopLeftBySupport(\n tlx, tly,\n { aabb: d.aabb, support: d.support },\n layout,\n controller.state.cfg.target,\n pointerR < layout.innerR\n );\n\n let tl = clamped;\n // Snap the *piece itself* to nearest nodes in the active sector (or inner ring),\n // and compute validity (silhouette: within snapRadius; workspace: always valid).\n const centerX = tl.x + d.aabb.width / 2;\n const centerY = tl.y + d.aabb.height / 2;\n const rFromCenter = Math.hypot(centerX - layout.cx, centerY - layout.cy);\n const inInnerRing = rFromCenter < layout.innerR;\n const secId = inInnerRing ? null : sectorIdAt(centerX, centerY);\n let snapNode: { x: number; y: number } | null = null;\n let snapDist: number | null = null;\n let snapSectorId: string | undefined = secId ?? undefined;\n let overlapsDetected = false;\n let maxExceededDetected = false;\n\n // Check for inner ring snapping first\n if (inInnerRing) {\n const innerEntry = anchorDots.find(a => a.sectorId === \"inner-ring\");\n if (innerEntry && innerEntry.valid.length) {\n const piece = pieceById(d.id);\n if (piece) {\n const bp = controller.getBlueprint(piece.blueprintId)!;\n const snap = nearestNodeSnap(tl, bp, controller.getPrimitive, innerEntry.valid);\n tl = snap.tl;\n snapNode = snap.node;\n snapDist = snap.dist;\n snapSectorId = undefined;\n }\n }\n // Inner ring shows RED (invalid) to indicate piece will be deleted\n d.validSnap = false;\n } else if (secId) {\n const isCompletedSector = isSectorLocked(secId);\n const entry = anchorDots.find(a => a.sectorId === secId);\n const allNodes =\n (cfg.target === \"workspace\" && cfg.mode !== \"prep\")\n ? (entry?.valid ?? []) // Construction workspace: only valid nodes\n : [ ...(entry?.valid ?? []), ...(entry?.invalid ?? []) ]; // Silhouette + Prep: all nodes\n\n // Snap to anchors even in completed sectors\n if (allNodes.length) {\n const piece = pieceById(d.id);\n if (piece) {\n const bp = controller.getBlueprint(piece.blueprintId)!;\n const snap = nearestNodeSnap(\n tl,\n bp,\n controller.getPrimitive,\n allNodes\n );\n tl = snap.tl;\n snapNode = snap.node;\n snapDist = snap.dist;\n snapSectorId = secId;\n\n // Completed sectors: always show red (invalid)\n if (isCompletedSector) {\n d.validSnap = false;\n } else {\n // Normal validation for incomplete sectors\n const radius = controller.state.cfg.snapRadiusPx;\n // Gather world polys for the carried piece at the *snapped* TL\n const carried = pieceById(d.id);\n let overlapsOk = true;\n if (carried) {\n const bpCar = controller.getBlueprint(carried.blueprintId)!;\n const bbCar = boundsOfBlueprint(\n bpCar,\n controller.getPrimitive\n );\n const carriedPolys = piecePolysAt(bpCar, bbCar, tl);\n\n // only compare against pieces in the same sector we're currently over\n const sameSector = pieces.filter(\n pp =>\n pp.id !== d.id &&\n sectorIdAt(\n pp.x +\n boundsOfBlueprint(\n controller.getBlueprint(pp.blueprintId)!,\n controller.getPrimitive\n ).width / 2,\n pp.y +\n boundsOfBlueprint(\n controller.getBlueprint(pp.blueprintId)!,\n controller.getPrimitive\n ).height / 2,\n ) === secId\n );\n\n for (const other of sameSector) {\n const bpO = controller.getBlueprint(other.blueprintId)!;\n const bbO = boundsOfBlueprint(\n bpO,\n controller.getPrimitive\n );\n const otherPolys = piecePolysAt(bpO, bbO, { x: other.x, y: other.y });\n if (polysOverlap(carriedPolys, otherPolys)) {\n overlapsOk = false;\n break;\n }\n }\n\n // workspace: validity depends on mode\n if (cfg.target === \"workspace\") {\n if (cfg.mode === \"prep\") {\n // Prep mode: ALWAYS allow movement (just show visual feedback)\n // Face-to-face validation only affects visual feedback, not movement\n const allPiecesInSector = controller.getPiecesInSector(secId);\n const otherPiecesInSector = allPiecesInSector.filter(piece => piece.id !== d.id);\n const isFirstPiece = otherPiecesInSector.length === 0;\n const storedPiece = controller.findPiece(d.id);\n const currentSectorId = storedPiece?.sectorId;\n const maxPieces = controller.state.cfg.maxCompositeSize ?? 0;\n const enforceMaxPieces = maxPieces > 0;\n const effectiveCount = allPiecesInSector.length - (currentSectorId === secId ? 1 : 0);\n const wouldExceedMax = enforceMaxPieces && (effectiveCount + 1 > maxPieces);\n\n if (isFirstPiece) {\n // First piece: visual feedback based on overlaps and max-piece limit\n d.validSnap = overlapsOk && !wouldExceedMax;\n maxExceededDetected = wouldExceedMax;\n } else if (storedPiece) {\n // Subsequent pieces: visual feedback based on face-to-face attachment\n const pieceAtDragPosition = {\n ...storedPiece,\n pos: { x: tl.x, y: tl.y }\n };\n\n const attachmentResult = checkFaceToFaceAttachment(\n pieceAtDragPosition,\n otherPiecesInSector,\n (id) => controller.getBlueprint(id),\n (kind) => controller.getPrimitive(kind)\n );\n\n d.validSnap = overlapsOk && attachmentResult.isAttached && !wouldExceedMax;\n maxExceededDetected = wouldExceedMax;\n } else {\n d.validSnap = overlapsOk && !wouldExceedMax;\n maxExceededDetected = wouldExceedMax;\n }\n\n // IMPORTANT: In prep mode, always allow movement regardless of validSnap\n // validSnap is only for visual feedback (red/blue coloring)\n } else {\n // Construction mode: original behavior (validSnap blocks movement)\n d.validSnap = overlapsOk;\n maxExceededDetected = false;\n }\n overlapsDetected = !overlapsOk;\n } else {\n // silhouette: node must be valid AND fully inside AND !overlap\n const key = (p: { x: number; y: number }) => `${p.x},${p.y}`;\n const validSet = new Set((entry?.valid ?? []).map(key));\n const nodeOk =\n !!snap.node && validSet.has(key(snap.node)) && snap.dist <= (radius ?? 0);\n let insideOk = false;\n if (nodeOk) {\n const silPolys = placedSilBySector.get(secId) ?? [];\n insideOk = polyFullyInside(carriedPolys, silPolys);\n }\n d.validSnap = nodeOk && insideOk && overlapsOk;\n overlapsDetected = !overlapsOk;\n }\n }\n }\n }\n }\n } else { \n // not over any sector band\n d.validSnap = (controller.state.cfg.target === \"workspace\");\n snapNode = null;\n snapDist = null;\n snapSectorId = undefined;\n maxExceededDetected = false;\n }\n d.overlaps = overlapsDetected;\n d.maxExceeded = maxExceededDetected;\n updateSnapAnchor(snapNode, snapSectorId, snapDist ?? undefined);\n d.tlx = tl.x; d.tly = tl.y;\n\n // If the validity state changed, force a React render so fill/stroke update immediately.\n if (d.prevValidSnap !== d.validSnap) {\n d.prevValidSnap = d.validSnap ?? false;\n force();\n }\n\n scheduleFrame();\n };\n\n const onPointerUp = () => {\n if (!dragRef.current) return;\n if (clickMode) return;\n\n const d = dragRef.current;\n // If the candidate is invalid for any reason (overlap/outside/bad node), handle based on mode\n if (d.validSnap === false) {\n const piece = controller.findPiece(d.id);\n const cfg = controller.state.cfg;\n const centerX = d.tlx + d.aabb.width / 2;\n const centerY = d.tly + d.aabb.height / 2;\n const attemptedSector = sectorIdAt(centerX, centerY);\n let invalidReason: 'overlapping' | 'outside_bounds' | 'no_valid_anchor' | 'sector_complete' = 'outside_bounds';\n if (d.maxExceeded) {\n invalidReason = 'no_valid_anchor';\n } else if (d.overlaps) {\n invalidReason = 'overlapping';\n } else if (attemptedSector) {\n invalidReason = 'no_valid_anchor';\n }\n emitClickEvent(\n { x: centerX, y: centerY },\n 'invalid_placement',\n { invalidPlacement: { reason: invalidReason, attemptedSectorId: attemptedSector ?? undefined } }\n );\n\n // In prep mode: return to original position (if exists) or delete (if from icon)\n if (cfg.mode === \"prep\" && d.originalPos) {\n // Return piece to its original position\n controller.move(d.id, { x: d.originalPos.x, y: d.originalPos.y });\n\n // Record placedown as \"placed\" back in original position\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n d.originalPos.sectorId,\n { x: d.originalPos.x, y: d.originalPos.y },\n getPieceVertices(d.id),\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n } else {\n // Construction mode or fromIcon in prep mode: delete piece\n const removedFromSector = piece?.sectorId;\n controller.remove(d.id);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n }\n\n dragRef.current = null;\n setDraggingId(null);\n force();\n return;\n }\n \n dragRef.current = null;\n if (d.raf) { cancelAnimationFrame(d.raf); d.raf = null; }\n\n const commitTL = { x: d.tlx, y: d.tly };\n const centerX = commitTL.x + d.aabb.width / 2;\n const centerY = commitTL.y + d.aabb.height / 2;\n\n // delete if inside the inner hole\n const rFromCenter = Math.hypot(centerX - layout.cx, centerY - layout.cy);\n if (rFromCenter < layout.innerR) {\n const piece = controller.findPiece(d.id);\n const removedFromSector = piece?.sectorId;\n controller.remove(d.id);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n\n setDraggingId(null);\n force();\n return;\n }\n\n const secId = sectorIdAt(centerX, centerY);\n\n // Completed sector: no-op (do nothing, same as clicking incomplete sector in silhouette mode)\n if (secId && isSectorLocked(secId)) {\n emitClickEvent(\n { x: centerX, y: centerY },\n 'sector_complete_attempt',\n { invalidPlacement: { reason: 'sector_complete', attemptedSectorId: secId } }\n );\n // Return piece to original position if it exists, otherwise delete (from icon spawn)\n if (d.originalPos) {\n controller.move(d.id, { x: d.originalPos.x, y: d.originalPos.y });\n if (d.originalPos.sectorId) {\n controller.drop(d.id, d.originalPos.sectorId);\n }\n\n // Record placedown as \"placed\" back in original position\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n d.originalPos.sectorId,\n { x: d.originalPos.x, y: d.originalPos.y },\n getPieceVertices(d.id),\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n } else {\n // Piece was spawned from icon and dropped in completed sector → delete\n controller.remove(d.id);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n undefined,\n undefined,\n undefined,\n d.snapAnchorId ?? undefined,\n false,\n d.overlaps ?? false\n );\n }\n }\n setDraggingId(null);\n force();\n return;\n }\n\n controller.move(d.id, commitTL);\n controller.drop(d.id, secId);\n\n const justCompleted = secId ? maybeCompleteSector(secId) : false;\n\n // Record placedown as \"placed\" successfully\n const wasValid = d.validSnap === undefined ? true : d.validSnap;\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n secId,\n commitTL,\n getPieceVertices(d.id),\n d.snapAnchorId ?? undefined,\n wasValid,\n d.overlaps ?? false,\n justCompleted\n );\n }\n\n setDraggingId(null);\n\n // auto-revert AFTER completing a drag spawn from the center\n if (d.fromIcon && controller.state.blueprintView === \"primitives\") {\n controller.switchBlueprintView();\n }\n force();\n };\n\n const onBlueprintPointerDown = (\n e: React.PointerEvent,\n bp: Blueprint,\n bpGeom: { bx: number; by: number; cx: number; cy: number }\n ) => {\n if (clickMode && draggingId) return;\n e.stopPropagation();\n\n const { x: px, y: py } = svgPoint(e.clientX, e.clientY);\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const support = computeSupportOffsets(bp, bb);\n\n if (clickMode) {\n // Click mode: spawn then enter carry state\n \n // Compute the local point of the blueprint glyph that was clicked\n const q = blueprintLocalFromWorld(px, py, bpGeom);\n // Compute TL so that the clicked point stays under the cursor\n const tl0 = { x: px - (q.x - bb.min.x), y: py - (q.y - bb.min.y) };\n const pointerR = Math.hypot(px - layout.cx, py - layout.cy);\n const allowInside = pointerR < layout.innerR;\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: bb, support },\n layout,\n controller.state.cfg.target,\n allowInside\n );\n const pieceId = controller.spawnFromBlueprint(bp, clamped);\n const pointerAnchorNode = anchorNodeFromPoint({ x: px, y: py });\n const pointerSector = sectorIdAt(px, py) ?? undefined;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event for blueprint spawn\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n pieceId,\n bp.id,\n blueprintType,\n 'blueprint',\n clamped,\n getPieceVertices(pieceId),\n undefined\n );\n }\n\n const tl = clamped;\n // If anchors mode, immediately snap initial TL to the nearest nodes in the active sector\n let finalTl = tl;\n let snapInfo: { node: { x: number; y: number } | null; dist: number } | null = null;\n const centerX = tl.x + bb.width / 2;\n const centerY = tl.y + bb.height / 2;\n const secId = sectorIdAt(centerX, centerY);\n if (secId) {\n const entry = anchorDots.find(a => a.sectorId === secId);\n const nodes =\n controller.state.cfg.target === \"workspace\"\n ? (entry?.valid ?? [])\n : [ ...(entry?.valid ?? []), ...(entry?.invalid ?? []) ];\n if (nodes.length) {\n const snap = nearestNodeSnap(tl, bp, controller.getPrimitive, nodes);\n finalTl = snap.tl;\n snapInfo = { node: snap.node, dist: snap.dist };\n }\n }\n \n controller.move(pieceId, finalTl);\n dragRef.current = {\n id: pieceId,\n dx: px - finalTl.x,\n dy: py - finalTl.y,\n tlx: finalTl.x,\n tly: finalTl.y,\n aabb: bb,\n minx: bb.min.x,\n miny: bb.min.y,\n support,\n fromIcon: true,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: undefined, // No original position for fromIcon drags\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n maxExceeded: false,\n };\n updatePointerAnchor({ x: px, y: py }, pointerSector);\n const snappingSecId = sectorIdAt(finalTl.x + bb.width / 2, finalTl.y + bb.height / 2) ?? undefined;\n updateSnapAnchor(snapInfo?.node ?? null, snappingSecId, snapInfo?.dist);\n setDraggingId(pieceId); // now onPointerMove will keep it in sync\n force();\n scheduleFrame();\n return;\n }\n\n // Drag mode: spawn at pointer with immediate drag\n svgRef.current?.setPointerCapture(e.pointerId);\n\n // Compute the local point of the blueprint glyph that was clicked\n const q = blueprintLocalFromWorld(px, py, bpGeom);\n // Compute TL so that the clicked point stays under the cursor\n const tl0 = { x: px - (q.x - bb.min.x), y: py - (q.y - bb.min.y) };\n const pointerR = Math.hypot(px - layout.cx, py - layout.cy);\n const allowInside = pointerR < layout.innerR;\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: bb, support },\n layout,\n controller.state.cfg.target,\n allowInside\n );\n const pieceId = controller.spawnFromBlueprint(bp, clamped);\n const pointerAnchorNode = anchorNodeFromPoint({ x: px, y: py });\n const pointerSector = sectorIdAt(px, py) ?? undefined;\n if (tracker?.recordMouseMove) {\n tracker.recordMouseMove(pointerAnchorNode.x, pointerAnchorNode.y, pointerSector);\n }\n\n // Record pickup event for blueprint spawn\n if (tracker) {\n const blueprintType = ('kind' in bp) ? 'primitive' : 'composite';\n tracker.recordPickup(\n pieceId,\n bp.id,\n blueprintType,\n 'blueprint',\n clamped,\n getPieceVertices(pieceId),\n undefined\n );\n }\n\n dragRef.current = {\n id: pieceId,\n dx: px - clamped.x,\n dy: py - clamped.y,\n tlx: clamped.x,\n tly: clamped.y,\n aabb: bb,\n minx: bb.min.x,\n miny: bb.min.y,\n support,\n fromIcon: true,\n validSnap: true,\n prevValidSnap: true,\n raf: null,\n originalPos: undefined, // No original position for fromIcon drags\n pointerAnchor: pointerAnchorNode,\n pointerAnchorId: anchorIdFromNode(pointerAnchorNode),\n pointerAnchorSectorId: pointerSector,\n snapAnchor: null,\n snapAnchorId: null,\n snapAnchorSectorId: undefined,\n snapAnchorDist: null,\n overlaps: false,\n };\n updatePointerAnchor({ x: px, y: py }, pointerSector);\n updateSnapAnchor(null, undefined);\n setDraggingId(pieceId);\n force();\n scheduleFrame();\n };\n\n return {\n // State\n draggingId,\n dragInvalid: !!(dragRef.current && dragRef.current.validSnap === false),\n lockedPieceId,\n svgRef,\n \n // Handlers\n onPiecePointerDown,\n onBlueprintPointerDown,\n onPointerMove,\n onPointerUp,\n setPieceRef,\n \n // Click controller integration\n setDraggingId,\n\n // TODO: Remove this once click mode is extracted - temporary for compatibility\n dragRef\n };\n}\n","import React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type { CircleLayout } from \"@/core/domain/layout\";\nimport { sectorAtPoint } from \"@/core/domain/layout\";\nimport { boundsOfBlueprint, computeSupportOffsets, clampTopLeftBySupport, piecePolysAt } from \"@/core/engine/geometry\";\nimport type { PieceData } from \"./usePieceState\";\n\n// Click controller state is managed internally with React hooks\n\n/**\n * Return interface for useClickController hook\n * \n * Provides click-based interaction functionality that works alongside\n * useDragController to support click-and-place interaction patterns.\n */\nexport interface ClickControllerHook {\n // State\n /** ID of pending blueprint for placement (from blueprint ring clicks) */\n pendingBpId: string | null;\n \n /** ID of currently selected piece (for click-to-move functionality) */\n selectedPieceId: string | null;\n \n // Handlers \n /** \n * Handler for root SVG clicks (placement, movement, deletion)\n * @param e - Pointer event from SVG root element\n */\n onRootPointerDown: (e: React.PointerEvent<SVGSVGElement>) => void;\n \n // Helper methods for drag controller integration\n /** Clear all selection state */\n clearSelection: () => void;\n \n /** \n * Set pending blueprint ID for placement\n * @param id - Blueprint ID or null to clear\n */\n setPendingBp: (id: string | null) => void;\n \n /** \n * Set selected piece ID for movement\n * @param id - Piece ID or null to clear\n */\n setSelectedPiece: (id: string | null) => void;\n}\n\n/**\n * Hook for managing click-based interactions in click input mode\n * \n * This hook works in conjunction with useDragController to provide click-and-place\n * interaction patterns. It manages the selection state for both blueprint icons and\n * live pieces, handling placement, movement, and deletion through click interactions.\n * \n * ## Click Interaction Patterns\n * - **Blueprint click**: Selects blueprint for placement (pendingBpId)\n * - **Piece click**: Starts \"carry\" state via drag controller integration\n * - **Empty click**: Places pending blueprint or moves selected piece\n * - **Center badge click**: Deletes carried/selected piece\n * - **Completed sector click**: Deletes pieces (invalid placement)\n * \n * ## State Management\n * - **pendingBpId**: Blueprint selected from ring, awaiting placement\n * - **selectedPieceId**: Live piece selected for movement\n * - **Integration with drag controller**: Uses draggingId for \"carry\" state\n * \n * ## Dependencies\n * This hook requires tight integration with useDragController as it uses the\n * drag controller's carry mechanism for piece movement in click mode.\n * \n * @param controller - BaseGameController for state management\n * @param layout - Computed CircleLayout for sector geometry\n * @param pieces - Current piece data from usePieceState\n * @param clickMode - Whether click input mode is active\n * @param draggingId - Current dragging piece ID from drag controller\n * @param setDraggingId - Setter for dragging ID (drag controller integration)\n * @param dragRef - Drag state ref from drag controller\n * @param isInsideBadge - Function to check if point is inside center badge\n * @param isSectorLocked - Function to check if sector is completed\n * @param maybeCompleteSector - Callback to check sector completion\n * @param svgPoint - Function to convert screen to SVG coordinates\n * @param force - Force React re-render function\n * @returns Hook interface with click state and handlers\n * \n * @example\n * ```typescript\n * const clickController = useClickController(\n * controller, layout, pieces, clickMode, \n * draggingId, setDraggingId, dragRef,\n * isInsideBadge, isSectorLocked, maybeCompleteSector, svgPoint, force\n * );\n * \n * // Usage in JSX:\n * <svg onPointerDown={clickController.onRootPointerDown}>\n * Game content\n * </svg>\n * ```\n */\nexport function useClickController(\n controller: BaseGameController,\n layout: CircleLayout,\n pieces: PieceData[],\n clickMode: boolean,\n draggingId: string | null,\n setDraggingId: (id: string | null) => void,\n dragRef: React.RefObject<any>,\n isInsideBadge: (x: number, y: number) => boolean,\n isSectorLocked: (id: string) => boolean,\n maybeCompleteSector: (secId: string) => boolean,\n svgPoint: (clientX: number, clientY: number) => { x: number; y: number },\n force: () => void,\n // Interaction tracking\n tracker?: {\n recordPlacedown: (\n outcome: 'placed' | 'deleted',\n sectorId?: string,\n position?: { x: number; y: number },\n vertices?: number[][][],\n anchorId?: string,\n wasValid?: boolean,\n wasOverlapping?: boolean,\n completedSector?: boolean\n ) => void;\n recordClickEvent?: (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => void;\n } | null\n): ClickControllerHook {\n const cfg = controller.state.cfg;\n const sectorIdAt = (x: number, y: number) => sectorAtPoint(x, y, layout, cfg.target);\n\n // Helper: Compute piece vertices in world space\n const getPieceVertices = (pieceId: string): number[][][] => {\n const piece = controller.findPiece(pieceId);\n if (!piece) return [];\n const bp = controller.getBlueprint(piece.blueprintId);\n if (!bp) return [];\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const polys = piecePolysAt(bp, bb, piece.pos);\n // Convert from {x,y}[][] to number[][][]\n return polys.map(ring => ring.map(pt => [pt.x, pt.y]));\n };\n\n const getCurrentAnchorInfo = () => {\n const d = dragRef.current;\n return {\n anchorId: d?.snapAnchorId ?? d?.pointerAnchorId ?? undefined,\n wasValid: d?.validSnap !== false,\n wasOverlapping: d?.overlaps ?? false,\n anchorX: d?.pointerAnchor?.x,\n anchorY: d?.pointerAnchor?.y,\n sectorId: d?.snapAnchorSectorId ?? d?.pointerAnchorSectorId\n };\n };\n\n const emitClickEvent = (\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: any\n ) => {\n if (!tracker?.recordClickEvent) return;\n tracker.recordClickEvent(location, clickType, metadata);\n };\n\n // Click mode state\n const [pendingBpId, setPendingBpId] = React.useState<string | null>(null); // selected icon\n const [selectedPieceId, setSelectedPieceId] = React.useState<string | null>(null); // selected live piece\n\n const onRootPointerDown = (e: React.PointerEvent<SVGSVGElement>) => {\n const { x: px, y: py } = svgPoint(e.clientX, e.clientY);\n\n // --- CLICK MODE: second-click behaviors (move/delete/place)\n if (clickMode) {\n const secId = sectorIdAt(px, py);\n\n // If we're currently carrying a piece (draggingId set via click), this click commits (or deletes)\n if (draggingId && dragRef.current) {\n const d = dragRef.current;\n const centerX2 = d.tlx + d.aabb.width / 2;\n const centerY2 = d.tly + d.aabb.height / 2;\n\n // delete/cancel if clicked center (carry piece is already under pointer)\n if (isInsideBadge(px, py)) {\n const piece = controller.findPiece(d.id);\n const removedFromSector = piece?.sectorId;\n const anchorInfo = getCurrentAnchorInfo();\n controller.remove(d.id);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n anchorInfo.anchorId,\n anchorInfo.wasValid,\n anchorInfo.wasOverlapping\n );\n }\n\n // TODO: Remove dragRef manipulation once drag controller provides proper interface\n // dragRef.current = null; // Cannot assign to readonly property - drag controller should handle this\n setDraggingId(null);\n setSelectedPieceId(null);\n setPendingBpId(null);\n force();\n return; // don't toggle view\n }\n\n // Check if piece is in inner ring - if so, delete it\n const rFromCenter = Math.hypot(centerX2 - layout.cx, centerY2 - layout.cy);\n if (rFromCenter < layout.innerR) {\n const piece = controller.findPiece(d.id);\n const removedFromSector = piece?.sectorId;\n const anchorInfo = getCurrentAnchorInfo();\n controller.remove(d.id);\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown(\n 'deleted',\n removedFromSector,\n undefined,\n undefined,\n anchorInfo.anchorId,\n anchorInfo.wasValid,\n anchorInfo.wasOverlapping\n );\n }\n\n setDraggingId(null);\n setSelectedPieceId(null);\n setPendingBpId(null);\n force();\n return;\n }\n\n const secId2 = sectorIdAt(centerX2, centerY2);\n\n if (!secId2) {\n emitClickEvent(\n { x: centerX2, y: centerY2 },\n 'invalid_placement',\n { invalidPlacement: { reason: 'outside_bounds' } }\n );\n force();\n return;\n }\n\n if (isSectorLocked(secId2)) {\n emitClickEvent(\n { x: centerX2, y: centerY2 },\n 'sector_complete_attempt',\n { invalidPlacement: { reason: 'sector_complete', attemptedSectorId: secId2 } }\n );\n force();\n return;\n }\n\n // If the candidate is invalid for any reason (overlap / outside / bad node), keep carrying\n if (d.validSnap === false) {\n const anchorInfo = getCurrentAnchorInfo();\n const invalidReason = anchorInfo.wasOverlapping ? 'overlapping' : 'no_valid_anchor';\n emitClickEvent(\n { x: centerX2, y: centerY2 },\n 'invalid_placement',\n { invalidPlacement: { reason: invalidReason, attemptedSectorId: secId2 } }\n );\n force();\n return;\n }\n \n controller.move(d.id, { x: d.tlx, y: d.tly }); // TL already snapped (valid)\n controller.drop(d.id, secId2);\n\n const anchorInfo = getCurrentAnchorInfo();\n const justCompleted = maybeCompleteSector(secId2);\n\n // Record placedown as \"placed\" successfully\n if (tracker) {\n tracker.recordPlacedown(\n 'placed',\n secId2,\n { x: d.tlx, y: d.tly },\n getPieceVertices(d.id),\n anchorInfo.anchorId,\n anchorInfo.wasValid,\n anchorInfo.wasOverlapping,\n justCompleted\n );\n }\n // TODO: Remove dragRef manipulation once drag controller provides proper interface\n // dragRef.current = null; // Cannot assign to readonly property - drag controller should handle this\n setDraggingId(null);\n setSelectedPieceId(null);\n setPendingBpId(null);\n // auto-revert AFTER placement completes (click mode)\n if (controller.state.blueprintView === \"primitives\") {\n controller.switchBlueprintView();\n }\n force();\n return;\n }\n\n // Selected piece → delete / move / deselect\n if (selectedPieceId) {\n if (isInsideBadge(px, py)) {\n const piece = controller.findPiece(selectedPieceId);\n const removedFromSector = piece?.sectorId;\n controller.remove(selectedPieceId);\n // Re-check completion for the sector the piece was removed from\n if (removedFromSector) maybeCompleteSector(removedFromSector);\n\n // Record placedown as \"deleted\"\n if (tracker) {\n tracker.recordPlacedown('deleted');\n }\n\n setSelectedPieceId(null);\n force();\n return; // DO NOT toggle view after delete\n }\n // Completed sector: no-op (do nothing, same as incomplete sector in silhouette mode)\n if (secId && isSectorLocked(secId)) {\n setSelectedPieceId(null);\n force();\n return;\n }\n if (secId) {\n const p = pieces.find(pp => pp.id === selectedPieceId);\n setSelectedPieceId(null);\n if (p) {\n const bp = controller.getBlueprint(p.blueprintId)!;\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const support = computeSupportOffsets(bp, bb);\n const tl0 = { x: px - bb.width / 2, y: py - bb.height / 2 };\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: { width: bb.width, height: bb.height }, support },\n layout,\n controller.state.cfg.target,\n false\n );\n\n const maxPieces = controller.state.cfg.maxCompositeSize ?? 0;\n if (controller.state.cfg.mode === \"prep\" && maxPieces > 0) {\n const sectorPieces = controller.getPiecesInSector(secId);\n const effectiveCount = sectorPieces.length - (p.sectorId === secId ? 1 : 0);\n if (effectiveCount + 1 > maxPieces) {\n force();\n return;\n }\n }\n\n controller.move(p.id, { x: clamped.x, y: clamped.y });\n controller.drop(p.id, secId);\n maybeCompleteSector(secId);\n force();\n }\n return;\n }\n // click outside → deselect only\n setSelectedPieceId(null);\n force();\n return;\n }\n\n // Pending icon → place\n if (pendingBpId) {\n const secId2 = sectorIdAt(px, py);\n\n if (isInsideBadge(px, py) || !secId2 || isSectorLocked(secId2)) {\n setPendingBpId(null); // cancel\n force();\n return;\n }\n\n const bp = controller.getBlueprint(pendingBpId)!;\n const bb = boundsOfBlueprint(bp, controller.getPrimitive);\n const support = computeSupportOffsets(bp, bb);\n const tl0 = { x: px - bb.width / 2, y: py - bb.height / 2 };\n const clamped = clampTopLeftBySupport(\n tl0.x, tl0.y,\n { aabb: { width: bb.width, height: bb.height }, support },\n layout,\n controller.state.cfg.target,\n false\n );\n const id = controller.spawnFromBlueprint(bp, clamped);\n\n const maxPieces = controller.state.cfg.maxCompositeSize ?? 0;\n if (controller.state.cfg.mode === \"prep\" && maxPieces > 0) {\n const sectorPieces = controller.getPiecesInSector(secId2);\n if (sectorPieces.length + 1 > maxPieces) {\n controller.remove(id);\n setPendingBpId(null);\n force();\n return;\n }\n }\n\n controller.drop(id, secId2);\n setPendingBpId(null);\n maybeCompleteSector(secId2);\n\n // auto-revert AFTER placement completes (click mode)\n if (controller.state.blueprintView === \"primitives\") controller.switchBlueprintView();\n force();\n return;\n }\n }\n };\n\n return {\n // State\n pendingBpId,\n selectedPieceId,\n \n // Handlers\n onRootPointerDown,\n \n // Helper methods for integration\n clearSelection: () => {\n setSelectedPieceId(null);\n setPendingBpId(null);\n },\n setPendingBp: setPendingBpId,\n setSelectedPiece: setSelectedPieceId,\n };\n}\n","/**\n * InteractionTracker - Event accumulation and data tracking for experiments\n *\n * This class listens to game controller events and builds structured data\n * according to the data-tracking.ts schema. It generates InteractionEvent\n * objects and accumulates TrialEndData for export.\n *\n * ## Key Responsibilities\n * - Track interaction lifecycle (pickup → placedown)\n * - Accumulate click events and mouse tracking between interactions\n * - Generate InteractionEvent objects with state snapshots\n * - Build TrialEndData on trial completion\n * - Call onInteraction/onTrialEnd callbacks for data export\n *\n * ## Architecture\n * ```\n * User Interaction\n * ↓\n * UI Controllers (drag/click)\n * ↓\n * BaseGameController Events\n * ↓\n * InteractionTracker\n * ↓\n * onInteraction(event) → socket.emit()\n * onTrialEnd(data) → socket.emit()\n * ```\n */\n\nimport { v4 as uuidv4 } from 'uuid';\nimport type { BaseGameController } from '../engine/state/BaseGameController';\nimport { boundsOfBlueprint, piecePolysAt } from '../engine/geometry';\nimport { CONFIG } from '../config/config';\nimport type {\n InteractionEvent,\n StateSnapshot,\n ConstructionTrialData,\n PrepTrialData,\n DataTrackingCallbacks,\n SectorSnapshot,\n PieceSnapshot,\n MacroSnapshot\n} from './data-tracking';\n\n/**\n * Pickup event data (temporary storage until placedown)\n */\ninterface PickupData {\n pieceId: string;\n blueprintId: string;\n blueprintType: 'primitive' | 'composite';\n timestamp: number;\n source: 'blueprint' | 'sector';\n sectorId: string | undefined;\n position: { x: number; y: number };\n vertices: number[][][];\n}\n\n/**\n * Click event data (accumulated until interaction completes)\n */\ninterface ClickEventData {\n timestamp: number;\n location: { x: number; y: number };\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt';\n blueprintViewSwitch?: {\n from: 'quickstash' | 'primitives';\n to: 'quickstash' | 'primitives';\n };\n invalidPlacement?: {\n reason: 'overlapping' | 'outside_bounds' | 'no_valid_anchor' | 'sector_complete';\n attemptedSectorId?: string;\n };\n}\n\n/**\n * Mouse tracking event data (accumulated until interaction completes)\n */\ninterface MouseTrackingData {\n timestamp: number;\n anchorX: number;\n anchorY: number;\n sectorId: string | undefined;\n phase: 'before_pickup' | 'while_holding';\n}\n\n/**\n * InteractionTracker - Main tracking class\n */\nexport class InteractionTracker {\n // Callbacks\n private callbacks: DataTrackingCallbacks;\n\n // Controller reference\n private controller: BaseGameController;\n\n // Trial parameters\n private trialParams: any;\n\n // Trial timing\n private trialStartTime: number;\n private completionTimes: Array<{ sectorId: string; completedAt: number }> = [];\n\n // Sector centers (set by GameBoard after layout computation)\n private sectorCenters: { [sectorId: string]: { x: number; y: number } } = {};\n\n // Interaction state\n private interactionIndex: number = 0;\n private currentPickup: PickupData | null = null;\n private previousSnapshotId: string | undefined = undefined;\n\n // Event accumulation (reset after each interaction)\n private clickEvents: ClickEventData[] = [];\n private mouseTracking: MouseTrackingData[] = [];\n\n // Interaction history (for TrialEndData)\n private interactions: InteractionEvent[] = [];\n\n // Prep-specific tracking\n private createdMacros: MacroSnapshot[] = [];\n\n // Grid step for coordinate conversion\n private gridStep: number;\n\n constructor(\n controller: BaseGameController,\n callbacks: DataTrackingCallbacks,\n trialParams: any\n ) {\n this.controller = controller;\n this.callbacks = callbacks;\n this.trialParams = trialParams;\n this.trialStartTime = Date.now();\n this.gridStep = CONFIG.layout.grid.stepPx;\n\n // Register tracking callbacks with controller\n this.controller.setTrackingCallbacks({\n onSectorCompleted: (sectorId) => this.recordSectorCompletion(sectorId)\n });\n }\n\n /**\n * Cleanup method to unregister from controller\n */\n dispose(): void {\n this.controller.setTrackingCallbacks(null);\n }\n\n // ===== Event Recording Methods =====\n // Called by UI controllers to record events\n\n /**\n * Record piece pickup event\n */\n recordPickup(\n pieceId: string,\n blueprintId: string,\n blueprintType: 'primitive' | 'composite',\n source: 'blueprint' | 'sector',\n position: { x: number; y: number },\n vertices: number[][][],\n sectorId?: string\n ): void {\n const anchorPosition = this.toAnchorPoint(position);\n const anchorVertices = this.toAnchorVertices(vertices);\n\n this.currentPickup = {\n pieceId,\n blueprintId,\n blueprintType,\n timestamp: Date.now(),\n source,\n sectorId,\n position: anchorPosition,\n vertices: anchorVertices\n };\n\n // Mark all subsequent mouse tracking as \"while_holding\"\n // (UI controllers should call recordMouseMove after this)\n }\n\n /**\n * Record piece placedown event\n */\n recordPlacedown(\n outcome: 'placed' | 'deleted',\n sectorId?: string,\n position?: { x: number; y: number },\n vertices?: number[][][],\n anchorId?: string,\n wasValid?: boolean,\n wasOverlapping?: boolean,\n completedSector?: boolean\n ): void {\n if (!this.currentPickup) {\n console.warn('[InteractionTracker] recordPlacedown called without pickup');\n return;\n }\n\n const interactionType = this.determineInteractionType(this.currentPickup.source, outcome);\n const placedownTimestamp = Date.now();\n const holdDuration = placedownTimestamp - this.currentPickup.timestamp;\n\n // Build post-interaction snapshot\n // If this placement completes a sector, mark it in the snapshot\n const postSnapshot = this.buildStateSnapshot(completedSector ? sectorId : undefined);\n\n const anchorPosition = position ? this.toAnchorPoint(position) : undefined;\n const anchorVertices = vertices ? this.toAnchorVertices(vertices) : undefined;\n\n // Create interaction event - build incrementally to satisfy exactOptionalPropertyTypes\n const event: InteractionEvent = {\n // Metadata\n interactionId: uuidv4(),\n interactionIndex: this.interactionIndex++,\n\n // Interaction type\n interactionType,\n\n // Piece information\n pieceId: this.currentPickup.pieceId,\n blueprintId: this.currentPickup.blueprintId,\n blueprintType: this.currentPickup.blueprintType,\n\n // Pickup event\n pickupTimestamp: this.currentPickup.timestamp,\n pickupSource: this.currentPickup.source,\n pickupSectorId: this.currentPickup.sectorId,\n pickupPosition: this.currentPickup.position,\n pickupVertices: this.currentPickup.vertices,\n\n // Placedown event\n placedownTimestamp,\n placedownOutcome: outcome,\n\n // Validation context\n wasValid: outcome === 'placed' && wasValid === true,\n wasOverlapping: outcome === 'placed' && wasOverlapping === true,\n\n // Timing\n holdDuration,\n\n // Events\n clickEvents: [...this.clickEvents],\n mouseTracking: [...this.mouseTracking],\n\n // Snapshots\n postSnapshot\n };\n\n // Add optional placedown properties based on outcome\n if (outcome === 'placed' && sectorId) {\n event.placedownSectorId = sectorId;\n }\n if (outcome === 'placed' && anchorPosition) {\n event.placedownPosition = anchorPosition;\n }\n if (outcome === 'placed' && anchorVertices) {\n event.placedownVertices = anchorVertices;\n }\n if (anchorId) {\n event.placedownAnchorId = anchorId;\n }\n if (this.previousSnapshotId !== undefined) {\n event.preSnapshotId = this.previousSnapshotId;\n }\n\n // Store for trial end data\n this.interactions.push(event);\n this.previousSnapshotId = postSnapshot.snapshotId;\n\n // Call interaction callback\n if (this.callbacks.onInteraction) {\n this.callbacks.onInteraction(event);\n }\n\n // Reset interaction state\n this.currentPickup = null;\n this.clickEvents = [];\n this.mouseTracking = [];\n }\n\n /**\n * Record click event\n */\n recordClickEvent(\n location: { x: number; y: number },\n clickType: 'blueprint_view_switch' | 'invalid_placement' | 'sector_complete_attempt',\n metadata?: {\n blueprintViewSwitch?: { from: 'quickstash' | 'primitives'; to: 'quickstash' | 'primitives' };\n invalidPlacement?: { reason: 'overlapping' | 'outside_bounds' | 'no_valid_anchor' | 'sector_complete'; attemptedSectorId?: string };\n }\n ): void {\n const anchorLocation = this.toAnchorPoint(location);\n\n this.clickEvents.push({\n timestamp: Date.now(),\n location: anchorLocation,\n clickType,\n ...metadata\n });\n }\n\n /**\n * Record mouse movement to different anchor\n */\n recordMouseMove(\n anchorX: number,\n anchorY: number,\n sectorId?: string\n ): void {\n const phase: 'before_pickup' | 'while_holding' = this.currentPickup ? 'while_holding' : 'before_pickup';\n const anchorCoordX = this.toAnchorValue(anchorX);\n const anchorCoordY = this.toAnchorValue(anchorY);\n\n // Only record if anchor position changed\n const lastTracking = this.mouseTracking[this.mouseTracking.length - 1];\n if (lastTracking && lastTracking.anchorX === anchorCoordX && lastTracking.anchorY === anchorCoordY) {\n return; // Same position, skip\n }\n\n this.mouseTracking.push({\n timestamp: Date.now(),\n anchorX: anchorCoordX,\n anchorY: anchorCoordY,\n sectorId,\n phase\n });\n }\n\n /**\n * Set sector centers (for anchor alignment)\n */\n setSectorCenters(centers: { [sectorId: string]: { x: number; y: number } }): void {\n this.sectorCenters = centers;\n }\n\n /**\n * Record a sector completion event\n */\n recordSectorCompletion(sectorId: string): void {\n this.completionTimes.push({\n sectorId,\n completedAt: Date.now()\n });\n }\n\n /**\n * Record macro creation (prep mode only)\n */\n recordMacroCreation(macro: MacroSnapshot): void {\n this.createdMacros.push(macro);\n }\n\n // ===== Trial Completion =====\n\n /**\n * Finalize trial and call onTrialEnd callback\n */\n finalizeTrial(endReason: 'timeout' | 'auto_complete' | 'submit'): void {\n const trialEndTime = Date.now();\n const totalDuration = trialEndTime - this.trialStartTime;\n const finalSnapshot = this.buildStateSnapshot();\n\n // Calculate anchor to stimuli ratio (grid step in stimuli units)\n // CONFIG.layout.grid.stepPx is the pixel size of one anchor unit\n // CONFIG.layout.grid.unitPx is the pixel size of one stimuli unit (UNIT in tangram.py)\n // So the ratio is stepPx / unitPx (typically 20 / 40 = 0.5)\n const anchorToStimuliRatio = CONFIG.layout.grid.stepPx / CONFIG.layout.grid.unitPx;\n\n const mode = this.controller.state.cfg.mode;\n\n if (mode === 'construction') {\n const finalBlueprintState = this.buildFinalBlueprintState(finalSnapshot);\n\n // Extract composites as quickstash macros (ready for next trial input)\n const quickstashMacros = finalBlueprintState\n .filter(bp => bp.blueprintType === 'composite')\n .map(bp => ({\n id: bp.blueprintId,\n parts: bp.parts!, // Composites always have parts\n ...(bp.label && { label: bp.label })\n }));\n\n const data: ConstructionTrialData = {\n trialType: 'construction',\n trialStartTime: this.trialStartTime,\n trialEndTime,\n totalDuration,\n anchorToStimuliRatio,\n trialParams: this.trialParams,\n endReason: endReason as 'timeout' | 'auto_complete',\n completionTimes: this.completionTimes,\n finalBlueprintState,\n quickstashMacros,\n finalSnapshot\n };\n\n if (this.callbacks.onTrialEnd) {\n this.callbacks.onTrialEnd(data);\n }\n } else {\n const finalMacros = this.createdMacros.length\n ? this.createdMacros\n : this.buildMacrosFromSnapshot(finalSnapshot);\n\n // Convert MacroSnapshot to quickstash input format\n // Ensure IDs start with \"comp:\" for proper border rendering\n const quickstashMacros = finalMacros.map(macro => ({\n id: macro.macroId.startsWith('comp:') ? macro.macroId : `comp:${macro.macroId}`,\n parts: macro.parts\n // Note: label not included in prep macros\n }));\n\n const data: PrepTrialData = {\n trialType: 'prep',\n trialStartTime: this.trialStartTime,\n trialEndTime,\n totalDuration,\n anchorToStimuliRatio,\n trialParams: this.trialParams,\n endReason: 'submit',\n createdMacros: finalMacros,\n quickstashMacros,\n finalSnapshot\n };\n\n if (this.callbacks.onTrialEnd) {\n this.callbacks.onTrialEnd(data);\n }\n }\n }\n\n // ===== Helper Methods =====\n\n /**\n * Determine interaction type from source and outcome\n */\n private determineInteractionType(\n source: 'blueprint' | 'sector',\n outcome: 'placed' | 'deleted'\n ): 'spawn' | 'move' | 'delete' {\n if (outcome === 'deleted') return 'delete';\n if (source === 'blueprint') return 'spawn';\n return 'move';\n }\n\n private toAnchorValue(value: number): number {\n return Math.round(value / this.gridStep);\n }\n\n private toAnchorPoint(point: { x: number; y: number }): { x: number; y: number } {\n return { x: this.toAnchorValue(point.x), y: this.toAnchorValue(point.y) };\n }\n\n private toAnchorVertices(vertices: number[][][]): number[][][] {\n return vertices.map(ring =>\n ring.map(vertex => [\n this.toAnchorValue(vertex[0]!),\n this.toAnchorValue(vertex[1]!)\n ])\n );\n }\n\n private buildMacrosFromSnapshot(snapshot: StateSnapshot): MacroSnapshot[] {\n return snapshot.sectors.map(sec => {\n // STEP 1: Convert bbox positions to shape origin positions in anchor coordinates\n const shapeOriginPositions = sec.pieces.map(piece => {\n const bp = this.controller.getBlueprint(piece.blueprintId);\n const kind = bp && 'kind' in bp ? bp.kind : piece.blueprintId;\n\n // Get the piece's actual position in pixels from controller state\n const actualPiece = this.controller.findPiece(piece.pieceId);\n if (!actualPiece || !bp) {\n return {\n kind,\n position: piece.position // Fallback to bbox position\n };\n }\n\n // Get bounding box of the blueprint using the geometry helper\n const bb = boundsOfBlueprint(bp, this.controller.getPrimitive);\n\n // Convert bbox position to shape origin position\n // In pixels: shapeOriginPos = piece.pos - bb.min\n // Then convert to anchor coordinates\n const shapeOriginPixels = {\n x: actualPiece.pos.x - bb.min.x,\n y: actualPiece.pos.y - bb.min.y\n };\n const shapeOriginAnchor = this.toAnchorPoint(shapeOriginPixels);\n\n return {\n kind,\n position: shapeOriginAnchor // Shape origin in anchor coordinates\n };\n });\n\n // STEP 2: Calculate centroid and convert to relative offsets\n if (shapeOriginPositions.length === 0) {\n return {\n macroId: sec.sectorId,\n parts: [],\n shape: [],\n pieceCount: 0\n };\n }\n\n // Calculate centroid of all pieces (in anchor coordinates)\n let sumX = 0, sumY = 0;\n for (const item of shapeOriginPositions) {\n sumX += item.position.x;\n sumY += item.position.y;\n }\n const centroidX = Math.round(sumX / shapeOriginPositions.length);\n const centroidY = Math.round(sumY / shapeOriginPositions.length);\n\n // Convert absolute positions to relative offsets (like ANCHOR_COMPOSITES format)\n const parts = shapeOriginPositions.map(item => ({\n kind: item.kind,\n anchorOffset: {\n x: Math.round(item.position.x - centroidX),\n y: Math.round(item.position.y - centroidY)\n }\n }));\n\n const shape = sec.pieces.flatMap(piece => piece.vertices || []);\n\n return {\n macroId: sec.sectorId,\n parts,\n shape,\n pieceCount: sec.pieceCount\n };\n });\n }\n\n /**\n * Build state snapshot from current controller state\n * @param justCompletedSectorId - Sector ID that was just completed (but controller state hasn't updated yet)\n */\n private buildStateSnapshot(justCompletedSectorId?: string): StateSnapshot {\n const snapshotId = uuidv4();\n const timestamp = Date.now();\n\n // Build sector snapshots\n const sectors: SectorSnapshot[] = [];\n const completedSectorIds: string[] = [];\n\n for (const sector of this.controller.state.cfg.sectors) {\n const sectorState = this.controller.state.sectors[sector.id];\n // Check if this sector was just completed OR is already completed\n const completed = sector.id === justCompletedSectorId || !!sectorState?.completedAt;\n\n if (completed) {\n completedSectorIds.push(sector.id);\n }\n\n const pieces: PieceSnapshot[] = (sectorState?.pieces || []).map(p => ({\n pieceId: p.id,\n blueprintId: p.blueprintId,\n blueprintType: this.getBlueprintType(p.blueprintId),\n position: this.toAnchorPoint(p.pos),\n vertices: this.getPieceVertices(p.id)\n }));\n\n const snapshot: SectorSnapshot = {\n sectorId: sector.id,\n completed,\n pieceCount: pieces.length,\n pieces,\n center: this.sectorCenters[sector.id] ? this.toAnchorPoint(this.sectorCenters[sector.id]) : undefined\n };\n\n if (sectorState?.completedAt !== undefined) {\n snapshot.completedAt = sectorState.completedAt;\n }\n\n sectors.push(snapshot);\n }\n\n // Build sector-tangram map\n const sectorTangramMap = this.controller.state.cfg.sectors.map(s => ({\n sectorId: s.id,\n tangramId: s.tangramId\n }));\n\n // Build blueprint order\n const blueprintOrder = {\n primitives: this.controller.state.primitives.map(bp => bp.id),\n quickstash: this.controller.state.quickstash.map(bp => bp.id)\n };\n\n return {\n snapshotId,\n timestamp,\n sectors,\n completedSectorIds,\n sectorTangramMap,\n blueprintOrder\n };\n }\n\n /**\n * Get blueprint type from blueprint ID\n */\n private getBlueprintType(blueprintId: string): 'primitive' | 'composite' {\n const bp = this.controller.getBlueprint(blueprintId);\n if (!bp) return 'primitive'; // Fallback\n return 'kind' in bp ? 'primitive' : 'composite';\n }\n\n /**\n * Get piece vertices in world space\n */\n private getPieceVertices(pieceId: string): number[][][] {\n const piece = this.controller.findPiece(pieceId);\n if (!piece) return [];\n\n const bp = this.controller.getBlueprint(piece.blueprintId);\n if (!bp) return [];\n\n const bb = boundsOfBlueprint(bp, (k) => this.controller.getPrimitive(k));\n const polys = piecePolysAt(bp, bb, piece.pos) ?? [];\n const asNumbers = polys.map(ring => ring.map(pt => [pt.x, pt.y] as [number, number]));\n return this.toAnchorVertices(asNumbers);\n }\n\n /**\n * Build final blueprint state (usage counts + definitions)\n */\n private buildFinalBlueprintState(snapshot: StateSnapshot): Array<{\n blueprintId: string;\n blueprintType: 'primitive' | 'composite';\n totalPieces: number;\n bySector: Array<{ sectorId: string; count: number }>;\n parts?: Array<{ kind: string; anchorOffset: { x: number; y: number } }>;\n shape?: Array<Array<{ x: number; y: number }>>;\n label?: string;\n }> {\n const counts = new Map<string, {\n blueprintType: 'primitive' | 'composite';\n totalPieces: number;\n bySector: Map<string, number>;\n }>();\n\n // Accumulate counts\n for (const sector of snapshot.sectors) {\n for (const piece of sector.pieces) {\n if (!counts.has(piece.blueprintId)) {\n counts.set(piece.blueprintId, {\n blueprintType: piece.blueprintType,\n totalPieces: 0,\n bySector: new Map()\n });\n }\n\n const entry = counts.get(piece.blueprintId)!;\n entry.totalPieces++;\n entry.bySector.set(sector.sectorId, (entry.bySector.get(sector.sectorId) || 0) + 1);\n }\n }\n\n // Ensure all primitives are represented, even if count is zero\n for (const primitive of this.controller.state.primitives) {\n if (!counts.has(primitive.id)) {\n counts.set(primitive.id, {\n blueprintType: 'primitive',\n totalPieces: 0,\n bySector: new Map()\n });\n }\n }\n\n // Ensure all composites are represented, even if count is zero\n for (const composite of this.controller.state.quickstash) {\n if (!counts.has(composite.id)) {\n counts.set(composite.id, {\n blueprintType: 'composite',\n totalPieces: 0,\n bySector: new Map()\n });\n }\n }\n\n // Convert to array format with blueprint definitions\n return Array.from(counts.entries()).map(([blueprintId, data]) => {\n const blueprint = this.controller.getBlueprint(blueprintId);\n\n const result: {\n blueprintId: string;\n blueprintType: 'primitive' | 'composite';\n totalPieces: number;\n bySector: Array<{ sectorId: string; count: number }>;\n parts?: Array<{ kind: string; anchorOffset: { x: number; y: number } }>;\n shape?: Array<Array<{ x: number; y: number }>>;\n label?: string;\n } = {\n blueprintId,\n blueprintType: data.blueprintType,\n totalPieces: data.totalPieces,\n bySector: Array.from(data.bySector.entries()).map(([sectorId, count]) => ({\n sectorId,\n count\n }))\n };\n\n // Add blueprint definition for both primitives and composites\n if (blueprint) {\n if (data.blueprintType === 'composite' && 'parts' in blueprint) {\n // Composite blueprint: convert pixel-based parts to anchor-based parts\n result.parts = blueprint.parts.map(part => ({\n kind: part.kind,\n anchorOffset: {\n x: Math.round(part.offset.x / this.gridStep),\n y: Math.round(part.offset.y / this.gridStep)\n }\n }));\n\n // Convert pixel-based shape to anchor-based shape\n if (blueprint.shape) {\n result.shape = blueprint.shape.map(poly =>\n poly.map(vertex => ({\n x: Math.round(vertex.x / this.gridStep),\n y: Math.round(vertex.y / this.gridStep)\n }))\n );\n }\n\n // Add label if available\n if (blueprint.label) {\n result.label = blueprint.label;\n }\n } else if (data.blueprintType === 'primitive' && 'kind' in blueprint) {\n // Primitive blueprint: convert pixel-based shape to anchor-based shape\n if (blueprint.shape) {\n result.shape = blueprint.shape.map(poly =>\n poly.map(vertex => ({\n x: Math.round(vertex.x / this.gridStep),\n y: Math.round(vertex.y / this.gridStep)\n }))\n );\n }\n\n // Primitives don't have labels, but we could add a default one based on kind\n result.label = blueprint.kind;\n }\n }\n\n return result;\n });\n }\n}\n","/**\n * GameBoard - Core reusable tangram game board component\n *\n * This component provides the complete tangram game functionality that can be\n * shared between jsPsych plugins. It handles both construction and preparation\n * game modes with full interaction support.\n *\n * ## Key Features\n * - **Dependency Injection**: All game content provided via props (no hardcoded data)\n * - **Multiple Input Modes**: Supports both click and drag interactions\n * - **Layout Flexibility**: Circle and semicircle layout modes\n * - **Event Tracking**: Comprehensive data collection for research\n * - **State Management**: Uses BaseGameController for robust state handling\n *\n * ## Architecture\n * - Uses modern React patterns with hooks\n * - Integrates with BaseGameController for state management\n * - Renders via Board component with computed layout\n * - Handles completion events and data collection\n *\n * ## Usage in Plugins\n * ```typescript\n * // In jsPsych plugin trial method:\n * const root = createRoot(display_element);\n * root.render(React.createElement(GameBoard, {\n * sectors: convertedSectors,\n * quickstash: convertedMacros,\n * primitives: PRIMITIVE_BLUEPRINTS,\n * layout: \"semicircle\",\n * target: \"silhouette\",\n * input: \"drag\",\n * onComplete: handleTrialComplete\n * }));\n * ```\n *\n * @see {@link BaseGameController} For state management details\n * @see {@link Board} For rendering implementation\n * @since Phase 3.3 - Extracted from monolithic Board component\n * @author Claude Code Assistant\n */\n\nimport React from \"react\";\nimport { BaseGameController } from \"@/core/engine/state/BaseGameController\";\nimport type {\n Sector,\n Blueprint,\n PrimitiveBlueprint,\n LayoutMode,\n PlacementTarget,\n InputMode\n} from \"@/core/domain/types\";\nimport { computeCircleLayout, rectForBand } from \"@/core/domain/layout\";\nimport { solveLogicalBox } from \"@/core/domain/solve\";\nimport type { Poly } from \"@/core/domain/types\";\nimport { CONFIG } from \"@/core/config/config\";\nimport BoardView, { type AnchorDots as DotsType } from \"./BoardView\";\nimport {\n inferUnitFromPolys,\n placeSilhouetteGridAlignedAsPolys } from \"@/core/engine/geometry\";\nimport { anchorsSilhouetteComplete, anchorsWorkspaceComplete } from \"@/core/engine/validation/complete\";\nimport { scalePolys } from \"@/core/components/board/utils\";\nimport { usePieceState } from \"@/core/components/board/usePieceState\";\nimport { useAnchorGrid } from \"@/core/components/board/useAnchorGrid\";\nimport { useDragController } from \"@/core/components/board/useDragController\";\nimport { useClickController } from \"@/core/components/board/useClickController\";\nimport { InteractionTracker } from \"@/core/io/InteractionTracker\";\n\n/**\n * Configuration interface for GameBoard component\n *\n * This interface defines all the required game content and behavior settings\n * that must be provided to the GameBoard component. All properties use\n * dependency injection - no defaults are provided.\n */\nexport interface GameBoardConfig {\n /**\n * Array of sector definitions containing target silhouettes to construct\n * Each sector represents one puzzle to solve\n */\n sectors: Sector[];\n\n /**\n * Array of pre-made composite piece blueprints (macros)\n * Usually created in prep trials and passed to construction trials\n */\n quickstash: Blueprint[];\n\n /**\n * Array of primitive tangram piece definitions\n * These are the basic 7 tangram shapes that never change\n */\n primitives: PrimitiveBlueprint[];\n\n /**\n * Layout mode for the game board\n * - \"circle\": Full circular layout with pieces arranged in complete circle\n * - \"semicircle\": Half-circle layout with pieces in arc above workspace\n */\n layout: LayoutMode;\n\n /**\n * Target placement mode for piece validation\n * - \"workspace\": Pieces can be placed freely in workspace area\n * - \"silhouette\": Pieces must be placed within target silhouette bounds\n */\n target: PlacementTarget;\n\n /**\n * Input interaction mode\n * - \"click\": Click to select pieces, click to place (better for touch)\n * - \"drag\": Drag pieces directly with mouse/touch\n */\n input: InputMode;\n\n /**\n * Time limit for the trial in milliseconds\n * Set to 0 for no time limit\n */\n timeLimitMs: number;\n\n /**\n * Maximum number of quickstash/macro slots to display\n * Controls size of the macro selection ring\n */\n maxQuickstashSlots: number;\n\n /**\n * Maximum number of primitive pieces allowed in a composite\n * Used for validation when creating macros (prep mode only)\n */\n maxCompositeSize?: number;\n\n /**\n * Game mode to determine behavior differences\n * - \"construction\": Standard puzzle-solving mode with toggle\n * - \"prep\": Macro creation mode with primitives-only center\n */\n mode?: \"construction\" | \"prep\";\n\n /**\n * Minimum pieces required per macro (prep mode only)\n * Used for submit button validation\n */\n minPiecesPerMacro?: number;\n\n /**\n * Whether all slots must be filled to complete trial (prep mode only)\n * Used for submit button validation\n */\n requireAllSlots?: boolean;\n\n /**\n * Whether to show tangram target shapes decomposed into individual primitives with borders\n * Independent from showBorders/hideTouchingBorders (which control spawned pieces)\n */\n showTangramDecomposition?: boolean;\n\n /**\n * HTML content to display above the gameboard as instructions\n * Allows rich formatting via HTML\n */\n instructions?: string;\n\n /**\n * Cleaned jsPsych plugin parameters (excluding callbacks)\n * Saved to trial data for analysis\n */\n trialParams?: any;\n\n /** Optional CSS width for the game board SVG */\n width?: number;\n\n /** Optional CSS height for the game board SVG */\n height?: number;\n}\n\n/**\n * Props interface for GameBoard component, extending configuration with event callbacks\n *\n * This interface includes all configuration options plus optional event handlers\n * that plugins can use to respond to game events and collect data.\n */\nexport interface GameBoardProps extends GameBoardConfig {\n /**\n * Called when an individual sector is completed\n * Useful for tracking progress through multi-sector trials\n */\n onSectorComplete?: (sectorId: string, snapshot: any) => void;\n\n /**\n * Called when a piece is successfully placed in a sector\n * Useful for real-time interaction tracking\n */\n onPiecePlace?: (pieceId: string, sectorId: string) => void;\n\n /**\n * Called when a piece is removed from a sector\n * Useful for tracking piece manipulation patterns\n */\n onPieceRemove?: (pieceId: string) => void;\n\n /**\n * Called immediately after each complete interaction (piece pickup + placedown)\n * Use for incremental data saving (e.g., socket.emit())\n */\n onInteraction?: (event: any) => void;\n\n /**\n * Called once when trial ends\n * Contains complete interaction history + final state\n * This is the primary mechanism for trial completion - plugins should handle\n * React cleanup and jsPsych.finishTrial() in their wrapper for this callback\n */\n onTrialEnd?: (data: any) => void;\n\n /**\n * Called when the game controller is ready\n * Useful for spawning initial pieces or setting up state\n */\n onControllerReady?: (controller: BaseGameController, layout?: any, force?: () => void) => void;\n\n /**\n * Whether to use distinct colors for each primitive shape type in blueprints\n * When true, each primitive type (square, triangle, etc.) gets its own color in dock area\n */\n usePrimitiveColorsBlueprints?: boolean;\n\n /**\n * Whether to use distinct colors for each primitive shape type in target tangrams\n * When true, each primitive type gets its own color in target silhouettes\n */\n usePrimitiveColorsTargets?: boolean;\n\n /**\n * Array of 5 integers mapping primitives to colors from CONFIG.color.primitiveColors\n * Maps [square, smalltriangle, parallelogram, medtriangle, largetriangle] to color indices\n */\n primitiveColorIndices?: number[];\n}\n\n/**\n * Core GameBoard component that encapsulates all tangram game functionality\n *\n * This is the main reusable component that provides complete tangram game\n * functionality for jsPsych plugins. It handles all aspects of the game\n * including piece interaction, collision detection, completion validation,\n * and data collection.\n *\n * ## Key Responsibilities\n * - Creates and manages BaseGameController for state management\n * - Computes layout geometry for board rendering\n * - Handles event callbacks for plugin integration\n * - Manages CSS sizing for responsive display\n *\n * ## State Management\n * Uses BaseGameController internally which provides:\n * - Piece placement and validation\n * - Sector completion tracking\n * - Event logging for data collection\n * - Collision detection and snapping\n *\n * @param props - Configuration and event callbacks for the game\n * @returns React component rendering the complete tangram game interface\n */\nexport default function GameBoard(props: GameBoardProps) {\n const {\n sectors,\n quickstash,\n primitives,\n layout: layoutMode,\n target,\n input,\n timeLimitMs,\n maxQuickstashSlots,\n maxCompositeSize,\n mode,\n showTangramDecomposition,\n instructions,\n trialParams,\n width: _width,\n height: _height,\n onSectorComplete,\n onPiecePlace,\n onPieceRemove,\n onInteraction,\n onTrialEnd,\n onControllerReady,\n usePrimitiveColorsBlueprints,\n usePrimitiveColorsTargets,\n primitiveColorIndices,\n } = props;\n\n // Timer state for countdown\n const [timeRemaining, setTimeRemaining] = React.useState(timeLimitMs > 0 ? Math.floor(timeLimitMs / 1000) : 0);\n\n // Initialize game controller with injected data\n const controller = React.useMemo(() => {\n const gameConfig = {\n n: sectors.length,\n layout: layoutMode,\n target,\n input,\n timeLimitMs,\n maxQuickstashSlots,\n ...(maxCompositeSize !== undefined && { maxCompositeSize }),\n mode: mode || \"construction\", // Default to construction mode for backwards compatibility\n ...(props.minPiecesPerMacro !== undefined && { minPiecesPerMacro: props.minPiecesPerMacro }),\n ...(props.requireAllSlots !== undefined && { requireAllSlots: props.requireAllSlots })\n };\n\n return new BaseGameController(\n sectors,\n quickstash,\n primitives,\n gameConfig\n );\n }, [sectors, quickstash, primitives, layoutMode, target, input, timeLimitMs, maxQuickstashSlots, maxCompositeSize, mode, props.minPiecesPerMacro, props.requireAllSlots]);\n\n // Initialize interaction tracker for data collection (if callbacks provided)\n const tracker = React.useMemo(() => {\n if (!onInteraction && !onTrialEnd) return null;\n\n const callbacks: { onInteraction?: (event: any) => void; onTrialEnd?: (data: any) => void } = {};\n if (onInteraction) callbacks.onInteraction = onInteraction;\n if (onTrialEnd) callbacks.onTrialEnd = onTrialEnd;\n\n return new InteractionTracker(controller, callbacks, trialParams);\n }, [controller, onInteraction, onTrialEnd, trialParams]);\n\n // Call onControllerReady when controller is ready\n React.useEffect(() => {\n if (onControllerReady) {\n onControllerReady(controller);\n }\n }, [controller, onControllerReady]);\n\n // Cleanup tracker on unmount\n React.useEffect(() => {\n return () => {\n if (tracker) {\n tracker.dispose();\n }\n };\n }, [tracker]);\n\n // Compute layout geometry\n const { layout, viewBox } = React.useMemo(() => {\n const nSectors = sectors.length;\n const sectorIds = sectors.map(s => s.id);\n const masksPerSector: Poly[][] = sectors.map(s => s.silhouette.mask ?? []);\n\n const logicalBox = solveLogicalBox({\n n: nSectors,\n layoutMode,\n target,\n qsMaxSlots: maxQuickstashSlots,\n primitivesSlots: primitives.length,\n layoutPadPx: CONFIG.layout.paddingPx,\n masks: masksPerSector,\n });\n\n const layout = computeCircleLayout(\n { w: logicalBox.LOGICAL_W, h: logicalBox.LOGICAL_H },\n nSectors,\n sectorIds,\n layoutMode,\n target,\n {\n qsMaxSlots: maxQuickstashSlots,\n primitivesSlots: primitives.length,\n masks: masksPerSector,\n }\n );\n\n return {\n layout,\n viewBox: { w: logicalBox.LOGICAL_W, h: logicalBox.LOGICAL_H }\n };\n }, [sectors, layoutMode, target, maxQuickstashSlots, primitives.length]);\n\n // Update tracker with sector centers whenever layout changes\n React.useEffect(() => {\n if (tracker && layout) {\n const centers: { [sectorId: string]: { x: number; y: number } } = {};\n layout.sectors.forEach(s => {\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n centers[s.id] = { x: rect.cx, y: rect.cy };\n });\n tracker.setSectorCenters(centers);\n }\n }, [tracker, layout]);\n\n // Force re-render utility\n const [, force] = React.useReducer((x) => x + 1, 0);\n\n // Call onControllerReady when controller and layout are ready\n React.useEffect(() => {\n if (onControllerReady) {\n onControllerReady(controller, layout, force);\n }\n }, [controller, layout, onControllerReady, force]);\n\n // Game completion tracking\n const [gameCompleted, setGameCompleted] = React.useState(false);\n\n // Watch for game completion\n React.useEffect(() => {\n const checkGameCompletion = () => {\n const allSectorsComplete = sectors.every(s =>\n controller.isSectorCompleted(s.id)\n );\n\n if (allSectorsComplete && !gameCompleted) {\n setGameCompleted(true);\n\n // Finalize trial data tracking (which calls onTrialEnd)\n // Defer to avoid unmounting React while still in commit phase\n if (tracker) {\n setTimeout(() => {\n tracker.finalizeTrial('auto_complete');\n }, 0);\n }\n }\n };\n\n // Check completion whenever controller state updates\n checkGameCompletion();\n }, [controller.updateCount, sectors, gameCompleted, controller, tracker]);\n\n // Sector completion callback\n const handleSectorComplete = React.useCallback((sectorId: string) => {\n if (onSectorComplete) {\n onSectorComplete(sectorId, controller.snapshot());\n }\n }, [onSectorComplete, controller]);\n\n // Event callbacks for plugin integration\n const eventCallbacks = React.useMemo(() => ({\n onSectorComplete: handleSectorComplete,\n onPiecePlace: onPiecePlace || (() => {}),\n onPieceRemove: onPieceRemove || (() => {})\n }), [handleSectorComplete, onPiecePlace, onPieceRemove]);\n\n // Calculate sizing based on layout mode\n const getGameboardStyle = () => {\n const baseStyle = {\n margin: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n position: 'relative' as const,\n };\n\n if (layoutMode === 'circle') {\n // Circle mode: square aspect ratio (height == width)\n const size = Math.min(window.innerWidth * CONFIG.layout.viewportScale, window.innerHeight * CONFIG.layout.viewportScale);\n return {\n ...baseStyle,\n width: `${size}px`,\n height: `${size}px`,\n };\n } else {\n // Semicircle mode: width is 2x height\n const maxWidth = Math.min(window.innerWidth * CONFIG.layout.viewportScale, window.innerHeight * CONFIG.layout.viewportScale * 2);\n const maxHeight = Math.min(window.innerWidth * CONFIG.layout.viewportScale / 2, window.innerHeight * CONFIG.layout.viewportScale);\n return {\n ...baseStyle,\n width: `${maxWidth}px`,\n height: `${maxHeight}px`,\n };\n }\n };\n\n // Calculate SVG dimensions to pass to Board component\n const getSvgDimensions = () => {\n if (layoutMode === 'circle') {\n // Circle mode: square aspect ratio (height == width)\n const size = Math.min(window.innerWidth * 0.96, window.innerHeight * 0.96);\n return { width: size, height: size };\n } else {\n // Semicircle mode: width is 2x height\n const maxWidth = Math.min(window.innerWidth * 0.96, window.innerHeight * 0.96 * 2);\n const maxHeight = Math.min(window.innerWidth * 0.96 / 2, window.innerHeight * 0.96);\n return { width: maxWidth, height: maxHeight };\n }\n };\n\n const svgDimensions = getSvgDimensions();\n\n React.useEffect(() => {\n if (controller.state.cfg.mode !== \"construction\") return;\n if (!timeLimitMs || timeLimitMs <= 0) return;\n if (gameCompleted) return;\n\n const timeoutId = window.setTimeout(() => {\n if (gameCompleted) return;\n\n if (!controller.state.endedAt) {\n controller.state.endedAt = performance.now();\n force();\n }\n\n tracker?.finalizeTrial('timeout');\n setGameCompleted(true);\n }, timeLimitMs);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [controller, timeLimitMs, gameCompleted, tracker, force]);\n\n const isSectorLocked = (id: string) => controller.isSectorCompleted(id);\n\n // Extract piece management to custom hook\n const { pieces, pieceById, getSectorPiecePolysCached } = usePieceState(controller);\n\n const clickMode = controller.state.cfg.input === \"click\";\n\n // Center badge geometry (visual + click target are identical)\n const badgeR = Math.max(CONFIG.size.centerBadge.minPx, layout.innerR * CONFIG.size.centerBadge.fractionOfOuterR);\n const badgeCenter = (controller.state.cfg.layout === \"semicircle\")\n ? { x: layout.cx, y: layout.cy - badgeR - CONFIG.size.centerBadge.marginPx }\n : { x: layout.cx, y: layout.cy };\n const isInsideBadge = (px: number, py: number) =>\n Math.hypot(px - badgeCenter.x, py - badgeCenter.y) <= badgeR;\n\n // All sector masks (raw)\n const allMasks: Poly[][] = React.useMemo(() => {\n return controller.state.cfg.sectors.map(sec => (sec.silhouette.mask ?? []));\n }, [controller.state.cfg.sectors]);\n\n // Canonical lattice scale: 1 raw UNIT → CONFIG.layout.grid.unitPx (so a unit edge = 2 grid nodes)\n // Keep a single scale so lattice density stays invariant across devices/zoom levels.\n const scaleS = React.useMemo(() => {\n const u = inferUnitFromPolys(allMasks.flat());\n return u ? (CONFIG.layout.grid.unitPx / u) : 1;\n }, [allMasks]);\n\n // Extract anchor grid logic to custom hook\n const { anchorDots } = useAnchorGrid(controller, layout, scaleS);\n\n // Placed silhouettes per sector (grid-aligned polys used for inclusion tests)\n const placedSilBySector = React.useMemo(() => {\n const m = new Map<string, Poly[]>();\n for (const s of layout.sectors) {\n const mask = controller.state.cfg.sectors.find(ss => ss.id === s.id)?.silhouette.mask ?? [];\n if (!mask?.length) continue;\n const rect = rectForBand(layout, s, \"silhouette\", 1.0);\n const placed = placeSilhouetteGridAlignedAsPolys(mask, scaleS, { cx: rect.cx, cy: rect.cy });\n m.set(s.id, placed);\n }\n return m;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [layout, scaleS, controller.state.cfg.sectors]);\n\n const maybeCompleteSector = (secId: string): boolean => {\n if (!secId) return false;\n if (isSectorLocked(secId)) return false;\n\n if (controller.state.cfg.target === \"silhouette\") {\n const sil = placedSilBySector.get(secId) ?? [];\n if (!sil.length) return false;\n const piecePolys = getSectorPiecePolysCached(secId);\n if (anchorsSilhouetteComplete(sil, piecePolys)) {\n controller.markSectorCompleted(secId);\n return true;\n }\n } else {\n const raw = controller.state.cfg.sectors.find(ss => ss.id === secId)?.silhouette.mask ?? [];\n if (!raw.length) return false;\n const scaledSil = scalePolys(raw, scaleS);\n const piecePolys = getSectorPiecePolysCached(secId);\n if (anchorsWorkspaceComplete(scaledSil, piecePolys)) {\n controller.markSectorCompleted(secId);\n return true;\n }\n }\n return false;\n };\n\n // ---- drag (RAF) - Extracted to useDragController hook ---\n const dragController = useDragController(\n controller,\n layout,\n pieces,\n pieceById,\n anchorDots,\n placedSilBySector,\n isSectorLocked,\n maybeCompleteSector,\n force,\n undefined, // clickController - will be set later\n tracker // Pass tracker for data collection\n );\n\n const {\n draggingId,\n dragInvalid,\n svgRef,\n onPiecePointerDown,\n onBlueprintPointerDown,\n onPointerMove,\n onPointerUp,\n setPieceRef,\n setDraggingId,\n lockedPieceId,\n dragRef // TODO: Remove once click mode is extracted\n } = dragController;\n\n // ---- CLICK controller - Extracted click mode logic ---\n const svgPoint = (clientX: number, clientY: number) => {\n const svg = svgRef.current!;\n const pt = svg.createSVGPoint();\n pt.x = clientX; pt.y = clientY;\n const ctm = svg.getScreenCTM();\n if (!ctm) return { x: 0, y: 0 };\n const sp = pt.matrixTransform(ctm.inverse());\n return { x: sp.x, y: sp.y };\n };\n\n const clickController = useClickController(\n controller,\n layout,\n pieces,\n clickMode,\n draggingId,\n setDraggingId,\n dragRef,\n isInsideBadge,\n isSectorLocked,\n maybeCompleteSector,\n svgPoint,\n force,\n tracker // Pass tracker for data collection\n );\n\n const {\n selectedPieceId,\n onRootPointerDown\n } = clickController;\n\n const onCenterBadgePointerDown = (e: React.PointerEvent) => {\n if (draggingId) return;\n const { x, y } = svgPoint(e.clientX, e.clientY);\n\n if (controller.state.cfg.mode === \"prep\") {\n if (!controller.isSubmitEnabled() || gameCompleted) {\n e.stopPropagation();\n return;\n }\n\n setGameCompleted(true);\n if (tracker) {\n tracker.finalizeTrial('submit');\n }\n e.stopPropagation();\n return;\n }\n\n // Construction mode: toggle blueprint view\n if (tracker?.recordClickEvent) {\n const from = controller.state.blueprintView;\n const to = from === \"primitives\" ? \"quickstash\" : \"primitives\";\n tracker.recordClickEvent({ x, y }, 'blueprint_view_switch', {\n blueprintViewSwitch: { from, to }\n });\n }\n controller.switchBlueprintView();\n force();\n e.stopPropagation();\n };\n\n // Timer effect\n React.useEffect(() => {\n if (timeLimitMs === 0) return;\n\n const interval = setInterval(() => {\n setTimeRemaining(prev => {\n if (prev <= 1) {\n clearInterval(interval);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(interval);\n }, [timeLimitMs]);\n\n // Format time helper\n const formatTime = (seconds: number): string => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n };\n\n // Container style\n const containerStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n // minHeight: '100vh'\n };\n\n // Header style (constrained to gameboard width)\n const headerStyle: React.CSSProperties = {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'center',\n alignItems: 'center',\n padding: '20px',\n background: CONFIG.color.background,\n flex: '0 0 auto'\n };\n\n // Header content wrapper (matches gameboard width)\n const headerContentStyle: React.CSSProperties = {\n position: 'relative',\n width: `${svgDimensions.width}px`,\n maxWidth: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center'\n };\n\n // Instructions style (always centered)\n const instructionsStyle: React.CSSProperties = {\n fontSize: '20px',\n lineHeight: 1.5,\n textAlign: 'center'\n };\n\n // Timer style - positioned absolutely to align right edge with semicircle's right edge\n // Independent of instructions content\n const scaleX = svgDimensions.width / viewBox.w;\n const rightEdgeOfSemicircleLogical = viewBox.w / 2 + layout.outerR;\n const distanceFromRightEdgeLogical = viewBox.w - rightEdgeOfSemicircleLogical;\n const distanceFromRightEdgePx = distanceFromRightEdgeLogical * scaleX;\n\n // Shift left by 5 monospaced characters (monospace is typically 0.6em wide per char)\n const charWidth = 24 * 0.6; // fontSize * typical monospace char width ratio\n const offsetLeft = charWidth * 5;\n\n const timerStyle: React.CSSProperties = {\n position: 'absolute',\n right: `${distanceFromRightEdgePx + offsetLeft}px`,\n fontSize: '24px',\n fontWeight: 'bold',\n fontFamily: 'monospace',\n color: '#333',\n whiteSpace: 'nowrap',\n textAlign: 'right'\n };\n\n // Gameboard wrapper style (to center the gameboard in remaining space)\n const gameboardWrapperStyle: React.CSSProperties = {\n flex: '1 1 auto',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden'\n };\n\n return (\n <div className=\"tangram-trial-container\" style={containerStyle}>\n {(instructions || timeLimitMs > 0) && (\n <div className=\"tangram-header\" style={headerStyle}>\n <div className=\"tangram-header-content\" style={headerContentStyle}>\n {instructions && (\n <div\n className=\"tangram-instructions\"\n style={instructionsStyle}\n dangerouslySetInnerHTML={{ __html: instructions }}\n />\n )}\n {timeLimitMs > 0 && (\n <div className=\"tangram-timer\" style={timerStyle}>\n {formatTime(timeRemaining)}\n </div>\n )}\n </div>\n </div>\n )}\n <div className=\"tangram-gameboard-wrapper\" style={gameboardWrapperStyle}>\n <div className=\"tangram-gameboard\" style={getGameboardStyle()}>\n <BoardView\n controller={controller}\n layout={layout}\n viewBox={viewBox}\n width={svgDimensions.width}\n height={svgDimensions.height}\n badgeR={badgeR}\n badgeCenter={badgeCenter}\n placedSilBySector={placedSilBySector}\n anchorDots={anchorDots as DotsType[]}\n pieces={pieces}\n clickMode={clickMode}\n draggingId={draggingId}\n selectedPieceId={selectedPieceId}\n dragInvalid={dragInvalid}\n lockedPieceId={lockedPieceId}\n svgRef={svgRef}\n setPieceRef={setPieceRef}\n onPiecePointerDown={onPiecePointerDown}\n onBlueprintPointerDown={onBlueprintPointerDown}\n onRootPointerDown={onRootPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onCenterBadgePointerDown={onCenterBadgePointerDown}\n showTangramDecomposition={showTangramDecomposition ?? false}\n scaleS={scaleS}\n usePrimitiveColorsBlueprints={usePrimitiveColorsBlueprints ?? false}\n usePrimitiveColorsTargets={usePrimitiveColorsTargets ?? false}\n primitiveColorIndices={primitiveColorIndices ?? [0, 1, 2, 3, 4]}\n {...eventCallbacks}\n />\n </div>\n </div>\n </div>\n );\n}\n","import type { PrimitiveBlueprint, Poly, Vec, TanKind } from \"@/core/domain/types\";\n\n// ===== numeric units (match Python SideLength scaling) ======================\nconst U = 40; // 1 UNIT in pixels\nconst HALFUNIT = U / 2;\nconst DIAGONAL = U * Math.SQRT2;\nconst HALFDIAGONAL = DIAGONAL / 2;\n\n// ===== small vec helpers ====================================================\nconst P = (x: number, y: number): Vec => ({ x, y });\n\n/** rotate array left by k (Python deque.rotate(-k)) */\nfunction rotLeft<T>(arr: T[], k: number): T[] {\n const n = arr.length; if (n === 0) return [];\n const s = ((k % n) + n) % n;\n return arr.slice(s).concat(arr.slice(0, s));\n}\n\n/**\n * Mirrors your Python `next_point`:\n * interior angle is CLOCKWISE at the vertex; we walk the boundary clockwise.\n */\nfunction nextPoint(\n x0: number, y0: number, // previous vertex\n x1: number, y1: number, // current vertex\n interiorDeg: number,\n dist: number\n): Vec {\n const phi = Math.atan2(y0 - y1, x0 - x1); // incoming edge (x0->x1)\n const theta = phi - (interiorDeg * Math.PI) / 180; // rotate clockwise by interior angle\n return P(x1 + dist * Math.cos(theta), y1 + dist * Math.sin(theta));\n}\n\n/**\n * Build polygon from side lengths & clockwise interior angles.\n * If `firstEdgeUnits` is provided ([(x0,y0),(x1,y1)] in **unit** coords with +y up),\n * we use that exact first edge. Otherwise we default to +X of length sideLens[0].\n * Returns vertices without repeating the start (close is implied).\n */\nfunction constructFromSpec(\n sideLens: number[],\n angles: number[],\n firstEdgeUnits?: [Vec, Vec]\n): Poly {\n let pts: Vec[];\n if (firstEdgeUnits) {\n // map unit coords (up +y) -> canvas coords (down +y): invert y and scale by U\n const a = firstEdgeUnits[0]; // typically (0,0)\n const b = firstEdgeUnits[1];\n const A = P(-a.x * U, a.y * U);\n const B = P(-b.x * U, b.y * U);\n pts = [A, B];\n } else {\n // default: first edge along +X\n const firstSideLen = sideLens[0];\n if (firstSideLen === undefined) throw new Error(\"No side lengths provided\");\n pts = [P(0, 0), P(firstSideLen, 0)];\n }\n\n // Python logic: rotate side lengths by -1 (since first edge already placed), angles unchanged\n const sidesRot = rotLeft(sideLens, 1);\n const angRot = angles;\n\n // add all but the final closing edge\n for (let i = 1; i < sideLens.length - 1; i++) {\n const last = pts[i - 1];\n const curr = pts[i];\n if (!last || !curr) continue;\n const sLen = sidesRot[i - 1];\n const aDeg = angRot[i - 1];\n if (sLen === undefined || aDeg === undefined) continue;\n pts.push(nextPoint(last.x, last.y, curr.x, curr.y, aDeg, sLen));\n }\n return pts;\n}\n\n// ===== default first edges in UNIT coords ( +y is UP here ) =================\n// Copied from your `default_pilot_rotations`. We invert y above for canvas.\nconst FIRST_EDGES_UNITS: Record<TanKind, [Vec, Vec]> = {\n \"smalltriangle\": [P(0, 0), P(0.5, 0.5)],\n \"parallelogram\": [P(0, 0), P(0.5, 0)],\n \"largetriangle\": [P(0, 0), P(0.5, -0.5)],\n \"medtriangle\": [P(0, 0), P(0.5, 0)],\n \"square\": [P(0, 0), P(0.5, 0)],\n};\n\n// ===== canonical half-edge primitives ===================\n// Unchanging primitive tangram pieces - these are constants, not configurable\nconst PRIMITIVE_BLUEPRINTS_CACHE = (() => {\n // Sequences copied verbatim from your Python tanprimitives_halfedges()\n const specs: Array<{\n id: string;\n kind: TanKind;\n sideLens: number[];\n angles: number[];\n color: string;\n }> = [\n {\n id: \"prim:square\",\n kind: \"square\",\n sideLens: [HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT],\n angles: [180, 90, 180, 90, 180, 90, 180, 90],\n color: \"#f43f5e\",\n },\n {\n id: \"prim:smalltriangle\",\n kind: \"smalltriangle\",\n sideLens: [HALFDIAGONAL, HALFDIAGONAL, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT],\n angles: [180, 45, 180, 90, 180, 45],\n color: \"#f59e0b\",\n },\n {\n id: \"prim:parallelogram\",\n kind: \"parallelogram\",\n sideLens: [HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL, HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL],\n angles: [180, 135, 180, 45, 180, 135, 180, 45],\n color: \"#10b981\",\n },\n {\n id: \"prim:medtriangle\",\n kind: \"medtriangle\",\n sideLens: [HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL],\n angles: [180, 180, 180, 45, 180, 90, 180, 45],\n color: \"#3b82f6\",\n },\n {\n id: \"prim:largetriangle\",\n kind: \"largetriangle\",\n sideLens: [\n HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL, HALFDIAGONAL,\n HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT, HALFUNIT\n ],\n angles: [\n 180, 180, 180, 45,\n 180, 180, 180, 90, 180, 180, 180, 45\n ],\n color: \"#8b5cf6\",\n },\n ];\n\n return specs.map(({ id, kind, sideLens, angles, color }) => {\n const firstEdge = FIRST_EDGES_UNITS[kind]; // always present for these 5\n const verts = constructFromSpec(sideLens, angles, firstEdge);\n return {\n id,\n kind,\n shape: [verts],\n colorHint: color,\n } as PrimitiveBlueprint;\n });\n})();\n\nexport function primitiveBlueprintsHalfEdge(): PrimitiveBlueprint[] {\n return PRIMITIVE_BLUEPRINTS_CACHE;\n}\n\n// Direct access to primitives constant (for dependency injection)\nexport const PRIMITIVE_BLUEPRINTS: PrimitiveBlueprint[] = PRIMITIVE_BLUEPRINTS_CACHE;\n","// src/core/io/quickstash.ts\nimport { CONFIG } from \"@/core/config/config\";\nimport type { Blueprint, CompositeBlueprint, PrimitiveBlueprint, TanKind, Vec } from \"@/core/domain/types\";\nimport { primitiveBlueprintsHalfEdge } from \"@/core/domain/primitives\";\n\n/**\n * Convert anchor-based composite definition to pixel-based composite with custom grid step\n * @param anchorComposite - Composite defined with anchor coordinates\n * @param primsByKind - Map of primitive blueprints by kind\n * @param gridStepPx - Grid step in pixels (defaults to current CONFIG)\n * @returns CompositeBlueprint with pixel coordinates\n */\nexport function convertAnchorCompositeToPixels(\n anchorComposite: { id: string; parts: Array<{ kind: TanKind; anchorOffset: { x: number; y: number } }>; label?: string },\n primsByKind: Map<TanKind, PrimitiveBlueprint>,\n gridStepPx: number = CONFIG.layout.grid.stepPx\n): CompositeBlueprint {\n const { id, parts, label } = anchorComposite;\n \n // Convert anchor offsets to pixel offsets using custom grid step\n const pixelParts: Array<{ kind: TanKind; offset: Vec }> = parts.map(p => ({\n kind: p.kind,\n offset: { \n x: p.anchorOffset.x * gridStepPx, \n y: p.anchorOffset.y * gridStepPx \n }\n }));\n \n // Compute shape using custom grid step\n const shape: Vec[][] = [];\n for (const p of parts) {\n const prim = primsByKind.get(p.kind);\n if (!prim) continue;\n \n const pixelOffset = { \n x: p.anchorOffset.x * gridStepPx, \n y: p.anchorOffset.y * gridStepPx \n };\n for (const poly of prim.shape) {\n shape.push(poly.map(v => ({ x: v.x + pixelOffset.x, y: v.y + pixelOffset.y })));\n }\n }\n \n return { id, parts: pixelParts, shape, label: label ?? `Composite-${id}` };\n}\n\n/**\n * Anchor-based composite definitions (configuration-independent)\n * These are converted to pixel coordinates at render time\n */\nconst ANCHOR_COMPOSITES = [\n {\n id: \"comp:parallelogram+parallelogram\",\n parts: [\n { kind: \"parallelogram\" as TanKind, anchorOffset: { x: 0, y: 0 } },\n { kind: \"parallelogram\" as TanKind, anchorOffset: { x: 2, y: 2 } }, // Diagonal contact\n ],\n label: \"Parallelogram+Parallelogram\"\n },\n {\n id: \"comp:smalltriangle+medtriangle\",\n parts: [\n { kind: \"smalltriangle\" as TanKind, anchorOffset: { x: -2, y: -2 } },\n { kind: \"medtriangle\" as TanKind, anchorOffset: { x: 0, y: 0 } },\n ],\n label: \"SmallTriangle+MedTriangle\"\n },\n {\n id: \"comp:square\",\n parts: [\n { kind: \"square\" as TanKind, anchorOffset: { x: 0, y: 0 } },\n ],\n label: \"Square\"\n }\n];\n\n/**\n * Create quickstash with custom grid step (useful for testing different configurations)\n * @param gridStepPx - Grid step in pixels\n * @returns Array of blueprints with pixel coordinates based on custom grid step\n */\nexport function createQuickstashWithGridStep(gridStepPx: number): Blueprint[] {\n const prims = primitiveBlueprintsHalfEdge();\n const byKind = new Map<TanKind, PrimitiveBlueprint>();\n prims.forEach(p => byKind.set(p.kind, p));\n\n // Convert anchor-based definitions to pixel-based composites with custom grid step\n const list: Blueprint[] = ANCHOR_COMPOSITES.map(anchorComposite => \n convertAnchorCompositeToPixels(anchorComposite, byKind, gridStepPx)\n );\n\n const maxSlots = CONFIG.layout.defaults.maxQuickstashSlots;\n if (list.length > maxSlots) {\n throw new Error(\n `Quickstash has ${list.length} items but max is ${maxSlots}. Trim defaultQuickstash() or raise CONFIG.layout.defaults.maxQuickstashSlots.`\n );\n }\n return list;\n}\n\n/**\n * Get anchor-based composite definitions (for debugging/testing)\n * @returns Array of anchor-based composite definitions\n */\nexport function getAnchorComposites() {\n return ANCHOR_COMPOSITES;\n}\n\n/**\n * Default Quickstash using anchor coordinates\n * Conversion to pixels happens at render time using current CONFIG\n */\nexport function defaultQuickstash(): Blueprint[] {\n return createQuickstashWithGridStep(CONFIG.layout.grid.stepPx);\n}","/**\n * ConstructionApp.tsx - React wrapper for tangram construction trials\n * \n * This component handles the React rendering logic for construction trials,\n * separating it from the pure jsPsych plugin class.\n */\n\nimport React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport { JsPsych } from \"jspsych\";\nimport { GameBoard } from \"../../core/components\";\nimport { PRIMITIVE_BLUEPRINTS } from \"../../core/domain/primitives\";\nimport { convertAnchorCompositeToPixels } from \"../../core/io/quickstash\";\nimport type { \n Sector, \n Blueprint, \n PlacementTarget, \n InputMode, \n LayoutMode,\n TanKind,\n PrimitiveBlueprint\n} from \"../../core/domain/types\";\nimport { CONFIG } from \"../../core/config/config\";\n\nexport interface StartConstructionTrialParams {\n tangrams: any[];\n quickstash_macros?: Blueprint[] | AnchorComposite[];\n primitiveOrder: string[];\n target?: PlacementTarget;\n input?: InputMode;\n layout?: LayoutMode;\n time_limit_ms: number;\n show_tangram_decomposition?: boolean;\n instructions?: string;\n onInteraction?: (event: any) => void;\n onTrialEnd?: (data: any) => void;\n usePrimitiveColorsBlueprints?: boolean;\n usePrimitiveColorsTargets?: boolean;\n primitiveColorIndices?: number[];\n}\n\n// Type for anchor-based composite definitions\ntype AnchorComposite = {\n id: string;\n parts: Array<{ kind: TanKind; anchorOffset: { x: number; y: number } }>;\n label?: string;\n};\n\n/**\n * Start a construction trial by rendering the GameBoard component\n */\nexport function startConstructionTrial(\n display_element: HTMLElement,\n params: StartConstructionTrialParams,\n _jsPsych: JsPsych\n) {\n // Canonical piece names we accept\n const CANON = new Set([\n \"square\",\n \"smalltriangle\",\n \"parallelogram\",\n \"medtriangle\",\n \"largetriangle\",\n ]);\n\n // make copy of PRIMITIVE_BLUEPRINTS sorted by primitiveOrder\n const PRIMITIVE_BLUEPRINTS_ORDERED = [...PRIMITIVE_BLUEPRINTS].sort((a, b) => params.primitiveOrder.indexOf(a.kind) - params.primitiveOrder.indexOf(b.kind));\n\n // Convert JSON plugin parameters to internal Sector[] format\n const sectors: Sector[] = params.tangrams.map((tangramSpec, index) => {\n \n // Filter to canonical pieces only and convert vertices to polygon format\n const filteredTans = tangramSpec.solutionTans.filter((tan: any) => {\n // Support both \"name\" and \"kind\" fields (different JSON formats)\n const tanName = tan.name ?? tan.kind;\n const isCanonical = CANON.has(tanName);\n return isCanonical;\n });\n\n const mask = filteredTans.map((tan: any) => {\n const polygon = tan.vertices.map(([x, y]: number[]) => ({ x: x ?? 0, y: -(y ?? 0) }));\n return polygon;\n });\n\n // Store primitive decomposition for optional decomposition view\n const primitiveDecomposition = filteredTans.map((tan: any) => ({\n kind: (tan.name ?? tan.kind) as TanKind,\n polygon: tan.vertices.map(([x, y]: number[]) => ({ x: x ?? 0, y: -(y ?? 0) }))\n }));\n\n // Assign sector ID from alphabetical sequence\n const sectorId = `sector${index}`;\n \n const sector = {\n id: sectorId,\n tangramId: tangramSpec.tangramID,\n silhouette: {\n id: sectorId,\n mask,\n primitiveDecomposition,\n },\n };\n\n return sector;\n });\n\n // Convert quickstash_macros to Blueprint[] format\n // Handle both anchor-based composites and pre-converted blueprints\n let quickstash: Blueprint[] = [];\n\n if (params.quickstash_macros && params.quickstash_macros.length > 0) {\n // Check if the first item has anchorOffset (anchor-based) or offset (pixel-based)\n const firstMacro = params.quickstash_macros[0];\n if (firstMacro && 'parts' in firstMacro && firstMacro.parts && firstMacro.parts[0] && 'anchorOffset' in firstMacro.parts[0]) {\n\n // Create primitive map for conversion\n const primsByKind = new Map<TanKind, PrimitiveBlueprint>();\n PRIMITIVE_BLUEPRINTS_ORDERED.forEach(p => primsByKind.set(p.kind, p));\n\n // Convert each anchor composite to pixel-based blueprint\n quickstash = (params.quickstash_macros as AnchorComposite[]).map(anchorComposite =>\n convertAnchorCompositeToPixels(anchorComposite, primsByKind, CONFIG.layout.grid.stepPx) // Use current CONFIG grid step\n );\n } else {\n // Already pixel-based blueprints\n quickstash = params.quickstash_macros as Blueprint[];\n }\n } else {\n }\n\n // Extract non-callback params for trial data\n const { onInteraction, onTrialEnd, ...trialParams } = params;\n\n // Create React root and render GameBoard\n const gameBoardProps = {\n sectors,\n quickstash,\n primitives: PRIMITIVE_BLUEPRINTS_ORDERED,\n layout: params.layout as LayoutMode,\n target: params.target as PlacementTarget,\n input: params.input as InputMode,\n timeLimitMs: params.time_limit_ms,\n maxQuickstashSlots: CONFIG.layout.defaults.maxQuickstashSlots,\n mode: 'construction' as const,\n showTangramDecomposition: params.show_tangram_decomposition ?? false,\n trialParams,\n ...(params.instructions && { instructions: params.instructions }),\n ...(params.onInteraction && { onInteraction: params.onInteraction }),\n ...(params.onTrialEnd && { onTrialEnd: params.onTrialEnd }),\n ...(params.usePrimitiveColorsBlueprints !== undefined && { usePrimitiveColorsBlueprints: params.usePrimitiveColorsBlueprints }),\n ...(params.usePrimitiveColorsTargets !== undefined && { usePrimitiveColorsTargets: params.usePrimitiveColorsTargets }),\n ...(params.primitiveColorIndices !== undefined && { primitiveColorIndices: params.primitiveColorIndices })\n };\n\n const root = createRoot(display_element);\n root.render(React.createElement(GameBoard, gameBoardProps));\n\n return { root, display_element, jsPsych: _jsPsych };\n}","import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\nimport { startConstructionTrial, StartConstructionTrialParams } from \"./ConstructionApp\";\n\nconst info = {\n name: \"tangram-construct\",\n version: \"1.0.0\",\n parameters: {\n /** Array of tangram specifications defining the puzzles to solve */\n tangrams: {\n type: ParameterType.COMPLEX,\n default: undefined,\n description: \"Array of TangramSpec objects defining target shapes to construct\"\n },\n /** Array of pre-made macro pieces from prep plugin */\n quickstash_macros: {\n type: ParameterType.COMPLEX,\n default: [],\n description: \"Array of MacroSpec objects created in prep trial\"\n },\n /** Array of primitive names in the order they should be displayed */\n primitive_order: {\n type: ParameterType.OBJECT,\n default: [\"square\", \"smalltriangle\", \"parallelogram\", \"medtriangle\", \"largetriangle\"],\n description: \"Array of primitive names in the order they should be displayed\"\n },\n /** Whether to place pieces in workspace or directly on silhouette */\n target: {\n type: ParameterType.SELECT,\n options: [\"workspace\", \"silhouette\"],\n default: \"silhouette\",\n description: \"Placement target: workspace (free placement) or silhouette (onto target shape)\"\n },\n /** Input method for piece manipulation */\n input: {\n type: ParameterType.SELECT,\n options: [\"click\", \"drag\"],\n default: \"drag\",\n description: \"Input mode: drag (mouse/touch drag) or click (click to select/place)\"\n },\n /** Layout style for piece arrangement */\n layout: {\n type: ParameterType.SELECT,\n options: [\"circle\", \"semicircle\"],\n default: \"semicircle\",\n description: \"Layout mode: full circle or semicircle piece arrangement\"\n },\n /** Maximum time allowed for trial in milliseconds */\n time_limit_ms: {\n type: ParameterType.INT,\n default: 0,\n description: \"Time limit in milliseconds (0 = no limit)\"\n },\n /** Snap radius for piece placement in pixels */\n snap_radius_px: {\n type: ParameterType.INT,\n default: 18,\n description: \"Snap radius for anchor-based piece placement\"\n },\n /** Whether to show tangram target shapes decomposed into individual primitives with borders */\n show_tangram_decomposition: {\n type: ParameterType.BOOL,\n default: false,\n description: \"Whether to show tangram target shapes decomposed into individual primitives with borders\"\n },\n /** HTML content to display above the gameboard as instructions */\n instructions: {\n type: ParameterType.STRING,\n default: \"\",\n description: \"HTML content to display above the gameboard as instructions\"\n },\n /** Callback fired after each interaction (piece pickup + placedown) */\n onInteraction: {\n type: ParameterType.FUNCTION,\n default: undefined,\n description: \"Callback for each interaction event (e.g., socket.emit)\"\n },\n /** Callback fired when trial ends */\n onTrialEnd: {\n type: ParameterType.FUNCTION,\n default: undefined,\n description: \"Callback when trial completes with full data\"\n },\n /** Whether to use distinct colors for each primitive shape type in blueprints */\n use_primitive_colors_blueprints: {\n type: ParameterType.BOOL,\n default: false,\n description: \"Whether each primitive shape type should have its own distinct color in the blueprint dock area\"\n },\n /** Whether to use distinct colors for each primitive shape type in target tangrams */\n use_primitive_colors_targets: {\n type: ParameterType.BOOL,\n default: false,\n description: \"Whether each primitive shape type should have its own distinct color in target tangram silhouettes\"\n },\n /** Indices mapping primitives to colors from the color palette */\n primitive_color_indices: {\n type: ParameterType.OBJECT,\n default: [0, 1, 2, 3, 4],\n description: \"Array of 5 integers indexing into primitiveColors array, mapping [square, smalltriangle, parallelogram, medtriangle, largetriangle] to colors\"\n }\n },\n data: {\n /** Array of all interaction events during trial */\n events: {\n type: ParameterType.COMPLEX,\n description: \"Chronological log of all user interactions and game events\"\n },\n /** Completion time for each sector/tangram */\n completion_times: {\n type: ParameterType.COMPLEX,\n description: \"Array of completion times in milliseconds for each tangram\"\n },\n /** Final completion state of each sector */\n final_state: {\n type: ParameterType.COMPLEX,\n description: \"Array describing completion status of each tangram sector\"\n },\n /** Usage statistics for macro pieces */\n macros_used: {\n type: ParameterType.COMPLEX,\n description: \"Array tracking which macros were used and when\"\n },\n /** Total trial duration in milliseconds */\n trial_duration_ms: {\n type: ParameterType.INT,\n description: \"Total time from trial start to completion\"\n }\n },\n citations: \"\"\n};\n\ntype Info = typeof info;\n\n/**\n * **tangram-construct**\n *\n * A jsPsych wrapper around the React-based construction interface.\n *\n * @author Justin Yang & Sean Paul Anderson\n * @see {@link https://github.com/cogtoolslab/tangram_construction.git/tree/main/experiments/jspsych-tangram-prep}\n */\nclass TangramConstructPlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n /**\n * Launches the trial by invoking startConstructionTrial\n * with the display element, parameters, and jsPsych instance.\n */\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n // Wrap onTrialEnd to handle React cleanup and jsPsych trial completion\n const wrappedOnTrialEnd = (data: any) => {\n // Call user-provided callback if exists\n if (trial.onTrialEnd) {\n trial.onTrialEnd(data);\n }\n\n // Clean up React first (before clearing DOM)\n const reactContext = (display_element as any).__reactContext;\n if (reactContext?.root) {\n reactContext.root.unmount();\n }\n\n // Clear display after React cleanup\n display_element.innerHTML = '';\n\n // Finish jsPsych trial with data\n this.jsPsych.finishTrial(data);\n };\n\n // Create parameter object for wrapper\n const params: StartConstructionTrialParams = {\n tangrams: trial.tangrams,\n quickstash_macros: trial.quickstash_macros,\n primitiveOrder: trial.primitive_order,\n target: trial.target,\n input: trial.input,\n layout: trial.layout,\n time_limit_ms: trial.time_limit_ms,\n show_tangram_decomposition: trial.show_tangram_decomposition,\n instructions: trial.instructions,\n onInteraction: trial.onInteraction,\n onTrialEnd: wrappedOnTrialEnd,\n usePrimitiveColorsBlueprints: trial.use_primitive_colors_blueprints,\n usePrimitiveColorsTargets: trial.use_primitive_colors_targets,\n primitiveColorIndices: trial.primitive_color_indices\n };\n\n // Use React wrapper to start the trial\n const { root, display_element: element, jsPsych } = startConstructionTrial(display_element, params, this.jsPsych);\n\n // Store React context for cleanup\n (element as any).__reactContext = { root, jsPsych };\n }\n}\n\nexport default TangramConstructPlugin;"],"names":["polysAABB","igcd","inferUnitFromPolys","outerR","bp","bb","support","x","y","pointerAnchorNode","pointerSector","piece","cfg","centerX","centerY","q","tl0","pointerR","allowInside","clamped","pieceId","anchorInfo","uuidv4","layout","createRoot","ParameterType"],"mappings":"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"}