@nodius/layouting 0.1.1 → 0.1.4
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.
- package/README.md +1136 -132
- package/dist/algorithms/crossing-minimization.d.ts +5 -1
- package/dist/algorithms/crossing-minimization.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +334 -87
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +334 -87
- package/dist/index.mjs.map +1 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/proposals.d.ts +14 -1
- package/dist/proposals.d.ts.map +1 -1
- package/dist/types.d.ts +60 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/graph.ts","../src/algorithms/cycle-breaking.ts","../src/algorithms/layer-assignment.ts","../src/algorithms/crossing-minimization.ts","../src/algorithms/coordinate-assignment.ts","../src/algorithms/value-placement.ts","../src/algorithms/edge-routing.ts","../src/algorithms/component-packing.ts","../src/proposals.ts","../src/layout.ts","../src/incremental.ts","../src/debug.ts"],"sourcesContent":["/** Position on a node where a handle can be placed */\nexport type HandleSide = 'top' | 'right' | 'bottom' | 'left';\n\n/** Handle type - input receives connections, output sends connections */\nexport type HandleType = 'input' | 'output';\n\n/** Layout direction. 'TB' or 'LR' are the supported strict reading axes. */\nexport type LayoutDirection = 'TB' | 'LR' | 'BT' | 'RL';\n\n/**\n * Edge kind drives the layout weight:\n * - `control`: full strength; defines the execution rail (layer count).\n * - `data`: light weight; values are pulled onto the same layer as their consumer\n * instead of extending the rail.\n */\nexport type EdgeKind = 'control' | 'data';\n\n/** A 2D point */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** Handle definition on a node */\nexport interface HandleInput {\n id: string;\n type: HandleType;\n position: HandleSide;\n /** Position along the side (0 = start, 1 = end). Default: 0.5 */\n offset?: number;\n}\n\n/** Node input definition */\nexport interface NodeInput {\n id: string;\n width: number;\n height: number;\n handles: HandleInput[];\n /** Parent node id for compound (nested) layouts. */\n parentId?: string;\n}\n\n/** Edge input definition */\nexport interface EdgeInput {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n /** Default: 'control' */\n kind?: EdgeKind;\n /** Explicit weight override. Defaults: 1 (control), 0.25 (data). */\n weight?: number;\n}\n\n/** Complete layout input */\nexport interface LayoutInput {\n nodes: NodeInput[];\n edges: EdgeInput[];\n}\n\n/** Per-kind default weight overrides. */\nexport interface EdgeWeights {\n control?: number;\n data?: number;\n}\n\n/**\n * A proposal the layout engine emits to the calling application during a pass.\n * The app inspects it and decides whether to accept it, modify it, or reject it\n * by returning either the (possibly tweaked) proposed node or `null`/`undefined`\n * to keep the original.\n */\nexport interface RotateProposal {\n type: 'rotate';\n /** The node being analyzed. */\n nodeId: string;\n /** Same node as provided in the input. */\n current: NodeInput;\n /** The engine's proposed version after rotating handles. */\n proposed: NodeInput;\n /** Rotation in degrees (CW = positive). */\n rotation: 90 | -90 | 180;\n /** Reason this proposal was emitted (handle layout mismatches direction, etc.). */\n reason: string;\n}\n\nexport type LayoutProposal = RotateProposal;\n\nexport type ProposalCallback = (proposal: LayoutProposal) => NodeInput | null | undefined | void;\n\n/** Layout configuration options */\nexport interface LayoutOptions {\n /** Layout direction. Default: 'TB' */\n direction?: LayoutDirection;\n /** Minimum spacing between nodes in the same layer. Default: 40 */\n nodeSpacing?: number;\n /** Minimum spacing between layers. Default: 60 */\n layerSpacing?: number;\n /** Number of iterations for crossing minimization. Default: 24 */\n crossingMinimizationIterations?: number;\n /** Number of iterations for coordinate optimization. Default: 8 */\n coordinateOptimizationIterations?: number;\n /** Margin for edge routing (distance from node before turning). Default: 20 */\n edgeMargin?: number;\n /** Override default per-kind weights. */\n edgeWeights?: EdgeWeights;\n /** When true, disjoint components are packed side-by-side. Default: true */\n packComponents?: boolean;\n /** Padding around compound (parent) bounding boxes. Default: 24 */\n compoundPadding?: number;\n /**\n * Called once per node when the engine thinks a rotation of the node's\n * handles would suit the chosen direction better. Return the (possibly\n * tweaked) proposed node to accept, or `null`/nothing to keep the original.\n */\n onProposal?: ProposalCallback;\n}\n\n/** Resolved options with all defaults applied */\nexport interface ResolvedOptions {\n direction: LayoutDirection;\n nodeSpacing: number;\n layerSpacing: number;\n crossingMinimizationIterations: number;\n coordinateOptimizationIterations: number;\n edgeMargin: number;\n controlWeight: number;\n dataWeight: number;\n packComponents: boolean;\n compoundPadding: number;\n onProposal?: ProposalCallback;\n}\n\nexport function resolveOptions(options?: LayoutOptions): ResolvedOptions {\n return {\n direction: options?.direction ?? 'TB',\n nodeSpacing: options?.nodeSpacing ?? 40,\n layerSpacing: options?.layerSpacing ?? 60,\n crossingMinimizationIterations: options?.crossingMinimizationIterations ?? 24,\n coordinateOptimizationIterations: options?.coordinateOptimizationIterations ?? 8,\n edgeMargin: options?.edgeMargin ?? 20,\n controlWeight: options?.edgeWeights?.control ?? 1,\n dataWeight: options?.edgeWeights?.data ?? 0.25,\n packComponents: options?.packComponents ?? true,\n compoundPadding: options?.compoundPadding ?? 24,\n onProposal: options?.onProposal,\n };\n}\n\n/** Positioned handle in the output */\nexport interface HandleOutput {\n id: string;\n type: HandleType;\n position: HandleSide;\n x: number;\n y: number;\n}\n\n/** Positioned node in the output */\nexport interface NodeOutput {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n handles: HandleOutput[];\n /** Echoed back so consumers can reconstruct the hierarchy. */\n parentId?: string;\n}\n\n/** Routed edge in the output */\nexport interface EdgeOutput {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n points: Point[];\n kind: EdgeKind;\n}\n\n/** Complete layout result */\nexport interface LayoutResult {\n nodes: NodeOutput[];\n edges: EdgeOutput[];\n}\n","import { HandleInput, HandleSide, NodeInput, EdgeInput, Point, EdgeKind } from './types';\n\nexport interface InternalNode {\n id: string;\n width: number;\n height: number;\n handles: HandleInput[];\n isDummy: boolean;\n layer: number;\n order: number;\n x: number;\n y: number;\n parentId?: string;\n /** True if this node represents a compound (its size was computed from children). */\n isCompound: boolean;\n /** True when the node has no control edges and only participates in data edges. */\n isValue: boolean;\n}\n\nexport interface InternalEdge {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n reversed: boolean;\n originalId: string;\n kind: EdgeKind;\n weight: number;\n}\n\nexport class Graph {\n nodes: Map<string, InternalNode> = new Map();\n edges: Map<string, InternalEdge> = new Map();\n outEdges: Map<string, Set<string>> = new Map();\n inEdges: Map<string, Set<string>> = new Map();\n\n addNode(node: InternalNode): void {\n this.nodes.set(node.id, node);\n if (!this.outEdges.has(node.id)) this.outEdges.set(node.id, new Set());\n if (!this.inEdges.has(node.id)) this.inEdges.set(node.id, new Set());\n }\n\n addEdge(edge: InternalEdge): void {\n this.edges.set(edge.id, edge);\n if (!this.outEdges.has(edge.from)) this.outEdges.set(edge.from, new Set());\n if (!this.inEdges.has(edge.to)) this.inEdges.set(edge.to, new Set());\n this.outEdges.get(edge.from)!.add(edge.id);\n this.inEdges.get(edge.to)!.add(edge.id);\n }\n\n removeEdge(edgeId: string): void {\n const edge = this.edges.get(edgeId);\n if (!edge) return;\n this.outEdges.get(edge.from)?.delete(edgeId);\n this.inEdges.get(edge.to)?.delete(edgeId);\n this.edges.delete(edgeId);\n }\n\n removeNode(nodeId: string): void {\n const outEdgeIds = [...(this.outEdges.get(nodeId) || [])];\n const inEdgeIds = [...(this.inEdges.get(nodeId) || [])];\n for (const eid of outEdgeIds) this.removeEdge(eid);\n for (const eid of inEdgeIds) this.removeEdge(eid);\n this.nodes.delete(nodeId);\n this.outEdges.delete(nodeId);\n this.inEdges.delete(nodeId);\n }\n\n predecessors(nodeId: string): string[] {\n const result: string[] = [];\n const inEdgeIds = this.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = this.edges.get(eid);\n if (edge) result.push(edge.from);\n }\n }\n return result;\n }\n\n successors(nodeId: string): string[] {\n const result: string[] = [];\n const outEdgeIds = this.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = this.edges.get(eid);\n if (edge) result.push(edge.to);\n }\n }\n return result;\n }\n}\n\nexport interface BuildGraphContext {\n controlWeight: number;\n dataWeight: number;\n}\n\nexport function buildGraph(\n nodes: NodeInput[],\n edges: EdgeInput[],\n ctx: BuildGraphContext = { controlWeight: 1, dataWeight: 0.25 }\n): Graph {\n const graph = new Graph();\n\n for (const node of nodes) {\n graph.addNode({\n id: node.id,\n width: node.width,\n height: node.height,\n handles: node.handles.map(h => ({ ...h, offset: h.offset ?? 0.5 })),\n isDummy: false,\n layer: -1,\n order: -1,\n x: 0,\n y: 0,\n parentId: node.parentId,\n isCompound: false,\n isValue: false,\n });\n }\n\n for (const edge of edges) {\n const kind: EdgeKind = edge.kind ?? 'control';\n const defaultWeight = kind === 'control' ? ctx.controlWeight : ctx.dataWeight;\n graph.addEdge({\n id: edge.id,\n from: edge.from,\n to: edge.to,\n fromHandle: edge.fromHandle,\n toHandle: edge.toHandle,\n reversed: false,\n originalId: edge.id,\n kind,\n weight: edge.weight ?? defaultWeight,\n });\n }\n\n // A node is a \"value\" if every incident edge is data.\n // Floating values (no incoming edges + only data outgoing) and pure data sinks\n // both qualify — they should be pulled toward their consumer's layer\n // rather than extending the control rail.\n for (const [nodeId, node] of graph.nodes) {\n const ins = graph.inEdges.get(nodeId);\n const outs = graph.outEdges.get(nodeId);\n let hasControl = false;\n if (ins) {\n for (const eid of ins) {\n if (graph.edges.get(eid)?.kind === 'control') { hasControl = true; break; }\n }\n }\n if (!hasControl && outs) {\n for (const eid of outs) {\n if (graph.edges.get(eid)?.kind === 'control') { hasControl = true; break; }\n }\n }\n const incidentCount = (ins?.size ?? 0) + (outs?.size ?? 0);\n node.isValue = !hasControl && incidentCount > 0;\n }\n\n return graph;\n}\n\n/** Compute the absolute position of a handle on a positioned node */\nexport function getHandlePosition(node: InternalNode, handleId: string): Point {\n const handle = node.handles.find(h => h.id === handleId);\n if (!handle) {\n return { x: node.x + node.width / 2, y: node.y + node.height / 2 };\n }\n\n const offset = handle.offset ?? 0.5;\n\n switch (handle.position) {\n case 'top':\n return { x: node.x + offset * node.width, y: node.y };\n case 'bottom':\n return { x: node.x + offset * node.width, y: node.y + node.height };\n case 'left':\n return { x: node.x, y: node.y + offset * node.height };\n case 'right':\n return { x: node.x + node.width, y: node.y + offset * node.height };\n }\n}\n\n/** Get the direction vector for exiting/entering a handle */\nexport function getHandleDirection(side: HandleSide): Point {\n switch (side) {\n case 'top': return { x: 0, y: -1 };\n case 'bottom': return { x: 0, y: 1 };\n case 'left': return { x: -1, y: 0 };\n case 'right': return { x: 1, y: 0 };\n }\n}\n","import { Graph } from '../graph';\n\n/**\n * Break cycles in the graph using DFS-based back edge detection.\n * Reverses back edges to make the graph a DAG.\n * Returns the set of reversed edge IDs.\n */\nexport function breakCycles(graph: Graph): Set<string> {\n const WHITE = 0, GRAY = 1, BLACK = 2;\n const state = new Map<string, number>();\n const reversed = new Set<string>();\n\n for (const nodeId of graph.nodes.keys()) {\n state.set(nodeId, WHITE);\n }\n\n // Process nodes with more outgoing than incoming edges first\n const nodeIds = [...graph.nodes.keys()].sort((a, b) => {\n const aDiff = (graph.outEdges.get(a)?.size || 0) - (graph.inEdges.get(a)?.size || 0);\n const bDiff = (graph.outEdges.get(b)?.size || 0) - (graph.inEdges.get(b)?.size || 0);\n return bDiff - aDiff;\n });\n\n function dfs(nodeId: string): void {\n state.set(nodeId, GRAY);\n\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const edgeId of outEdgeIds) {\n const edge = graph.edges.get(edgeId);\n if (!edge) continue;\n\n const targetState = state.get(edge.to);\n if (targetState === GRAY) {\n reversed.add(edgeId);\n } else if (targetState === WHITE) {\n dfs(edge.to);\n }\n }\n }\n\n state.set(nodeId, BLACK);\n }\n\n for (const nodeId of nodeIds) {\n if (state.get(nodeId) === WHITE) {\n dfs(nodeId);\n }\n }\n\n // Reverse the back edges in the graph\n for (const edgeId of reversed) {\n const edge = graph.edges.get(edgeId);\n if (!edge) continue;\n\n graph.removeEdge(edgeId);\n graph.addEdge({\n ...edge,\n from: edge.to,\n to: edge.from,\n fromHandle: edge.toHandle,\n toHandle: edge.fromHandle,\n reversed: !edge.reversed,\n });\n }\n\n return reversed;\n}\n","import { Graph } from '../graph';\n\n/**\n * Two-pass layer assignment:\n *\n * Pass A (control rail): longest-path on the subgraph induced by control\n * edges between non-value nodes. This defines the canonical execution\n * timeline — value nodes do not extend it.\n *\n * Pass B (value pull): each value node is assigned the median layer of its\n * non-value neighbors. This snaps floating constants/imports onto the same\n * layer as the consumer that needs them, where they can be packed laterally.\n */\nexport function assignLayers(graph: Graph): string[][] {\n const layers = new Map<string, number>();\n const visiting = new Set<string>();\n\n // ----- Pass A: control rail -----\n function controlLayer(nodeId: string): number {\n if (layers.has(nodeId)) return layers.get(nodeId)!;\n if (visiting.has(nodeId)) return 0;\n\n const node = graph.nodes.get(nodeId);\n if (!node || node.isValue) return -1;\n\n visiting.add(nodeId);\n\n const inEdgeIds = graph.inEdges.get(nodeId);\n let maxPredLayer = -1;\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge || edge.kind !== 'control') continue;\n const pred = graph.nodes.get(edge.from);\n if (!pred || pred.isValue) continue;\n maxPredLayer = Math.max(maxPredLayer, controlLayer(edge.from));\n }\n }\n\n const layer = maxPredLayer + 1;\n layers.set(nodeId, layer);\n node.layer = layer;\n visiting.delete(nodeId);\n return layer;\n }\n\n for (const [nodeId, node] of graph.nodes) {\n if (!node.isValue) controlLayer(nodeId);\n }\n\n // ----- Pass B: value pull -----\n for (const [nodeId, node] of graph.nodes) {\n if (!node.isValue) continue;\n\n const neighborLayers: number[] = [];\n\n const inEdgeIds = graph.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const nbr = graph.nodes.get(edge.from);\n if (nbr && !nbr.isValue && layers.has(edge.from)) {\n neighborLayers.push(layers.get(edge.from)!);\n }\n }\n }\n\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const nbr = graph.nodes.get(edge.to);\n if (nbr && !nbr.isValue && layers.has(edge.to)) {\n neighborLayers.push(layers.get(edge.to)!);\n }\n }\n }\n\n let layer: number;\n if (neighborLayers.length > 0) {\n neighborLayers.sort((a, b) => a - b);\n layer = neighborLayers[Math.floor(neighborLayers.length / 2)];\n } else {\n layer = 0;\n }\n layers.set(nodeId, layer);\n node.layer = layer;\n }\n\n // Catch-all: isolated nodes go on layer 0.\n for (const [nodeId, node] of graph.nodes) {\n if (!layers.has(nodeId)) {\n layers.set(nodeId, 0);\n node.layer = 0;\n }\n }\n\n // Normalize so the smallest layer is 0.\n let minLayer = Infinity;\n let maxLayer = -Infinity;\n for (const l of layers.values()) {\n if (l < minLayer) minLayer = l;\n if (l > maxLayer) maxLayer = l;\n }\n if (!isFinite(minLayer)) return [];\n if (minLayer !== 0) {\n for (const [id, l] of layers) {\n const adj = l - minLayer;\n layers.set(id, adj);\n const n = graph.nodes.get(id);\n if (n) n.layer = adj;\n }\n maxLayer -= minLayer;\n }\n\n const layersArray: string[][] = Array.from({ length: maxLayer + 1 }, () => []);\n for (const [nodeId, layer] of layers) {\n layersArray[layer].push(nodeId);\n }\n\n return layersArray;\n}\n\n/**\n * Insert dummy nodes only for control edges that span multiple layers.\n * Data edges keep their layer-span; routing handles them directly because\n * they're typically short and decorative.\n */\nexport function insertDummyNodes(graph: Graph, layers: string[][]): string[][] {\n let dummyCounter = 0;\n const edgesToProcess = [...graph.edges.values()];\n\n for (const edge of edgesToProcess) {\n if (edge.kind !== 'control') continue;\n\n const fromNode = graph.nodes.get(edge.from);\n const toNode = graph.nodes.get(edge.to);\n if (!fromNode || !toNode) continue;\n\n const fromLayer = fromNode.layer;\n const toLayer = toNode.layer;\n const span = toLayer - fromLayer;\n\n if (span <= 1) continue;\n\n graph.removeEdge(edge.id);\n\n let prevNodeId = edge.from;\n let prevHandleId = edge.fromHandle;\n\n for (let l = fromLayer + 1; l < toLayer; l++) {\n const dummyId = `__dummy_${dummyCounter++}`;\n\n graph.addNode({\n id: dummyId,\n width: 0,\n height: 0,\n handles: [\n { id: 'in', type: 'input', position: 'top', offset: 0.5 },\n { id: 'out', type: 'output', position: 'bottom', offset: 0.5 },\n ],\n isDummy: true,\n layer: l,\n order: -1,\n x: 0,\n y: 0,\n isCompound: false,\n isValue: false,\n });\n\n layers[l].push(dummyId);\n\n graph.addEdge({\n id: `__dedge_${dummyCounter}_${l}_in`,\n from: prevNodeId,\n to: dummyId,\n fromHandle: prevHandleId,\n toHandle: 'in',\n reversed: edge.reversed,\n originalId: edge.originalId,\n kind: edge.kind,\n weight: edge.weight,\n });\n\n prevNodeId = dummyId;\n prevHandleId = 'out';\n }\n\n graph.addEdge({\n id: `__dedge_${dummyCounter}_final`,\n from: prevNodeId,\n to: edge.to,\n fromHandle: prevHandleId,\n toHandle: edge.toHandle,\n reversed: edge.reversed,\n originalId: edge.originalId,\n kind: edge.kind,\n weight: edge.weight,\n });\n }\n\n return layers;\n}\n","import { Graph } from '../graph';\n\n/**\n * Minimize edge crossings using barycenter heuristic with transpose improvement.\n */\nexport function minimizeCrossings(\n graph: Graph,\n layers: string[][],\n iterations: number\n): string[][] {\n if (layers.length <= 1) return layers;\n\n const totalNodes = layers.reduce((s, l) => s + l.length, 0);\n\n // Adaptive: reduce iterations for large graphs\n const effectiveIter = totalNodes > 500\n ? Math.min(iterations, 6)\n : totalNodes > 200\n ? Math.min(iterations, 12)\n : iterations;\n\n // Skip transpose for very large layers\n const skipTranspose = totalNodes > 800;\n\n // Initialize node orders\n for (let l = 0; l < layers.length; l++) {\n for (let i = 0; i < layers[l].length; i++) {\n const node = graph.nodes.get(layers[l][i]);\n if (node) node.order = i;\n }\n }\n\n let bestLayers = layers.map(l => [...l]);\n let bestCrossings = countAllCrossings(graph, layers);\n let noImprovementCount = 0;\n\n for (let iter = 0; iter < effectiveIter; iter++) {\n // Down sweep\n for (let l = 1; l < layers.length; l++) {\n orderByBarycenter(graph, layers, l, 'up');\n }\n\n // Up sweep\n for (let l = layers.length - 2; l >= 0; l--) {\n orderByBarycenter(graph, layers, l, 'down');\n }\n\n // Transpose improvement\n if (!skipTranspose) {\n for (let l = 0; l < layers.length; l++) {\n if (layers[l].length <= 100) {\n transposeImprove(graph, layers, l);\n }\n }\n }\n\n const crossings = countAllCrossings(graph, layers);\n if (crossings < bestCrossings) {\n bestCrossings = crossings;\n bestLayers = layers.map(l => [...l]);\n noImprovementCount = 0;\n } else {\n noImprovementCount++;\n }\n\n if (crossings === 0 || noImprovementCount >= 3) break;\n }\n\n // Restore best ordering\n for (let l = 0; l < layers.length; l++) {\n layers[l] = bestLayers[l];\n for (let i = 0; i < layers[l].length; i++) {\n const node = graph.nodes.get(layers[l][i]);\n if (node) node.order = i;\n }\n }\n\n return layers;\n}\n\nfunction orderByBarycenter(\n graph: Graph,\n layers: string[][],\n layerIndex: number,\n direction: 'up' | 'down'\n): void {\n const layer = layers[layerIndex];\n const adjLayerIndex = direction === 'up' ? layerIndex - 1 : layerIndex + 1;\n\n if (adjLayerIndex < 0 || adjLayerIndex >= layers.length) return;\n\n // Build position lookup for adjacent layer using node.order\n const adjLayerSet = new Set(layers[adjLayerIndex]);\n\n const barycenters = new Map<string, number>();\n\n for (let i = 0; i < layer.length; i++) {\n const nodeId = layer[i];\n\n // Get neighbor positions directly using node.order\n let sum = 0;\n let count = 0;\n\n if (direction === 'up') {\n const inEdgeIds = graph.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (edge && adjLayerSet.has(edge.from)) {\n const neighbor = graph.nodes.get(edge.from);\n if (neighbor) {\n sum += neighbor.order;\n count++;\n }\n }\n }\n }\n } else {\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (edge && adjLayerSet.has(edge.to)) {\n const neighbor = graph.nodes.get(edge.to);\n if (neighbor) {\n sum += neighbor.order;\n count++;\n }\n }\n }\n }\n }\n\n barycenters.set(nodeId, count > 0 ? sum / count : i);\n }\n\n layer.sort((a, b) => barycenters.get(a)! - barycenters.get(b)!);\n\n for (let i = 0; i < layer.length; i++) {\n const node = graph.nodes.get(layer[i]);\n if (node) node.order = i;\n }\n}\n\nfunction transposeImprove(graph: Graph, layers: string[][], layerIndex: number): void {\n const layer = layers[layerIndex];\n if (layer.length <= 1) return;\n\n let improved = true;\n let passes = 0;\n\n while (improved && passes < 2) {\n improved = false;\n passes++;\n for (let i = 0; i < layer.length - 1; i++) {\n const nodeA = layer[i];\n const nodeB = layer[i + 1];\n\n const crossingsBefore = countPairCrossings(graph, layers, layerIndex, nodeA, nodeB);\n\n // Swap in-place\n layer[i] = nodeB;\n layer[i + 1] = nodeA;\n const nA = graph.nodes.get(nodeA);\n const nB = graph.nodes.get(nodeB);\n if (nA) nA.order = i + 1;\n if (nB) nB.order = i;\n\n const crossingsAfter = countPairCrossings(graph, layers, layerIndex, nodeB, nodeA);\n\n if (crossingsAfter < crossingsBefore) {\n improved = true;\n } else {\n // Revert\n layer[i] = nodeA;\n layer[i + 1] = nodeB;\n if (nA) nA.order = i;\n if (nB) nB.order = i + 1;\n }\n }\n }\n}\n\n/**\n * Count crossings involving a specific pair of adjacent nodes using node.order directly.\n */\nfunction countPairCrossings(\n graph: Graph,\n layers: string[][],\n layerIndex: number,\n nodeA: string,\n nodeB: string\n): number {\n let crossings = 0;\n\n // Check with upper layer\n if (layerIndex > 0) {\n const upperLayer = new Set(layers[layerIndex - 1]);\n\n const predsA: number[] = [];\n const predsB: number[] = [];\n\n const inA = graph.inEdges.get(nodeA);\n if (inA) {\n for (const eid of inA) {\n const edge = graph.edges.get(eid);\n if (edge && upperLayer.has(edge.from)) {\n const n = graph.nodes.get(edge.from);\n if (n) predsA.push(n.order);\n }\n }\n }\n\n const inB = graph.inEdges.get(nodeB);\n if (inB) {\n for (const eid of inB) {\n const edge = graph.edges.get(eid);\n if (edge && upperLayer.has(edge.from)) {\n const n = graph.nodes.get(edge.from);\n if (n) predsB.push(n.order);\n }\n }\n }\n\n for (const pA of predsA) {\n for (const pB of predsB) {\n if (pA > pB) crossings++;\n }\n }\n }\n\n // Check with lower layer\n if (layerIndex < layers.length - 1) {\n const lowerLayer = new Set(layers[layerIndex + 1]);\n\n const succsA: number[] = [];\n const succsB: number[] = [];\n\n const outA = graph.outEdges.get(nodeA);\n if (outA) {\n for (const eid of outA) {\n const edge = graph.edges.get(eid);\n if (edge && lowerLayer.has(edge.to)) {\n const n = graph.nodes.get(edge.to);\n if (n) succsA.push(n.order);\n }\n }\n }\n\n const outB = graph.outEdges.get(nodeB);\n if (outB) {\n for (const eid of outB) {\n const edge = graph.edges.get(eid);\n if (edge && lowerLayer.has(edge.to)) {\n const n = graph.nodes.get(edge.to);\n if (n) succsB.push(n.order);\n }\n }\n }\n\n for (const sA of succsA) {\n for (const sB of succsB) {\n if (sA > sB) crossings++;\n }\n }\n }\n\n return crossings;\n}\n\nexport function countAllCrossings(graph: Graph, layers: string[][]): number {\n let total = 0;\n for (let l = 0; l < layers.length - 1; l++) {\n total += countLayerCrossings(graph, layers[l], layers[l + 1]);\n }\n return total;\n}\n\n/**\n * Count crossings between two adjacent layers using merge-sort based\n * inversion counting. O(E log V) instead of O(E^2).\n */\nfunction countLayerCrossings(\n graph: Graph,\n upperLayer: string[],\n lowerLayer: string[]\n): number {\n const lowerPos = new Map<string, number>();\n lowerLayer.forEach((id, pos) => lowerPos.set(id, pos));\n\n // Collect edge endpoint pairs sorted by upper position\n const edgePairs: [number, number][] = [];\n for (let uPos = 0; uPos < upperLayer.length; uPos++) {\n const nodeId = upperLayer[uPos];\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (!outEdgeIds) continue;\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const lp = lowerPos.get(edge.to);\n if (lp !== undefined) {\n edgePairs.push([uPos, lp]);\n }\n }\n }\n\n if (edgePairs.length <= 1) return 0;\n\n // Sort by upper position, then by lower\n edgePairs.sort((a, b) => a[0] - b[0] || a[1] - b[1]);\n\n // Count inversions in the lower positions\n const lowerPositions = edgePairs.map(e => e[1]);\n return mergeSortCount(lowerPositions);\n}\n\nfunction mergeSortCount(arr: number[]): number {\n if (arr.length <= 1) return 0;\n\n const mid = arr.length >> 1;\n const left = arr.slice(0, mid);\n const right = arr.slice(mid);\n\n let count = mergeSortCount(left) + mergeSortCount(right);\n\n let i = 0, j = 0, k = 0;\n while (i < left.length && j < right.length) {\n if (left[i] <= right[j]) {\n arr[k++] = left[i++];\n } else {\n count += left.length - i;\n arr[k++] = right[j++];\n }\n }\n\n while (i < left.length) arr[k++] = left[i++];\n while (j < right.length) arr[k++] = right[j++];\n\n return count;\n}\n","import { Graph } from '../graph';\nimport { LayoutDirection, ResolvedOptions } from '../types';\n\n/**\n * Assign x,y coordinates to all nodes using a median-based iterative approach.\n */\nexport function assignCoordinates(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions\n): void {\n const isHorizontal = options.direction === 'LR' || options.direction === 'RL';\n const isReversed = options.direction === 'BT' || options.direction === 'RL';\n\n assignRankPositions(graph, layers, options, isHorizontal, isReversed);\n assignOrderPositions(graph, layers, options, isHorizontal);\n optimizePositions(graph, layers, options, isHorizontal);\n}\n\n/**\n * Assign positions along the rank axis (y for TB/BT, x for LR/RL).\n */\nfunction assignRankPositions(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n isHorizontal: boolean,\n isReversed: boolean\n): void {\n // Compute layer sizes (max node size in rank direction)\n const layerSizes: number[] = [];\n for (const layer of layers) {\n let maxSize = 0;\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const size = isHorizontal ? node.width : node.height;\n maxSize = Math.max(maxSize, size);\n }\n layerSizes.push(maxSize);\n }\n\n // Compute cumulative positions\n const layerPositions: number[] = [];\n let pos = 0;\n for (let l = 0; l < layers.length; l++) {\n layerPositions.push(pos);\n pos += layerSizes[l] + options.layerSpacing;\n }\n\n // If reversed, flip positions\n if (isReversed) {\n const totalSize = pos - options.layerSpacing;\n for (let l = 0; l < layerPositions.length; l++) {\n layerPositions[l] = totalSize - layerPositions[l] - layerSizes[l];\n }\n }\n\n // Assign positions\n for (let l = 0; l < layers.length; l++) {\n for (const nodeId of layers[l]) {\n const node = graph.nodes.get(nodeId)!;\n const nodeSize = isHorizontal ? node.width : node.height;\n const offset = (layerSizes[l] - nodeSize) / 2;\n\n if (isHorizontal) {\n node.x = layerPositions[l] + offset;\n } else {\n node.y = layerPositions[l] + offset;\n }\n }\n }\n}\n\n/**\n * Assign positions along the order axis (x for TB/BT, y for LR/RL).\n * Initial even spacing, centered.\n */\nfunction assignOrderPositions(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n isHorizontal: boolean\n): void {\n for (const layer of layers) {\n let pos = 0;\n\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const size = isHorizontal ? node.height : node.width;\n\n if (isHorizontal) {\n node.y = pos;\n } else {\n node.x = pos;\n }\n\n pos += size + options.nodeSpacing;\n }\n\n // Center the layer\n const totalSize = pos - options.nodeSpacing;\n const centerOffset = -totalSize / 2;\n\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n if (isHorizontal) {\n node.y += centerOffset;\n } else {\n node.x += centerOffset;\n }\n }\n }\n}\n\n/**\n * Iteratively optimize positions by aligning nodes with their connected neighbors.\n */\nfunction optimizePositions(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n isHorizontal: boolean\n): void {\n for (let iter = 0; iter < options.coordinateOptimizationIterations; iter++) {\n // Down sweep\n for (let l = 0; l < layers.length; l++) {\n optimizeLayer(graph, layers[l], options, isHorizontal);\n }\n\n // Up sweep\n for (let l = layers.length - 1; l >= 0; l--) {\n optimizeLayer(graph, layers[l], options, isHorizontal);\n }\n }\n\n centerAllLayers(graph, layers, isHorizontal);\n}\n\nfunction optimizeLayer(\n graph: Graph,\n layer: string[],\n options: ResolvedOptions,\n isHorizontal: boolean\n): void {\n if (layer.length === 0) return;\n\n // Compute desired positions\n const desired = new Map<string, number>();\n\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const connected = [...graph.predecessors(nodeId), ...graph.successors(nodeId)];\n\n if (connected.length === 0) {\n desired.set(nodeId, getOrderPos(node, isHorizontal));\n continue;\n }\n\n // Median of connected nodes' center positions\n const positions = connected\n .map(cId => {\n const c = graph.nodes.get(cId)!;\n return getOrderPos(c, isHorizontal) + getOrderSize(c, isHorizontal) / 2;\n })\n .sort((a, b) => a - b);\n\n const nodeSize = getOrderSize(node, isHorizontal);\n const median = positions.length % 2 === 0\n ? (positions[positions.length / 2 - 1] + positions[positions.length / 2]) / 2\n : positions[Math.floor(positions.length / 2)];\n\n desired.set(nodeId, median - nodeSize / 2);\n }\n\n // Forward pass: apply desired positions with spacing constraints\n for (let i = 0; i < layer.length; i++) {\n const nodeId = layer[i];\n const node = graph.nodes.get(nodeId)!;\n let desiredPos = desired.get(nodeId)!;\n\n if (i > 0) {\n const prevId = layer[i - 1];\n const prev = graph.nodes.get(prevId)!;\n const prevEnd = getOrderPos(prev, isHorizontal) + getOrderSize(prev, isHorizontal);\n desiredPos = Math.max(desiredPos, prevEnd + options.nodeSpacing);\n }\n\n setOrderPos(node, isHorizontal, desiredPos);\n }\n\n // Backward pass: fix overlaps from right\n for (let i = layer.length - 2; i >= 0; i--) {\n const nodeId = layer[i];\n const node = graph.nodes.get(nodeId)!;\n const nextId = layer[i + 1];\n const next = graph.nodes.get(nextId)!;\n\n const nodeEnd = getOrderPos(node, isHorizontal) + getOrderSize(node, isHorizontal);\n const nextStart = getOrderPos(next, isHorizontal);\n\n if (nodeEnd + options.nodeSpacing > nextStart) {\n setOrderPos(node, isHorizontal, nextStart - options.nodeSpacing - getOrderSize(node, isHorizontal));\n }\n }\n}\n\nfunction centerAllLayers(\n graph: Graph,\n layers: string[][],\n isHorizontal: boolean\n): void {\n if (layers.length === 0) return;\n\n // Find global bounds\n let globalMin = Infinity;\n let globalMax = -Infinity;\n\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const pos = getOrderPos(node, isHorizontal);\n const size = getOrderSize(node, isHorizontal);\n globalMin = Math.min(globalMin, pos);\n globalMax = Math.max(globalMax, pos + size);\n }\n }\n\n // Shift everything so the layout starts at 0\n const offset = -globalMin;\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n setOrderPos(node, isHorizontal, getOrderPos(node, isHorizontal) + offset);\n }\n }\n\n // Also shift rank positions to start at 0\n let rankMin = Infinity;\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const pos = isHorizontal ? node.x : node.y;\n rankMin = Math.min(rankMin, pos);\n }\n }\n\n if (rankMin !== 0) {\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n if (isHorizontal) {\n node.x -= rankMin;\n } else {\n node.y -= rankMin;\n }\n }\n }\n }\n}\n\nfunction getOrderPos(node: { x: number; y: number }, isHorizontal: boolean): number {\n return isHorizontal ? node.y : node.x;\n}\n\nfunction setOrderPos(node: { x: number; y: number }, isHorizontal: boolean, value: number): void {\n if (isHorizontal) {\n node.y = value;\n } else {\n node.x = value;\n }\n}\n\nfunction getOrderSize(node: { width: number; height: number }, isHorizontal: boolean): number {\n return isHorizontal ? node.height : node.width;\n}\n","import { Graph } from '../graph';\nimport { LayoutDirection, ResolvedOptions } from '../types';\n\n/**\n * Sidecar placement for value nodes.\n *\n * Values (nodes whose every incident edge is a data edge) are NOT laid out\n * alongside the control rail — they are attached as sidecars to the flanks of\n * their dominant consumer once the rail is finalized. This way:\n *\n * - the rail stays perfectly aligned (its layout is computed without values)\n * - values cluster around the node that actually uses them\n * - extra values don't widen/displace the rail\n *\n * In TB direction, sidecars sit at the consumer's vertical center, alternating\n * left/right. In LR direction, they sit at the consumer's horizontal center,\n * alternating top/bottom.\n */\nexport function placeValueSidecars(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n): void {\n const isHorizontal = options.direction === 'LR' || options.direction === 'RL';\n\n // Identify all values and which consumer each belongs to.\n interface Attachment {\n valueId: string;\n consumerId: string;\n }\n const attachments: Attachment[] = [];\n const orphanValues: string[] = [];\n\n for (const [nodeId, node] of graph.nodes) {\n if (!node.isValue || node.isDummy) continue;\n\n const consumer = findDominantConsumer(graph, nodeId);\n if (consumer) {\n attachments.push({ valueId: nodeId, consumerId: consumer });\n } else {\n orphanValues.push(nodeId);\n }\n }\n\n // Group attachments by consumer.\n const byConsumer = new Map<string, string[]>();\n for (const { valueId, consumerId } of attachments) {\n const arr = byConsumer.get(consumerId) ?? [];\n arr.push(valueId);\n byConsumer.set(consumerId, arr);\n }\n\n // For each consumer, split its values into the two sides and place them.\n for (const [consumerId, vIds] of byConsumer) {\n const consumer = graph.nodes.get(consumerId);\n if (!consumer) continue;\n\n const { beforeSide, afterSide } = splitValuesBySide(graph, consumerId, vIds, isHorizontal);\n\n if (isHorizontal) {\n // LR/RL: 'before' = above the consumer (decreasing Y), 'after' = below.\n const cxCenter = consumer.x + consumer.width / 2;\n let topEdge = consumer.y;\n for (const vid of beforeSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.y = topEdge - options.nodeSpacing - v.height;\n v.x = cxCenter - v.width / 2;\n topEdge = v.y;\n }\n let bottomEdge = consumer.y + consumer.height;\n for (const vid of afterSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.y = bottomEdge + options.nodeSpacing;\n v.x = cxCenter - v.width / 2;\n bottomEdge = v.y + v.height;\n }\n } else {\n // TB/BT: 'before' = left of consumer (decreasing X), 'after' = right.\n const cyCenter = consumer.y + consumer.height / 2;\n let leftEdge = consumer.x;\n for (const vid of beforeSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.x = leftEdge - options.nodeSpacing - v.width;\n v.y = cyCenter - v.height / 2;\n leftEdge = v.x;\n }\n let rightEdge = consumer.x + consumer.width;\n for (const vid of afterSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.x = rightEdge + options.nodeSpacing;\n v.y = cyCenter - v.height / 2;\n rightEdge = v.x + v.width;\n }\n }\n }\n\n // Orphan values: no consumer found — place them in a stack at the layout origin.\n // Should be rare; mostly happens for truly isolated nodes.\n let orphanX = 0, orphanY = 0;\n for (const orphanId of orphanValues) {\n const v = graph.nodes.get(orphanId);\n if (!v) continue;\n v.x = orphanX;\n v.y = orphanY;\n if (isHorizontal) orphanX += v.width + options.nodeSpacing;\n else orphanY += v.height + options.nodeSpacing;\n }\n}\n\n/**\n * The \"dominant consumer\" of a value is the non-value neighbor with the most\n * edges connecting them. If multiple tie, pick by id for stability.\n */\nfunction findDominantConsumer(graph: Graph, valueId: string): string | null {\n const counts = new Map<string, number>();\n\n const outs = graph.outEdges.get(valueId);\n if (outs) {\n for (const eid of outs) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const other = graph.nodes.get(edge.to);\n if (other && !other.isValue && !other.isDummy) {\n counts.set(edge.to, (counts.get(edge.to) ?? 0) + 1);\n }\n }\n }\n const ins = graph.inEdges.get(valueId);\n if (ins) {\n for (const eid of ins) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const other = graph.nodes.get(edge.from);\n if (other && !other.isValue && !other.isDummy) {\n counts.set(edge.from, (counts.get(edge.from) ?? 0) + 1);\n }\n }\n }\n\n let bestId: string | null = null;\n let bestCount = -1;\n for (const [id, count] of counts) {\n if (count > bestCount || (count === bestCount && bestId !== null && id < bestId)) {\n bestId = id;\n bestCount = count;\n }\n }\n return bestId;\n}\n\n/**\n * Split values into the two sides of a consumer, using each value's connecting\n * handle as a hint:\n * - handle on the consumer's `left` (TB) / `top` (LR) → \"before\" side\n * - handle on the consumer's `right` (TB) / `bottom` (LR) → \"after\" side\n * - otherwise → balance the two sides\n *\n * Within each side, values are sorted by the handle offset so they stack in\n * a predictable order along the perpendicular axis.\n */\nfunction splitValuesBySide(\n graph: Graph,\n consumerId: string,\n valueIds: string[],\n isHorizontal: boolean,\n): { beforeSide: string[]; afterSide: string[] } {\n const consumer = graph.nodes.get(consumerId);\n if (!consumer) return { beforeSide: [...valueIds].sort(), afterSide: [] };\n\n type Slot = { id: string; side: 'before' | 'after' | 'neutral'; offset: number };\n const slots: Slot[] = [];\n\n for (const vId of valueIds) {\n let side: Slot['side'] = 'neutral';\n let offset = 0.5;\n\n const inspectHandle = (handleId: string | undefined) => {\n if (!handleId) return;\n const handle = consumer.handles.find(h => h.id === handleId);\n if (!handle) return;\n offset = handle.offset ?? 0.5;\n if (isHorizontal) {\n if (handle.position === 'top') side = 'before';\n else if (handle.position === 'bottom') side = 'after';\n } else {\n if (handle.position === 'left') side = 'before';\n else if (handle.position === 'right') side = 'after';\n }\n };\n\n // Find the edge between value and consumer, then look at the handle ON the consumer.\n const outs = graph.outEdges.get(vId);\n if (outs) for (const eid of outs) {\n const e = graph.edges.get(eid);\n if (e && e.to === consumerId) { inspectHandle(e.toHandle); break; }\n }\n if (side === 'neutral') {\n const ins = graph.inEdges.get(vId);\n if (ins) for (const eid of ins) {\n const e = graph.edges.get(eid);\n if (e && e.from === consumerId) { inspectHandle(e.fromHandle); break; }\n }\n }\n\n slots.push({ id: vId, side, offset });\n }\n\n const before = slots.filter(s => s.side === 'before');\n const after = slots.filter(s => s.side === 'after');\n const neutral = slots.filter(s => s.side === 'neutral');\n\n // Balance neutrals across the two sides for compactness.\n for (const n of neutral) {\n if (before.length <= after.length) before.push(n);\n else after.push(n);\n }\n\n // Sort each side: smaller offset first (so values stack predictably, closest\n // to the matching handle nearest to the consumer body).\n const cmp = (a: Slot, b: Slot) => (a.offset - b.offset) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\n before.sort(cmp);\n after.sort(cmp);\n\n return {\n beforeSide: before.map(s => s.id),\n afterSide: after.map(s => s.id),\n };\n}\n\nexport function isValueLayer(layer: string[], graph: Graph): boolean {\n for (const id of layer) {\n const n = graph.nodes.get(id);\n if (n && !n.isValue && !n.isDummy) return false;\n }\n return true;\n}\n\n/** Filter layers to keep only non-value, non-dummy nodes per layer. */\nexport function railLayers(layers: string[][], graph: Graph): string[][] {\n return layers.map(layer =>\n layer.filter(id => {\n const n = graph.nodes.get(id);\n return n && !n.isValue;\n }),\n );\n}\n\nexport function getDirection(direction: LayoutDirection): { isHorizontal: boolean } {\n return { isHorizontal: direction === 'LR' || direction === 'RL' };\n}\n","import { Graph, getHandlePosition, getHandleDirection } from '../graph';\nimport { Point, HandleSide, LayoutDirection, EdgeKind } from '../types';\n\nexport interface RoutedEdge {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n points: Point[];\n kind: EdgeKind;\n}\n\n/**\n * Route all edges with orthogonal paths.\n * Reconstructs original edges from dummy node chains.\n */\nexport function routeEdges(\n graph: Graph,\n direction: LayoutDirection,\n edgeMargin: number\n): RoutedEdge[] {\n const chains = collectEdgeChains(graph);\n const routes: RoutedEdge[] = [];\n\n for (const chain of chains) {\n routes.push(routeChain(graph, chain, direction, edgeMargin));\n }\n\n return routes;\n}\n\ninterface EdgeChain {\n originalId: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n dummyNodes: string[];\n reversed: boolean;\n kind: EdgeKind;\n}\n\nfunction collectEdgeChains(graph: Graph): EdgeChain[] {\n const chains: EdgeChain[] = [];\n const visited = new Set<string>();\n\n for (const [edgeId, edge] of graph.edges) {\n if (visited.has(edgeId)) continue;\n\n const fromNode = graph.nodes.get(edge.from);\n if (!fromNode || fromNode.isDummy) continue;\n\n const dummyNodes: string[] = [];\n let currentEdge = edge;\n visited.add(edgeId);\n\n while (true) {\n const toNode = graph.nodes.get(currentEdge.to);\n if (!toNode || !toNode.isDummy) break;\n\n dummyNodes.push(currentEdge.to);\n\n const outEdgeIds = graph.outEdges.get(currentEdge.to);\n if (!outEdgeIds || outEdgeIds.size === 0) break;\n\n let nextEdge = null;\n for (const eid of outEdgeIds) {\n const e = graph.edges.get(eid);\n if (e && e.originalId === edge.originalId) {\n nextEdge = e;\n visited.add(eid);\n break;\n }\n }\n\n if (!nextEdge) {\n const eid = outEdgeIds.values().next().value;\n if (!eid) break;\n nextEdge = graph.edges.get(eid);\n if (!nextEdge) break;\n visited.add(eid);\n }\n\n currentEdge = nextEdge;\n }\n\n chains.push({\n originalId: edge.originalId,\n from: edge.from,\n to: currentEdge.to,\n fromHandle: edge.fromHandle,\n toHandle: currentEdge.toHandle,\n dummyNodes,\n reversed: edge.reversed,\n kind: edge.kind,\n });\n }\n\n return chains;\n}\n\nfunction routeChain(\n graph: Graph,\n chain: EdgeChain,\n direction: LayoutDirection,\n margin: number\n): RoutedEdge {\n const fromNode = graph.nodes.get(chain.from)!;\n const toNode = graph.nodes.get(chain.to)!;\n\n const actualFrom = chain.reversed ? chain.to : chain.from;\n const actualTo = chain.reversed ? chain.from : chain.to;\n const actualFromHandle = chain.reversed ? chain.toHandle : chain.fromHandle;\n const actualToHandle = chain.reversed ? chain.fromHandle : chain.toHandle;\n\n const sourceNode = chain.reversed ? toNode : fromNode;\n const targetNode = chain.reversed ? fromNode : toNode;\n\n const sourcePos = getHandlePosition(sourceNode, actualFromHandle);\n const targetPos = getHandlePosition(targetNode, actualToHandle);\n\n const sourceHandle = sourceNode.handles.find(h => h.id === actualFromHandle);\n const targetHandle = targetNode.handles.find(h => h.id === actualToHandle);\n\n const sourceSide = sourceHandle?.position || getDefaultSourceSide(direction);\n const targetSide = targetHandle?.position || getDefaultTargetSide(direction);\n\n const rawPoints: Point[] = [];\n\n rawPoints.push(sourcePos);\n\n const exitDir = getHandleDirection(sourceSide);\n rawPoints.push({\n x: sourcePos.x + exitDir.x * margin,\n y: sourcePos.y + exitDir.y * margin,\n });\n\n const dummies = chain.reversed ? [...chain.dummyNodes].reverse() : chain.dummyNodes;\n for (const dummyId of dummies) {\n const dummy = graph.nodes.get(dummyId)!;\n rawPoints.push({ x: dummy.x, y: dummy.y });\n }\n\n const entryDir = getHandleDirection(targetSide);\n rawPoints.push({\n x: targetPos.x + entryDir.x * margin,\n y: targetPos.y + entryDir.y * margin,\n });\n\n rawPoints.push(targetPos);\n\n const points = makeOrthogonal(rawPoints, direction);\n\n return {\n id: chain.originalId,\n from: actualFrom,\n to: actualTo,\n fromHandle: actualFromHandle,\n toHandle: actualToHandle,\n points,\n kind: chain.kind,\n };\n}\n\nfunction makeOrthogonal(points: Point[], direction: LayoutDirection): Point[] {\n if (points.length < 2) return points;\n\n const result: Point[] = [points[0]];\n const isVerticalFlow = direction === 'TB' || direction === 'BT';\n\n for (let i = 1; i < points.length; i++) {\n const prev = result[result.length - 1];\n const curr = points[i];\n\n const dx = Math.abs(prev.x - curr.x);\n const dy = Math.abs(prev.y - curr.y);\n\n if (dx < 0.01 || dy < 0.01) {\n result.push(curr);\n continue;\n }\n\n if (isVerticalFlow) {\n const midY = (prev.y + curr.y) / 2;\n result.push({ x: prev.x, y: midY });\n result.push({ x: curr.x, y: midY });\n } else {\n const midX = (prev.x + curr.x) / 2;\n result.push({ x: midX, y: prev.y });\n result.push({ x: midX, y: curr.y });\n }\n\n result.push(curr);\n }\n\n return cleanupPoints(result);\n}\n\nfunction cleanupPoints(points: Point[]): Point[] {\n if (points.length <= 2) return points;\n\n const result: Point[] = [points[0]];\n\n for (let i = 1; i < points.length - 1; i++) {\n const prev = result[result.length - 1];\n const curr = points[i];\n const next = points[i + 1];\n\n const sameX = Math.abs(prev.x - curr.x) < 0.01 && Math.abs(curr.x - next.x) < 0.01;\n const sameY = Math.abs(prev.y - curr.y) < 0.01 && Math.abs(curr.y - next.y) < 0.01;\n\n if (!sameX && !sameY) {\n result.push(curr);\n } else if (sameX || sameY) {\n continue;\n } else {\n result.push(curr);\n }\n }\n\n result.push(points[points.length - 1]);\n return result;\n}\n\nfunction getDefaultSourceSide(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'bottom';\n case 'BT': return 'top';\n case 'LR': return 'right';\n case 'RL': return 'left';\n }\n}\n\nfunction getDefaultTargetSide(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'top';\n case 'BT': return 'bottom';\n case 'LR': return 'left';\n case 'RL': return 'right';\n }\n}\n","import { EdgeOutput, NodeOutput, ResolvedOptions } from '../types';\n\n/**\n * Pack disjoint connected components side-by-side (in the order axis) so the\n * overall layout is roughly square instead of a long ribbon.\n *\n * Compound parents are kept as atomic groups: children move with their parent.\n */\nexport function packComponents(\n nodes: NodeOutput[],\n edges: EdgeOutput[],\n options: ResolvedOptions,\n): void {\n if (nodes.length === 0) return;\n\n // Walk the parentId chain to find the top-level ancestor of every node.\n const idToNode = new Map<string, NodeOutput>();\n for (const n of nodes) idToNode.set(n.id, n);\n const rootOf = new Map<string, string>();\n function topAncestor(id: string): string {\n if (rootOf.has(id)) return rootOf.get(id)!;\n const n = idToNode.get(id);\n if (!n || !n.parentId || !idToNode.has(n.parentId)) {\n rootOf.set(id, id);\n return id;\n }\n const r = topAncestor(n.parentId);\n rootOf.set(id, r);\n return r;\n }\n for (const n of nodes) topAncestor(n.id);\n\n // Union-find by edge connectivity, but only over top-level ancestors so\n // children of a single compound stay with the compound.\n const parent = new Map<string, string>();\n function find(x: string): string {\n let cur = x;\n while (parent.get(cur) !== cur) {\n const p = parent.get(cur)!;\n parent.set(cur, parent.get(p)!);\n cur = parent.get(cur)!;\n }\n return cur;\n }\n function union(a: string, b: string): void {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n }\n for (const n of nodes) parent.set(topAncestor(n.id), topAncestor(n.id));\n for (const e of edges) {\n const ra = topAncestor(e.from);\n const rb = topAncestor(e.to);\n if (idToNode.has(ra) && idToNode.has(rb)) union(ra, rb);\n }\n\n // Group every node (including children) by its component's representative.\n const groups = new Map<string, NodeOutput[]>();\n for (const n of nodes) {\n const root = topAncestor(n.id);\n const comp = find(root);\n const arr = groups.get(comp) ?? [];\n arr.push(n);\n groups.set(comp, arr);\n }\n\n if (groups.size <= 1) return;\n\n const isHorizontal = options.direction === 'LR' || options.direction === 'RL';\n\n // Build per-component bounding boxes (including their edge bend points).\n const edgesByComp = new Map<string, EdgeOutput[]>();\n for (const e of edges) {\n const root = topAncestor(e.from);\n const comp = find(root);\n const arr = edgesByComp.get(comp) ?? [];\n arr.push(e);\n edgesByComp.set(comp, arr);\n }\n\n interface CompBox {\n id: string;\n nodes: NodeOutput[];\n edges: EdgeOutput[];\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n }\n\n const boxes: CompBox[] = [];\n for (const [compId, group] of groups) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of group) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n const compEdges = edgesByComp.get(compId) ?? [];\n for (const e of compEdges) {\n for (const p of e.points) {\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 boxes.push({ id: compId, nodes: group, edges: compEdges, minX, minY, maxX, maxY });\n }\n\n // Sort largest-first along the rank axis so we lead with the dominant component.\n boxes.sort((a, b) => {\n const sizeA = isHorizontal ? a.maxX - a.minX : a.maxY - a.minY;\n const sizeB = isHorizontal ? b.maxX - b.minX : b.maxY - b.minY;\n return sizeB - sizeA;\n });\n\n const gap = options.layerSpacing;\n let cursor = 0;\n for (const box of boxes) {\n if (isHorizontal) {\n // Pack vertically (order axis is Y for LR).\n const dy = cursor - box.minY;\n const dx = -box.minX;\n for (const n of box.nodes) {\n n.x += dx;\n n.y += dy;\n for (const h of n.handles) {\n h.x += dx;\n h.y += dy;\n }\n }\n for (const e of box.edges) {\n for (const p of e.points) {\n p.x += dx;\n p.y += dy;\n }\n }\n cursor += (box.maxY - box.minY) + gap;\n } else {\n // Pack horizontally (order axis is X for TB).\n const dx = cursor - box.minX;\n const dy = -box.minY;\n for (const n of box.nodes) {\n n.x += dx;\n n.y += dy;\n for (const h of n.handles) {\n h.x += dx;\n h.y += dy;\n }\n }\n for (const e of box.edges) {\n for (const p of e.points) {\n p.x += dx;\n p.y += dy;\n }\n }\n cursor += (box.maxX - box.minX) + gap;\n }\n }\n}\n","import {\n EdgeInput,\n HandleInput,\n HandleSide,\n LayoutDirection,\n LayoutInput,\n NodeInput,\n ResolvedOptions,\n} from './types';\n\n/**\n * Inspect every input node and offer rotation proposals to the application\n * when the node's handle layout doesn't match how the layout engine will end\n * up placing it.\n *\n * The expected handle orientation depends on the node's role:\n *\n * - **Rail nodes** (with at least one control edge): they flow along the\n * global direction. In TB: inputs on top, outputs on bottom.\n * - **Value nodes** (only data edges): they end up as sidecars on the side\n * of their consumer. Their handles must point TOWARD the consumer — i.e.\n * opposite to the consumer's handle. A value attached to a `left` handle\n * of the consumer will sit on the consumer's left flank, so its output\n * needs to face `right`.\n *\n * The application's `onProposal` callback may:\n * - accept by returning the proposed node (or a modified version)\n * - reject by returning `null` / `undefined` / nothing\n */\nexport function applyRotationProposals(input: LayoutInput, options: ResolvedOptions): LayoutInput {\n if (!options.onProposal) return input;\n\n const nodeIndex = new Map<string, NodeInput>(input.nodes.map(n => [n.id, n]));\n\n const newNodes = input.nodes.map(node => {\n const role = classifyNode(node, input.edges);\n const expected = expectedSidesFor(node, role, input.edges, nodeIndex, options.direction);\n\n const proposal = computeProposal(node, expected, options.direction, role);\n if (!proposal) return node;\n const accepted = options.onProposal!(proposal);\n return accepted ?? node;\n });\n\n return { nodes: newNodes, edges: input.edges };\n}\n\ntype NodeRole =\n | { kind: 'rail' }\n | { kind: 'value'; consumerSide: HandleSide | null }\n | { kind: 'isolated' };\n\nfunction classifyNode(node: NodeInput, edges: EdgeInput[]): NodeRole {\n const incident = edges.filter(e => e.from === node.id || e.to === node.id);\n if (incident.length === 0) return { kind: 'isolated' };\n\n const allData = incident.every(e => (e.kind ?? 'control') === 'data');\n if (!allData) return { kind: 'rail' };\n\n // Value node — find which side of the (first) consumer it lands on.\n // A value typically has a single consumer; if it has several, the first one\n // wins (the sidecar placement uses the dominant consumer too, so this is a\n // reasonable approximation at proposal time).\n for (const e of incident) {\n const consumerId = e.from === node.id ? e.to : e.from;\n const consumerHandleId = e.from === node.id ? e.toHandle : e.fromHandle;\n const sideHint = sideHintFromHandle(consumerId, consumerHandleId, edges, /* recursing */ false);\n if (sideHint) return { kind: 'value', consumerSide: sideHint };\n }\n return { kind: 'value', consumerSide: null };\n}\n\nfunction sideHintFromHandle(\n _consumerId: string,\n _handleId: string,\n _edges: EdgeInput[],\n _recursing: boolean,\n): HandleSide | null {\n // The handle's position is on the consumer's node — but we don't have direct\n // access to the consumer NodeInput here without an index. The caller of\n // `classifyNode` resolves this through `expectedSidesFor` below.\n return null;\n}\n\nfunction expectedSidesFor(\n node: NodeInput,\n role: NodeRole,\n edges: EdgeInput[],\n index: Map<string, NodeInput>,\n direction: LayoutDirection,\n): { input: HandleSide; output: HandleSide } {\n if (role.kind === 'isolated' || role.kind === 'rail') {\n return { input: inputSideFor(direction), output: outputSideFor(direction) };\n }\n\n // Value: figure out which side of the consumer the value will land on.\n const consumerHandleSide = findConsumerHandleSide(node, edges, index);\n if (!consumerHandleSide) {\n return { input: inputSideFor(direction), output: outputSideFor(direction) };\n }\n\n // Sidecar placement only re-positions along the layout's order axis:\n // - TB/BT (vertical flow): values go on the consumer's left/right\n // ↳ a 'left' handle on the consumer → value sits at left → value's\n // output handle must face 'right' to reach the consumer.\n // ↳ symmetric for 'right'.\n // ↳ a 'top'/'bottom' handle: the value will be balanced left/right by\n // `splitValuesBySide`. We bias to face horizontally (right) for TB.\n // - LR/RL (horizontal flow): values go above/below.\n // ↳ 'top' handle → value sits above → output 'bottom'.\n // ↳ 'bottom' handle → output 'top'.\n // ↳ 'left'/'right' handle: bias vertically (bottom for LR).\n const isVerticalFlow = direction === 'TB' || direction === 'BT';\n\n let outputSide: HandleSide;\n if (isVerticalFlow) {\n if (consumerHandleSide === 'left') outputSide = 'right';\n else if (consumerHandleSide === 'right') outputSide = 'left';\n else outputSide = 'right'; // neutral, default to facing right\n } else {\n if (consumerHandleSide === 'top') outputSide = 'bottom';\n else if (consumerHandleSide === 'bottom') outputSide = 'top';\n else outputSide = 'bottom';\n }\n\n return { input: outputSide, output: outputSide };\n}\n\nfunction findConsumerHandleSide(\n value: NodeInput,\n edges: EdgeInput[],\n index: Map<string, NodeInput>,\n): HandleSide | null {\n for (const e of edges) {\n const isFromValue = e.from === value.id;\n const isToValue = e.to === value.id;\n if (!isFromValue && !isToValue) continue;\n\n const consumerId = isFromValue ? e.to : e.from;\n const consumer = index.get(consumerId);\n if (!consumer) continue;\n\n const consumerHandleId = isFromValue ? e.toHandle : e.fromHandle;\n const consumerHandle = consumer.handles.find(h => h.id === consumerHandleId);\n if (consumerHandle) return consumerHandle.position;\n }\n return null;\n}\n\nfunction computeProposal(\n node: NodeInput,\n expected: { input: HandleSide; output: HandleSide },\n direction: LayoutDirection,\n role: NodeRole,\n): ReturnType<typeof buildProposal> | null {\n if (node.handles.length === 0) return null;\n const currentScore = score(node.handles, expected);\n if (currentScore.matchRatio >= 1) return null;\n\n const candidates: { rotation: 90 | -90 | 180; score: ReturnType<typeof score> }[] = [];\n for (const rot of [90, -90, 180] as const) {\n const rotated = rotateHandles(node.handles, rot);\n candidates.push({ rotation: rot, score: score(rotated, expected) });\n }\n\n candidates.sort((a, b) => b.score.matchRatio - a.score.matchRatio);\n const best = candidates[0];\n if (best.score.matchRatio <= currentScore.matchRatio) return null;\n\n return buildProposal(node, best.rotation, currentScore, best.score, direction, expected, role);\n}\n\nfunction buildProposal(\n node: NodeInput,\n rotation: 90 | -90 | 180,\n current: ReturnType<typeof score>,\n proposedScore: ReturnType<typeof score>,\n direction: LayoutDirection,\n expected: { input: HandleSide; output: HandleSide },\n role: NodeRole,\n) {\n const proposed: NodeInput = { ...node, handles: rotateHandles(node.handles, rotation) };\n const roleDesc = role.kind === 'value'\n ? `value node should face ${expected.output} (its sidecar lands opposite the consumer's handle)`\n : `direction ${direction} expects inputs on ${expected.input} and outputs on ${expected.output}`;\n return {\n type: 'rotate' as const,\n nodeId: node.id,\n current: node,\n proposed,\n rotation,\n reason: `${roleDesc}; ${current.matched}/${current.total} handles match, ${proposedScore.matched}/${proposedScore.total} after rotation`,\n };\n}\n\nfunction inputSideFor(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'top';\n case 'BT': return 'bottom';\n case 'LR': return 'left';\n case 'RL': return 'right';\n }\n}\n\nfunction outputSideFor(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'bottom';\n case 'BT': return 'top';\n case 'LR': return 'right';\n case 'RL': return 'left';\n }\n}\n\nfunction score(\n handles: HandleInput[],\n expected: { input: HandleSide; output: HandleSide },\n): { matched: number; total: number; matchRatio: number } {\n let matched = 0;\n let total = 0;\n for (const h of handles) {\n total++;\n if (h.type === 'input' && h.position === expected.input) matched++;\n else if (h.type === 'output' && h.position === expected.output) matched++;\n }\n return { matched, total, matchRatio: total === 0 ? 1 : matched / total };\n}\n\n/**\n * Rotate a set of handles by `rot` degrees clockwise. The handles' position\n * along the side (offset) is preserved.\n *\n * Note: width/height of the node are NOT swapped here. The caller is free to\n * swap them when accepting the proposal (most layouts use square-ish nodes,\n * so we don't enforce a dimension swap).\n */\nexport function rotateHandles(handles: HandleInput[], rot: 90 | -90 | 180): HandleInput[] {\n const rotateSide = (s: HandleSide): HandleSide => {\n if (rot === 180) {\n return s === 'top' ? 'bottom' : s === 'bottom' ? 'top' : s === 'left' ? 'right' : 'left';\n }\n if (rot === 90) {\n return s === 'top' ? 'right' : s === 'right' ? 'bottom' : s === 'bottom' ? 'left' : 'top';\n }\n return s === 'top' ? 'left' : s === 'left' ? 'bottom' : s === 'bottom' ? 'right' : 'top';\n };\n return handles.map(h => ({ ...h, position: rotateSide(h.position) }));\n}\n","import {\n LayoutInput,\n LayoutOptions,\n LayoutResult,\n NodeOutput,\n EdgeOutput,\n HandleOutput,\n NodeInput,\n EdgeInput,\n resolveOptions,\n ResolvedOptions,\n} from './types';\nimport { Graph, buildGraph, getHandlePosition } from './graph';\nimport { breakCycles } from './algorithms/cycle-breaking';\nimport { assignLayers, insertDummyNodes } from './algorithms/layer-assignment';\nimport { minimizeCrossings } from './algorithms/crossing-minimization';\nimport { assignCoordinates } from './algorithms/coordinate-assignment';\nimport { placeValueSidecars, railLayers } from './algorithms/value-placement';\nimport { routeEdges } from './algorithms/edge-routing';\nimport { packComponents } from './algorithms/component-packing';\nimport { applyRotationProposals } from './proposals';\n\n/** Vertical room reserved at the top of a compound for the parent's own label. */\nconst COMPOUND_HEADER = 28;\n\n/**\n * Compute a complete layout for the given graph, with full compound (nested)\n * support and disjoint-component packing.\n */\nexport function layout(input: LayoutInput, options?: LayoutOptions): LayoutResult {\n const resolved = resolveOptions(options);\n if (input.nodes.length === 0) return { nodes: [], edges: [] };\n const adjusted = applyRotationProposals(input, resolved);\n return layoutCompound(adjusted, resolved);\n}\n\n/** Flat (single-level) layout on an already-built graph. */\nexport function computeLayout(graph: Graph, options: ResolvedOptions): LayoutResult {\n if (graph.nodes.size === 0) return { nodes: [], edges: [] };\n\n breakCycles(graph);\n\n let layers = assignLayers(graph);\n layers = insertDummyNodes(graph, layers);\n\n // Rail-only layers drive crossings + coords. Values are attached afterwards.\n let rail = railLayers(layers, graph);\n rail = minimizeCrossings(graph, rail, options.crossingMinimizationIterations);\n assignCoordinates(graph, rail, options);\n\n // Attach value nodes as sidecars to their dominant consumer.\n placeValueSidecars(graph, layers, options);\n\n const routedEdges = routeEdges(graph, options.direction, options.edgeMargin);\n return buildResult(graph, routedEdges);\n}\n\nfunction buildResult(graph: Graph, routedEdges: ReturnType<typeof routeEdges>): LayoutResult {\n const nodes: NodeOutput[] = [];\n const edges: EdgeOutput[] = [];\n\n for (const [, node] of graph.nodes) {\n if (node.isDummy) continue;\n\n const handles: HandleOutput[] = node.handles.map(h => {\n const pos = getHandlePosition(node, h.id);\n return { id: h.id, type: h.type, position: h.position, x: pos.x, y: pos.y };\n });\n\n nodes.push({\n id: node.id,\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n handles,\n parentId: node.parentId,\n });\n }\n\n for (const route of routedEdges) {\n edges.push({\n id: route.id,\n from: route.from,\n to: route.to,\n fromHandle: route.fromHandle,\n toHandle: route.toHandle,\n points: route.points,\n kind: route.kind,\n });\n }\n\n return { nodes, edges };\n}\n\n/**\n * Compound Sugiyama: process nests bottom-up so each compound has its size\n * computed from its laid-out children before it appears in a higher-level pass.\n */\nfunction layoutCompound(input: LayoutInput, options: ResolvedOptions): LayoutResult {\n const nodeMap = new Map(input.nodes.map(n => [n.id, n]));\n\n const childrenByParent = new Map<string, NodeInput[]>();\n const rootNodes: NodeInput[] = [];\n for (const n of input.nodes) {\n if (n.parentId && nodeMap.has(n.parentId)) {\n const arr = childrenByParent.get(n.parentId) ?? [];\n arr.push(n);\n childrenByParent.set(n.parentId, arr);\n } else {\n rootNodes.push(n);\n }\n }\n\n const compoundIds = new Set(childrenByParent.keys());\n\n // Compute nesting depth so we can process compounds deepest-first.\n const depthCache = new Map<string, number>();\n function depthOf(id: string): number {\n if (depthCache.has(id)) return depthCache.get(id)!;\n const n = nodeMap.get(id);\n const d = n?.parentId && nodeMap.has(n.parentId) ? depthOf(n.parentId) + 1 : 0;\n depthCache.set(id, d);\n return d;\n }\n for (const n of input.nodes) depthOf(n.id);\n\n const sortedCompounds = [...compoundIds].sort((a, b) => depthOf(b) - depthOf(a));\n\n // Sub-layouts of each compound, keyed by the compound's id.\n const subLayouts = new Map<string, LayoutResult>();\n // Final published sizes for each compound (after children were laid out).\n const compoundSize = new Map<string, { width: number; height: number }>();\n\n for (const compoundId of sortedCompounds) {\n const children = childrenByParent.get(compoundId) ?? [];\n if (children.length === 0) continue;\n\n const childIdSet = new Set(children.map(c => c.id));\n const subEdges = input.edges.filter(e => childIdSet.has(e.from) && childIdSet.has(e.to));\n\n // Swap in computed sizes for any nested compounds among the children.\n const sizedChildren = children.map(c => {\n const sz = compoundSize.get(c.id);\n return sz ? { ...c, width: sz.width, height: sz.height } : c;\n });\n\n // Force packComponents off inside compounds — children are presumed connected\n // (and packing inside a parent box would visually conflict).\n const subOptions: ResolvedOptions = { ...options, packComponents: false };\n const subInput: LayoutInput = { nodes: sizedChildren.map(stripParent), edges: subEdges };\n const subResult = layoutFlat(subInput, subOptions);\n subLayouts.set(compoundId, subResult);\n\n // Compound size: bounding box of children + padding + header for the label.\n const bbox = computeBoundingBox(subResult.nodes);\n const innerW = bbox.width + options.compoundPadding * 2;\n const innerH = bbox.height + options.compoundPadding * 2 + COMPOUND_HEADER;\n\n const original = nodeMap.get(compoundId)!;\n compoundSize.set(compoundId, {\n width: Math.max(innerW, original.width),\n height: Math.max(innerH, original.height),\n });\n }\n\n // Root-level layout: compounds participate with their inflated size.\n const sizedRootNodes = rootNodes.map(n => {\n const sz = compoundSize.get(n.id);\n return sz ? { ...n, width: sz.width, height: sz.height } : n;\n });\n const rootIdSet = new Set(rootNodes.map(n => n.id));\n const rootEdges = input.edges.filter(e => {\n // Edges between root-level entities (compound boundaries count as roots).\n return rootIdSet.has(e.from) && rootIdSet.has(e.to);\n });\n\n const rootResult = layoutFlat({ nodes: sizedRootNodes.map(stripParent), edges: rootEdges }, options);\n\n // Final assembly: drop root nodes in, then translate each compound's children\n // by an offset that places them inside their parent's interior.\n const finalNodes: NodeOutput[] = [];\n const finalEdges: EdgeOutput[] = [];\n\n // First, replay the root result. Compound parents stay as visible rectangles.\n for (const n of rootResult.nodes) {\n const wasCompound = compoundIds.has(n.id);\n finalNodes.push({\n ...n,\n parentId: nodeMap.get(n.id)?.parentId,\n });\n if (wasCompound) {\n placeCompoundChildren(n, compoundId => subLayouts.get(compoundId), finalNodes, finalEdges, options, nodeMap);\n }\n }\n finalEdges.push(...rootResult.edges);\n\n if (options.packComponents) {\n packComponents(finalNodes, finalEdges, options);\n }\n\n return { nodes: finalNodes, edges: finalEdges };\n}\n\n/**\n * Recursively place a compound's children inside the parent's bounding box.\n * Translates positions from the sub-layout's local coords to the parent's frame.\n */\nfunction placeCompoundChildren(\n parent: NodeOutput,\n getSub: (compoundId: string) => LayoutResult | undefined,\n finalNodes: NodeOutput[],\n finalEdges: EdgeOutput[],\n options: ResolvedOptions,\n nodeMap: Map<string, NodeInput>,\n): void {\n const sub = getSub(parent.id);\n if (!sub) return;\n\n const bbox = computeBoundingBox(sub.nodes);\n // local-origin = (bbox.minX, bbox.minY) -> map to parent.x + padding, parent.y + padding + header\n const dx = parent.x + options.compoundPadding - bbox.minX;\n const dy = parent.y + options.compoundPadding + COMPOUND_HEADER - bbox.minY;\n\n // Center horizontally inside available space if the parent was inflated past\n // the children's natural width.\n const availableW = parent.width - options.compoundPadding * 2;\n const slackX = (availableW - bbox.width) / 2;\n const availableH = parent.height - options.compoundPadding * 2 - COMPOUND_HEADER;\n const slackY = (availableH - bbox.height) / 2;\n const cx = dx + Math.max(0, slackX);\n const cy = dy + Math.max(0, slackY);\n\n for (const child of sub.nodes) {\n const placed: NodeOutput = {\n ...child,\n x: child.x + cx,\n y: child.y + cy,\n handles: child.handles.map(h => ({ ...h, x: h.x + cx, y: h.y + cy })),\n parentId: nodeMap.get(child.id)?.parentId ?? parent.id,\n };\n finalNodes.push(placed);\n if (getSub(child.id)) {\n placeCompoundChildren(placed, getSub, finalNodes, finalEdges, options, nodeMap);\n }\n }\n\n for (const edge of sub.edges) {\n finalEdges.push({\n ...edge,\n points: edge.points.map(p => ({ x: p.x + cx, y: p.y + cy })),\n });\n }\n}\n\n/** Strip parentId from a node copy so flat layout won't recurse. */\nfunction stripParent(n: NodeInput): NodeInput {\n const { parentId: _ignored, ...rest } = n;\n return rest;\n}\n\nfunction layoutFlat(input: LayoutInput, options: ResolvedOptions): LayoutResult {\n const graph = buildGraph(input.nodes, input.edges, {\n controlWeight: options.controlWeight,\n dataWeight: options.dataWeight,\n });\n return computeLayout(graph, options);\n}\n\nfunction computeBoundingBox(\n nodes: { x: number; y: number; width: number; height: number }[],\n): { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number } {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n if (!isFinite(minX)) {\n minX = 0; minY = 0; maxX = 0; maxY = 0;\n }\n return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY };\n}\n","import {\n LayoutInput,\n LayoutOptions,\n LayoutResult,\n NodeInput,\n EdgeInput,\n resolveOptions,\n ResolvedOptions,\n} from './types';\nimport { layout } from './layout';\n\n/**\n * Incremental layout engine.\n * Maintains layout state and supports adding/removing nodes\n * without full recomputation.\n *\n * Compound layouts and value-pulled nodes are handled through the unified\n * `layout()` entry point, so any input change re-uses the same logic.\n */\nexport class IncrementalLayout {\n private resolvedOptions: ResolvedOptions;\n private options: LayoutOptions | undefined;\n private inputNodes: Map<string, NodeInput> = new Map();\n private inputEdges: Map<string, EdgeInput> = new Map();\n private lastResult: LayoutResult | null = null;\n private nodePositions: Map<string, { x: number; y: number }> = new Map();\n\n constructor(options?: LayoutOptions) {\n this.options = options;\n this.resolvedOptions = resolveOptions(options);\n }\n\n setGraph(input: LayoutInput): LayoutResult {\n this.inputNodes.clear();\n this.inputEdges.clear();\n for (const node of input.nodes) this.inputNodes.set(node.id, node);\n for (const edge of input.edges) this.inputEdges.set(edge.id, edge);\n return this.recompute();\n }\n\n addNodes(nodes: NodeInput[], edges?: EdgeInput[]): LayoutResult {\n for (const node of nodes) this.inputNodes.set(node.id, node);\n if (edges) for (const edge of edges) this.inputEdges.set(edge.id, edge);\n return this.recomputeWithStability(new Set(nodes.map(n => n.id)));\n }\n\n removeNodes(nodeIds: string[]): LayoutResult {\n const removedSet = new Set(nodeIds);\n for (const id of nodeIds) this.inputNodes.delete(id);\n for (const [edgeId, edge] of this.inputEdges) {\n if (removedSet.has(edge.from) || removedSet.has(edge.to)) {\n this.inputEdges.delete(edgeId);\n }\n }\n for (const id of nodeIds) this.nodePositions.delete(id);\n return this.recompute();\n }\n\n addEdges(edges: EdgeInput[]): LayoutResult {\n for (const edge of edges) this.inputEdges.set(edge.id, edge);\n return this.recomputeWithStability(new Set<string>());\n }\n\n removeEdges(edgeIds: string[]): LayoutResult {\n for (const id of edgeIds) this.inputEdges.delete(id);\n return this.recompute();\n }\n\n getResult(): LayoutResult | null {\n return this.lastResult;\n }\n\n private recompute(): LayoutResult {\n const input: LayoutInput = {\n nodes: [...this.inputNodes.values()],\n edges: [...this.inputEdges.values()],\n };\n this.lastResult = layout(input, this.options);\n this.cachePositions();\n return this.lastResult;\n }\n\n private recomputeWithStability(newNodeIds: Set<string>): LayoutResult {\n const input: LayoutInput = {\n nodes: [...this.inputNodes.values()],\n edges: [...this.inputEdges.values()],\n };\n\n const fresh = layout(input, this.options);\n this.lastResult = this.applyStability(fresh, newNodeIds);\n this.cachePositions();\n return this.lastResult;\n }\n\n /**\n * Blend the freshly computed positions with the previous ones, so existing\n * nodes don't jump too far when a small change happens.\n */\n private applyStability(fresh: LayoutResult, newNodeIds: Set<string>): LayoutResult {\n if (this.nodePositions.size === 0) return fresh;\n const STABILITY_WEIGHT = 0.3;\n\n const blended: LayoutResult = {\n nodes: fresh.nodes.map(n => {\n if (newNodeIds.has(n.id)) return n;\n const old = this.nodePositions.get(n.id);\n if (!old) return n;\n const dx = old.x - n.x;\n const dy = old.y - n.y;\n const x = n.x + dx * STABILITY_WEIGHT;\n const y = n.y + dy * STABILITY_WEIGHT;\n const ddx = x - n.x;\n const ddy = y - n.y;\n return {\n ...n,\n x,\n y,\n handles: n.handles.map(h => ({ ...h, x: h.x + ddx, y: h.y + ddy })),\n };\n }),\n edges: fresh.edges,\n };\n return blended;\n }\n\n private cachePositions(): void {\n if (!this.lastResult) return;\n this.nodePositions.clear();\n for (const node of this.lastResult.nodes) {\n this.nodePositions.set(node.id, { x: node.x, y: node.y });\n }\n }\n}\n","import { LayoutResult, NodeOutput, EdgeOutput } from './types';\n\n/**\n * Render a `LayoutResult` to a human-readable text block.\n *\n * Useful when iterating on the algorithm without opening a browser:\n * - a per-layer summary (Y bands in TB, X bands in LR-ish)\n * - per-node hierarchy + bbox\n * - per-edge endpoints and kind\n * - an ASCII grid (optional) sketching the final layout\n */\nexport interface PrintLayoutOptions {\n /** Include an ASCII grid sketch (default: true). */\n grid?: boolean;\n /** Grid resolution: characters per coordinate unit (default: auto). */\n gridScale?: number;\n /** Max grid width in characters (default: 80). */\n gridWidth?: number;\n}\n\nexport function printLayout(result: LayoutResult, options: PrintLayoutOptions = {}): string {\n const lines: string[] = [];\n const { nodes, edges } = result;\n\n if (nodes.length === 0) return '(empty layout)';\n\n // ----- bounding box -----\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n lines.push(`=== layout ${nodes.length} nodes, ${edges.length} edges ===`);\n lines.push(`bbox: x=[${minX.toFixed(0)}..${maxX.toFixed(0)}] y=[${minY.toFixed(0)}..${maxY.toFixed(0)}] (${(maxX - minX).toFixed(0)} x ${(maxY - minY).toFixed(0)})`);\n\n // ----- Y bands (TB-style) -----\n const byY = [...nodes].sort((a, b) => a.y - b.y || a.x - b.x);\n const bands: NodeOutput[][] = [];\n for (const n of byY) {\n const placed = bands.find(b => Math.abs(b[0].y - n.y) < 1);\n if (placed) placed.push(n);\n else bands.push([n]);\n }\n\n lines.push('');\n lines.push('--- Y bands ---');\n for (const band of bands) {\n const sorted = [...band].sort((a, b) => a.x - b.x);\n const summary = sorted.map(n => {\n const p = n.parentId ? `[${n.parentId}/]` : '';\n return `${p}${n.id}@(${n.x.toFixed(0)},${n.y.toFixed(0)} ${n.width}x${n.height})`;\n }).join(' ');\n lines.push(` y=${band[0].y.toFixed(0).padStart(4)} : ${summary}`);\n }\n\n // ----- hierarchy -----\n const byParent = new Map<string | undefined, NodeOutput[]>();\n for (const n of nodes) {\n const key = n.parentId;\n const arr = byParent.get(key) ?? [];\n arr.push(n);\n byParent.set(key, arr);\n }\n const compoundIds = new Set<string>();\n for (const k of byParent.keys()) {\n if (k && nodes.find(n => n.id === k)) compoundIds.add(k);\n }\n if (compoundIds.size > 0) {\n lines.push('');\n lines.push('--- hierarchy ---');\n function printSubtree(id: string | undefined, depth: number) {\n const children = byParent.get(id) ?? [];\n for (const c of children) {\n const prefix = ' '.repeat(depth);\n const tag = compoundIds.has(c.id) ? ' (compound)' : '';\n lines.push(`${prefix}- ${c.id}${tag} bbox=(${c.x.toFixed(0)},${c.y.toFixed(0)})..(${(c.x + c.width).toFixed(0)},${(c.y + c.height).toFixed(0)})`);\n if (compoundIds.has(c.id)) printSubtree(c.id, depth + 1);\n }\n }\n printSubtree(undefined, 0);\n }\n\n // ----- edges -----\n lines.push('');\n lines.push('--- edges ---');\n for (const e of edges) {\n const head = e.points[0];\n const tail = e.points[e.points.length - 1];\n lines.push(` [${e.kind}] ${e.from}.${e.fromHandle} → ${e.to}.${e.toHandle} (${head.x.toFixed(0)},${head.y.toFixed(0)}) → (${tail.x.toFixed(0)},${tail.y.toFixed(0)}) via ${e.points.length} pts`);\n }\n\n // ----- overlap check -----\n const overlaps = findOverlaps(nodes);\n if (overlaps.length > 0) {\n lines.push('');\n lines.push('--- OVERLAPS (problem!) ---');\n for (const o of overlaps) {\n lines.push(` ${o.a} overlaps ${o.b}`);\n }\n }\n\n if (options.grid !== false) {\n lines.push('');\n lines.push('--- ASCII grid ---');\n lines.push(asciiGrid(nodes, edges, options));\n }\n\n return lines.join('\\n');\n}\n\nfunction findOverlaps(nodes: NodeOutput[]): { a: string; b: string }[] {\n const out: { a: string; b: string }[] = [];\n const compoundIds = new Set<string>();\n for (const n of nodes) if (n.parentId) compoundIds.add(n.parentId);\n\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const a = nodes[i];\n const b = nodes[j];\n // Skip compound-vs-child intentional overlap (compound contains its kids).\n if (a.id === b.parentId || b.id === a.parentId) continue;\n // Skip sibling values vs compound parent (handled by hierarchy).\n const overlapX = a.x < b.x + b.width && b.x < a.x + a.width;\n const overlapY = a.y < b.y + b.height && b.y < a.y + a.height;\n if (overlapX && overlapY) {\n out.push({ a: a.id, b: b.id });\n }\n }\n }\n return out;\n}\n\nfunction asciiGrid(nodes: NodeOutput[], edges: EdgeOutput[], options: PrintLayoutOptions): string {\n if (nodes.length === 0) return '';\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n for (const e of edges) for (const p of e.points) {\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 targetW = options.gridWidth ?? 80;\n const layoutW = Math.max(1, maxX - minX);\n const layoutH = Math.max(1, maxY - minY);\n const scaleX = options.gridScale ?? targetW / layoutW;\n // Characters are roughly twice as tall as wide -> halve Y scale.\n const scaleY = scaleX * 0.5;\n\n const w = Math.max(1, Math.ceil(layoutW * scaleX) + 1);\n const h = Math.max(1, Math.ceil(layoutH * scaleY) + 1);\n\n if (h > 80) return '(grid suppressed: too tall — pass {grid:false} to skip)';\n\n const grid: string[][] = Array.from({ length: h }, () => Array.from({ length: w }, () => ' '));\n\n const compoundIds = new Set<string>();\n for (const n of nodes) if (n.parentId) compoundIds.add(n.parentId);\n\n // Draw nodes\n for (const n of nodes) {\n const x0 = Math.round((n.x - minX) * scaleX);\n const y0 = Math.round((n.y - minY) * scaleY);\n const x1 = Math.max(x0, Math.round((n.x + n.width - minX) * scaleX) - 1);\n const y1 = Math.max(y0, Math.round((n.y + n.height - minY) * scaleY) - 1);\n const isCompound = compoundIds.has(n.id);\n const ch = isCompound ? '.' : '#';\n for (let y = y0; y <= y1 && y < h; y++) {\n for (let x = x0; x <= x1 && x < w; x++) {\n if (y < 0 || x < 0) continue;\n if (y === y0 || y === y1 || x === x0 || x === x1) grid[y][x] = ch;\n else if (isCompound) {\n // empty interior for compounds\n } else grid[y][x] = ch;\n }\n }\n // Label: first letters of id, centered top-left of box\n const label = n.id.slice(0, Math.min(n.id.length, Math.max(2, x1 - x0 - 1)));\n const lx = Math.max(0, x0 + 1);\n const ly = Math.max(0, y0);\n for (let i = 0; i < label.length && lx + i < w; i++) {\n if (ly < h) grid[ly][lx + i] = label[i];\n }\n }\n\n return grid.map(row => row.join('')).join('\\n');\n}\n"],"mappings":";AAsIO,SAAS,eAAe,SAA0C;AACvE,SAAO;AAAA,IACL,WAAW,SAAS,aAAa;AAAA,IACjC,aAAa,SAAS,eAAe;AAAA,IACrC,cAAc,SAAS,gBAAgB;AAAA,IACvC,gCAAgC,SAAS,kCAAkC;AAAA,IAC3E,kCAAkC,SAAS,oCAAoC;AAAA,IAC/E,YAAY,SAAS,cAAc;AAAA,IACnC,eAAe,SAAS,aAAa,WAAW;AAAA,IAChD,YAAY,SAAS,aAAa,QAAQ;AAAA,IAC1C,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,iBAAiB,SAAS,mBAAmB;AAAA,IAC7C,YAAY,SAAS;AAAA,EACvB;AACF;;;ACrHO,IAAM,QAAN,MAAY;AAAA,EAAZ;AACL,iBAAmC,oBAAI,IAAI;AAC3C,iBAAmC,oBAAI,IAAI;AAC3C,oBAAqC,oBAAI,IAAI;AAC7C,mBAAoC,oBAAI,IAAI;AAAA;AAAA,EAE5C,QAAQ,MAA0B;AAChC,SAAK,MAAM,IAAI,KAAK,IAAI,IAAI;AAC5B,QAAI,CAAC,KAAK,SAAS,IAAI,KAAK,EAAE,EAAG,MAAK,SAAS,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AACrE,QAAI,CAAC,KAAK,QAAQ,IAAI,KAAK,EAAE,EAAG,MAAK,QAAQ,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AAAA,EACrE;AAAA,EAEA,QAAQ,MAA0B;AAChC,SAAK,MAAM,IAAI,KAAK,IAAI,IAAI;AAC5B,QAAI,CAAC,KAAK,SAAS,IAAI,KAAK,IAAI,EAAG,MAAK,SAAS,IAAI,KAAK,MAAM,oBAAI,IAAI,CAAC;AACzE,QAAI,CAAC,KAAK,QAAQ,IAAI,KAAK,EAAE,EAAG,MAAK,QAAQ,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AACnE,SAAK,SAAS,IAAI,KAAK,IAAI,EAAG,IAAI,KAAK,EAAE;AACzC,SAAK,QAAQ,IAAI,KAAK,EAAE,EAAG,IAAI,KAAK,EAAE;AAAA,EACxC;AAAA,EAEA,WAAW,QAAsB;AAC/B,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM;AACX,SAAK,SAAS,IAAI,KAAK,IAAI,GAAG,OAAO,MAAM;AAC3C,SAAK,QAAQ,IAAI,KAAK,EAAE,GAAG,OAAO,MAAM;AACxC,SAAK,MAAM,OAAO,MAAM;AAAA,EAC1B;AAAA,EAEA,WAAW,QAAsB;AAC/B,UAAM,aAAa,CAAC,GAAI,KAAK,SAAS,IAAI,MAAM,KAAK,CAAC,CAAE;AACxD,UAAM,YAAY,CAAC,GAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC,CAAE;AACtD,eAAW,OAAO,WAAY,MAAK,WAAW,GAAG;AACjD,eAAW,OAAO,UAAW,MAAK,WAAW,GAAG;AAChD,SAAK,MAAM,OAAO,MAAM;AACxB,SAAK,SAAS,OAAO,MAAM;AAC3B,SAAK,QAAQ,OAAO,MAAM;AAAA,EAC5B;AAAA,EAEA,aAAa,QAA0B;AACrC,UAAM,SAAmB,CAAC;AAC1B,UAAM,YAAY,KAAK,QAAQ,IAAI,MAAM;AACzC,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,YAAI,KAAM,QAAO,KAAK,KAAK,IAAI;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,QAA0B;AACnC,UAAM,SAAmB,CAAC;AAC1B,UAAM,aAAa,KAAK,SAAS,IAAI,MAAM;AAC3C,QAAI,YAAY;AACd,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,YAAI,KAAM,QAAO,KAAK,KAAK,EAAE;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAOO,SAAS,WACd,OACA,OACA,MAAyB,EAAE,eAAe,GAAG,YAAY,KAAK,GACvD;AACP,QAAM,QAAQ,IAAI,MAAM;AAExB,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ;AAAA,MACZ,IAAI,KAAK;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,QAAQ,EAAE,UAAU,IAAI,EAAE;AAAA,MAClE,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU,KAAK;AAAA,MACf,YAAY;AAAA,MACZ,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAiB,KAAK,QAAQ;AACpC,UAAM,gBAAgB,SAAS,YAAY,IAAI,gBAAgB,IAAI;AACnE,UAAM,QAAQ;AAAA,MACZ,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,UAAU;AAAA,MACV,YAAY,KAAK;AAAA,MACjB;AAAA,MACA,QAAQ,KAAK,UAAU;AAAA,IACzB,CAAC;AAAA,EACH;AAMA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,UAAM,MAAM,MAAM,QAAQ,IAAI,MAAM;AACpC,UAAM,OAAO,MAAM,SAAS,IAAI,MAAM;AACtC,QAAI,aAAa;AACjB,QAAI,KAAK;AACP,iBAAW,OAAO,KAAK;AACrB,YAAI,MAAM,MAAM,IAAI,GAAG,GAAG,SAAS,WAAW;AAAE,uBAAa;AAAM;AAAA,QAAO;AAAA,MAC5E;AAAA,IACF;AACA,QAAI,CAAC,cAAc,MAAM;AACvB,iBAAW,OAAO,MAAM;AACtB,YAAI,MAAM,MAAM,IAAI,GAAG,GAAG,SAAS,WAAW;AAAE,uBAAa;AAAM;AAAA,QAAO;AAAA,MAC5E;AAAA,IACF;AACA,UAAM,iBAAiB,KAAK,QAAQ,MAAM,MAAM,QAAQ;AACxD,SAAK,UAAU,CAAC,cAAc,gBAAgB;AAAA,EAChD;AAEA,SAAO;AACT;AAGO,SAAS,kBAAkB,MAAoB,UAAyB;AAC7E,QAAM,SAAS,KAAK,QAAQ,KAAK,OAAK,EAAE,OAAO,QAAQ;AACvD,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,GAAG,KAAK,IAAI,KAAK,QAAQ,GAAG,GAAG,KAAK,IAAI,KAAK,SAAS,EAAE;AAAA,EACnE;AAEA,QAAM,SAAS,OAAO,UAAU;AAEhC,UAAQ,OAAO,UAAU;AAAA,IACvB,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO,GAAG,KAAK,EAAE;AAAA,IACtD,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO,GAAG,KAAK,IAAI,KAAK,OAAO;AAAA,IACpE,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO;AAAA,IACvD,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,KAAK,OAAO,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO;AAAA,EACtE;AACF;AAGO,SAAS,mBAAmB,MAAyB;AAC1D,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAO,aAAO,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACjC,KAAK;AAAU,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACnC,KAAK;AAAQ,aAAO,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IAClC,KAAK;AAAS,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACpC;AACF;;;AC1LO,SAAS,YAAY,OAA2B;AACrD,QAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ;AACnC,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,WAAW,oBAAI,IAAY;AAEjC,aAAW,UAAU,MAAM,MAAM,KAAK,GAAG;AACvC,UAAM,IAAI,QAAQ,KAAK;AAAA,EACzB;AAGA,QAAM,UAAU,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACrD,UAAM,SAAS,MAAM,SAAS,IAAI,CAAC,GAAG,QAAQ,MAAM,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ;AAClF,UAAM,SAAS,MAAM,SAAS,IAAI,CAAC,GAAG,QAAQ,MAAM,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ;AAClF,WAAO,QAAQ;AAAA,EACjB,CAAC;AAED,WAAS,IAAI,QAAsB;AACjC,UAAM,IAAI,QAAQ,IAAI;AAEtB,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,YAAY;AACd,iBAAW,UAAU,YAAY;AAC/B,cAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAI,CAAC,KAAM;AAEX,cAAM,cAAc,MAAM,IAAI,KAAK,EAAE;AACrC,YAAI,gBAAgB,MAAM;AACxB,mBAAS,IAAI,MAAM;AAAA,QACrB,WAAW,gBAAgB,OAAO;AAChC,cAAI,KAAK,EAAE;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI,QAAQ,KAAK;AAAA,EACzB;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,MAAM,IAAI,MAAM,MAAM,OAAO;AAC/B,UAAI,MAAM;AAAA,IACZ;AAAA,EACF;AAGA,aAAW,UAAU,UAAU;AAC7B,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,CAAC,KAAM;AAEX,UAAM,WAAW,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,UAAU,CAAC,KAAK;AAAA,IAClB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACtDO,SAAS,aAAa,OAA0B;AACrD,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,WAAW,oBAAI,IAAY;AAGjC,WAAS,aAAa,QAAwB;AAC5C,QAAI,OAAO,IAAI,MAAM,EAAG,QAAO,OAAO,IAAI,MAAM;AAChD,QAAI,SAAS,IAAI,MAAM,EAAG,QAAO;AAEjC,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,CAAC,QAAQ,KAAK,QAAS,QAAO;AAElC,aAAS,IAAI,MAAM;AAEnB,UAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,QAAI,eAAe;AACnB,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,QAAQ,KAAK,SAAS,UAAW;AACtC,cAAM,OAAO,MAAM,MAAM,IAAI,KAAK,IAAI;AACtC,YAAI,CAAC,QAAQ,KAAK,QAAS;AAC3B,uBAAe,KAAK,IAAI,cAAc,aAAa,KAAK,IAAI,CAAC;AAAA,MAC/D;AAAA,IACF;AAEA,UAAM,QAAQ,eAAe;AAC7B,WAAO,IAAI,QAAQ,KAAK;AACxB,SAAK,QAAQ;AACb,aAAS,OAAO,MAAM;AACtB,WAAO;AAAA,EACT;AAEA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,KAAK,QAAS,cAAa,MAAM;AAAA,EACxC;AAGA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,iBAA2B,CAAC;AAElC,UAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,MAAM,MAAM,MAAM,IAAI,KAAK,IAAI;AACrC,YAAI,OAAO,CAAC,IAAI,WAAW,OAAO,IAAI,KAAK,IAAI,GAAG;AAChD,yBAAe,KAAK,OAAO,IAAI,KAAK,IAAI,CAAE;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,YAAY;AACd,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,MAAM,MAAM,MAAM,IAAI,KAAK,EAAE;AACnC,YAAI,OAAO,CAAC,IAAI,WAAW,OAAO,IAAI,KAAK,EAAE,GAAG;AAC9C,yBAAe,KAAK,OAAO,IAAI,KAAK,EAAE,CAAE;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,eAAe,SAAS,GAAG;AAC7B,qBAAe,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACnC,cAAQ,eAAe,KAAK,MAAM,eAAe,SAAS,CAAC,CAAC;AAAA,IAC9D,OAAO;AACL,cAAQ;AAAA,IACV;AACA,WAAO,IAAI,QAAQ,KAAK;AACxB,SAAK,QAAQ;AAAA,EACf;AAGA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,OAAO,IAAI,MAAM,GAAG;AACvB,aAAO,IAAI,QAAQ,CAAC;AACpB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAGA,MAAI,WAAW;AACf,MAAI,WAAW;AACf,aAAW,KAAK,OAAO,OAAO,GAAG;AAC/B,QAAI,IAAI,SAAU,YAAW;AAC7B,QAAI,IAAI,SAAU,YAAW;AAAA,EAC/B;AACA,MAAI,CAAC,SAAS,QAAQ,EAAG,QAAO,CAAC;AACjC,MAAI,aAAa,GAAG;AAClB,eAAW,CAAC,IAAI,CAAC,KAAK,QAAQ;AAC5B,YAAM,MAAM,IAAI;AAChB,aAAO,IAAI,IAAI,GAAG;AAClB,YAAM,IAAI,MAAM,MAAM,IAAI,EAAE;AAC5B,UAAI,EAAG,GAAE,QAAQ;AAAA,IACnB;AACA,gBAAY;AAAA,EACd;AAEA,QAAM,cAA0B,MAAM,KAAK,EAAE,QAAQ,WAAW,EAAE,GAAG,MAAM,CAAC,CAAC;AAC7E,aAAW,CAAC,QAAQ,KAAK,KAAK,QAAQ;AACpC,gBAAY,KAAK,EAAE,KAAK,MAAM;AAAA,EAChC;AAEA,SAAO;AACT;AAOO,SAAS,iBAAiB,OAAc,QAAgC;AAC7E,MAAI,eAAe;AACnB,QAAM,iBAAiB,CAAC,GAAG,MAAM,MAAM,OAAO,CAAC;AAE/C,aAAW,QAAQ,gBAAgB;AACjC,QAAI,KAAK,SAAS,UAAW;AAE7B,UAAM,WAAW,MAAM,MAAM,IAAI,KAAK,IAAI;AAC1C,UAAM,SAAS,MAAM,MAAM,IAAI,KAAK,EAAE;AACtC,QAAI,CAAC,YAAY,CAAC,OAAQ;AAE1B,UAAM,YAAY,SAAS;AAC3B,UAAM,UAAU,OAAO;AACvB,UAAM,OAAO,UAAU;AAEvB,QAAI,QAAQ,EAAG;AAEf,UAAM,WAAW,KAAK,EAAE;AAExB,QAAI,aAAa,KAAK;AACtB,QAAI,eAAe,KAAK;AAExB,aAAS,IAAI,YAAY,GAAG,IAAI,SAAS,KAAK;AAC5C,YAAM,UAAU,WAAW,cAAc;AAEzC,YAAM,QAAQ;AAAA,QACZ,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,EAAE,IAAI,MAAM,MAAM,SAAS,UAAU,OAAO,QAAQ,IAAI;AAAA,UACxD,EAAE,IAAI,OAAO,MAAM,UAAU,UAAU,UAAU,QAAQ,IAAI;AAAA,QAC/D;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,QACP,GAAG;AAAA,QACH,GAAG;AAAA,QACH,YAAY;AAAA,QACZ,SAAS;AAAA,MACX,CAAC;AAED,aAAO,CAAC,EAAE,KAAK,OAAO;AAEtB,YAAM,QAAQ;AAAA,QACZ,IAAI,WAAW,YAAY,IAAI,CAAC;AAAA,QAChC,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,MAAM,KAAK;AAAA,QACX,QAAQ,KAAK;AAAA,MACf,CAAC;AAED,mBAAa;AACb,qBAAe;AAAA,IACjB;AAEA,UAAM,QAAQ;AAAA,MACZ,IAAI,WAAW,YAAY;AAAA,MAC3B,MAAM;AAAA,MACN,IAAI,KAAK;AAAA,MACT,YAAY;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,MACjB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACvMO,SAAS,kBACd,OACA,QACA,YACY;AACZ,MAAI,OAAO,UAAU,EAAG,QAAO;AAE/B,QAAM,aAAa,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAG1D,QAAM,gBAAgB,aAAa,MAC/B,KAAK,IAAI,YAAY,CAAC,IACtB,aAAa,MACX,KAAK,IAAI,YAAY,EAAE,IACvB;AAGN,QAAM,gBAAgB,aAAa;AAGnC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,aAAS,IAAI,GAAG,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK;AACzC,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;AACzC,UAAI,KAAM,MAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,aAAa,OAAO,IAAI,OAAK,CAAC,GAAG,CAAC,CAAC;AACvC,MAAI,gBAAgB,kBAAkB,OAAO,MAAM;AACnD,MAAI,qBAAqB;AAEzB,WAAS,OAAO,GAAG,OAAO,eAAe,QAAQ;AAE/C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,wBAAkB,OAAO,QAAQ,GAAG,IAAI;AAAA,IAC1C;AAGA,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,wBAAkB,OAAO,QAAQ,GAAG,MAAM;AAAA,IAC5C;AAGA,QAAI,CAAC,eAAe;AAClB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAI,OAAO,CAAC,EAAE,UAAU,KAAK;AAC3B,2BAAiB,OAAO,QAAQ,CAAC;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,kBAAkB,OAAO,MAAM;AACjD,QAAI,YAAY,eAAe;AAC7B,sBAAgB;AAChB,mBAAa,OAAO,IAAI,OAAK,CAAC,GAAG,CAAC,CAAC;AACnC,2BAAqB;AAAA,IACvB,OAAO;AACL;AAAA,IACF;AAEA,QAAI,cAAc,KAAK,sBAAsB,EAAG;AAAA,EAClD;AAGA,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,WAAO,CAAC,IAAI,WAAW,CAAC;AACxB,aAAS,IAAI,GAAG,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK;AACzC,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;AACzC,UAAI,KAAM,MAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBACP,OACA,QACA,YACA,WACM;AACN,QAAM,QAAQ,OAAO,UAAU;AAC/B,QAAM,gBAAgB,cAAc,OAAO,aAAa,IAAI,aAAa;AAEzE,MAAI,gBAAgB,KAAK,iBAAiB,OAAO,OAAQ;AAGzD,QAAM,cAAc,IAAI,IAAI,OAAO,aAAa,CAAC;AAEjD,QAAM,cAAc,oBAAI,IAAoB;AAE5C,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,SAAS,MAAM,CAAC;AAGtB,QAAI,MAAM;AACV,QAAI,QAAQ;AAEZ,QAAI,cAAc,MAAM;AACtB,YAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,UAAI,WAAW;AACb,mBAAW,OAAO,WAAW;AAC3B,gBAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,cAAI,QAAQ,YAAY,IAAI,KAAK,IAAI,GAAG;AACtC,kBAAM,WAAW,MAAM,MAAM,IAAI,KAAK,IAAI;AAC1C,gBAAI,UAAU;AACZ,qBAAO,SAAS;AAChB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,UAAI,YAAY;AACd,mBAAW,OAAO,YAAY;AAC5B,gBAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,cAAI,QAAQ,YAAY,IAAI,KAAK,EAAE,GAAG;AACpC,kBAAM,WAAW,MAAM,MAAM,IAAI,KAAK,EAAE;AACxC,gBAAI,UAAU;AACZ,qBAAO,SAAS;AAChB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,gBAAY,IAAI,QAAQ,QAAQ,IAAI,MAAM,QAAQ,CAAC;AAAA,EACrD;AAEA,QAAM,KAAK,CAAC,GAAG,MAAM,YAAY,IAAI,CAAC,IAAK,YAAY,IAAI,CAAC,CAAE;AAE9D,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM,CAAC,CAAC;AACrC,QAAI,KAAM,MAAK,QAAQ;AAAA,EACzB;AACF;AAEA,SAAS,iBAAiB,OAAc,QAAoB,YAA0B;AACpF,QAAM,QAAQ,OAAO,UAAU;AAC/B,MAAI,MAAM,UAAU,EAAG;AAEvB,MAAI,WAAW;AACf,MAAI,SAAS;AAEb,SAAO,YAAY,SAAS,GAAG;AAC7B,eAAW;AACX;AACA,aAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,YAAM,QAAQ,MAAM,CAAC;AACrB,YAAM,QAAQ,MAAM,IAAI,CAAC;AAEzB,YAAM,kBAAkB,mBAAmB,OAAO,QAAQ,YAAY,OAAO,KAAK;AAGlF,YAAM,CAAC,IAAI;AACX,YAAM,IAAI,CAAC,IAAI;AACf,YAAM,KAAK,MAAM,MAAM,IAAI,KAAK;AAChC,YAAM,KAAK,MAAM,MAAM,IAAI,KAAK;AAChC,UAAI,GAAI,IAAG,QAAQ,IAAI;AACvB,UAAI,GAAI,IAAG,QAAQ;AAEnB,YAAM,iBAAiB,mBAAmB,OAAO,QAAQ,YAAY,OAAO,KAAK;AAEjF,UAAI,iBAAiB,iBAAiB;AACpC,mBAAW;AAAA,MACb,OAAO;AAEL,cAAM,CAAC,IAAI;AACX,cAAM,IAAI,CAAC,IAAI;AACf,YAAI,GAAI,IAAG,QAAQ;AACnB,YAAI,GAAI,IAAG,QAAQ,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,mBACP,OACA,QACA,YACA,OACA,OACQ;AACR,MAAI,YAAY;AAGhB,MAAI,aAAa,GAAG;AAClB,UAAM,aAAa,IAAI,IAAI,OAAO,aAAa,CAAC,CAAC;AAEjD,UAAM,SAAmB,CAAC;AAC1B,UAAM,SAAmB,CAAC;AAE1B,UAAM,MAAM,MAAM,QAAQ,IAAI,KAAK;AACnC,QAAI,KAAK;AACP,iBAAW,OAAO,KAAK;AACrB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,QAAQ,WAAW,IAAI,KAAK,IAAI,GAAG;AACrC,gBAAM,IAAI,MAAM,MAAM,IAAI,KAAK,IAAI;AACnC,cAAI,EAAG,QAAO,KAAK,EAAE,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,QAAQ,IAAI,KAAK;AACnC,QAAI,KAAK;AACP,iBAAW,OAAO,KAAK;AACrB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,QAAQ,WAAW,IAAI,KAAK,IAAI,GAAG;AACrC,gBAAM,IAAI,MAAM,MAAM,IAAI,KAAK,IAAI;AACnC,cAAI,EAAG,QAAO,KAAK,EAAE,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,eAAW,MAAM,QAAQ;AACvB,iBAAW,MAAM,QAAQ;AACvB,YAAI,KAAK,GAAI;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,aAAa,OAAO,SAAS,GAAG;AAClC,UAAM,aAAa,IAAI,IAAI,OAAO,aAAa,CAAC,CAAC;AAEjD,UAAM,SAAmB,CAAC;AAC1B,UAAM,SAAmB,CAAC;AAE1B,UAAM,OAAO,MAAM,SAAS,IAAI,KAAK;AACrC,QAAI,MAAM;AACR,iBAAW,OAAO,MAAM;AACtB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,QAAQ,WAAW,IAAI,KAAK,EAAE,GAAG;AACnC,gBAAM,IAAI,MAAM,MAAM,IAAI,KAAK,EAAE;AACjC,cAAI,EAAG,QAAO,KAAK,EAAE,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,SAAS,IAAI,KAAK;AACrC,QAAI,MAAM;AACR,iBAAW,OAAO,MAAM;AACtB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,QAAQ,WAAW,IAAI,KAAK,EAAE,GAAG;AACnC,gBAAM,IAAI,MAAM,MAAM,IAAI,KAAK,EAAE;AACjC,cAAI,EAAG,QAAO,KAAK,EAAE,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,eAAW,MAAM,QAAQ;AACvB,iBAAW,MAAM,QAAQ;AACvB,YAAI,KAAK,GAAI;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,kBAAkB,OAAc,QAA4B;AAC1E,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC1C,aAAS,oBAAoB,OAAO,OAAO,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAAA,EAC9D;AACA,SAAO;AACT;AAMA,SAAS,oBACP,OACA,YACA,YACQ;AACR,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,QAAQ,CAAC,IAAI,QAAQ,SAAS,IAAI,IAAI,GAAG,CAAC;AAGrD,QAAM,YAAgC,CAAC;AACvC,WAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ;AACnD,UAAM,SAAS,WAAW,IAAI;AAC9B,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,CAAC,WAAY;AACjB,eAAW,OAAO,YAAY;AAC5B,YAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,UAAI,CAAC,KAAM;AACX,YAAM,KAAK,SAAS,IAAI,KAAK,EAAE;AAC/B,UAAI,OAAO,QAAW;AACpB,kBAAU,KAAK,CAAC,MAAM,EAAE,CAAC;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,UAAU,EAAG,QAAO;AAGlC,YAAU,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAGnD,QAAM,iBAAiB,UAAU,IAAI,OAAK,EAAE,CAAC,CAAC;AAC9C,SAAO,eAAe,cAAc;AACtC;AAEA,SAAS,eAAe,KAAuB;AAC7C,MAAI,IAAI,UAAU,EAAG,QAAO;AAE5B,QAAM,MAAM,IAAI,UAAU;AAC1B,QAAM,OAAO,IAAI,MAAM,GAAG,GAAG;AAC7B,QAAM,QAAQ,IAAI,MAAM,GAAG;AAE3B,MAAI,QAAQ,eAAe,IAAI,IAAI,eAAe,KAAK;AAEvD,MAAI,IAAI,GAAG,IAAI,GAAG,IAAI;AACtB,SAAO,IAAI,KAAK,UAAU,IAAI,MAAM,QAAQ;AAC1C,QAAI,KAAK,CAAC,KAAK,MAAM,CAAC,GAAG;AACvB,UAAI,GAAG,IAAI,KAAK,GAAG;AAAA,IACrB,OAAO;AACL,eAAS,KAAK,SAAS;AACvB,UAAI,GAAG,IAAI,MAAM,GAAG;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,IAAI,KAAK,OAAQ,KAAI,GAAG,IAAI,KAAK,GAAG;AAC3C,SAAO,IAAI,MAAM,OAAQ,KAAI,GAAG,IAAI,MAAM,GAAG;AAE7C,SAAO;AACT;;;AC7UO,SAAS,kBACd,OACA,QACA,SACM;AACN,QAAM,eAAe,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AACzE,QAAM,aAAa,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAEvE,sBAAoB,OAAO,QAAQ,SAAS,cAAc,UAAU;AACpE,uBAAqB,OAAO,QAAQ,SAAS,YAAY;AACzD,oBAAkB,OAAO,QAAQ,SAAS,YAAY;AACxD;AAKA,SAAS,oBACP,OACA,QACA,SACA,cACA,YACM;AAEN,QAAM,aAAuB,CAAC;AAC9B,aAAW,SAAS,QAAQ;AAC1B,QAAI,UAAU;AACd,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,OAAO,eAAe,KAAK,QAAQ,KAAK;AAC9C,gBAAU,KAAK,IAAI,SAAS,IAAI;AAAA,IAClC;AACA,eAAW,KAAK,OAAO;AAAA,EACzB;AAGA,QAAM,iBAA2B,CAAC;AAClC,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,mBAAe,KAAK,GAAG;AACvB,WAAO,WAAW,CAAC,IAAI,QAAQ;AAAA,EACjC;AAGA,MAAI,YAAY;AACd,UAAM,YAAY,MAAM,QAAQ;AAChC,aAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,qBAAe,CAAC,IAAI,YAAY,eAAe,CAAC,IAAI,WAAW,CAAC;AAAA,IAClE;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,eAAW,UAAU,OAAO,CAAC,GAAG;AAC9B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,WAAW,eAAe,KAAK,QAAQ,KAAK;AAClD,YAAM,UAAU,WAAW,CAAC,IAAI,YAAY;AAE5C,UAAI,cAAc;AAChB,aAAK,IAAI,eAAe,CAAC,IAAI;AAAA,MAC/B,OAAO;AACL,aAAK,IAAI,eAAe,CAAC,IAAI;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,qBACP,OACA,QACA,SACA,cACM;AACN,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM;AAEV,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,OAAO,eAAe,KAAK,SAAS,KAAK;AAE/C,UAAI,cAAc;AAChB,aAAK,IAAI;AAAA,MACX,OAAO;AACL,aAAK,IAAI;AAAA,MACX;AAEA,aAAO,OAAO,QAAQ;AAAA,IACxB;AAGA,UAAM,YAAY,MAAM,QAAQ;AAChC,UAAM,eAAe,CAAC,YAAY;AAElC,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,UAAI,cAAc;AAChB,aAAK,KAAK;AAAA,MACZ,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,kBACP,OACA,QACA,SACA,cACM;AACN,WAAS,OAAO,GAAG,OAAO,QAAQ,kCAAkC,QAAQ;AAE1E,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,oBAAc,OAAO,OAAO,CAAC,GAAG,SAAS,YAAY;AAAA,IACvD;AAGA,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,oBAAc,OAAO,OAAO,CAAC,GAAG,SAAS,YAAY;AAAA,IACvD;AAAA,EACF;AAEA,kBAAgB,OAAO,QAAQ,YAAY;AAC7C;AAEA,SAAS,cACP,OACA,OACA,SACA,cACM;AACN,MAAI,MAAM,WAAW,EAAG;AAGxB,QAAM,UAAU,oBAAI,IAAoB;AAExC,aAAW,UAAU,OAAO;AAC1B,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,UAAM,YAAY,CAAC,GAAG,MAAM,aAAa,MAAM,GAAG,GAAG,MAAM,WAAW,MAAM,CAAC;AAE7E,QAAI,UAAU,WAAW,GAAG;AAC1B,cAAQ,IAAI,QAAQ,YAAY,MAAM,YAAY,CAAC;AACnD;AAAA,IACF;AAGA,UAAM,YAAY,UACf,IAAI,SAAO;AACV,YAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,aAAO,YAAY,GAAG,YAAY,IAAI,aAAa,GAAG,YAAY,IAAI;AAAA,IACxE,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAEvB,UAAM,WAAW,aAAa,MAAM,YAAY;AAChD,UAAM,SAAS,UAAU,SAAS,MAAM,KACnC,UAAU,UAAU,SAAS,IAAI,CAAC,IAAI,UAAU,UAAU,SAAS,CAAC,KAAK,IAC1E,UAAU,KAAK,MAAM,UAAU,SAAS,CAAC,CAAC;AAE9C,YAAQ,IAAI,QAAQ,SAAS,WAAW,CAAC;AAAA,EAC3C;AAGA,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,aAAa,QAAQ,IAAI,MAAM;AAEnC,QAAI,IAAI,GAAG;AACT,YAAM,SAAS,MAAM,IAAI,CAAC;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,UAAU,YAAY,MAAM,YAAY,IAAI,aAAa,MAAM,YAAY;AACjF,mBAAa,KAAK,IAAI,YAAY,UAAU,QAAQ,WAAW;AAAA,IACjE;AAEA,gBAAY,MAAM,cAAc,UAAU;AAAA,EAC5C;AAGA,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC1C,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,UAAM,SAAS,MAAM,IAAI,CAAC;AAC1B,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AAEnC,UAAM,UAAU,YAAY,MAAM,YAAY,IAAI,aAAa,MAAM,YAAY;AACjF,UAAM,YAAY,YAAY,MAAM,YAAY;AAEhD,QAAI,UAAU,QAAQ,cAAc,WAAW;AAC7C,kBAAY,MAAM,cAAc,YAAY,QAAQ,cAAc,aAAa,MAAM,YAAY,CAAC;AAAA,IACpG;AAAA,EACF;AACF;AAEA,SAAS,gBACP,OACA,QACA,cACM;AACN,MAAI,OAAO,WAAW,EAAG;AAGzB,MAAI,YAAY;AAChB,MAAI,YAAY;AAEhB,aAAW,SAAS,QAAQ;AAC1B,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,MAAM,YAAY,MAAM,YAAY;AAC1C,YAAM,OAAO,aAAa,MAAM,YAAY;AAC5C,kBAAY,KAAK,IAAI,WAAW,GAAG;AACnC,kBAAY,KAAK,IAAI,WAAW,MAAM,IAAI;AAAA,IAC5C;AAAA,EACF;AAGA,QAAM,SAAS,CAAC;AAChB,aAAW,SAAS,QAAQ;AAC1B,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,kBAAY,MAAM,cAAc,YAAY,MAAM,YAAY,IAAI,MAAM;AAAA,IAC1E;AAAA,EACF;AAGA,MAAI,UAAU;AACd,aAAW,SAAS,QAAQ;AAC1B,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,MAAM,eAAe,KAAK,IAAI,KAAK;AACzC,gBAAU,KAAK,IAAI,SAAS,GAAG;AAAA,IACjC;AAAA,EACF;AAEA,MAAI,YAAY,GAAG;AACjB,eAAW,SAAS,QAAQ;AAC1B,iBAAW,UAAU,OAAO;AAC1B,cAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAI,cAAc;AAChB,eAAK,KAAK;AAAA,QACZ,OAAO;AACL,eAAK,KAAK;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,YAAY,MAAgC,cAA+B;AAClF,SAAO,eAAe,KAAK,IAAI,KAAK;AACtC;AAEA,SAAS,YAAY,MAAgC,cAAuB,OAAqB;AAC/F,MAAI,cAAc;AAChB,SAAK,IAAI;AAAA,EACX,OAAO;AACL,SAAK,IAAI;AAAA,EACX;AACF;AAEA,SAAS,aAAa,MAAyC,cAA+B;AAC5F,SAAO,eAAe,KAAK,SAAS,KAAK;AAC3C;;;AChQO,SAAS,mBACd,OACA,QACA,SACM;AACN,QAAM,eAAe,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAOzE,QAAM,cAA4B,CAAC;AACnC,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,KAAK,WAAW,KAAK,QAAS;AAEnC,UAAM,WAAW,qBAAqB,OAAO,MAAM;AACnD,QAAI,UAAU;AACZ,kBAAY,KAAK,EAAE,SAAS,QAAQ,YAAY,SAAS,CAAC;AAAA,IAC5D,OAAO;AACL,mBAAa,KAAK,MAAM;AAAA,IAC1B;AAAA,EACF;AAGA,QAAM,aAAa,oBAAI,IAAsB;AAC7C,aAAW,EAAE,SAAS,WAAW,KAAK,aAAa;AACjD,UAAM,MAAM,WAAW,IAAI,UAAU,KAAK,CAAC;AAC3C,QAAI,KAAK,OAAO;AAChB,eAAW,IAAI,YAAY,GAAG;AAAA,EAChC;AAGA,aAAW,CAAC,YAAY,IAAI,KAAK,YAAY;AAC3C,UAAM,WAAW,MAAM,MAAM,IAAI,UAAU;AAC3C,QAAI,CAAC,SAAU;AAEf,UAAM,EAAE,YAAY,UAAU,IAAI,kBAAkB,OAAO,YAAY,MAAM,YAAY;AAEzF,QAAI,cAAc;AAEhB,YAAM,WAAW,SAAS,IAAI,SAAS,QAAQ;AAC/C,UAAI,UAAU,SAAS;AACvB,iBAAW,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,UAAU,QAAQ,cAAc,EAAE;AACxC,UAAE,IAAI,WAAW,EAAE,QAAQ;AAC3B,kBAAU,EAAE;AAAA,MACd;AACA,UAAI,aAAa,SAAS,IAAI,SAAS;AACvC,iBAAW,OAAO,WAAW;AAC3B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,aAAa,QAAQ;AAC3B,UAAE,IAAI,WAAW,EAAE,QAAQ;AAC3B,qBAAa,EAAE,IAAI,EAAE;AAAA,MACvB;AAAA,IACF,OAAO;AAEL,YAAM,WAAW,SAAS,IAAI,SAAS,SAAS;AAChD,UAAI,WAAW,SAAS;AACxB,iBAAW,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,WAAW,QAAQ,cAAc,EAAE;AACzC,UAAE,IAAI,WAAW,EAAE,SAAS;AAC5B,mBAAW,EAAE;AAAA,MACf;AACA,UAAI,YAAY,SAAS,IAAI,SAAS;AACtC,iBAAW,OAAO,WAAW;AAC3B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,YAAY,QAAQ;AAC1B,UAAE,IAAI,WAAW,EAAE,SAAS;AAC5B,oBAAY,EAAE,IAAI,EAAE;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAIA,MAAI,UAAU,GAAG,UAAU;AAC3B,aAAW,YAAY,cAAc;AACnC,UAAM,IAAI,MAAM,MAAM,IAAI,QAAQ;AAClC,QAAI,CAAC,EAAG;AACR,MAAE,IAAI;AACN,MAAE,IAAI;AACN,QAAI,aAAc,YAAW,EAAE,QAAQ,QAAQ;AAAA,QAC1C,YAAW,EAAE,SAAS,QAAQ;AAAA,EACrC;AACF;AAMA,SAAS,qBAAqB,OAAc,SAAgC;AAC1E,QAAM,SAAS,oBAAI,IAAoB;AAEvC,QAAM,OAAO,MAAM,SAAS,IAAI,OAAO;AACvC,MAAI,MAAM;AACR,eAAW,OAAO,MAAM;AACtB,YAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,UAAI,CAAC,KAAM;AACX,YAAM,QAAQ,MAAM,MAAM,IAAI,KAAK,EAAE;AACrC,UAAI,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,SAAS;AAC7C,eAAO,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACA,QAAM,MAAM,MAAM,QAAQ,IAAI,OAAO;AACrC,MAAI,KAAK;AACP,eAAW,OAAO,KAAK;AACrB,YAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,UAAI,CAAC,KAAM;AACX,YAAM,QAAQ,MAAM,MAAM,IAAI,KAAK,IAAI;AACvC,UAAI,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,SAAS;AAC7C,eAAO,IAAI,KAAK,OAAO,OAAO,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAwB;AAC5B,MAAI,YAAY;AAChB,aAAW,CAAC,IAAI,KAAK,KAAK,QAAQ;AAChC,QAAI,QAAQ,aAAc,UAAU,aAAa,WAAW,QAAQ,KAAK,QAAS;AAChF,eAAS;AACT,kBAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;AAYA,SAAS,kBACP,OACA,YACA,UACA,cAC+C;AAC/C,QAAM,WAAW,MAAM,MAAM,IAAI,UAAU;AAC3C,MAAI,CAAC,SAAU,QAAO,EAAE,YAAY,CAAC,GAAG,QAAQ,EAAE,KAAK,GAAG,WAAW,CAAC,EAAE;AAGxE,QAAM,QAAgB,CAAC;AAEvB,aAAW,OAAO,UAAU;AAC1B,QAAI,OAAqB;AACzB,QAAI,SAAS;AAEb,UAAM,gBAAgB,CAAC,aAAiC;AACtD,UAAI,CAAC,SAAU;AACf,YAAM,SAAS,SAAS,QAAQ,KAAK,OAAK,EAAE,OAAO,QAAQ;AAC3D,UAAI,CAAC,OAAQ;AACb,eAAS,OAAO,UAAU;AAC1B,UAAI,cAAc;AAChB,YAAI,OAAO,aAAa,MAAO,QAAO;AAAA,iBAC7B,OAAO,aAAa,SAAU,QAAO;AAAA,MAChD,OAAO;AACL,YAAI,OAAO,aAAa,OAAQ,QAAO;AAAA,iBAC9B,OAAO,aAAa,QAAS,QAAO;AAAA,MAC/C;AAAA,IACF;AAGA,UAAM,OAAO,MAAM,SAAS,IAAI,GAAG;AACnC,QAAI,KAAM,YAAW,OAAO,MAAM;AAChC,YAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,UAAI,KAAK,EAAE,OAAO,YAAY;AAAE,sBAAc,EAAE,QAAQ;AAAG;AAAA,MAAO;AAAA,IACpE;AACA,QAAI,SAAS,WAAW;AACtB,YAAM,MAAM,MAAM,QAAQ,IAAI,GAAG;AACjC,UAAI,IAAK,YAAW,OAAO,KAAK;AAC9B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,KAAK,EAAE,SAAS,YAAY;AAAE,wBAAc,EAAE,UAAU;AAAG;AAAA,QAAO;AAAA,MACxE;AAAA,IACF;AAEA,UAAM,KAAK,EAAE,IAAI,KAAK,MAAM,OAAO,CAAC;AAAA,EACtC;AAEA,QAAM,SAAS,MAAM,OAAO,OAAK,EAAE,SAAS,QAAQ;AACpD,QAAM,QAAQ,MAAM,OAAO,OAAK,EAAE,SAAS,OAAO;AAClD,QAAM,UAAU,MAAM,OAAO,OAAK,EAAE,SAAS,SAAS;AAGtD,aAAW,KAAK,SAAS;AACvB,QAAI,OAAO,UAAU,MAAM,OAAQ,QAAO,KAAK,CAAC;AAAA,QAC3C,OAAM,KAAK,CAAC;AAAA,EACnB;AAIA,QAAM,MAAM,CAAC,GAAS,MAAa,EAAE,SAAS,EAAE,WAAY,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI;AACjG,SAAO,KAAK,GAAG;AACf,QAAM,KAAK,GAAG;AAEd,SAAO;AAAA,IACL,YAAY,OAAO,IAAI,OAAK,EAAE,EAAE;AAAA,IAChC,WAAW,MAAM,IAAI,OAAK,EAAE,EAAE;AAAA,EAChC;AACF;AAWO,SAAS,WAAW,QAAoB,OAA0B;AACvE,SAAO,OAAO;AAAA,IAAI,WAChB,MAAM,OAAO,QAAM;AACjB,YAAM,IAAI,MAAM,MAAM,IAAI,EAAE;AAC5B,aAAO,KAAK,CAAC,EAAE;AAAA,IACjB,CAAC;AAAA,EACH;AACF;;;ACxOO,SAAS,WACd,OACA,WACA,YACc;AACd,QAAM,SAAS,kBAAkB,KAAK;AACtC,QAAM,SAAuB,CAAC;AAE9B,aAAW,SAAS,QAAQ;AAC1B,WAAO,KAAK,WAAW,OAAO,OAAO,WAAW,UAAU,CAAC;AAAA,EAC7D;AAEA,SAAO;AACT;AAaA,SAAS,kBAAkB,OAA2B;AACpD,QAAM,SAAsB,CAAC;AAC7B,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,QAAQ,IAAI,MAAM,EAAG;AAEzB,UAAM,WAAW,MAAM,MAAM,IAAI,KAAK,IAAI;AAC1C,QAAI,CAAC,YAAY,SAAS,QAAS;AAEnC,UAAM,aAAuB,CAAC;AAC9B,QAAI,cAAc;AAClB,YAAQ,IAAI,MAAM;AAElB,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,MAAM,IAAI,YAAY,EAAE;AAC7C,UAAI,CAAC,UAAU,CAAC,OAAO,QAAS;AAEhC,iBAAW,KAAK,YAAY,EAAE;AAE9B,YAAM,aAAa,MAAM,SAAS,IAAI,YAAY,EAAE;AACpD,UAAI,CAAC,cAAc,WAAW,SAAS,EAAG;AAE1C,UAAI,WAAW;AACf,iBAAW,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,KAAK,EAAE,eAAe,KAAK,YAAY;AACzC,qBAAW;AACX,kBAAQ,IAAI,GAAG;AACf;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,UAAU;AACb,cAAM,MAAM,WAAW,OAAO,EAAE,KAAK,EAAE;AACvC,YAAI,CAAC,IAAK;AACV,mBAAW,MAAM,MAAM,IAAI,GAAG;AAC9B,YAAI,CAAC,SAAU;AACf,gBAAQ,IAAI,GAAG;AAAA,MACjB;AAEA,oBAAc;AAAA,IAChB;AAEA,WAAO,KAAK;AAAA,MACV,YAAY,KAAK;AAAA,MACjB,MAAM,KAAK;AAAA,MACX,IAAI,YAAY;AAAA,MAChB,YAAY,KAAK;AAAA,MACjB,UAAU,YAAY;AAAA,MACtB;AAAA,MACA,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,WACP,OACA,OACA,WACA,QACY;AACZ,QAAM,WAAW,MAAM,MAAM,IAAI,MAAM,IAAI;AAC3C,QAAM,SAAS,MAAM,MAAM,IAAI,MAAM,EAAE;AAEvC,QAAM,aAAa,MAAM,WAAW,MAAM,KAAK,MAAM;AACrD,QAAM,WAAW,MAAM,WAAW,MAAM,OAAO,MAAM;AACrD,QAAM,mBAAmB,MAAM,WAAW,MAAM,WAAW,MAAM;AACjE,QAAM,iBAAiB,MAAM,WAAW,MAAM,aAAa,MAAM;AAEjE,QAAM,aAAa,MAAM,WAAW,SAAS;AAC7C,QAAM,aAAa,MAAM,WAAW,WAAW;AAE/C,QAAM,YAAY,kBAAkB,YAAY,gBAAgB;AAChE,QAAM,YAAY,kBAAkB,YAAY,cAAc;AAE9D,QAAM,eAAe,WAAW,QAAQ,KAAK,OAAK,EAAE,OAAO,gBAAgB;AAC3E,QAAM,eAAe,WAAW,QAAQ,KAAK,OAAK,EAAE,OAAO,cAAc;AAEzE,QAAM,aAAa,cAAc,YAAY,qBAAqB,SAAS;AAC3E,QAAM,aAAa,cAAc,YAAY,qBAAqB,SAAS;AAE3E,QAAM,YAAqB,CAAC;AAE5B,YAAU,KAAK,SAAS;AAExB,QAAM,UAAU,mBAAmB,UAAU;AAC7C,YAAU,KAAK;AAAA,IACb,GAAG,UAAU,IAAI,QAAQ,IAAI;AAAA,IAC7B,GAAG,UAAU,IAAI,QAAQ,IAAI;AAAA,EAC/B,CAAC;AAED,QAAM,UAAU,MAAM,WAAW,CAAC,GAAG,MAAM,UAAU,EAAE,QAAQ,IAAI,MAAM;AACzE,aAAW,WAAW,SAAS;AAC7B,UAAM,QAAQ,MAAM,MAAM,IAAI,OAAO;AACrC,cAAU,KAAK,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAAA,EAC3C;AAEA,QAAM,WAAW,mBAAmB,UAAU;AAC9C,YAAU,KAAK;AAAA,IACb,GAAG,UAAU,IAAI,SAAS,IAAI;AAAA,IAC9B,GAAG,UAAU,IAAI,SAAS,IAAI;AAAA,EAChC,CAAC;AAED,YAAU,KAAK,SAAS;AAExB,QAAM,SAAS,eAAe,WAAW,SAAS;AAElD,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV;AAAA,IACA,MAAM,MAAM;AAAA,EACd;AACF;AAEA,SAAS,eAAe,QAAiB,WAAqC;AAC5E,MAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,QAAM,SAAkB,CAAC,OAAO,CAAC,CAAC;AAClC,QAAM,iBAAiB,cAAc,QAAQ,cAAc;AAE3D,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,UAAM,OAAO,OAAO,CAAC;AAErB,UAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AACnC,UAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAEnC,QAAI,KAAK,QAAQ,KAAK,MAAM;AAC1B,aAAO,KAAK,IAAI;AAChB;AAAA,IACF;AAEA,QAAI,gBAAgB;AAClB,YAAM,QAAQ,KAAK,IAAI,KAAK,KAAK;AACjC,aAAO,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,CAAC;AAClC,aAAO,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,CAAC;AAAA,IACpC,OAAO;AACL,YAAM,QAAQ,KAAK,IAAI,KAAK,KAAK;AACjC,aAAO,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;AAClC,aAAO,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;AAAA,IACpC;AAEA,WAAO,KAAK,IAAI;AAAA,EAClB;AAEA,SAAO,cAAc,MAAM;AAC7B;AAEA,SAAS,cAAc,QAA0B;AAC/C,MAAI,OAAO,UAAU,EAAG,QAAO;AAE/B,QAAM,SAAkB,CAAC,OAAO,CAAC,CAAC;AAElC,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC1C,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,UAAM,OAAO,OAAO,CAAC;AACrB,UAAM,OAAO,OAAO,IAAI,CAAC;AAEzB,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI;AAC9E,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI;AAE9E,QAAI,CAAC,SAAS,CAAC,OAAO;AACpB,aAAO,KAAK,IAAI;AAAA,IAClB,WAAW,SAAS,OAAO;AACzB;AAAA,IACF,OAAO;AACL,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,KAAK,OAAO,OAAO,SAAS,CAAC,CAAC;AACrC,SAAO;AACT;AAEA,SAAS,qBAAqB,WAAwC;AACpE,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;AAEA,SAAS,qBAAqB,WAAwC;AACpE,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;;;ACzOO,SAAS,eACd,OACA,OACA,SACM;AACN,MAAI,MAAM,WAAW,EAAG;AAGxB,QAAM,WAAW,oBAAI,IAAwB;AAC7C,aAAW,KAAK,MAAO,UAAS,IAAI,EAAE,IAAI,CAAC;AAC3C,QAAM,SAAS,oBAAI,IAAoB;AACvC,WAAS,YAAY,IAAoB;AACvC,QAAI,OAAO,IAAI,EAAE,EAAG,QAAO,OAAO,IAAI,EAAE;AACxC,UAAM,IAAI,SAAS,IAAI,EAAE;AACzB,QAAI,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,SAAS,IAAI,EAAE,QAAQ,GAAG;AAClD,aAAO,IAAI,IAAI,EAAE;AACjB,aAAO;AAAA,IACT;AACA,UAAM,IAAI,YAAY,EAAE,QAAQ;AAChC,WAAO,IAAI,IAAI,CAAC;AAChB,WAAO;AAAA,EACT;AACA,aAAW,KAAK,MAAO,aAAY,EAAE,EAAE;AAIvC,QAAM,SAAS,oBAAI,IAAoB;AACvC,WAAS,KAAK,GAAmB;AAC/B,QAAI,MAAM;AACV,WAAO,OAAO,IAAI,GAAG,MAAM,KAAK;AAC9B,YAAM,IAAI,OAAO,IAAI,GAAG;AACxB,aAAO,IAAI,KAAK,OAAO,IAAI,CAAC,CAAE;AAC9B,YAAM,OAAO,IAAI,GAAG;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AACA,WAAS,MAAM,GAAW,GAAiB;AACzC,UAAM,KAAK,KAAK,CAAC;AACjB,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,OAAO,GAAI,QAAO,IAAI,IAAI,EAAE;AAAA,EAClC;AACA,aAAW,KAAK,MAAO,QAAO,IAAI,YAAY,EAAE,EAAE,GAAG,YAAY,EAAE,EAAE,CAAC;AACtE,aAAW,KAAK,OAAO;AACrB,UAAM,KAAK,YAAY,EAAE,IAAI;AAC7B,UAAM,KAAK,YAAY,EAAE,EAAE;AAC3B,QAAI,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,EAAG,OAAM,IAAI,EAAE;AAAA,EACxD;AAGA,QAAM,SAAS,oBAAI,IAA0B;AAC7C,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,YAAY,EAAE,EAAE;AAC7B,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC;AACjC,QAAI,KAAK,CAAC;AACV,WAAO,IAAI,MAAM,GAAG;AAAA,EACtB;AAEA,MAAI,OAAO,QAAQ,EAAG;AAEtB,QAAM,eAAe,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAGzE,QAAM,cAAc,oBAAI,IAA0B;AAClD,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,YAAY,EAAE,IAAI;AAC/B,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,MAAM,YAAY,IAAI,IAAI,KAAK,CAAC;AACtC,QAAI,KAAK,CAAC;AACV,gBAAY,IAAI,MAAM,GAAG;AAAA,EAC3B;AAYA,QAAM,QAAmB,CAAC;AAC1B,aAAW,CAAC,QAAQ,KAAK,KAAK,QAAQ;AACpC,QAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,eAAW,KAAK,OAAO;AACrB,UAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,UAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,UAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,UAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,IAC5C;AACA,UAAM,YAAY,YAAY,IAAI,MAAM,KAAK,CAAC;AAC9C,eAAW,KAAK,WAAW;AACzB,iBAAW,KAAK,EAAE,QAAQ;AACxB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AAAA,MAC3B;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,QAAQ,OAAO,OAAO,OAAO,WAAW,MAAM,MAAM,MAAM,KAAK,CAAC;AAAA,EACnF;AAGA,QAAM,KAAK,CAAC,GAAG,MAAM;AACnB,UAAM,QAAQ,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;AAC1D,UAAM,QAAQ,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;AAC1D,WAAO,QAAQ;AAAA,EACjB,CAAC;AAED,QAAM,MAAM,QAAQ;AACpB,MAAI,SAAS;AACb,aAAW,OAAO,OAAO;AACvB,QAAI,cAAc;AAEhB,YAAM,KAAK,SAAS,IAAI;AACxB,YAAM,KAAK,CAAC,IAAI;AAChB,iBAAW,KAAK,IAAI,OAAO;AACzB,UAAE,KAAK;AACP,UAAE,KAAK;AACP,mBAAW,KAAK,EAAE,SAAS;AACzB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,iBAAW,KAAK,IAAI,OAAO;AACzB,mBAAW,KAAK,EAAE,QAAQ;AACxB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,gBAAW,IAAI,OAAO,IAAI,OAAQ;AAAA,IACpC,OAAO;AAEL,YAAM,KAAK,SAAS,IAAI;AACxB,YAAM,KAAK,CAAC,IAAI;AAChB,iBAAW,KAAK,IAAI,OAAO;AACzB,UAAE,KAAK;AACP,UAAE,KAAK;AACP,mBAAW,KAAK,EAAE,SAAS;AACzB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,iBAAW,KAAK,IAAI,OAAO;AACzB,mBAAW,KAAK,EAAE,QAAQ;AACxB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,gBAAW,IAAI,OAAO,IAAI,OAAQ;AAAA,IACpC;AAAA,EACF;AACF;;;ACpIO,SAAS,uBAAuB,OAAoB,SAAuC;AAChG,MAAI,CAAC,QAAQ,WAAY,QAAO;AAEhC,QAAM,YAAY,IAAI,IAAuB,MAAM,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAE5E,QAAM,WAAW,MAAM,MAAM,IAAI,UAAQ;AACvC,UAAM,OAAO,aAAa,MAAM,MAAM,KAAK;AAC3C,UAAM,WAAW,iBAAiB,MAAM,MAAM,MAAM,OAAO,WAAW,QAAQ,SAAS;AAEvF,UAAM,WAAW,gBAAgB,MAAM,UAAU,QAAQ,WAAW,IAAI;AACxE,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,WAAW,QAAQ,WAAY,QAAQ;AAC7C,WAAO,YAAY;AAAA,EACrB,CAAC;AAED,SAAO,EAAE,OAAO,UAAU,OAAO,MAAM,MAAM;AAC/C;AAOA,SAAS,aAAa,MAAiB,OAA8B;AACnE,QAAM,WAAW,MAAM,OAAO,OAAK,EAAE,SAAS,KAAK,MAAM,EAAE,OAAO,KAAK,EAAE;AACzE,MAAI,SAAS,WAAW,EAAG,QAAO,EAAE,MAAM,WAAW;AAErD,QAAM,UAAU,SAAS,MAAM,QAAM,EAAE,QAAQ,eAAe,MAAM;AACpE,MAAI,CAAC,QAAS,QAAO,EAAE,MAAM,OAAO;AAMpC,aAAW,KAAK,UAAU;AACxB,UAAM,aAAa,EAAE,SAAS,KAAK,KAAK,EAAE,KAAK,EAAE;AACjD,UAAM,mBAAmB,EAAE,SAAS,KAAK,KAAK,EAAE,WAAW,EAAE;AAC7D,UAAM,WAAW;AAAA,MAAmB;AAAA,MAAY;AAAA,MAAkB;AAAA;AAAA,MAAuB;AAAA,IAAK;AAC9F,QAAI,SAAU,QAAO,EAAE,MAAM,SAAS,cAAc,SAAS;AAAA,EAC/D;AACA,SAAO,EAAE,MAAM,SAAS,cAAc,KAAK;AAC7C;AAEA,SAAS,mBACP,aACA,WACA,QACA,YACmB;AAInB,SAAO;AACT;AAEA,SAAS,iBACP,MACA,MACA,OACA,OACA,WAC2C;AAC3C,MAAI,KAAK,SAAS,cAAc,KAAK,SAAS,QAAQ;AACpD,WAAO,EAAE,OAAO,aAAa,SAAS,GAAG,QAAQ,cAAc,SAAS,EAAE;AAAA,EAC5E;AAGA,QAAM,qBAAqB,uBAAuB,MAAM,OAAO,KAAK;AACpE,MAAI,CAAC,oBAAoB;AACvB,WAAO,EAAE,OAAO,aAAa,SAAS,GAAG,QAAQ,cAAc,SAAS,EAAE;AAAA,EAC5E;AAaA,QAAM,iBAAiB,cAAc,QAAQ,cAAc;AAE3D,MAAI;AACJ,MAAI,gBAAgB;AAClB,QAAI,uBAAuB,OAAQ,cAAa;AAAA,aACvC,uBAAuB,QAAS,cAAa;AAAA,QACjD,cAAa;AAAA,EACpB,OAAO;AACL,QAAI,uBAAuB,MAAO,cAAa;AAAA,aACtC,uBAAuB,SAAU,cAAa;AAAA,QAClD,cAAa;AAAA,EACpB;AAEA,SAAO,EAAE,OAAO,YAAY,QAAQ,WAAW;AACjD;AAEA,SAAS,uBACP,OACA,OACA,OACmB;AACnB,aAAW,KAAK,OAAO;AACrB,UAAM,cAAc,EAAE,SAAS,MAAM;AACrC,UAAM,YAAY,EAAE,OAAO,MAAM;AACjC,QAAI,CAAC,eAAe,CAAC,UAAW;AAEhC,UAAM,aAAa,cAAc,EAAE,KAAK,EAAE;AAC1C,UAAM,WAAW,MAAM,IAAI,UAAU;AACrC,QAAI,CAAC,SAAU;AAEf,UAAM,mBAAmB,cAAc,EAAE,WAAW,EAAE;AACtD,UAAM,iBAAiB,SAAS,QAAQ,KAAK,OAAK,EAAE,OAAO,gBAAgB;AAC3E,QAAI,eAAgB,QAAO,eAAe;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,gBACP,MACA,UACA,WACA,MACyC;AACzC,MAAI,KAAK,QAAQ,WAAW,EAAG,QAAO;AACtC,QAAM,eAAe,MAAM,KAAK,SAAS,QAAQ;AACjD,MAAI,aAAa,cAAc,EAAG,QAAO;AAEzC,QAAM,aAA8E,CAAC;AACrF,aAAW,OAAO,CAAC,IAAI,KAAK,GAAG,GAAY;AACzC,UAAM,UAAU,cAAc,KAAK,SAAS,GAAG;AAC/C,eAAW,KAAK,EAAE,UAAU,KAAK,OAAO,MAAM,SAAS,QAAQ,EAAE,CAAC;AAAA,EACpE;AAEA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,aAAa,EAAE,MAAM,UAAU;AACjE,QAAM,OAAO,WAAW,CAAC;AACzB,MAAI,KAAK,MAAM,cAAc,aAAa,WAAY,QAAO;AAE7D,SAAO,cAAc,MAAM,KAAK,UAAU,cAAc,KAAK,OAAO,WAAW,UAAU,IAAI;AAC/F;AAEA,SAAS,cACP,MACA,UACA,SACA,eACA,WACA,UACA,MACA;AACA,QAAM,WAAsB,EAAE,GAAG,MAAM,SAAS,cAAc,KAAK,SAAS,QAAQ,EAAE;AACtF,QAAM,WAAW,KAAK,SAAS,UAC3B,0BAA0B,SAAS,MAAM,wDACzC,aAAa,SAAS,sBAAsB,SAAS,KAAK,mBAAmB,SAAS,MAAM;AAChG,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,QAAQ,GAAG,QAAQ,KAAK,QAAQ,OAAO,IAAI,QAAQ,KAAK,mBAAmB,cAAc,OAAO,IAAI,cAAc,KAAK;AAAA,EACzH;AACF;AAEA,SAAS,aAAa,WAAwC;AAC5D,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;AAEA,SAAS,cAAc,WAAwC;AAC7D,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;AAEA,SAAS,MACP,SACA,UACwD;AACxD,MAAI,UAAU;AACd,MAAI,QAAQ;AACZ,aAAW,KAAK,SAAS;AACvB;AACA,QAAI,EAAE,SAAS,WAAW,EAAE,aAAa,SAAS,MAAO;AAAA,aAChD,EAAE,SAAS,YAAY,EAAE,aAAa,SAAS,OAAQ;AAAA,EAClE;AACA,SAAO,EAAE,SAAS,OAAO,YAAY,UAAU,IAAI,IAAI,UAAU,MAAM;AACzE;AAUO,SAAS,cAAc,SAAwB,KAAoC;AACxF,QAAM,aAAa,CAAC,MAA8B;AAChD,QAAI,QAAQ,KAAK;AACf,aAAO,MAAM,QAAQ,WAAW,MAAM,WAAW,QAAQ,MAAM,SAAS,UAAU;AAAA,IACpF;AACA,QAAI,QAAQ,IAAI;AACd,aAAO,MAAM,QAAQ,UAAU,MAAM,UAAU,WAAW,MAAM,WAAW,SAAS;AAAA,IACtF;AACA,WAAO,MAAM,QAAQ,SAAS,MAAM,SAAS,WAAW,MAAM,WAAW,UAAU;AAAA,EACrF;AACA,SAAO,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,UAAU,WAAW,EAAE,QAAQ,EAAE,EAAE;AACtE;;;AC/NA,IAAM,kBAAkB;AAMjB,SAAS,OAAO,OAAoB,SAAuC;AAChF,QAAM,WAAW,eAAe,OAAO;AACvC,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAC5D,QAAM,WAAW,uBAAuB,OAAO,QAAQ;AACvD,SAAO,eAAe,UAAU,QAAQ;AAC1C;AAGO,SAAS,cAAc,OAAc,SAAwC;AAClF,MAAI,MAAM,MAAM,SAAS,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAE1D,cAAY,KAAK;AAEjB,MAAI,SAAS,aAAa,KAAK;AAC/B,WAAS,iBAAiB,OAAO,MAAM;AAGvC,MAAI,OAAO,WAAW,QAAQ,KAAK;AACnC,SAAO,kBAAkB,OAAO,MAAM,QAAQ,8BAA8B;AAC5E,oBAAkB,OAAO,MAAM,OAAO;AAGtC,qBAAmB,OAAO,QAAQ,OAAO;AAEzC,QAAM,cAAc,WAAW,OAAO,QAAQ,WAAW,QAAQ,UAAU;AAC3E,SAAO,YAAY,OAAO,WAAW;AACvC;AAEA,SAAS,YAAY,OAAc,aAA0D;AAC3F,QAAM,QAAsB,CAAC;AAC7B,QAAM,QAAsB,CAAC;AAE7B,aAAW,CAAC,EAAE,IAAI,KAAK,MAAM,OAAO;AAClC,QAAI,KAAK,QAAS;AAElB,UAAM,UAA0B,KAAK,QAAQ,IAAI,OAAK;AACpD,YAAM,MAAM,kBAAkB,MAAM,EAAE,EAAE;AACxC,aAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AAAA,IAC5E,CAAC;AAED,UAAM,KAAK;AAAA,MACT,IAAI,KAAK;AAAA,MACT,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,aAAW,SAAS,aAAa;AAC/B,UAAM,KAAK;AAAA,MACT,IAAI,MAAM;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,IAAI,MAAM;AAAA,MACV,YAAY,MAAM;AAAA,MAClB,UAAU,MAAM;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,MAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,OAAO,MAAM;AACxB;AAMA,SAAS,eAAe,OAAoB,SAAwC;AAClF,QAAM,UAAU,IAAI,IAAI,MAAM,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEvD,QAAM,mBAAmB,oBAAI,IAAyB;AACtD,QAAM,YAAyB,CAAC;AAChC,aAAW,KAAK,MAAM,OAAO;AAC3B,QAAI,EAAE,YAAY,QAAQ,IAAI,EAAE,QAAQ,GAAG;AACzC,YAAM,MAAM,iBAAiB,IAAI,EAAE,QAAQ,KAAK,CAAC;AACjD,UAAI,KAAK,CAAC;AACV,uBAAiB,IAAI,EAAE,UAAU,GAAG;AAAA,IACtC,OAAO;AACL,gBAAU,KAAK,CAAC;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,cAAc,IAAI,IAAI,iBAAiB,KAAK,CAAC;AAGnD,QAAM,aAAa,oBAAI,IAAoB;AAC3C,WAAS,QAAQ,IAAoB;AACnC,QAAI,WAAW,IAAI,EAAE,EAAG,QAAO,WAAW,IAAI,EAAE;AAChD,UAAM,IAAI,QAAQ,IAAI,EAAE;AACxB,UAAM,IAAI,GAAG,YAAY,QAAQ,IAAI,EAAE,QAAQ,IAAI,QAAQ,EAAE,QAAQ,IAAI,IAAI;AAC7E,eAAW,IAAI,IAAI,CAAC;AACpB,WAAO;AAAA,EACT;AACA,aAAW,KAAK,MAAM,MAAO,SAAQ,EAAE,EAAE;AAEzC,QAAM,kBAAkB,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC;AAG/E,QAAM,aAAa,oBAAI,IAA0B;AAEjD,QAAM,eAAe,oBAAI,IAA+C;AAExE,aAAW,cAAc,iBAAiB;AACxC,UAAM,WAAW,iBAAiB,IAAI,UAAU,KAAK,CAAC;AACtD,QAAI,SAAS,WAAW,EAAG;AAE3B,UAAM,aAAa,IAAI,IAAI,SAAS,IAAI,OAAK,EAAE,EAAE,CAAC;AAClD,UAAM,WAAW,MAAM,MAAM,OAAO,OAAK,WAAW,IAAI,EAAE,IAAI,KAAK,WAAW,IAAI,EAAE,EAAE,CAAC;AAGvF,UAAM,gBAAgB,SAAS,IAAI,OAAK;AACtC,YAAM,KAAK,aAAa,IAAI,EAAE,EAAE;AAChC,aAAO,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,IAAI;AAAA,IAC7D,CAAC;AAID,UAAM,aAA8B,EAAE,GAAG,SAAS,gBAAgB,MAAM;AACxE,UAAM,WAAwB,EAAE,OAAO,cAAc,IAAI,WAAW,GAAG,OAAO,SAAS;AACvF,UAAM,YAAY,WAAW,UAAU,UAAU;AACjD,eAAW,IAAI,YAAY,SAAS;AAGpC,UAAM,OAAO,mBAAmB,UAAU,KAAK;AAC/C,UAAM,SAAS,KAAK,QAAQ,QAAQ,kBAAkB;AACtD,UAAM,SAAS,KAAK,SAAS,QAAQ,kBAAkB,IAAI;AAE3D,UAAM,WAAW,QAAQ,IAAI,UAAU;AACvC,iBAAa,IAAI,YAAY;AAAA,MAC3B,OAAO,KAAK,IAAI,QAAQ,SAAS,KAAK;AAAA,MACtC,QAAQ,KAAK,IAAI,QAAQ,SAAS,MAAM;AAAA,IAC1C,CAAC;AAAA,EACH;AAGA,QAAM,iBAAiB,UAAU,IAAI,OAAK;AACxC,UAAM,KAAK,aAAa,IAAI,EAAE,EAAE;AAChC,WAAO,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,IAAI;AAAA,EAC7D,CAAC;AACD,QAAM,YAAY,IAAI,IAAI,UAAU,IAAI,OAAK,EAAE,EAAE,CAAC;AAClD,QAAM,YAAY,MAAM,MAAM,OAAO,OAAK;AAExC,WAAO,UAAU,IAAI,EAAE,IAAI,KAAK,UAAU,IAAI,EAAE,EAAE;AAAA,EACpD,CAAC;AAED,QAAM,aAAa,WAAW,EAAE,OAAO,eAAe,IAAI,WAAW,GAAG,OAAO,UAAU,GAAG,OAAO;AAInG,QAAM,aAA2B,CAAC;AAClC,QAAM,aAA2B,CAAC;AAGlC,aAAW,KAAK,WAAW,OAAO;AAChC,UAAM,cAAc,YAAY,IAAI,EAAE,EAAE;AACxC,eAAW,KAAK;AAAA,MACd,GAAG;AAAA,MACH,UAAU,QAAQ,IAAI,EAAE,EAAE,GAAG;AAAA,IAC/B,CAAC;AACD,QAAI,aAAa;AACf,4BAAsB,GAAG,gBAAc,WAAW,IAAI,UAAU,GAAG,YAAY,YAAY,SAAS,OAAO;AAAA,IAC7G;AAAA,EACF;AACA,aAAW,KAAK,GAAG,WAAW,KAAK;AAEnC,MAAI,QAAQ,gBAAgB;AAC1B,mBAAe,YAAY,YAAY,OAAO;AAAA,EAChD;AAEA,SAAO,EAAE,OAAO,YAAY,OAAO,WAAW;AAChD;AAMA,SAAS,sBACP,QACA,QACA,YACA,YACA,SACA,SACM;AACN,QAAM,MAAM,OAAO,OAAO,EAAE;AAC5B,MAAI,CAAC,IAAK;AAEV,QAAM,OAAO,mBAAmB,IAAI,KAAK;AAEzC,QAAM,KAAK,OAAO,IAAI,QAAQ,kBAAkB,KAAK;AACrD,QAAM,KAAK,OAAO,IAAI,QAAQ,kBAAkB,kBAAkB,KAAK;AAIvE,QAAM,aAAa,OAAO,QAAQ,QAAQ,kBAAkB;AAC5D,QAAM,UAAU,aAAa,KAAK,SAAS;AAC3C,QAAM,aAAa,OAAO,SAAS,QAAQ,kBAAkB,IAAI;AACjE,QAAM,UAAU,aAAa,KAAK,UAAU;AAC5C,QAAM,KAAK,KAAK,KAAK,IAAI,GAAG,MAAM;AAClC,QAAM,KAAK,KAAK,KAAK,IAAI,GAAG,MAAM;AAElC,aAAW,SAAS,IAAI,OAAO;AAC7B,UAAM,SAAqB;AAAA,MACzB,GAAG;AAAA,MACH,GAAG,MAAM,IAAI;AAAA,MACb,GAAG,MAAM,IAAI;AAAA,MACb,SAAS,MAAM,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE;AAAA,MACpE,UAAU,QAAQ,IAAI,MAAM,EAAE,GAAG,YAAY,OAAO;AAAA,IACtD;AACA,eAAW,KAAK,MAAM;AACtB,QAAI,OAAO,MAAM,EAAE,GAAG;AACpB,4BAAsB,QAAQ,QAAQ,YAAY,YAAY,SAAS,OAAO;AAAA,IAChF;AAAA,EACF;AAEA,aAAW,QAAQ,IAAI,OAAO;AAC5B,eAAW,KAAK;AAAA,MACd,GAAG;AAAA,MACH,QAAQ,KAAK,OAAO,IAAI,QAAM,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE;AAAA,IAC7D,CAAC;AAAA,EACH;AACF;AAGA,SAAS,YAAY,GAAyB;AAC5C,QAAM,EAAE,UAAU,UAAU,GAAG,KAAK,IAAI;AACxC,SAAO;AACT;AAEA,SAAS,WAAW,OAAoB,SAAwC;AAC9E,QAAM,QAAQ,WAAW,MAAM,OAAO,MAAM,OAAO;AAAA,IACjD,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,EACtB,CAAC;AACD,SAAO,cAAc,OAAO,OAAO;AACrC;AAEA,SAAS,mBACP,OAC2F;AAC3F,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,QAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EAC5C;AACA,MAAI,CAAC,SAAS,IAAI,GAAG;AACnB,WAAO;AAAG,WAAO;AAAG,WAAO;AAAG,WAAO;AAAA,EACvC;AACA,SAAO,EAAE,MAAM,MAAM,MAAM,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AAC3E;;;ACxQO,IAAM,oBAAN,MAAwB;AAAA,EAQ7B,YAAY,SAAyB;AALrC,SAAQ,aAAqC,oBAAI,IAAI;AACrD,SAAQ,aAAqC,oBAAI,IAAI;AACrD,SAAQ,aAAkC;AAC1C,SAAQ,gBAAuD,oBAAI,IAAI;AAGrE,SAAK,UAAU;AACf,SAAK,kBAAkB,eAAe,OAAO;AAAA,EAC/C;AAAA,EAEA,SAAS,OAAkC;AACzC,SAAK,WAAW,MAAM;AACtB,SAAK,WAAW,MAAM;AACtB,eAAW,QAAQ,MAAM,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AACjE,eAAW,QAAQ,MAAM,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AACjE,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,SAAS,OAAoB,OAAmC;AAC9D,eAAW,QAAQ,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AAC3D,QAAI,MAAO,YAAW,QAAQ,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AACtE,WAAO,KAAK,uBAAuB,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,EAAE,CAAC,CAAC;AAAA,EAClE;AAAA,EAEA,YAAY,SAAiC;AAC3C,UAAM,aAAa,IAAI,IAAI,OAAO;AAClC,eAAW,MAAM,QAAS,MAAK,WAAW,OAAO,EAAE;AACnD,eAAW,CAAC,QAAQ,IAAI,KAAK,KAAK,YAAY;AAC5C,UAAI,WAAW,IAAI,KAAK,IAAI,KAAK,WAAW,IAAI,KAAK,EAAE,GAAG;AACxD,aAAK,WAAW,OAAO,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,eAAW,MAAM,QAAS,MAAK,cAAc,OAAO,EAAE;AACtD,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,SAAS,OAAkC;AACzC,eAAW,QAAQ,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AAC3D,WAAO,KAAK,uBAAuB,oBAAI,IAAY,CAAC;AAAA,EACtD;AAAA,EAEA,YAAY,SAAiC;AAC3C,eAAW,MAAM,QAAS,MAAK,WAAW,OAAO,EAAE;AACnD,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,YAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,YAA0B;AAChC,UAAM,QAAqB;AAAA,MACzB,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,MACnC,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,IACrC;AACA,SAAK,aAAa,OAAO,OAAO,KAAK,OAAO;AAC5C,SAAK,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,uBAAuB,YAAuC;AACpE,UAAM,QAAqB;AAAA,MACzB,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,MACnC,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,IACrC;AAEA,UAAM,QAAQ,OAAO,OAAO,KAAK,OAAO;AACxC,SAAK,aAAa,KAAK,eAAe,OAAO,UAAU;AACvD,SAAK,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,OAAqB,YAAuC;AACjF,QAAI,KAAK,cAAc,SAAS,EAAG,QAAO;AAC1C,UAAM,mBAAmB;AAEzB,UAAM,UAAwB;AAAA,MAC5B,OAAO,MAAM,MAAM,IAAI,OAAK;AAC1B,YAAI,WAAW,IAAI,EAAE,EAAE,EAAG,QAAO;AACjC,cAAM,MAAM,KAAK,cAAc,IAAI,EAAE,EAAE;AACvC,YAAI,CAAC,IAAK,QAAO;AACjB,cAAM,KAAK,IAAI,IAAI,EAAE;AACrB,cAAM,KAAK,IAAI,IAAI,EAAE;AACrB,cAAM,IAAI,EAAE,IAAI,KAAK;AACrB,cAAM,IAAI,EAAE,IAAI,KAAK;AACrB,cAAM,MAAM,IAAI,EAAE;AAClB,cAAM,MAAM,IAAI,EAAE;AAClB,eAAO;AAAA,UACL,GAAG;AAAA,UACH;AAAA,UACA;AAAA,UACA,SAAS,EAAE,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,IAAI,EAAE;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,MACD,OAAO,MAAM;AAAA,IACf;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,WAAY;AACtB,SAAK,cAAc,MAAM;AACzB,eAAW,QAAQ,KAAK,WAAW,OAAO;AACxC,WAAK,cAAc,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;;;AChHO,SAAS,YAAY,QAAsB,UAA8B,CAAC,GAAW;AAC1F,QAAM,QAAkB,CAAC;AACzB,QAAM,EAAE,OAAO,MAAM,IAAI;AAEzB,MAAI,MAAM,WAAW,EAAG,QAAO;AAG/B,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,QAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EAC5C;AACA,QAAM,KAAK,cAAc,MAAM,MAAM,WAAW,MAAM,MAAM,YAAY;AACxE,QAAM,KAAK,YAAY,KAAK,QAAQ,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,OAAO,OAAO,MAAM,QAAQ,CAAC,CAAC,OAAO,OAAO,MAAM,QAAQ,CAAC,CAAC,GAAG;AAGpK,QAAM,MAAM,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5D,QAAM,QAAwB,CAAC;AAC/B,aAAW,KAAK,KAAK;AACnB,UAAM,SAAS,MAAM,KAAK,OAAK,KAAK,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC;AACzD,QAAI,OAAQ,QAAO,KAAK,CAAC;AAAA,QACpB,OAAM,KAAK,CAAC,CAAC,CAAC;AAAA,EACrB;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,iBAAiB;AAC5B,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AACjD,UAAM,UAAU,OAAO,IAAI,OAAK;AAC9B,YAAM,IAAI,EAAE,WAAW,IAAI,EAAE,QAAQ,OAAO;AAC5C,aAAO,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM;AAAA,IAChF,CAAC,EAAE,KAAK,IAAI;AACZ,UAAM,KAAK,OAAO,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,OAAO,EAAE;AAAA,EACpE;AAGA,QAAM,WAAW,oBAAI,IAAsC;AAC3D,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,EAAE;AACd,UAAM,MAAM,SAAS,IAAI,GAAG,KAAK,CAAC;AAClC,QAAI,KAAK,CAAC;AACV,aAAS,IAAI,KAAK,GAAG;AAAA,EACvB;AACA,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,SAAS,KAAK,GAAG;AAC/B,QAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,CAAC,EAAG,aAAY,IAAI,CAAC;AAAA,EACzD;AACA,MAAI,YAAY,OAAO,GAAG;AAGxB,QAASA,gBAAT,SAAsB,IAAwB,OAAe;AAC3D,YAAM,WAAW,SAAS,IAAI,EAAE,KAAK,CAAC;AACtC,iBAAW,KAAK,UAAU;AACxB,cAAM,SAAS,KAAK,OAAO,KAAK;AAChC,cAAM,MAAM,YAAY,IAAI,EAAE,EAAE,IAAI,gBAAgB;AACpD,cAAM,KAAK,GAAG,MAAM,KAAK,EAAE,EAAE,GAAG,GAAG,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,QAAQ,CAAC,CAAC,GAAG;AACjJ,YAAI,YAAY,IAAI,EAAE,EAAE,EAAG,CAAAA,cAAa,EAAE,IAAI,QAAQ,CAAC;AAAA,MACzD;AAAA,IACF;AARS,uBAAAA;AAFT,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mBAAmB;AAU9B,IAAAA,cAAa,QAAW,CAAC;AAAA,EAC3B;AAGA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,eAAe;AAC1B,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,EAAE,OAAO,CAAC;AACvB,UAAM,OAAO,EAAE,OAAO,EAAE,OAAO,SAAS,CAAC;AACzC,UAAM,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,IAAI,IAAI,EAAE,UAAU,WAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,MAAM,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC,aAAQ,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC,UAAU,EAAE,OAAO,MAAM,MAAM;AAAA,EACrM;AAGA,QAAM,WAAW,aAAa,KAAK;AACnC,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,6BAA6B;AACxC,eAAW,KAAK,UAAU;AACxB,YAAM,KAAK,KAAK,EAAE,CAAC,aAAa,EAAE,CAAC,EAAE;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,OAAO;AAC1B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,UAAU,OAAO,OAAO,OAAO,CAAC;AAAA,EAC7C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,OAAiD;AACrE,QAAM,MAAkC,CAAC;AACzC,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,MAAO,KAAI,EAAE,SAAU,aAAY,IAAI,EAAE,QAAQ;AAEjE,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,aAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,YAAM,IAAI,MAAM,CAAC;AACjB,YAAM,IAAI,MAAM,CAAC;AAEjB,UAAI,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAU;AAEhD,YAAM,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;AACtD,YAAM,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE;AACvD,UAAI,YAAY,UAAU;AACxB,YAAI,KAAK,EAAE,GAAG,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,UAAU,OAAqB,OAAqB,SAAqC;AAChG,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,QAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EAC5C;AACA,aAAW,KAAK,MAAO,YAAW,KAAK,EAAE,QAAQ;AAC/C,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AAAA,EAC3B;AAEA,QAAM,UAAU,QAAQ,aAAa;AACrC,QAAM,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI;AACvC,QAAM,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI;AACvC,QAAM,SAAS,QAAQ,aAAa,UAAU;AAE9C,QAAM,SAAS,SAAS;AAExB,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,MAAM,IAAI,CAAC;AACrD,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,MAAM,IAAI,CAAC;AAErD,MAAI,IAAI,GAAI,QAAO;AAEnB,QAAM,OAAmB,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC;AAE7F,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,MAAO,KAAI,EAAE,SAAU,aAAY,IAAI,EAAE,QAAQ;AAGjE,aAAW,KAAK,OAAO;AACrB,UAAM,KAAK,KAAK,OAAO,EAAE,IAAI,QAAQ,MAAM;AAC3C,UAAM,KAAK,KAAK,OAAO,EAAE,IAAI,QAAQ,MAAM;AAC3C,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO,EAAE,IAAI,EAAE,QAAQ,QAAQ,MAAM,IAAI,CAAC;AACvE,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO,EAAE,IAAI,EAAE,SAAS,QAAQ,MAAM,IAAI,CAAC;AACxE,UAAM,aAAa,YAAY,IAAI,EAAE,EAAE;AACvC,UAAM,KAAK,aAAa,MAAM;AAC9B,aAAS,IAAI,IAAI,KAAK,MAAM,IAAI,GAAG,KAAK;AACtC,eAAS,IAAI,IAAI,KAAK,MAAM,IAAI,GAAG,KAAK;AACtC,YAAI,IAAI,KAAK,IAAI,EAAG;AACpB,YAAI,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,GAAI,MAAK,CAAC,EAAE,CAAC,IAAI;AAAA,iBACtD,YAAY;AAAA,QAErB,MAAO,MAAK,CAAC,EAAE,CAAC,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,QAAQ,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,EAAE,GAAG,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;AAC3E,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AAC7B,UAAM,KAAK,KAAK,IAAI,GAAG,EAAE;AACzB,aAAS,IAAI,GAAG,IAAI,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK;AACnD,UAAI,KAAK,EAAG,MAAK,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,KAAK,IAAI,SAAO,IAAI,KAAK,EAAE,CAAC,EAAE,KAAK,IAAI;AAChD;","names":["printSubtree"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/graph.ts","../src/algorithms/cycle-breaking.ts","../src/algorithms/layer-assignment.ts","../src/algorithms/crossing-minimization.ts","../src/algorithms/coordinate-assignment.ts","../src/algorithms/value-placement.ts","../src/algorithms/edge-routing.ts","../src/algorithms/component-packing.ts","../src/proposals.ts","../src/layout.ts","../src/incremental.ts","../src/debug.ts"],"sourcesContent":["/** Position on a node where a handle can be placed */\nexport type HandleSide = 'top' | 'right' | 'bottom' | 'left';\n\n/** Handle type - input receives connections, output sends connections */\nexport type HandleType = 'input' | 'output';\n\n/** Layout direction. 'TB' or 'LR' are the supported strict reading axes. */\nexport type LayoutDirection = 'TB' | 'LR' | 'BT' | 'RL';\n\n/**\n * Edge kind drives the layout weight:\n * - `control`: full strength; defines the execution rail (layer count).\n * - `data`: light weight; values are pulled onto the same layer as their consumer\n * instead of extending the rail.\n */\nexport type EdgeKind = 'control' | 'data';\n\n/** A 2D point */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** Handle definition on a node */\nexport interface HandleInput {\n id: string;\n type: HandleType;\n position: HandleSide;\n /** Position along the side (0 = start, 1 = end). Default: 0.5 */\n offset?: number;\n}\n\n/** Node input definition */\nexport interface NodeInput {\n id: string;\n width: number;\n height: number;\n handles: HandleInput[];\n /** Parent node id for compound (nested) layouts. */\n parentId?: string;\n}\n\n/** Edge input definition */\nexport interface EdgeInput {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n /** Default: 'control' */\n kind?: EdgeKind;\n /** Explicit weight override. Defaults: 1 (control), 0.25 (data). */\n weight?: number;\n}\n\n/** Complete layout input */\nexport interface LayoutInput {\n nodes: NodeInput[];\n edges: EdgeInput[];\n}\n\n/** Per-kind default weight overrides. */\nexport interface EdgeWeights {\n control?: number;\n data?: number;\n}\n\n/**\n * A proposal the layout engine emits to the calling application during a pass.\n * The app inspects it and decides whether to accept it, modify it, or reject it\n * by returning either the (possibly tweaked) proposed node or `null`/`undefined`\n * to keep the original.\n */\nexport interface RotateProposal {\n type: 'rotate';\n /** The node being analyzed. */\n nodeId: string;\n /** Same node as provided in the input. */\n current: NodeInput;\n /** The engine's proposed version after rotating handles. */\n proposed: NodeInput;\n /** Rotation in degrees (CW = positive). */\n rotation: 90 | -90 | 180;\n /** Reason this proposal was emitted (handle layout mismatches direction, etc.). */\n reason: string;\n}\n\n/**\n * A per-handle strategic placement proposal. Unlike `RotateProposal` (which\n * moves every handle uniformly), this proposal lifts each handle individually\n * to the side that points toward its actual neighbor — computed from a preview\n * layout pass, so the suggested sides reflect the real geometry.\n *\n * Example: a node with three outputs `out1`, `out2`, `out3` whose neighbors\n * end up below, to the right, and above respectively will receive a proposal\n * moving `out1` to `bottom`, `out2` to `right`, and `out3` to `top` — without\n * touching unused handles.\n */\nexport interface RelocateHandlesProposal {\n type: 'relocate-handles';\n /** The node being analyzed. */\n nodeId: string;\n /** Same node as provided in the input. */\n current: NodeInput;\n /** Node with each affected handle moved to its optimal side. Unused handles are preserved. */\n proposed: NodeInput;\n /**\n * Per-handle changes: { handleId → { from, to } }. Only handles whose side\n * differs from the input are present.\n */\n changes: Record<string, { from: HandleSide; to: HandleSide }>;\n /** Reason: which handles benefit from which moves. */\n reason: string;\n}\n\nexport type LayoutProposal = RotateProposal | RelocateHandlesProposal;\n\nexport type ProposalCallback = (proposal: LayoutProposal) => NodeInput | null | undefined | void;\n\n/**\n * Quality / speed trade-off preset.\n * - 'draft' : ~3× faster than balanced. Skips the transpose pass and uses\n * far fewer iterations. Visually acceptable for previews,\n * large graphs, or interactive scrubbing where the user is\n * about to layout again anyway. Output is NOT bit-compatible\n * with 'balanced'.\n * - 'balanced' : default. Bit-identical to past releases.\n * - 'high' : ~2× slower than balanced. More iterations of barycenter +\n * coordinate optimization. Negligible quality gain on most\n * realistic inputs — use only when the graph is dense.\n */\nexport type LayoutQuality = 'draft' | 'balanced' | 'high';\n\n/** Layout configuration options */\nexport interface LayoutOptions {\n /** Layout direction. Default: 'TB' */\n direction?: LayoutDirection;\n /**\n * Speed / quality trade-off. Default: 'balanced'. Scales iteration counts\n * and toggles optional passes. Explicit numeric overrides\n * (`crossingMinimizationIterations`, `coordinateOptimizationIterations`)\n * take precedence over the preset.\n */\n quality?: LayoutQuality;\n /** Minimum spacing between nodes in the same layer. Default: 40 */\n nodeSpacing?: number;\n /** Minimum spacing between layers. Default: 60 */\n layerSpacing?: number;\n /** Number of iterations for crossing minimization. Default: 24 */\n crossingMinimizationIterations?: number;\n /** Number of iterations for coordinate optimization. Default: 8 */\n coordinateOptimizationIterations?: number;\n /**\n * Force-skip the per-layer transpose pass in crossing minimization. The\n * preset already disables it for very large graphs; setting this to `true`\n * disables it unconditionally for an additional speedup (lower quality).\n * Default: false.\n */\n skipTranspose?: boolean;\n /** Margin for edge routing (distance from node before turning). Default: 20 */\n edgeMargin?: number;\n /** Override default per-kind weights. */\n edgeWeights?: EdgeWeights;\n /** When true, disjoint components are packed side-by-side. Default: true */\n packComponents?: boolean;\n /** Padding around compound (parent) bounding boxes. Default: 24 */\n compoundPadding?: number;\n /**\n * Called once per node when the engine thinks a rotation of the node's\n * handles would suit the chosen direction better. Return the (possibly\n * tweaked) proposed node to accept, or `null`/nothing to keep the original.\n */\n onProposal?: ProposalCallback;\n}\n\n/** Resolved options with all defaults applied */\nexport interface ResolvedOptions {\n direction: LayoutDirection;\n quality: LayoutQuality;\n nodeSpacing: number;\n layerSpacing: number;\n crossingMinimizationIterations: number;\n coordinateOptimizationIterations: number;\n skipTranspose: boolean;\n edgeMargin: number;\n controlWeight: number;\n dataWeight: number;\n packComponents: boolean;\n compoundPadding: number;\n onProposal?: ProposalCallback;\n}\n\ninterface QualityProfile {\n crossingMinimizationIterations: number;\n coordinateOptimizationIterations: number;\n skipTranspose: boolean;\n}\n\nconst QUALITY_PROFILES: Record<LayoutQuality, QualityProfile> = {\n draft: {\n crossingMinimizationIterations: 6,\n coordinateOptimizationIterations: 2,\n skipTranspose: true,\n },\n balanced: {\n crossingMinimizationIterations: 24,\n coordinateOptimizationIterations: 8,\n skipTranspose: false,\n },\n high: {\n crossingMinimizationIterations: 48,\n coordinateOptimizationIterations: 16,\n skipTranspose: false,\n },\n};\n\nexport function resolveOptions(options?: LayoutOptions): ResolvedOptions {\n const quality: LayoutQuality = options?.quality ?? 'balanced';\n const profile = QUALITY_PROFILES[quality];\n return {\n direction: options?.direction ?? 'TB',\n quality,\n nodeSpacing: options?.nodeSpacing ?? 40,\n layerSpacing: options?.layerSpacing ?? 60,\n crossingMinimizationIterations:\n options?.crossingMinimizationIterations ?? profile.crossingMinimizationIterations,\n coordinateOptimizationIterations:\n options?.coordinateOptimizationIterations ?? profile.coordinateOptimizationIterations,\n skipTranspose: options?.skipTranspose ?? profile.skipTranspose,\n edgeMargin: options?.edgeMargin ?? 20,\n controlWeight: options?.edgeWeights?.control ?? 1,\n dataWeight: options?.edgeWeights?.data ?? 0.25,\n packComponents: options?.packComponents ?? true,\n compoundPadding: options?.compoundPadding ?? 24,\n onProposal: options?.onProposal,\n };\n}\n\n/** Positioned handle in the output */\nexport interface HandleOutput {\n id: string;\n type: HandleType;\n position: HandleSide;\n x: number;\n y: number;\n}\n\n/** Positioned node in the output */\nexport interface NodeOutput {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n handles: HandleOutput[];\n /** Echoed back so consumers can reconstruct the hierarchy. */\n parentId?: string;\n}\n\n/** Routed edge in the output */\nexport interface EdgeOutput {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n points: Point[];\n kind: EdgeKind;\n}\n\n/** Complete layout result */\nexport interface LayoutResult {\n nodes: NodeOutput[];\n edges: EdgeOutput[];\n}\n","import { HandleInput, HandleSide, NodeInput, EdgeInput, Point, EdgeKind } from './types';\n\nexport interface InternalNode {\n id: string;\n width: number;\n height: number;\n handles: HandleInput[];\n isDummy: boolean;\n layer: number;\n order: number;\n x: number;\n y: number;\n parentId?: string;\n /** True if this node represents a compound (its size was computed from children). */\n isCompound: boolean;\n /** True when the node has no control edges and only participates in data edges. */\n isValue: boolean;\n}\n\nexport interface InternalEdge {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n reversed: boolean;\n originalId: string;\n kind: EdgeKind;\n weight: number;\n}\n\nexport class Graph {\n nodes: Map<string, InternalNode> = new Map();\n edges: Map<string, InternalEdge> = new Map();\n outEdges: Map<string, Set<string>> = new Map();\n inEdges: Map<string, Set<string>> = new Map();\n\n addNode(node: InternalNode): void {\n this.nodes.set(node.id, node);\n if (!this.outEdges.has(node.id)) this.outEdges.set(node.id, new Set());\n if (!this.inEdges.has(node.id)) this.inEdges.set(node.id, new Set());\n }\n\n addEdge(edge: InternalEdge): void {\n this.edges.set(edge.id, edge);\n if (!this.outEdges.has(edge.from)) this.outEdges.set(edge.from, new Set());\n if (!this.inEdges.has(edge.to)) this.inEdges.set(edge.to, new Set());\n this.outEdges.get(edge.from)!.add(edge.id);\n this.inEdges.get(edge.to)!.add(edge.id);\n }\n\n removeEdge(edgeId: string): void {\n const edge = this.edges.get(edgeId);\n if (!edge) return;\n this.outEdges.get(edge.from)?.delete(edgeId);\n this.inEdges.get(edge.to)?.delete(edgeId);\n this.edges.delete(edgeId);\n }\n\n removeNode(nodeId: string): void {\n const outEdgeIds = [...(this.outEdges.get(nodeId) || [])];\n const inEdgeIds = [...(this.inEdges.get(nodeId) || [])];\n for (const eid of outEdgeIds) this.removeEdge(eid);\n for (const eid of inEdgeIds) this.removeEdge(eid);\n this.nodes.delete(nodeId);\n this.outEdges.delete(nodeId);\n this.inEdges.delete(nodeId);\n }\n\n predecessors(nodeId: string): string[] {\n const result: string[] = [];\n const inEdgeIds = this.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = this.edges.get(eid);\n if (edge) result.push(edge.from);\n }\n }\n return result;\n }\n\n successors(nodeId: string): string[] {\n const result: string[] = [];\n const outEdgeIds = this.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = this.edges.get(eid);\n if (edge) result.push(edge.to);\n }\n }\n return result;\n }\n}\n\nexport interface BuildGraphContext {\n controlWeight: number;\n dataWeight: number;\n}\n\nexport function buildGraph(\n nodes: NodeInput[],\n edges: EdgeInput[],\n ctx: BuildGraphContext = { controlWeight: 1, dataWeight: 0.25 }\n): Graph {\n const graph = new Graph();\n\n for (const node of nodes) {\n graph.addNode({\n id: node.id,\n width: node.width,\n height: node.height,\n handles: node.handles.map(h => ({ ...h, offset: h.offset ?? 0.5 })),\n isDummy: false,\n layer: -1,\n order: -1,\n x: 0,\n y: 0,\n parentId: node.parentId,\n isCompound: false,\n isValue: false,\n });\n }\n\n for (const edge of edges) {\n const kind: EdgeKind = edge.kind ?? 'control';\n const defaultWeight = kind === 'control' ? ctx.controlWeight : ctx.dataWeight;\n graph.addEdge({\n id: edge.id,\n from: edge.from,\n to: edge.to,\n fromHandle: edge.fromHandle,\n toHandle: edge.toHandle,\n reversed: false,\n originalId: edge.id,\n kind,\n weight: edge.weight ?? defaultWeight,\n });\n }\n\n // A node is a \"value\" if every incident edge is data.\n // Floating values (no incoming edges + only data outgoing) and pure data sinks\n // both qualify — they should be pulled toward their consumer's layer\n // rather than extending the control rail.\n for (const [nodeId, node] of graph.nodes) {\n const ins = graph.inEdges.get(nodeId);\n const outs = graph.outEdges.get(nodeId);\n let hasControl = false;\n if (ins) {\n for (const eid of ins) {\n if (graph.edges.get(eid)?.kind === 'control') { hasControl = true; break; }\n }\n }\n if (!hasControl && outs) {\n for (const eid of outs) {\n if (graph.edges.get(eid)?.kind === 'control') { hasControl = true; break; }\n }\n }\n const incidentCount = (ins?.size ?? 0) + (outs?.size ?? 0);\n node.isValue = !hasControl && incidentCount > 0;\n }\n\n return graph;\n}\n\n/** Compute the absolute position of a handle on a positioned node */\nexport function getHandlePosition(node: InternalNode, handleId: string): Point {\n const handle = node.handles.find(h => h.id === handleId);\n if (!handle) {\n return { x: node.x + node.width / 2, y: node.y + node.height / 2 };\n }\n\n const offset = handle.offset ?? 0.5;\n\n switch (handle.position) {\n case 'top':\n return { x: node.x + offset * node.width, y: node.y };\n case 'bottom':\n return { x: node.x + offset * node.width, y: node.y + node.height };\n case 'left':\n return { x: node.x, y: node.y + offset * node.height };\n case 'right':\n return { x: node.x + node.width, y: node.y + offset * node.height };\n }\n}\n\n/** Get the direction vector for exiting/entering a handle */\nexport function getHandleDirection(side: HandleSide): Point {\n switch (side) {\n case 'top': return { x: 0, y: -1 };\n case 'bottom': return { x: 0, y: 1 };\n case 'left': return { x: -1, y: 0 };\n case 'right': return { x: 1, y: 0 };\n }\n}\n","import { Graph } from '../graph';\n\n/**\n * Break cycles in the graph using DFS-based back edge detection.\n * Reverses back edges to make the graph a DAG.\n * Returns the set of reversed edge IDs.\n */\nexport function breakCycles(graph: Graph): Set<string> {\n const WHITE = 0, GRAY = 1, BLACK = 2;\n const state = new Map<string, number>();\n const reversed = new Set<string>();\n\n for (const nodeId of graph.nodes.keys()) {\n state.set(nodeId, WHITE);\n }\n\n // Process nodes with more outgoing than incoming edges first\n const nodeIds = [...graph.nodes.keys()].sort((a, b) => {\n const aDiff = (graph.outEdges.get(a)?.size || 0) - (graph.inEdges.get(a)?.size || 0);\n const bDiff = (graph.outEdges.get(b)?.size || 0) - (graph.inEdges.get(b)?.size || 0);\n return bDiff - aDiff;\n });\n\n function dfs(nodeId: string): void {\n state.set(nodeId, GRAY);\n\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const edgeId of outEdgeIds) {\n const edge = graph.edges.get(edgeId);\n if (!edge) continue;\n\n const targetState = state.get(edge.to);\n if (targetState === GRAY) {\n reversed.add(edgeId);\n } else if (targetState === WHITE) {\n dfs(edge.to);\n }\n }\n }\n\n state.set(nodeId, BLACK);\n }\n\n for (const nodeId of nodeIds) {\n if (state.get(nodeId) === WHITE) {\n dfs(nodeId);\n }\n }\n\n // Reverse the back edges in the graph\n for (const edgeId of reversed) {\n const edge = graph.edges.get(edgeId);\n if (!edge) continue;\n\n graph.removeEdge(edgeId);\n graph.addEdge({\n ...edge,\n from: edge.to,\n to: edge.from,\n fromHandle: edge.toHandle,\n toHandle: edge.fromHandle,\n reversed: !edge.reversed,\n });\n }\n\n return reversed;\n}\n","import { Graph } from '../graph';\n\n/**\n * Two-pass layer assignment:\n *\n * Pass A (control rail): longest-path on the subgraph induced by control\n * edges between non-value nodes. This defines the canonical execution\n * timeline — value nodes do not extend it.\n *\n * Pass B (value pull): each value node is assigned the median layer of its\n * non-value neighbors. This snaps floating constants/imports onto the same\n * layer as the consumer that needs them, where they can be packed laterally.\n */\nexport function assignLayers(graph: Graph): string[][] {\n const layers = new Map<string, number>();\n const visiting = new Set<string>();\n\n // ----- Pass A: control rail -----\n function controlLayer(nodeId: string): number {\n if (layers.has(nodeId)) return layers.get(nodeId)!;\n if (visiting.has(nodeId)) return 0;\n\n const node = graph.nodes.get(nodeId);\n if (!node || node.isValue) return -1;\n\n visiting.add(nodeId);\n\n const inEdgeIds = graph.inEdges.get(nodeId);\n let maxPredLayer = -1;\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge || edge.kind !== 'control') continue;\n const pred = graph.nodes.get(edge.from);\n if (!pred || pred.isValue) continue;\n maxPredLayer = Math.max(maxPredLayer, controlLayer(edge.from));\n }\n }\n\n const layer = maxPredLayer + 1;\n layers.set(nodeId, layer);\n node.layer = layer;\n visiting.delete(nodeId);\n return layer;\n }\n\n for (const [nodeId, node] of graph.nodes) {\n if (!node.isValue) controlLayer(nodeId);\n }\n\n // ----- Pass B: value pull -----\n for (const [nodeId, node] of graph.nodes) {\n if (!node.isValue) continue;\n\n const neighborLayers: number[] = [];\n\n const inEdgeIds = graph.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const nbr = graph.nodes.get(edge.from);\n if (nbr && !nbr.isValue && layers.has(edge.from)) {\n neighborLayers.push(layers.get(edge.from)!);\n }\n }\n }\n\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const nbr = graph.nodes.get(edge.to);\n if (nbr && !nbr.isValue && layers.has(edge.to)) {\n neighborLayers.push(layers.get(edge.to)!);\n }\n }\n }\n\n let layer: number;\n if (neighborLayers.length > 0) {\n neighborLayers.sort((a, b) => a - b);\n layer = neighborLayers[Math.floor(neighborLayers.length / 2)];\n } else {\n layer = 0;\n }\n layers.set(nodeId, layer);\n node.layer = layer;\n }\n\n // Catch-all: isolated nodes go on layer 0.\n for (const [nodeId, node] of graph.nodes) {\n if (!layers.has(nodeId)) {\n layers.set(nodeId, 0);\n node.layer = 0;\n }\n }\n\n // Normalize so the smallest layer is 0.\n let minLayer = Infinity;\n let maxLayer = -Infinity;\n for (const l of layers.values()) {\n if (l < minLayer) minLayer = l;\n if (l > maxLayer) maxLayer = l;\n }\n if (!isFinite(minLayer)) return [];\n if (minLayer !== 0) {\n for (const [id, l] of layers) {\n const adj = l - minLayer;\n layers.set(id, adj);\n const n = graph.nodes.get(id);\n if (n) n.layer = adj;\n }\n maxLayer -= minLayer;\n }\n\n const layersArray: string[][] = Array.from({ length: maxLayer + 1 }, () => []);\n for (const [nodeId, layer] of layers) {\n layersArray[layer].push(nodeId);\n }\n\n return layersArray;\n}\n\n/**\n * Insert dummy nodes only for control edges that span multiple layers.\n * Data edges keep their layer-span; routing handles them directly because\n * they're typically short and decorative.\n */\nexport function insertDummyNodes(graph: Graph, layers: string[][]): string[][] {\n let dummyCounter = 0;\n const edgesToProcess = [...graph.edges.values()];\n\n for (const edge of edgesToProcess) {\n if (edge.kind !== 'control') continue;\n\n const fromNode = graph.nodes.get(edge.from);\n const toNode = graph.nodes.get(edge.to);\n if (!fromNode || !toNode) continue;\n\n const fromLayer = fromNode.layer;\n const toLayer = toNode.layer;\n const span = toLayer - fromLayer;\n\n if (span <= 1) continue;\n\n graph.removeEdge(edge.id);\n\n let prevNodeId = edge.from;\n let prevHandleId = edge.fromHandle;\n\n for (let l = fromLayer + 1; l < toLayer; l++) {\n const dummyId = `__dummy_${dummyCounter++}`;\n\n graph.addNode({\n id: dummyId,\n width: 0,\n height: 0,\n handles: [\n { id: 'in', type: 'input', position: 'top', offset: 0.5 },\n { id: 'out', type: 'output', position: 'bottom', offset: 0.5 },\n ],\n isDummy: true,\n layer: l,\n order: -1,\n x: 0,\n y: 0,\n isCompound: false,\n isValue: false,\n });\n\n layers[l].push(dummyId);\n\n graph.addEdge({\n id: `__dedge_${dummyCounter}_${l}_in`,\n from: prevNodeId,\n to: dummyId,\n fromHandle: prevHandleId,\n toHandle: 'in',\n reversed: edge.reversed,\n originalId: edge.originalId,\n kind: edge.kind,\n weight: edge.weight,\n });\n\n prevNodeId = dummyId;\n prevHandleId = 'out';\n }\n\n graph.addEdge({\n id: `__dedge_${dummyCounter}_final`,\n from: prevNodeId,\n to: edge.to,\n fromHandle: prevHandleId,\n toHandle: edge.toHandle,\n reversed: edge.reversed,\n originalId: edge.originalId,\n kind: edge.kind,\n weight: edge.weight,\n });\n }\n\n return layers;\n}\n","import { Graph } from '../graph';\n\n/**\n * Minimize edge crossings using barycenter heuristic with transpose improvement.\n *\n * @param iterations Maximum number of barycenter sweep iterations.\n * @param forceSkipTranspose When true, never run the transpose pass — used by\n * the 'draft' quality preset for ~3× speedup at the cost of some crossings.\n */\nexport function minimizeCrossings(\n graph: Graph,\n layers: string[][],\n iterations: number,\n forceSkipTranspose: boolean = false\n): string[][] {\n if (layers.length <= 1) return layers;\n\n const totalNodes = layers.reduce((s, l) => s + l.length, 0);\n\n // Adaptive: reduce iterations for large graphs\n const effectiveIter = totalNodes > 500\n ? Math.min(iterations, 6)\n : totalNodes > 200\n ? Math.min(iterations, 12)\n : iterations;\n\n // Skip transpose for very large layers (or if forced by quality profile).\n const skipTranspose = forceSkipTranspose || totalNodes > 800;\n\n // Initialize node orders\n for (let l = 0; l < layers.length; l++) {\n for (let i = 0; i < layers[l].length; i++) {\n const node = graph.nodes.get(layers[l][i]);\n if (node) node.order = i;\n }\n }\n\n let bestLayers = layers.map(l => [...l]);\n let bestCrossings = countAllCrossings(graph, layers);\n let noImprovementCount = 0;\n\n for (let iter = 0; iter < effectiveIter; iter++) {\n // Down sweep\n for (let l = 1; l < layers.length; l++) {\n orderByBarycenter(graph, layers, l, 'up');\n }\n\n // Up sweep\n for (let l = layers.length - 2; l >= 0; l--) {\n orderByBarycenter(graph, layers, l, 'down');\n }\n\n // Transpose improvement\n if (!skipTranspose) {\n for (let l = 0; l < layers.length; l++) {\n if (layers[l].length <= 100) {\n transposeImprove(graph, layers, l);\n }\n }\n }\n\n const crossings = countAllCrossings(graph, layers);\n if (crossings < bestCrossings) {\n bestCrossings = crossings;\n bestLayers = layers.map(l => [...l]);\n noImprovementCount = 0;\n } else {\n noImprovementCount++;\n }\n\n if (crossings === 0 || noImprovementCount >= 3) break;\n }\n\n // Restore best ordering\n for (let l = 0; l < layers.length; l++) {\n layers[l] = bestLayers[l];\n for (let i = 0; i < layers[l].length; i++) {\n const node = graph.nodes.get(layers[l][i]);\n if (node) node.order = i;\n }\n }\n\n return layers;\n}\n\nfunction orderByBarycenter(\n graph: Graph,\n layers: string[][],\n layerIndex: number,\n direction: 'up' | 'down'\n): void {\n const layer = layers[layerIndex];\n const adjLayerIndex = direction === 'up' ? layerIndex - 1 : layerIndex + 1;\n\n if (adjLayerIndex < 0 || adjLayerIndex >= layers.length) return;\n\n // Adjacency check via node.layer === adjLayerIndex (set by layer-assignment).\n // Avoids allocating a per-call Set of layer membership.\n\n // Parallel arrays of (originalIndex, barycenter) — pre-sized, no Map.\n const n = layer.length;\n const bary = new Float64Array(n);\n\n if (direction === 'up') {\n for (let i = 0; i < n; i++) {\n const nodeId = layer[i];\n let sum = 0;\n let count = 0;\n const inEdgeIds = graph.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const neighbor = graph.nodes.get(edge.from);\n if (neighbor && neighbor.layer === adjLayerIndex) {\n sum += neighbor.order;\n count++;\n }\n }\n }\n bary[i] = count > 0 ? sum / count : i;\n }\n } else {\n for (let i = 0; i < n; i++) {\n const nodeId = layer[i];\n let sum = 0;\n let count = 0;\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const neighbor = graph.nodes.get(edge.to);\n if (neighbor && neighbor.layer === adjLayerIndex) {\n sum += neighbor.order;\n count++;\n }\n }\n }\n bary[i] = count > 0 ? sum / count : i;\n }\n }\n\n // Build an index array and sort it by barycenter — preserves stable original\n // index for the comparator (Array.prototype.sort is stable in modern JS).\n const indices = new Array<number>(n);\n for (let i = 0; i < n; i++) indices[i] = i;\n indices.sort((a, b) => bary[a] - bary[b]);\n\n // Rebuild layer in-place in the new order.\n const reordered = new Array<string>(n);\n for (let i = 0; i < n; i++) reordered[i] = layer[indices[i]];\n for (let i = 0; i < n; i++) {\n layer[i] = reordered[i];\n const node = graph.nodes.get(layer[i]);\n if (node) node.order = i;\n }\n}\n\nfunction transposeImprove(graph: Graph, layers: string[][], layerIndex: number): void {\n const layer = layers[layerIndex];\n if (layer.length <= 1) return;\n\n let improved = true;\n let passes = 0;\n\n while (improved && passes < 2) {\n improved = false;\n passes++;\n for (let i = 0; i < layer.length - 1; i++) {\n const nodeA = layer[i];\n const nodeB = layer[i + 1];\n\n const crossingsBefore = countPairCrossings(graph, layers, layerIndex, nodeA, nodeB);\n\n // Swap in-place\n layer[i] = nodeB;\n layer[i + 1] = nodeA;\n const nA = graph.nodes.get(nodeA);\n const nB = graph.nodes.get(nodeB);\n if (nA) nA.order = i + 1;\n if (nB) nB.order = i;\n\n const crossingsAfter = countPairCrossings(graph, layers, layerIndex, nodeB, nodeA);\n\n if (crossingsAfter < crossingsBefore) {\n improved = true;\n } else {\n // Revert\n layer[i] = nodeA;\n layer[i + 1] = nodeB;\n if (nA) nA.order = i;\n if (nB) nB.order = i + 1;\n }\n }\n }\n}\n\n/** Scratch buffers reused across countPairCrossings calls. */\nconst _scratchA: number[] = [];\nconst _scratchB: number[] = [];\n\n/**\n * Count crossings involving a specific pair of adjacent nodes using node.order\n * directly. Adjacency to the neighbor layer is determined by `node.layer`\n * (set during layer assignment) — no per-call Set construction.\n */\nfunction countPairCrossings(\n graph: Graph,\n layers: string[][],\n layerIndex: number,\n nodeA: string,\n nodeB: string\n): number {\n let crossings = 0;\n\n // Check with upper layer\n if (layerIndex > 0) {\n const upperIdx = layerIndex - 1;\n\n _scratchA.length = 0;\n _scratchB.length = 0;\n\n const inA = graph.inEdges.get(nodeA);\n if (inA) {\n for (const eid of inA) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const n = graph.nodes.get(edge.from);\n if (n && n.layer === upperIdx) _scratchA.push(n.order);\n }\n }\n\n const inB = graph.inEdges.get(nodeB);\n if (inB) {\n for (const eid of inB) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const n = graph.nodes.get(edge.from);\n if (n && n.layer === upperIdx) _scratchB.push(n.order);\n }\n }\n\n for (let i = 0; i < _scratchA.length; i++) {\n const pA = _scratchA[i];\n for (let j = 0; j < _scratchB.length; j++) {\n if (pA > _scratchB[j]) crossings++;\n }\n }\n }\n\n // Check with lower layer\n if (layerIndex < layers.length - 1) {\n const lowerIdx = layerIndex + 1;\n\n _scratchA.length = 0;\n _scratchB.length = 0;\n\n const outA = graph.outEdges.get(nodeA);\n if (outA) {\n for (const eid of outA) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const n = graph.nodes.get(edge.to);\n if (n && n.layer === lowerIdx) _scratchA.push(n.order);\n }\n }\n\n const outB = graph.outEdges.get(nodeB);\n if (outB) {\n for (const eid of outB) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const n = graph.nodes.get(edge.to);\n if (n && n.layer === lowerIdx) _scratchB.push(n.order);\n }\n }\n\n for (let i = 0; i < _scratchA.length; i++) {\n const sA = _scratchA[i];\n for (let j = 0; j < _scratchB.length; j++) {\n if (sA > _scratchB[j]) crossings++;\n }\n }\n }\n\n return crossings;\n}\n\nexport function countAllCrossings(graph: Graph, layers: string[][]): number {\n let total = 0;\n for (let l = 0; l < layers.length - 1; l++) {\n total += countLayerCrossings(graph, layers[l], layers[l + 1]);\n }\n return total;\n}\n\n/**\n * Count crossings between two adjacent layers using merge-sort based\n * inversion counting. O(E log V) instead of O(E^2).\n */\nfunction countLayerCrossings(\n graph: Graph,\n upperLayer: string[],\n lowerLayer: string[]\n): number {\n const lowerPos = new Map<string, number>();\n lowerLayer.forEach((id, pos) => lowerPos.set(id, pos));\n\n // Collect edge endpoint pairs sorted by upper position\n const edgePairs: [number, number][] = [];\n for (let uPos = 0; uPos < upperLayer.length; uPos++) {\n const nodeId = upperLayer[uPos];\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (!outEdgeIds) continue;\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const lp = lowerPos.get(edge.to);\n if (lp !== undefined) {\n edgePairs.push([uPos, lp]);\n }\n }\n }\n\n if (edgePairs.length <= 1) return 0;\n\n // Sort by upper position, then by lower\n edgePairs.sort((a, b) => a[0] - b[0] || a[1] - b[1]);\n\n // Count inversions in the lower positions\n const lowerPositions = edgePairs.map(e => e[1]);\n return mergeSortCount(lowerPositions);\n}\n\n/**\n * Bottom-up iterative merge sort that counts inversions. Uses one auxiliary\n * buffer instead of allocating fresh `.slice()` arrays at every recursion\n * level. ~3–5× faster on large layers.\n */\nfunction mergeSortCount(arr: number[]): number {\n const n = arr.length;\n if (n <= 1) return 0;\n\n let buf = new Array<number>(n);\n let src = arr;\n let dst = buf;\n let count = 0;\n\n for (let width = 1; width < n; width <<= 1) {\n for (let i = 0; i < n; i += width << 1) {\n const left = i;\n const mid = Math.min(i + width, n);\n const right = Math.min(i + (width << 1), n);\n let a = left, b = mid, k = left;\n while (a < mid && b < right) {\n if (src[a] <= src[b]) {\n dst[k++] = src[a++];\n } else {\n count += mid - a;\n dst[k++] = src[b++];\n }\n }\n while (a < mid) dst[k++] = src[a++];\n while (b < right) dst[k++] = src[b++];\n }\n const tmp = src;\n src = dst;\n dst = tmp;\n }\n\n // If the final sorted data ended up in `buf`, copy back to satisfy callers\n // that may inspect `arr` (they don't here, but harmless).\n if (src !== arr) {\n for (let i = 0; i < n; i++) arr[i] = src[i];\n }\n return count;\n}\n","import { Graph } from '../graph';\nimport { LayoutDirection, ResolvedOptions } from '../types';\n\n/**\n * Assign x,y coordinates to all nodes using a median-based iterative approach.\n */\nexport function assignCoordinates(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions\n): void {\n const isHorizontal = options.direction === 'LR' || options.direction === 'RL';\n const isReversed = options.direction === 'BT' || options.direction === 'RL';\n\n assignRankPositions(graph, layers, options, isHorizontal, isReversed);\n assignOrderPositions(graph, layers, options, isHorizontal);\n optimizePositions(graph, layers, options, isHorizontal);\n}\n\n/**\n * Assign positions along the rank axis (y for TB/BT, x for LR/RL).\n */\nfunction assignRankPositions(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n isHorizontal: boolean,\n isReversed: boolean\n): void {\n // Compute layer sizes (max node size in rank direction)\n const layerSizes: number[] = [];\n for (const layer of layers) {\n let maxSize = 0;\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const size = isHorizontal ? node.width : node.height;\n maxSize = Math.max(maxSize, size);\n }\n layerSizes.push(maxSize);\n }\n\n // Compute cumulative positions\n const layerPositions: number[] = [];\n let pos = 0;\n for (let l = 0; l < layers.length; l++) {\n layerPositions.push(pos);\n pos += layerSizes[l] + options.layerSpacing;\n }\n\n // If reversed, flip positions\n if (isReversed) {\n const totalSize = pos - options.layerSpacing;\n for (let l = 0; l < layerPositions.length; l++) {\n layerPositions[l] = totalSize - layerPositions[l] - layerSizes[l];\n }\n }\n\n // Assign positions\n for (let l = 0; l < layers.length; l++) {\n for (const nodeId of layers[l]) {\n const node = graph.nodes.get(nodeId)!;\n const nodeSize = isHorizontal ? node.width : node.height;\n const offset = (layerSizes[l] - nodeSize) / 2;\n\n if (isHorizontal) {\n node.x = layerPositions[l] + offset;\n } else {\n node.y = layerPositions[l] + offset;\n }\n }\n }\n}\n\n/**\n * Assign positions along the order axis (x for TB/BT, y for LR/RL).\n * Initial even spacing, centered.\n */\nfunction assignOrderPositions(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n isHorizontal: boolean\n): void {\n for (const layer of layers) {\n let pos = 0;\n\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const size = isHorizontal ? node.height : node.width;\n\n if (isHorizontal) {\n node.y = pos;\n } else {\n node.x = pos;\n }\n\n pos += size + options.nodeSpacing;\n }\n\n // Center the layer\n const totalSize = pos - options.nodeSpacing;\n const centerOffset = -totalSize / 2;\n\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n if (isHorizontal) {\n node.y += centerOffset;\n } else {\n node.x += centerOffset;\n }\n }\n }\n}\n\n/**\n * Iteratively optimize positions by aligning nodes with their connected neighbors.\n */\nfunction optimizePositions(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n isHorizontal: boolean\n): void {\n for (let iter = 0; iter < options.coordinateOptimizationIterations; iter++) {\n // Down sweep\n for (let l = 0; l < layers.length; l++) {\n optimizeLayer(graph, layers[l], options, isHorizontal);\n }\n\n // Up sweep\n for (let l = layers.length - 1; l >= 0; l--) {\n optimizeLayer(graph, layers[l], options, isHorizontal);\n }\n }\n\n centerAllLayers(graph, layers, isHorizontal);\n}\n\n// Shared scratch buffers (per-call, no concurrent use). Float64Array gives\n// dense, GC-free storage for the neighbor positions before median selection.\nlet _neighborBuf: Float64Array = new Float64Array(64);\nlet _desiredBuf: Float64Array = new Float64Array(64);\n\nfunction ensureBufSize(size: number): void {\n if (_neighborBuf.length < size) _neighborBuf = new Float64Array(size * 2);\n if (_desiredBuf.length < size) _desiredBuf = new Float64Array(size * 2);\n}\n\nfunction optimizeLayer(\n graph: Graph,\n layer: string[],\n options: ResolvedOptions,\n isHorizontal: boolean\n): void {\n const n = layer.length;\n if (n === 0) return;\n\n // Worst-case neighbor count per node = max total degree across the layer.\n let maxDegree = 0;\n for (let i = 0; i < n; i++) {\n const id = layer[i];\n const d = (graph.inEdges.get(id)?.size ?? 0) + (graph.outEdges.get(id)?.size ?? 0);\n if (d > maxDegree) maxDegree = d;\n }\n ensureBufSize(Math.max(n, maxDegree));\n const desired = _desiredBuf;\n\n // Compute desired positions — direct neighbor walk, no intermediate arrays.\n for (let i = 0; i < n; i++) {\n const nodeId = layer[i];\n const node = graph.nodes.get(nodeId)!;\n let nbCount = 0;\n\n const inEdgeIds = graph.inEdges.get(nodeId);\n if (inEdgeIds) {\n for (const eid of inEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const c = graph.nodes.get(edge.from);\n if (!c) continue;\n _neighborBuf[nbCount++] = getOrderPos(c, isHorizontal) + getOrderSize(c, isHorizontal) / 2;\n }\n }\n const outEdgeIds = graph.outEdges.get(nodeId);\n if (outEdgeIds) {\n for (const eid of outEdgeIds) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const c = graph.nodes.get(edge.to);\n if (!c) continue;\n _neighborBuf[nbCount++] = getOrderPos(c, isHorizontal) + getOrderSize(c, isHorizontal) / 2;\n }\n }\n\n if (nbCount === 0) {\n desired[i] = getOrderPos(node, isHorizontal);\n continue;\n }\n\n // Median of neighbor positions. Use a partial in-place sort.\n sortPrefix(_neighborBuf, nbCount);\n\n const nodeSize = getOrderSize(node, isHorizontal);\n const median = (nbCount & 1) === 0\n ? (_neighborBuf[(nbCount >> 1) - 1] + _neighborBuf[nbCount >> 1]) / 2\n : _neighborBuf[nbCount >> 1];\n\n desired[i] = median - nodeSize / 2;\n }\n\n // Forward pass: apply desired positions with spacing constraints\n for (let i = 0; i < n; i++) {\n const nodeId = layer[i];\n const node = graph.nodes.get(nodeId)!;\n let desiredPos = desired[i];\n\n if (i > 0) {\n const prevId = layer[i - 1];\n const prev = graph.nodes.get(prevId)!;\n const prevEnd = getOrderPos(prev, isHorizontal) + getOrderSize(prev, isHorizontal);\n if (desiredPos < prevEnd + options.nodeSpacing) desiredPos = prevEnd + options.nodeSpacing;\n }\n\n setOrderPos(node, isHorizontal, desiredPos);\n }\n\n // Backward pass: fix overlaps from right\n for (let i = n - 2; i >= 0; i--) {\n const nodeId = layer[i];\n const node = graph.nodes.get(nodeId)!;\n const nextId = layer[i + 1];\n const next = graph.nodes.get(nextId)!;\n\n const nodeEnd = getOrderPos(node, isHorizontal) + getOrderSize(node, isHorizontal);\n const nextStart = getOrderPos(next, isHorizontal);\n\n if (nodeEnd + options.nodeSpacing > nextStart) {\n setOrderPos(node, isHorizontal, nextStart - options.nodeSpacing - getOrderSize(node, isHorizontal));\n }\n }\n}\n\n/** In-place insertion sort over the first `count` items of `arr` — fast for\n * the small neighbor counts typical here (median ~2-4). */\nfunction sortPrefix(arr: Float64Array, count: number): void {\n for (let i = 1; i < count; i++) {\n const x = arr[i];\n let j = i - 1;\n while (j >= 0 && arr[j] > x) {\n arr[j + 1] = arr[j];\n j--;\n }\n arr[j + 1] = x;\n }\n}\n\nfunction centerAllLayers(\n graph: Graph,\n layers: string[][],\n isHorizontal: boolean\n): void {\n if (layers.length === 0) return;\n\n // Find global bounds\n let globalMin = Infinity;\n let globalMax = -Infinity;\n\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const pos = getOrderPos(node, isHorizontal);\n const size = getOrderSize(node, isHorizontal);\n globalMin = Math.min(globalMin, pos);\n globalMax = Math.max(globalMax, pos + size);\n }\n }\n\n // Shift everything so the layout starts at 0\n const offset = -globalMin;\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n setOrderPos(node, isHorizontal, getOrderPos(node, isHorizontal) + offset);\n }\n }\n\n // Also shift rank positions to start at 0\n let rankMin = Infinity;\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n const pos = isHorizontal ? node.x : node.y;\n rankMin = Math.min(rankMin, pos);\n }\n }\n\n if (rankMin !== 0) {\n for (const layer of layers) {\n for (const nodeId of layer) {\n const node = graph.nodes.get(nodeId)!;\n if (isHorizontal) {\n node.x -= rankMin;\n } else {\n node.y -= rankMin;\n }\n }\n }\n }\n}\n\nfunction getOrderPos(node: { x: number; y: number }, isHorizontal: boolean): number {\n return isHorizontal ? node.y : node.x;\n}\n\nfunction setOrderPos(node: { x: number; y: number }, isHorizontal: boolean, value: number): void {\n if (isHorizontal) {\n node.y = value;\n } else {\n node.x = value;\n }\n}\n\nfunction getOrderSize(node: { width: number; height: number }, isHorizontal: boolean): number {\n return isHorizontal ? node.height : node.width;\n}\n","import { Graph } from '../graph';\nimport { LayoutDirection, ResolvedOptions } from '../types';\n\n/**\n * Sidecar placement for value nodes.\n *\n * Values (nodes whose every incident edge is a data edge) are NOT laid out\n * alongside the control rail — they are attached as sidecars to the flanks of\n * their dominant consumer once the rail is finalized. This way:\n *\n * - the rail stays perfectly aligned (its layout is computed without values)\n * - values cluster around the node that actually uses them\n * - extra values don't widen/displace the rail\n *\n * In TB direction, sidecars sit at the consumer's vertical center, alternating\n * left/right. In LR direction, they sit at the consumer's horizontal center,\n * alternating top/bottom.\n */\nexport function placeValueSidecars(\n graph: Graph,\n layers: string[][],\n options: ResolvedOptions,\n): void {\n const isHorizontal = options.direction === 'LR' || options.direction === 'RL';\n\n // Identify all values and which consumer each belongs to.\n interface Attachment {\n valueId: string;\n consumerId: string;\n }\n const attachments: Attachment[] = [];\n const orphanValues: string[] = [];\n\n for (const [nodeId, node] of graph.nodes) {\n if (!node.isValue || node.isDummy) continue;\n\n const consumer = findDominantConsumer(graph, nodeId);\n if (consumer) {\n attachments.push({ valueId: nodeId, consumerId: consumer });\n } else {\n orphanValues.push(nodeId);\n }\n }\n\n // Group attachments by consumer.\n const byConsumer = new Map<string, string[]>();\n for (const { valueId, consumerId } of attachments) {\n const arr = byConsumer.get(consumerId) ?? [];\n arr.push(valueId);\n byConsumer.set(consumerId, arr);\n }\n\n // For each consumer, split its values into the two sides and place them.\n for (const [consumerId, vIds] of byConsumer) {\n const consumer = graph.nodes.get(consumerId);\n if (!consumer) continue;\n\n const { beforeSide, afterSide } = splitValuesBySide(graph, consumerId, vIds, isHorizontal);\n\n if (isHorizontal) {\n // LR/RL: 'before' = above the consumer (decreasing Y), 'after' = below.\n const cxCenter = consumer.x + consumer.width / 2;\n let topEdge = consumer.y;\n for (const vid of beforeSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.y = topEdge - options.nodeSpacing - v.height;\n v.x = cxCenter - v.width / 2;\n topEdge = v.y;\n }\n let bottomEdge = consumer.y + consumer.height;\n for (const vid of afterSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.y = bottomEdge + options.nodeSpacing;\n v.x = cxCenter - v.width / 2;\n bottomEdge = v.y + v.height;\n }\n } else {\n // TB/BT: 'before' = left of consumer (decreasing X), 'after' = right.\n const cyCenter = consumer.y + consumer.height / 2;\n let leftEdge = consumer.x;\n for (const vid of beforeSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.x = leftEdge - options.nodeSpacing - v.width;\n v.y = cyCenter - v.height / 2;\n leftEdge = v.x;\n }\n let rightEdge = consumer.x + consumer.width;\n for (const vid of afterSide) {\n const v = graph.nodes.get(vid);\n if (!v) continue;\n v.x = rightEdge + options.nodeSpacing;\n v.y = cyCenter - v.height / 2;\n rightEdge = v.x + v.width;\n }\n }\n }\n\n // Orphan values: no consumer found — place them in a stack at the layout origin.\n // Should be rare; mostly happens for truly isolated nodes.\n let orphanX = 0, orphanY = 0;\n for (const orphanId of orphanValues) {\n const v = graph.nodes.get(orphanId);\n if (!v) continue;\n v.x = orphanX;\n v.y = orphanY;\n if (isHorizontal) orphanX += v.width + options.nodeSpacing;\n else orphanY += v.height + options.nodeSpacing;\n }\n}\n\n/**\n * The \"dominant consumer\" of a value is the non-value neighbor with the most\n * edges connecting them. If multiple tie, pick by id for stability.\n */\nfunction findDominantConsumer(graph: Graph, valueId: string): string | null {\n const counts = new Map<string, number>();\n\n const outs = graph.outEdges.get(valueId);\n if (outs) {\n for (const eid of outs) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const other = graph.nodes.get(edge.to);\n if (other && !other.isValue && !other.isDummy) {\n counts.set(edge.to, (counts.get(edge.to) ?? 0) + 1);\n }\n }\n }\n const ins = graph.inEdges.get(valueId);\n if (ins) {\n for (const eid of ins) {\n const edge = graph.edges.get(eid);\n if (!edge) continue;\n const other = graph.nodes.get(edge.from);\n if (other && !other.isValue && !other.isDummy) {\n counts.set(edge.from, (counts.get(edge.from) ?? 0) + 1);\n }\n }\n }\n\n let bestId: string | null = null;\n let bestCount = -1;\n for (const [id, count] of counts) {\n if (count > bestCount || (count === bestCount && bestId !== null && id < bestId)) {\n bestId = id;\n bestCount = count;\n }\n }\n return bestId;\n}\n\n/**\n * Split values into the two sides of a consumer, using each value's connecting\n * handle as a hint:\n * - handle on the consumer's `left` (TB) / `top` (LR) → \"before\" side\n * - handle on the consumer's `right` (TB) / `bottom` (LR) → \"after\" side\n * - otherwise → balance the two sides\n *\n * Within each side, values are sorted by the handle offset so they stack in\n * a predictable order along the perpendicular axis.\n */\nfunction splitValuesBySide(\n graph: Graph,\n consumerId: string,\n valueIds: string[],\n isHorizontal: boolean,\n): { beforeSide: string[]; afterSide: string[] } {\n const consumer = graph.nodes.get(consumerId);\n if (!consumer) return { beforeSide: [...valueIds].sort(), afterSide: [] };\n\n type Slot = { id: string; side: 'before' | 'after' | 'neutral'; offset: number };\n const slots: Slot[] = [];\n\n for (const vId of valueIds) {\n let side: Slot['side'] = 'neutral';\n let offset = 0.5;\n\n const inspectHandle = (handleId: string | undefined) => {\n if (!handleId) return;\n const handle = consumer.handles.find(h => h.id === handleId);\n if (!handle) return;\n offset = handle.offset ?? 0.5;\n if (isHorizontal) {\n if (handle.position === 'top') side = 'before';\n else if (handle.position === 'bottom') side = 'after';\n } else {\n if (handle.position === 'left') side = 'before';\n else if (handle.position === 'right') side = 'after';\n }\n };\n\n // Find the edge between value and consumer, then look at the handle ON the consumer.\n const outs = graph.outEdges.get(vId);\n if (outs) for (const eid of outs) {\n const e = graph.edges.get(eid);\n if (e && e.to === consumerId) { inspectHandle(e.toHandle); break; }\n }\n if (side === 'neutral') {\n const ins = graph.inEdges.get(vId);\n if (ins) for (const eid of ins) {\n const e = graph.edges.get(eid);\n if (e && e.from === consumerId) { inspectHandle(e.fromHandle); break; }\n }\n }\n\n slots.push({ id: vId, side, offset });\n }\n\n const before = slots.filter(s => s.side === 'before');\n const after = slots.filter(s => s.side === 'after');\n const neutral = slots.filter(s => s.side === 'neutral');\n\n // Balance neutrals across the two sides for compactness.\n for (const n of neutral) {\n if (before.length <= after.length) before.push(n);\n else after.push(n);\n }\n\n // Sort each side: smaller offset first (so values stack predictably, closest\n // to the matching handle nearest to the consumer body).\n const cmp = (a: Slot, b: Slot) => (a.offset - b.offset) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\n before.sort(cmp);\n after.sort(cmp);\n\n return {\n beforeSide: before.map(s => s.id),\n afterSide: after.map(s => s.id),\n };\n}\n\nexport function isValueLayer(layer: string[], graph: Graph): boolean {\n for (const id of layer) {\n const n = graph.nodes.get(id);\n if (n && !n.isValue && !n.isDummy) return false;\n }\n return true;\n}\n\n/** Filter layers to keep only non-value, non-dummy nodes per layer. */\nexport function railLayers(layers: string[][], graph: Graph): string[][] {\n return layers.map(layer =>\n layer.filter(id => {\n const n = graph.nodes.get(id);\n return n && !n.isValue;\n }),\n );\n}\n\nexport function getDirection(direction: LayoutDirection): { isHorizontal: boolean } {\n return { isHorizontal: direction === 'LR' || direction === 'RL' };\n}\n","import { Graph, getHandlePosition, getHandleDirection } from '../graph';\nimport { Point, HandleSide, LayoutDirection, EdgeKind } from '../types';\n\nexport interface RoutedEdge {\n id: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n points: Point[];\n kind: EdgeKind;\n}\n\n/**\n * Route all edges with orthogonal paths.\n * Reconstructs original edges from dummy node chains.\n */\nexport function routeEdges(\n graph: Graph,\n direction: LayoutDirection,\n edgeMargin: number\n): RoutedEdge[] {\n const chains = collectEdgeChains(graph);\n const routes: RoutedEdge[] = [];\n\n for (const chain of chains) {\n routes.push(routeChain(graph, chain, direction, edgeMargin));\n }\n\n return routes;\n}\n\ninterface EdgeChain {\n originalId: string;\n from: string;\n to: string;\n fromHandle: string;\n toHandle: string;\n dummyNodes: string[];\n reversed: boolean;\n kind: EdgeKind;\n}\n\nfunction collectEdgeChains(graph: Graph): EdgeChain[] {\n const chains: EdgeChain[] = [];\n const visited = new Set<string>();\n\n for (const [edgeId, edge] of graph.edges) {\n if (visited.has(edgeId)) continue;\n\n const fromNode = graph.nodes.get(edge.from);\n if (!fromNode || fromNode.isDummy) continue;\n\n const dummyNodes: string[] = [];\n let currentEdge = edge;\n visited.add(edgeId);\n\n while (true) {\n const toNode = graph.nodes.get(currentEdge.to);\n if (!toNode || !toNode.isDummy) break;\n\n dummyNodes.push(currentEdge.to);\n\n const outEdgeIds = graph.outEdges.get(currentEdge.to);\n if (!outEdgeIds || outEdgeIds.size === 0) break;\n\n let nextEdge = null;\n for (const eid of outEdgeIds) {\n const e = graph.edges.get(eid);\n if (e && e.originalId === edge.originalId) {\n nextEdge = e;\n visited.add(eid);\n break;\n }\n }\n\n if (!nextEdge) {\n const eid = outEdgeIds.values().next().value;\n if (!eid) break;\n nextEdge = graph.edges.get(eid);\n if (!nextEdge) break;\n visited.add(eid);\n }\n\n currentEdge = nextEdge;\n }\n\n chains.push({\n originalId: edge.originalId,\n from: edge.from,\n to: currentEdge.to,\n fromHandle: edge.fromHandle,\n toHandle: currentEdge.toHandle,\n dummyNodes,\n reversed: edge.reversed,\n kind: edge.kind,\n });\n }\n\n return chains;\n}\n\nfunction routeChain(\n graph: Graph,\n chain: EdgeChain,\n direction: LayoutDirection,\n margin: number\n): RoutedEdge {\n const fromNode = graph.nodes.get(chain.from)!;\n const toNode = graph.nodes.get(chain.to)!;\n\n const actualFrom = chain.reversed ? chain.to : chain.from;\n const actualTo = chain.reversed ? chain.from : chain.to;\n const actualFromHandle = chain.reversed ? chain.toHandle : chain.fromHandle;\n const actualToHandle = chain.reversed ? chain.fromHandle : chain.toHandle;\n\n const sourceNode = chain.reversed ? toNode : fromNode;\n const targetNode = chain.reversed ? fromNode : toNode;\n\n const sourcePos = getHandlePosition(sourceNode, actualFromHandle);\n const targetPos = getHandlePosition(targetNode, actualToHandle);\n\n const sourceHandle = sourceNode.handles.find(h => h.id === actualFromHandle);\n const targetHandle = targetNode.handles.find(h => h.id === actualToHandle);\n\n const sourceSide = sourceHandle?.position || getDefaultSourceSide(direction);\n const targetSide = targetHandle?.position || getDefaultTargetSide(direction);\n\n const rawPoints: Point[] = [];\n\n rawPoints.push(sourcePos);\n\n const exitDir = getHandleDirection(sourceSide);\n rawPoints.push({\n x: sourcePos.x + exitDir.x * margin,\n y: sourcePos.y + exitDir.y * margin,\n });\n\n const dummies = chain.reversed ? [...chain.dummyNodes].reverse() : chain.dummyNodes;\n for (const dummyId of dummies) {\n const dummy = graph.nodes.get(dummyId)!;\n rawPoints.push({ x: dummy.x, y: dummy.y });\n }\n\n const entryDir = getHandleDirection(targetSide);\n rawPoints.push({\n x: targetPos.x + entryDir.x * margin,\n y: targetPos.y + entryDir.y * margin,\n });\n\n rawPoints.push(targetPos);\n\n const points = makeOrthogonal(rawPoints, direction);\n\n return {\n id: chain.originalId,\n from: actualFrom,\n to: actualTo,\n fromHandle: actualFromHandle,\n toHandle: actualToHandle,\n points,\n kind: chain.kind,\n };\n}\n\nfunction makeOrthogonal(points: Point[], direction: LayoutDirection): Point[] {\n if (points.length < 2) return points;\n\n const result: Point[] = [points[0]];\n const isVerticalFlow = direction === 'TB' || direction === 'BT';\n\n for (let i = 1; i < points.length; i++) {\n const prev = result[result.length - 1];\n const curr = points[i];\n\n const dx = Math.abs(prev.x - curr.x);\n const dy = Math.abs(prev.y - curr.y);\n\n if (dx < 0.01 || dy < 0.01) {\n result.push(curr);\n continue;\n }\n\n if (isVerticalFlow) {\n const midY = (prev.y + curr.y) / 2;\n result.push({ x: prev.x, y: midY });\n result.push({ x: curr.x, y: midY });\n } else {\n const midX = (prev.x + curr.x) / 2;\n result.push({ x: midX, y: prev.y });\n result.push({ x: midX, y: curr.y });\n }\n\n result.push(curr);\n }\n\n return cleanupPoints(result);\n}\n\nfunction cleanupPoints(points: Point[]): Point[] {\n if (points.length <= 2) return points;\n\n const result: Point[] = [points[0]];\n\n for (let i = 1; i < points.length - 1; i++) {\n const prev = result[result.length - 1];\n const curr = points[i];\n const next = points[i + 1];\n\n const sameX = Math.abs(prev.x - curr.x) < 0.01 && Math.abs(curr.x - next.x) < 0.01;\n const sameY = Math.abs(prev.y - curr.y) < 0.01 && Math.abs(curr.y - next.y) < 0.01;\n\n if (!sameX && !sameY) {\n result.push(curr);\n } else if (sameX || sameY) {\n continue;\n } else {\n result.push(curr);\n }\n }\n\n result.push(points[points.length - 1]);\n return result;\n}\n\nfunction getDefaultSourceSide(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'bottom';\n case 'BT': return 'top';\n case 'LR': return 'right';\n case 'RL': return 'left';\n }\n}\n\nfunction getDefaultTargetSide(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'top';\n case 'BT': return 'bottom';\n case 'LR': return 'left';\n case 'RL': return 'right';\n }\n}\n","import { EdgeOutput, NodeOutput, ResolvedOptions } from '../types';\n\n/**\n * Pack disjoint connected components side-by-side (in the order axis) so the\n * overall layout is roughly square instead of a long ribbon.\n *\n * Compound parents are kept as atomic groups: children move with their parent.\n */\nexport function packComponents(\n nodes: NodeOutput[],\n edges: EdgeOutput[],\n options: ResolvedOptions,\n): void {\n if (nodes.length === 0) return;\n\n // Walk the parentId chain to find the top-level ancestor of every node.\n const idToNode = new Map<string, NodeOutput>();\n for (const n of nodes) idToNode.set(n.id, n);\n const rootOf = new Map<string, string>();\n function topAncestor(id: string): string {\n if (rootOf.has(id)) return rootOf.get(id)!;\n const n = idToNode.get(id);\n if (!n || !n.parentId || !idToNode.has(n.parentId)) {\n rootOf.set(id, id);\n return id;\n }\n const r = topAncestor(n.parentId);\n rootOf.set(id, r);\n return r;\n }\n for (const n of nodes) topAncestor(n.id);\n\n // Union-find by edge connectivity, but only over top-level ancestors so\n // children of a single compound stay with the compound.\n const parent = new Map<string, string>();\n function find(x: string): string {\n let cur = x;\n while (parent.get(cur) !== cur) {\n const p = parent.get(cur)!;\n parent.set(cur, parent.get(p)!);\n cur = parent.get(cur)!;\n }\n return cur;\n }\n function union(a: string, b: string): void {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n }\n for (const n of nodes) parent.set(topAncestor(n.id), topAncestor(n.id));\n for (const e of edges) {\n const ra = topAncestor(e.from);\n const rb = topAncestor(e.to);\n if (idToNode.has(ra) && idToNode.has(rb)) union(ra, rb);\n }\n\n // Group every node (including children) by its component's representative.\n const groups = new Map<string, NodeOutput[]>();\n for (const n of nodes) {\n const root = topAncestor(n.id);\n const comp = find(root);\n const arr = groups.get(comp) ?? [];\n arr.push(n);\n groups.set(comp, arr);\n }\n\n if (groups.size <= 1) return;\n\n const isHorizontal = options.direction === 'LR' || options.direction === 'RL';\n\n // Build per-component bounding boxes (including their edge bend points).\n const edgesByComp = new Map<string, EdgeOutput[]>();\n for (const e of edges) {\n const root = topAncestor(e.from);\n const comp = find(root);\n const arr = edgesByComp.get(comp) ?? [];\n arr.push(e);\n edgesByComp.set(comp, arr);\n }\n\n interface CompBox {\n id: string;\n nodes: NodeOutput[];\n edges: EdgeOutput[];\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n }\n\n const boxes: CompBox[] = [];\n for (const [compId, group] of groups) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of group) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n const compEdges = edgesByComp.get(compId) ?? [];\n for (const e of compEdges) {\n for (const p of e.points) {\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 boxes.push({ id: compId, nodes: group, edges: compEdges, minX, minY, maxX, maxY });\n }\n\n // Sort largest-first along the rank axis so we lead with the dominant component.\n boxes.sort((a, b) => {\n const sizeA = isHorizontal ? a.maxX - a.minX : a.maxY - a.minY;\n const sizeB = isHorizontal ? b.maxX - b.minX : b.maxY - b.minY;\n return sizeB - sizeA;\n });\n\n const gap = options.layerSpacing;\n let cursor = 0;\n for (const box of boxes) {\n if (isHorizontal) {\n // Pack vertically (order axis is Y for LR).\n const dy = cursor - box.minY;\n const dx = -box.minX;\n for (const n of box.nodes) {\n n.x += dx;\n n.y += dy;\n for (const h of n.handles) {\n h.x += dx;\n h.y += dy;\n }\n }\n for (const e of box.edges) {\n for (const p of e.points) {\n p.x += dx;\n p.y += dy;\n }\n }\n cursor += (box.maxY - box.minY) + gap;\n } else {\n // Pack horizontally (order axis is X for TB).\n const dx = cursor - box.minX;\n const dy = -box.minY;\n for (const n of box.nodes) {\n n.x += dx;\n n.y += dy;\n for (const h of n.handles) {\n h.x += dx;\n h.y += dy;\n }\n }\n for (const e of box.edges) {\n for (const p of e.points) {\n p.x += dx;\n p.y += dy;\n }\n }\n cursor += (box.maxX - box.minX) + gap;\n }\n }\n}\n","import {\n EdgeInput,\n HandleInput,\n HandleSide,\n LayoutDirection,\n LayoutInput,\n LayoutResult,\n NodeInput,\n NodeOutput,\n RelocateHandlesProposal,\n ResolvedOptions,\n} from './types';\n\n/**\n * Inspect every input node and offer rotation proposals to the application\n * when the node's handle layout doesn't match how the layout engine will end\n * up placing it.\n *\n * The expected handle orientation depends on the node's role:\n *\n * - **Rail nodes** (with at least one control edge): they flow along the\n * global direction. In TB: inputs on top, outputs on bottom.\n * - **Value nodes** (only data edges): they end up as sidecars on the side\n * of their consumer. Their handles must point TOWARD the consumer — i.e.\n * opposite to the consumer's handle. A value attached to a `left` handle\n * of the consumer will sit on the consumer's left flank, so its output\n * needs to face `right`.\n *\n * The application's `onProposal` callback may:\n * - accept by returning the proposed node (or a modified version)\n * - reject by returning `null` / `undefined` / nothing\n */\nexport function applyRotationProposals(input: LayoutInput, options: ResolvedOptions): LayoutInput {\n if (!options.onProposal) return input;\n\n const nodeIndex = new Map<string, NodeInput>(input.nodes.map(n => [n.id, n]));\n\n const newNodes = input.nodes.map(node => {\n const role = classifyNode(node, input.edges);\n const expected = expectedSidesFor(node, role, input.edges, nodeIndex, options.direction);\n\n const proposal = computeProposal(node, expected, options.direction, role);\n if (!proposal) return node;\n const accepted = options.onProposal!(proposal);\n return accepted ?? node;\n });\n\n return { nodes: newNodes, edges: input.edges };\n}\n\ntype NodeRole =\n | { kind: 'rail' }\n | { kind: 'value'; consumerSide: HandleSide | null }\n | { kind: 'isolated' };\n\nfunction classifyNode(node: NodeInput, edges: EdgeInput[]): NodeRole {\n const incident = edges.filter(e => e.from === node.id || e.to === node.id);\n if (incident.length === 0) return { kind: 'isolated' };\n\n const allData = incident.every(e => (e.kind ?? 'control') === 'data');\n if (!allData) return { kind: 'rail' };\n\n // Value node — find which side of the (first) consumer it lands on.\n // A value typically has a single consumer; if it has several, the first one\n // wins (the sidecar placement uses the dominant consumer too, so this is a\n // reasonable approximation at proposal time).\n for (const e of incident) {\n const consumerId = e.from === node.id ? e.to : e.from;\n const consumerHandleId = e.from === node.id ? e.toHandle : e.fromHandle;\n const sideHint = sideHintFromHandle(consumerId, consumerHandleId, edges, /* recursing */ false);\n if (sideHint) return { kind: 'value', consumerSide: sideHint };\n }\n return { kind: 'value', consumerSide: null };\n}\n\nfunction sideHintFromHandle(\n _consumerId: string,\n _handleId: string,\n _edges: EdgeInput[],\n _recursing: boolean,\n): HandleSide | null {\n // The handle's position is on the consumer's node — but we don't have direct\n // access to the consumer NodeInput here without an index. The caller of\n // `classifyNode` resolves this through `expectedSidesFor` below.\n return null;\n}\n\nfunction expectedSidesFor(\n node: NodeInput,\n role: NodeRole,\n edges: EdgeInput[],\n index: Map<string, NodeInput>,\n direction: LayoutDirection,\n): { input: HandleSide; output: HandleSide } {\n if (role.kind === 'isolated' || role.kind === 'rail') {\n return { input: inputSideFor(direction), output: outputSideFor(direction) };\n }\n\n // Value: figure out which side of the consumer the value will land on.\n const consumerHandleSide = findConsumerHandleSide(node, edges, index);\n if (!consumerHandleSide) {\n return { input: inputSideFor(direction), output: outputSideFor(direction) };\n }\n\n // Sidecar placement only re-positions along the layout's order axis:\n // - TB/BT (vertical flow): values go on the consumer's left/right\n // ↳ a 'left' handle on the consumer → value sits at left → value's\n // output handle must face 'right' to reach the consumer.\n // ↳ symmetric for 'right'.\n // ↳ a 'top'/'bottom' handle: the value will be balanced left/right by\n // `splitValuesBySide`. We bias to face horizontally (right) for TB.\n // - LR/RL (horizontal flow): values go above/below.\n // ↳ 'top' handle → value sits above → output 'bottom'.\n // ↳ 'bottom' handle → output 'top'.\n // ↳ 'left'/'right' handle: bias vertically (bottom for LR).\n const isVerticalFlow = direction === 'TB' || direction === 'BT';\n\n let outputSide: HandleSide;\n if (isVerticalFlow) {\n if (consumerHandleSide === 'left') outputSide = 'right';\n else if (consumerHandleSide === 'right') outputSide = 'left';\n else outputSide = 'right'; // neutral, default to facing right\n } else {\n if (consumerHandleSide === 'top') outputSide = 'bottom';\n else if (consumerHandleSide === 'bottom') outputSide = 'top';\n else outputSide = 'bottom';\n }\n\n return { input: outputSide, output: outputSide };\n}\n\nfunction findConsumerHandleSide(\n value: NodeInput,\n edges: EdgeInput[],\n index: Map<string, NodeInput>,\n): HandleSide | null {\n for (const e of edges) {\n const isFromValue = e.from === value.id;\n const isToValue = e.to === value.id;\n if (!isFromValue && !isToValue) continue;\n\n const consumerId = isFromValue ? e.to : e.from;\n const consumer = index.get(consumerId);\n if (!consumer) continue;\n\n const consumerHandleId = isFromValue ? e.toHandle : e.fromHandle;\n const consumerHandle = consumer.handles.find(h => h.id === consumerHandleId);\n if (consumerHandle) return consumerHandle.position;\n }\n return null;\n}\n\nfunction computeProposal(\n node: NodeInput,\n expected: { input: HandleSide; output: HandleSide },\n direction: LayoutDirection,\n role: NodeRole,\n): ReturnType<typeof buildProposal> | null {\n if (node.handles.length === 0) return null;\n const currentScore = score(node.handles, expected);\n if (currentScore.matchRatio >= 1) return null;\n\n const candidates: { rotation: 90 | -90 | 180; score: ReturnType<typeof score> }[] = [];\n for (const rot of [90, -90, 180] as const) {\n const rotated = rotateHandles(node.handles, rot);\n candidates.push({ rotation: rot, score: score(rotated, expected) });\n }\n\n candidates.sort((a, b) => b.score.matchRatio - a.score.matchRatio);\n const best = candidates[0];\n if (best.score.matchRatio <= currentScore.matchRatio) return null;\n\n return buildProposal(node, best.rotation, currentScore, best.score, direction, expected, role);\n}\n\nfunction buildProposal(\n node: NodeInput,\n rotation: 90 | -90 | 180,\n current: ReturnType<typeof score>,\n proposedScore: ReturnType<typeof score>,\n direction: LayoutDirection,\n expected: { input: HandleSide; output: HandleSide },\n role: NodeRole,\n) {\n const proposed: NodeInput = { ...node, handles: rotateHandles(node.handles, rotation) };\n const roleDesc = role.kind === 'value'\n ? `value node should face ${expected.output} (its sidecar lands opposite the consumer's handle)`\n : `direction ${direction} expects inputs on ${expected.input} and outputs on ${expected.output}`;\n return {\n type: 'rotate' as const,\n nodeId: node.id,\n current: node,\n proposed,\n rotation,\n reason: `${roleDesc}; ${current.matched}/${current.total} handles match, ${proposedScore.matched}/${proposedScore.total} after rotation`,\n };\n}\n\nfunction inputSideFor(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'top';\n case 'BT': return 'bottom';\n case 'LR': return 'left';\n case 'RL': return 'right';\n }\n}\n\nfunction outputSideFor(direction: LayoutDirection): HandleSide {\n switch (direction) {\n case 'TB': return 'bottom';\n case 'BT': return 'top';\n case 'LR': return 'right';\n case 'RL': return 'left';\n }\n}\n\nfunction score(\n handles: HandleInput[],\n expected: { input: HandleSide; output: HandleSide },\n): { matched: number; total: number; matchRatio: number } {\n let matched = 0;\n let total = 0;\n for (const h of handles) {\n total++;\n if (h.type === 'input' && h.position === expected.input) matched++;\n else if (h.type === 'output' && h.position === expected.output) matched++;\n }\n return { matched, total, matchRatio: total === 0 ? 1 : matched / total };\n}\n\n/**\n * Per-handle strategic placement. Unlike `applyRotationProposals` which rotates\n * every handle uniformly, this pass uses the geometry from a preview layout to\n * suggest, for each handle, the side that actually points toward its neighbor.\n *\n * The caller must provide a `preview` layout — typically obtained by running\n * a first layout pass with `onProposal` unset.\n *\n * The application's `onProposal` callback receives a single\n * `RelocateHandlesProposal` per node (with all per-handle moves bundled). It\n * may accept it as-is, modify per-handle, or reject.\n */\nexport function applyRelocateProposals(\n input: LayoutInput,\n preview: LayoutResult,\n options: ResolvedOptions,\n): LayoutInput {\n if (!options.onProposal) return input;\n\n const previewIndex = new Map<string, NodeOutput>(preview.nodes.map(n => [n.id, n]));\n const inputIndex = new Map<string, NodeInput>(input.nodes.map(n => [n.id, n]));\n\n const newNodes = input.nodes.map(node => {\n const proposal = computeRelocateProposal(node, input.edges, inputIndex, previewIndex, options.direction);\n if (!proposal) return node;\n const accepted = options.onProposal!(proposal);\n return accepted ?? node;\n });\n\n return { nodes: newNodes, edges: input.edges };\n}\n\n/** Classification of one neighbor relative to a node, in preview geometry. */\ninterface NeighborHit {\n /** Strength of the vote (1 / distance, or 1 if coincident). */\n weight: number;\n /** True when the neighbor is in a different rank band (a flow pred/successor). */\n isFlow: boolean;\n /** The flow-axis side facing the neighbor (top/bottom in TB, left/right in LR). */\n flowSide: HandleSide;\n /** The perpendicular side facing the neighbor. */\n perpSide: HandleSide;\n /** Neighbor center on the order axis (x for TB/BT, y for LR/RL). */\n orderCoord: number;\n /** Neighbor center on the rank axis (y for TB/BT, x for LR/RL). */\n rankCoord: number;\n /** -1 if the neighbor is beyond the node's order-min, +1 beyond order-max, 0 within. */\n beyond: -1 | 0 | 1;\n}\n\nfunction computeRelocateProposal(\n node: NodeInput,\n edges: EdgeInput[],\n inputIndex: Map<string, NodeInput>,\n previewIndex: Map<string, NodeOutput>,\n direction: LayoutDirection,\n): RelocateHandlesProposal | null {\n const selfPreview = previewIndex.get(node.id);\n if (!selfPreview) return null;\n if (node.handles.length === 0) return null;\n\n const isHorizontal = direction === 'LR' || direction === 'RL';\n\n // Rank axis = flow axis; order axis = perpendicular axis.\n const rankMin = isHorizontal ? selfPreview.x : selfPreview.y;\n const rankMax = isHorizontal ? selfPreview.x + selfPreview.width : selfPreview.y + selfPreview.height;\n const orderMin = isHorizontal ? selfPreview.y : selfPreview.x;\n const orderMax = isHorizontal ? selfPreview.y + selfPreview.height : selfPreview.x + selfPreview.width;\n const orderCenter = (orderMin + orderMax) / 2;\n\n const usedHandleIds = new Set<string>();\n for (const e of edges) {\n if (e.from === node.id) usedHandleIds.add(e.fromHandle);\n if (e.to === node.id) usedHandleIds.add(e.toHandle);\n }\n if (usedHandleIds.size === 0) return null;\n\n // Group votes per handle: each vote carries the neighbor's full classification.\n const votesByHandle = new Map<string, NeighborHit[]>();\n\n for (const e of edges) {\n const isFrom = e.from === node.id;\n const isTo = e.to === node.id;\n if (!isFrom && !isTo) continue;\n\n const handleId = isFrom ? e.fromHandle : e.toHandle;\n const neighborId = isFrom ? e.to : e.from;\n const np = previewIndex.get(neighborId);\n if (!np) continue;\n\n const nbrRankMin = isHorizontal ? np.x : np.y;\n const nbrRankMax = isHorizontal ? np.x + np.width : np.y + np.height;\n const overlap = Math.min(rankMax, nbrRankMax) - Math.max(rankMin, nbrRankMin);\n const isFlow = overlap <= 0;\n\n const nbrOrderC = isHorizontal ? np.y + np.height / 2 : np.x + np.width / 2;\n const nbrRankC = isHorizontal ? np.x + np.width / 2 : np.y + np.height / 2;\n const selfRankC = isHorizontal ? selfPreview.x + selfPreview.width / 2 : selfPreview.y + selfPreview.height / 2;\n\n // Flow side: which way along the rank axis the neighbor lies.\n const nbrIsBefore = nbrRankMax <= rankMin || (overlap <= 0 && nbrRankC < selfRankC);\n const flowSide: HandleSide = isHorizontal\n ? (nbrIsBefore ? 'left' : 'right')\n : (nbrIsBefore ? 'top' : 'bottom');\n\n // Perpendicular side: which way along the order axis.\n const d = nbrOrderC - orderCenter;\n const perpSide: HandleSide = isHorizontal\n ? (d >= 0 ? 'bottom' : 'top')\n : (d >= 0 ? 'right' : 'left');\n\n const beyond: -1 | 0 | 1 = nbrOrderC > orderMax ? 1 : nbrOrderC < orderMin ? -1 : 0;\n\n const dist = Math.hypot(nbrRankC - selfRankC, nbrOrderC - orderCenter);\n const weight = dist > 0 ? 1 / dist : 1;\n\n const arr = votesByHandle.get(handleId) ?? [];\n arr.push({ weight, isFlow, flowSide, perpSide, orderCoord: nbrOrderC, rankCoord: nbrRankC, beyond });\n votesByHandle.set(handleId, arr);\n }\n\n // Resolve each handle to its dominant neighbor's classification (highest weight).\n interface Resolved { side: HandleSide; isFlow: boolean; flowSide: HandleSide; perpSide: HandleSide; orderCoord: number; rankCoord: number; beyond: -1 | 0 | 1 }\n const resolved = new Map<string, Resolved>();\n for (const [handleId, votes] of votesByHandle) {\n if (votes.length === 0) continue;\n // Winner side: weighted tally over each vote's preferred side (flow if a\n // flow neighbor, else perpendicular).\n const tallies: Record<HandleSide, number> = { top: 0, right: 0, bottom: 0, left: 0 };\n let dom = votes[0];\n for (const v of votes) {\n tallies[v.isFlow ? v.flowSide : v.perpSide] += v.weight;\n if (v.weight > dom.weight) dom = v;\n }\n const side = (Object.entries(tallies) as [HandleSide, number][])\n .reduce((acc, cur) => (cur[1] > acc[1] ? cur : acc), ['top' as HandleSide, -Infinity])[0];\n resolved.set(handleId, {\n side, isFlow: dom.isFlow, flowSide: dom.flowSide, perpSide: dom.perpSide,\n orderCoord: dom.orderCoord, rankCoord: dom.rankCoord, beyond: dom.beyond,\n });\n }\n\n // ---- Lopsided correction ------------------------------------------------\n // When the flow-side neighbors of a node all sit on ONE side of its order\n // center (a one-directional fan, e.g. a node whose successors are all pushed\n // right), routing them on the flow edge crowds them and they cross. In that\n // case, neighbors that fall BEYOND the node's order extent are better served\n // by a perpendicular (side) handle. When the fan is balanced around the\n // center (e.g. a hub feeding children both left and right), the flow edge\n // routes cleanly and we keep everything on it.\n for (const flowSide of ['top', 'bottom', 'left', 'right'] as HandleSide[]) {\n const group = [...resolved.entries()].filter(([, r]) => r.isFlow && r.side === flowSide);\n if (group.length < 2) continue;\n let hasLeft = false, hasRight = false;\n for (const [, r] of group) {\n if (r.orderCoord < orderCenter) hasLeft = true;\n else if (r.orderCoord > orderCenter) hasRight = true;\n }\n // A fan that reaches both sides of the node's order center routes cleanly on\n // the flow edge — leave it. Only a one-directional fan congests.\n if (hasLeft && hasRight) continue;\n\n // Among the neighbors that fall BEYOND the node's order extent, the nearest\n // *distinct* neighbor still routes cleanly on the flow edge (it's adjacent\n // to the in-extent handles). Any farther neighbors crowd it and cross, so\n // their handles move to the perpendicular flank facing them. Handles that\n // target the SAME neighbor are grouped (same order coordinate) so they move\n // together — otherwise two handles to one diagonal neighbor would split.\n const distOf = (oc: number) => (oc > orderMax ? oc - orderMax : orderMin - oc);\n const distinctCoords = [...new Set(group.filter(([, r]) => r.beyond !== 0).map(([, r]) => r.orderCoord))]\n .sort((a, b) => distOf(a) - distOf(b));\n if (distinctCoords.length >= 2) {\n const keep = distinctCoords[0];\n for (const [, r] of group) {\n if (r.beyond !== 0 && r.orderCoord !== keep) r.side = r.perpSide;\n }\n }\n }\n\n // Build the side change set.\n const sideChanges: Record<string, { from: HandleSide; to: HandleSide }> = {};\n const newSideById = new Map<string, HandleSide>();\n for (const h of node.handles) {\n const r = resolved.get(h.id);\n if (!r) continue;\n newSideById.set(h.id, r.side);\n if (r.side !== h.position) sideChanges[h.id] = { from: h.position, to: r.side };\n }\n\n // Offset reordering: when 2+ handles end up on the SAME side, permute their\n // offsets so they're ordered to match their neighbors along that side — this\n // prevents edges from crossing as they leave a shared edge of the node. The\n // sort key is the neighbor's coordinate on the side's perpendicular axis.\n const newOffsetById = new Map<string, number>();\n const bySide = new Map<HandleSide, string[]>();\n for (const [hid, r] of resolved) {\n const arr = bySide.get(r.side) ?? [];\n arr.push(hid);\n bySide.set(r.side, arr);\n }\n for (const [side, handleIds] of bySide) {\n if (handleIds.length < 2) continue;\n const offsets = handleIds\n .map(hid => node.handles.find(h => h.id === hid)!.offset ?? 0.5)\n .sort((a, b) => a - b);\n // Handles arranged along a top/bottom edge are ordered by the neighbor's\n // X (the order axis in TB); along a left/right edge, by the neighbor's Y\n // (the rank axis in TB). Pick the coordinate that runs along this side.\n const horizontalSide = side === 'top' || side === 'bottom';\n const sortKey = (hid: string): number => {\n const r = resolved.get(hid)!;\n // In TB: order axis = X, rank axis = Y. In LR they swap. `orderCoord` is\n // always the order axis, `rankCoord` the rank axis.\n if (isHorizontal) {\n // LR: left/right sides run along Y = order axis? No — in LR the order\n // axis is Y, so top/bottom sides run along X (rank), left/right run\n // along Y (order). Mirror of TB.\n return horizontalSide ? r.rankCoord : r.orderCoord;\n }\n return horizontalSide ? r.orderCoord : r.rankCoord;\n };\n const sortedHandles = [...handleIds].sort((a, b) => {\n const ra = sortKey(a), rb = sortKey(b);\n return ra - rb || (a < b ? -1 : a > b ? 1 : 0);\n });\n for (let i = 0; i < sortedHandles.length; i++) {\n newOffsetById.set(sortedHandles[i], offsets[i]);\n }\n }\n\n // Assemble the proposed handles and detect whether anything actually changed.\n let changed = false;\n const newHandles = node.handles.map(h => {\n const side = newSideById.get(h.id) ?? h.position;\n const offset = newOffsetById.has(h.id) ? newOffsetById.get(h.id)! : (h.offset ?? 0.5);\n if (side !== h.position || offset !== (h.offset ?? 0.5)) {\n changed = true;\n return { ...h, position: side, offset };\n }\n return h;\n });\n\n if (!changed) return null;\n\n const proposed: NodeInput = { ...node, handles: newHandles };\n const sideSummary = Object.entries(sideChanges)\n .map(([id, c]) => `${id}: ${c.from}→${c.to}`)\n .join(', ');\n const reason = sideSummary\n ? `${Object.keys(sideChanges).length} handle(s) repositioned toward their neighbor (${sideSummary})`\n : `handles on a shared side reordered to match neighbor order`;\n\n return {\n type: 'relocate-handles',\n nodeId: node.id,\n current: node,\n proposed,\n changes: sideChanges,\n reason,\n };\n}\n\n/**\n * Rotate a set of handles by `rot` degrees clockwise. The handles' position\n * along the side (offset) is preserved.\n *\n * Note: width/height of the node are NOT swapped here. The caller is free to\n * swap them when accepting the proposal (most layouts use square-ish nodes,\n * so we don't enforce a dimension swap).\n */\nexport function rotateHandles(handles: HandleInput[], rot: 90 | -90 | 180): HandleInput[] {\n const rotateSide = (s: HandleSide): HandleSide => {\n if (rot === 180) {\n return s === 'top' ? 'bottom' : s === 'bottom' ? 'top' : s === 'left' ? 'right' : 'left';\n }\n if (rot === 90) {\n return s === 'top' ? 'right' : s === 'right' ? 'bottom' : s === 'bottom' ? 'left' : 'top';\n }\n return s === 'top' ? 'left' : s === 'left' ? 'bottom' : s === 'bottom' ? 'right' : 'top';\n };\n return handles.map(h => ({ ...h, position: rotateSide(h.position) }));\n}\n","import {\n LayoutInput,\n LayoutOptions,\n LayoutResult,\n NodeOutput,\n EdgeOutput,\n HandleOutput,\n NodeInput,\n EdgeInput,\n resolveOptions,\n ResolvedOptions,\n} from './types';\nimport { Graph, buildGraph, getHandlePosition } from './graph';\nimport { breakCycles } from './algorithms/cycle-breaking';\nimport { assignLayers, insertDummyNodes } from './algorithms/layer-assignment';\nimport { minimizeCrossings } from './algorithms/crossing-minimization';\nimport { assignCoordinates } from './algorithms/coordinate-assignment';\nimport { placeValueSidecars, railLayers } from './algorithms/value-placement';\nimport { routeEdges } from './algorithms/edge-routing';\nimport { packComponents } from './algorithms/component-packing';\nimport { applyRelocateProposals, applyRotationProposals } from './proposals';\n\n/** Vertical room reserved at the top of a compound for the parent's own label. */\nconst COMPOUND_HEADER = 28;\n\n/**\n * Compute a complete layout for the given graph, with full compound (nested)\n * support and disjoint-component packing.\n */\nexport function layout(input: LayoutInput, options?: LayoutOptions): LayoutResult {\n const resolved = resolveOptions(options);\n if (input.nodes.length === 0) return { nodes: [], edges: [] };\n\n // Phase 1: rotate proposals — direction-mismatch detection only, no preview needed.\n let adjusted = applyRotationProposals(input, resolved);\n\n // Phase 2: relocate proposals — needs a preview layout to know where each\n // neighbor actually ends up. We only pay this extra pass when onProposal\n // is provided.\n if (resolved.onProposal) {\n const previewOptions: ResolvedOptions = { ...resolved, onProposal: undefined };\n const preview = layoutCompound(adjusted, previewOptions);\n adjusted = applyRelocateProposals(adjusted, preview, resolved);\n }\n\n return layoutCompound(adjusted, resolved);\n}\n\n/** Flat (single-level) layout on an already-built graph. */\nexport function computeLayout(graph: Graph, options: ResolvedOptions): LayoutResult {\n if (graph.nodes.size === 0) return { nodes: [], edges: [] };\n\n breakCycles(graph);\n\n let layers = assignLayers(graph);\n layers = insertDummyNodes(graph, layers);\n\n // Rail-only layers drive crossings + coords. Values are attached afterwards.\n let rail = railLayers(layers, graph);\n rail = minimizeCrossings(\n graph,\n rail,\n options.crossingMinimizationIterations,\n options.skipTranspose,\n );\n assignCoordinates(graph, rail, options);\n\n // Attach value nodes as sidecars to their dominant consumer.\n placeValueSidecars(graph, layers, options);\n\n const routedEdges = routeEdges(graph, options.direction, options.edgeMargin);\n return buildResult(graph, routedEdges);\n}\n\nfunction buildResult(graph: Graph, routedEdges: ReturnType<typeof routeEdges>): LayoutResult {\n const nodes: NodeOutput[] = [];\n const edges: EdgeOutput[] = [];\n\n for (const [, node] of graph.nodes) {\n if (node.isDummy) continue;\n\n const handles: HandleOutput[] = node.handles.map(h => {\n const pos = getHandlePosition(node, h.id);\n return { id: h.id, type: h.type, position: h.position, x: pos.x, y: pos.y };\n });\n\n nodes.push({\n id: node.id,\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n handles,\n parentId: node.parentId,\n });\n }\n\n for (const route of routedEdges) {\n edges.push({\n id: route.id,\n from: route.from,\n to: route.to,\n fromHandle: route.fromHandle,\n toHandle: route.toHandle,\n points: route.points,\n kind: route.kind,\n });\n }\n\n return { nodes, edges };\n}\n\n/**\n * Compound Sugiyama: process nests bottom-up so each compound has its size\n * computed from its laid-out children before it appears in a higher-level pass.\n */\nfunction layoutCompound(input: LayoutInput, options: ResolvedOptions): LayoutResult {\n const nodeMap = new Map(input.nodes.map(n => [n.id, n]));\n\n const childrenByParent = new Map<string, NodeInput[]>();\n const rootNodes: NodeInput[] = [];\n for (const n of input.nodes) {\n if (n.parentId && nodeMap.has(n.parentId)) {\n const arr = childrenByParent.get(n.parentId) ?? [];\n arr.push(n);\n childrenByParent.set(n.parentId, arr);\n } else {\n rootNodes.push(n);\n }\n }\n\n const compoundIds = new Set(childrenByParent.keys());\n\n // Compute nesting depth so we can process compounds deepest-first.\n const depthCache = new Map<string, number>();\n function depthOf(id: string): number {\n if (depthCache.has(id)) return depthCache.get(id)!;\n const n = nodeMap.get(id);\n const d = n?.parentId && nodeMap.has(n.parentId) ? depthOf(n.parentId) + 1 : 0;\n depthCache.set(id, d);\n return d;\n }\n for (const n of input.nodes) depthOf(n.id);\n\n const sortedCompounds = [...compoundIds].sort((a, b) => depthOf(b) - depthOf(a));\n\n // Sub-layouts of each compound, keyed by the compound's id.\n const subLayouts = new Map<string, LayoutResult>();\n // Final published sizes for each compound (after children were laid out).\n const compoundSize = new Map<string, { width: number; height: number }>();\n\n for (const compoundId of sortedCompounds) {\n const children = childrenByParent.get(compoundId) ?? [];\n if (children.length === 0) continue;\n\n const childIdSet = new Set(children.map(c => c.id));\n const subEdges = input.edges.filter(e => childIdSet.has(e.from) && childIdSet.has(e.to));\n\n // Swap in computed sizes for any nested compounds among the children.\n const sizedChildren = children.map(c => {\n const sz = compoundSize.get(c.id);\n return sz ? { ...c, width: sz.width, height: sz.height } : c;\n });\n\n // Force packComponents off inside compounds — children are presumed connected\n // (and packing inside a parent box would visually conflict).\n const subOptions: ResolvedOptions = { ...options, packComponents: false };\n const subInput: LayoutInput = { nodes: sizedChildren.map(stripParent), edges: subEdges };\n const subResult = layoutFlat(subInput, subOptions);\n subLayouts.set(compoundId, subResult);\n\n // Compound size: bounding box of children + padding + header for the label.\n const bbox = computeBoundingBox(subResult.nodes);\n const innerW = bbox.width + options.compoundPadding * 2;\n const innerH = bbox.height + options.compoundPadding * 2 + COMPOUND_HEADER;\n\n const original = nodeMap.get(compoundId)!;\n compoundSize.set(compoundId, {\n width: Math.max(innerW, original.width),\n height: Math.max(innerH, original.height),\n });\n }\n\n // Root-level layout: compounds participate with their inflated size.\n const sizedRootNodes = rootNodes.map(n => {\n const sz = compoundSize.get(n.id);\n return sz ? { ...n, width: sz.width, height: sz.height } : n;\n });\n const rootIdSet = new Set(rootNodes.map(n => n.id));\n const rootEdges = input.edges.filter(e => {\n // Edges between root-level entities (compound boundaries count as roots).\n return rootIdSet.has(e.from) && rootIdSet.has(e.to);\n });\n\n const rootResult = layoutFlat({ nodes: sizedRootNodes.map(stripParent), edges: rootEdges }, options);\n\n // Final assembly: drop root nodes in, then translate each compound's children\n // by an offset that places them inside their parent's interior.\n const finalNodes: NodeOutput[] = [];\n const finalEdges: EdgeOutput[] = [];\n\n // First, replay the root result. Compound parents stay as visible rectangles.\n for (const n of rootResult.nodes) {\n const wasCompound = compoundIds.has(n.id);\n finalNodes.push({\n ...n,\n parentId: nodeMap.get(n.id)?.parentId,\n });\n if (wasCompound) {\n placeCompoundChildren(n, compoundId => subLayouts.get(compoundId), finalNodes, finalEdges, options, nodeMap);\n }\n }\n finalEdges.push(...rootResult.edges);\n\n if (options.packComponents) {\n packComponents(finalNodes, finalEdges, options);\n }\n\n return { nodes: finalNodes, edges: finalEdges };\n}\n\n/**\n * Recursively place a compound's children inside the parent's bounding box.\n * Translates positions from the sub-layout's local coords to the parent's frame.\n */\nfunction placeCompoundChildren(\n parent: NodeOutput,\n getSub: (compoundId: string) => LayoutResult | undefined,\n finalNodes: NodeOutput[],\n finalEdges: EdgeOutput[],\n options: ResolvedOptions,\n nodeMap: Map<string, NodeInput>,\n): void {\n const sub = getSub(parent.id);\n if (!sub) return;\n\n const bbox = computeBoundingBox(sub.nodes);\n // local-origin = (bbox.minX, bbox.minY) -> map to parent.x + padding, parent.y + padding + header\n const dx = parent.x + options.compoundPadding - bbox.minX;\n const dy = parent.y + options.compoundPadding + COMPOUND_HEADER - bbox.minY;\n\n // Center horizontally inside available space if the parent was inflated past\n // the children's natural width.\n const availableW = parent.width - options.compoundPadding * 2;\n const slackX = (availableW - bbox.width) / 2;\n const availableH = parent.height - options.compoundPadding * 2 - COMPOUND_HEADER;\n const slackY = (availableH - bbox.height) / 2;\n const cx = dx + Math.max(0, slackX);\n const cy = dy + Math.max(0, slackY);\n\n for (const child of sub.nodes) {\n const placed: NodeOutput = {\n ...child,\n x: child.x + cx,\n y: child.y + cy,\n handles: child.handles.map(h => ({ ...h, x: h.x + cx, y: h.y + cy })),\n parentId: nodeMap.get(child.id)?.parentId ?? parent.id,\n };\n finalNodes.push(placed);\n if (getSub(child.id)) {\n placeCompoundChildren(placed, getSub, finalNodes, finalEdges, options, nodeMap);\n }\n }\n\n for (const edge of sub.edges) {\n finalEdges.push({\n ...edge,\n points: edge.points.map(p => ({ x: p.x + cx, y: p.y + cy })),\n });\n }\n}\n\n/** Strip parentId from a node copy so flat layout won't recurse. */\nfunction stripParent(n: NodeInput): NodeInput {\n const { parentId: _ignored, ...rest } = n;\n return rest;\n}\n\nfunction layoutFlat(input: LayoutInput, options: ResolvedOptions): LayoutResult {\n const graph = buildGraph(input.nodes, input.edges, {\n controlWeight: options.controlWeight,\n dataWeight: options.dataWeight,\n });\n return computeLayout(graph, options);\n}\n\nfunction computeBoundingBox(\n nodes: { x: number; y: number; width: number; height: number }[],\n): { minX: number; minY: number; maxX: number; maxY: number; width: number; height: number } {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n if (!isFinite(minX)) {\n minX = 0; minY = 0; maxX = 0; maxY = 0;\n }\n return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY };\n}\n","import {\n LayoutInput,\n LayoutOptions,\n LayoutResult,\n NodeInput,\n EdgeInput,\n resolveOptions,\n ResolvedOptions,\n} from './types';\nimport { layout } from './layout';\n\n/**\n * Incremental layout engine.\n * Maintains layout state and supports adding/removing nodes\n * without full recomputation.\n *\n * Compound layouts and value-pulled nodes are handled through the unified\n * `layout()` entry point, so any input change re-uses the same logic.\n */\nexport class IncrementalLayout {\n private resolvedOptions: ResolvedOptions;\n private options: LayoutOptions | undefined;\n private inputNodes: Map<string, NodeInput> = new Map();\n private inputEdges: Map<string, EdgeInput> = new Map();\n private lastResult: LayoutResult | null = null;\n private nodePositions: Map<string, { x: number; y: number }> = new Map();\n\n constructor(options?: LayoutOptions) {\n this.options = options;\n this.resolvedOptions = resolveOptions(options);\n }\n\n setGraph(input: LayoutInput): LayoutResult {\n this.inputNodes.clear();\n this.inputEdges.clear();\n for (const node of input.nodes) this.inputNodes.set(node.id, node);\n for (const edge of input.edges) this.inputEdges.set(edge.id, edge);\n return this.recompute();\n }\n\n addNodes(nodes: NodeInput[], edges?: EdgeInput[]): LayoutResult {\n for (const node of nodes) this.inputNodes.set(node.id, node);\n if (edges) for (const edge of edges) this.inputEdges.set(edge.id, edge);\n return this.recomputeWithStability(new Set(nodes.map(n => n.id)));\n }\n\n removeNodes(nodeIds: string[]): LayoutResult {\n const removedSet = new Set(nodeIds);\n for (const id of nodeIds) this.inputNodes.delete(id);\n for (const [edgeId, edge] of this.inputEdges) {\n if (removedSet.has(edge.from) || removedSet.has(edge.to)) {\n this.inputEdges.delete(edgeId);\n }\n }\n for (const id of nodeIds) this.nodePositions.delete(id);\n return this.recompute();\n }\n\n addEdges(edges: EdgeInput[]): LayoutResult {\n for (const edge of edges) this.inputEdges.set(edge.id, edge);\n return this.recomputeWithStability(new Set<string>());\n }\n\n removeEdges(edgeIds: string[]): LayoutResult {\n for (const id of edgeIds) this.inputEdges.delete(id);\n return this.recompute();\n }\n\n getResult(): LayoutResult | null {\n return this.lastResult;\n }\n\n private recompute(): LayoutResult {\n const input: LayoutInput = {\n nodes: [...this.inputNodes.values()],\n edges: [...this.inputEdges.values()],\n };\n this.lastResult = layout(input, this.options);\n this.cachePositions();\n return this.lastResult;\n }\n\n private recomputeWithStability(newNodeIds: Set<string>): LayoutResult {\n const input: LayoutInput = {\n nodes: [...this.inputNodes.values()],\n edges: [...this.inputEdges.values()],\n };\n\n const fresh = layout(input, this.options);\n this.lastResult = this.applyStability(fresh, newNodeIds);\n this.cachePositions();\n return this.lastResult;\n }\n\n /**\n * Blend the freshly computed positions with the previous ones, so existing\n * nodes don't jump too far when a small change happens.\n */\n private applyStability(fresh: LayoutResult, newNodeIds: Set<string>): LayoutResult {\n if (this.nodePositions.size === 0) return fresh;\n const STABILITY_WEIGHT = 0.3;\n\n const blended: LayoutResult = {\n nodes: fresh.nodes.map(n => {\n if (newNodeIds.has(n.id)) return n;\n const old = this.nodePositions.get(n.id);\n if (!old) return n;\n const dx = old.x - n.x;\n const dy = old.y - n.y;\n const x = n.x + dx * STABILITY_WEIGHT;\n const y = n.y + dy * STABILITY_WEIGHT;\n const ddx = x - n.x;\n const ddy = y - n.y;\n return {\n ...n,\n x,\n y,\n handles: n.handles.map(h => ({ ...h, x: h.x + ddx, y: h.y + ddy })),\n };\n }),\n edges: fresh.edges,\n };\n return blended;\n }\n\n private cachePositions(): void {\n if (!this.lastResult) return;\n this.nodePositions.clear();\n for (const node of this.lastResult.nodes) {\n this.nodePositions.set(node.id, { x: node.x, y: node.y });\n }\n }\n}\n","import { LayoutResult, NodeOutput, EdgeOutput } from './types';\n\n/**\n * Render a `LayoutResult` to a human-readable text block.\n *\n * Useful when iterating on the algorithm without opening a browser:\n * - a per-layer summary (Y bands in TB, X bands in LR-ish)\n * - per-node hierarchy + bbox\n * - per-edge endpoints and kind\n * - an ASCII grid (optional) sketching the final layout\n */\nexport interface PrintLayoutOptions {\n /** Include an ASCII grid sketch (default: true). */\n grid?: boolean;\n /** Grid resolution: characters per coordinate unit (default: auto). */\n gridScale?: number;\n /** Max grid width in characters (default: 80). */\n gridWidth?: number;\n}\n\nexport function printLayout(result: LayoutResult, options: PrintLayoutOptions = {}): string {\n const lines: string[] = [];\n const { nodes, edges } = result;\n\n if (nodes.length === 0) return '(empty layout)';\n\n // ----- bounding box -----\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n lines.push(`=== layout ${nodes.length} nodes, ${edges.length} edges ===`);\n lines.push(`bbox: x=[${minX.toFixed(0)}..${maxX.toFixed(0)}] y=[${minY.toFixed(0)}..${maxY.toFixed(0)}] (${(maxX - minX).toFixed(0)} x ${(maxY - minY).toFixed(0)})`);\n\n // ----- Y bands (TB-style) -----\n const byY = [...nodes].sort((a, b) => a.y - b.y || a.x - b.x);\n const bands: NodeOutput[][] = [];\n for (const n of byY) {\n const placed = bands.find(b => Math.abs(b[0].y - n.y) < 1);\n if (placed) placed.push(n);\n else bands.push([n]);\n }\n\n lines.push('');\n lines.push('--- Y bands ---');\n for (const band of bands) {\n const sorted = [...band].sort((a, b) => a.x - b.x);\n const summary = sorted.map(n => {\n const p = n.parentId ? `[${n.parentId}/]` : '';\n return `${p}${n.id}@(${n.x.toFixed(0)},${n.y.toFixed(0)} ${n.width}x${n.height})`;\n }).join(' ');\n lines.push(` y=${band[0].y.toFixed(0).padStart(4)} : ${summary}`);\n }\n\n // ----- hierarchy -----\n const byParent = new Map<string | undefined, NodeOutput[]>();\n for (const n of nodes) {\n const key = n.parentId;\n const arr = byParent.get(key) ?? [];\n arr.push(n);\n byParent.set(key, arr);\n }\n const compoundIds = new Set<string>();\n for (const k of byParent.keys()) {\n if (k && nodes.find(n => n.id === k)) compoundIds.add(k);\n }\n if (compoundIds.size > 0) {\n lines.push('');\n lines.push('--- hierarchy ---');\n function printSubtree(id: string | undefined, depth: number) {\n const children = byParent.get(id) ?? [];\n for (const c of children) {\n const prefix = ' '.repeat(depth);\n const tag = compoundIds.has(c.id) ? ' (compound)' : '';\n lines.push(`${prefix}- ${c.id}${tag} bbox=(${c.x.toFixed(0)},${c.y.toFixed(0)})..(${(c.x + c.width).toFixed(0)},${(c.y + c.height).toFixed(0)})`);\n if (compoundIds.has(c.id)) printSubtree(c.id, depth + 1);\n }\n }\n printSubtree(undefined, 0);\n }\n\n // ----- edges -----\n lines.push('');\n lines.push('--- edges ---');\n for (const e of edges) {\n const head = e.points[0];\n const tail = e.points[e.points.length - 1];\n lines.push(` [${e.kind}] ${e.from}.${e.fromHandle} → ${e.to}.${e.toHandle} (${head.x.toFixed(0)},${head.y.toFixed(0)}) → (${tail.x.toFixed(0)},${tail.y.toFixed(0)}) via ${e.points.length} pts`);\n }\n\n // ----- overlap check -----\n const overlaps = findOverlaps(nodes);\n if (overlaps.length > 0) {\n lines.push('');\n lines.push('--- OVERLAPS (problem!) ---');\n for (const o of overlaps) {\n lines.push(` ${o.a} overlaps ${o.b}`);\n }\n }\n\n if (options.grid !== false) {\n lines.push('');\n lines.push('--- ASCII grid ---');\n lines.push(asciiGrid(nodes, edges, options));\n }\n\n return lines.join('\\n');\n}\n\nfunction findOverlaps(nodes: NodeOutput[]): { a: string; b: string }[] {\n const out: { a: string; b: string }[] = [];\n const compoundIds = new Set<string>();\n for (const n of nodes) if (n.parentId) compoundIds.add(n.parentId);\n\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const a = nodes[i];\n const b = nodes[j];\n // Skip compound-vs-child intentional overlap (compound contains its kids).\n if (a.id === b.parentId || b.id === a.parentId) continue;\n // Skip sibling values vs compound parent (handled by hierarchy).\n const overlapX = a.x < b.x + b.width && b.x < a.x + a.width;\n const overlapY = a.y < b.y + b.height && b.y < a.y + a.height;\n if (overlapX && overlapY) {\n out.push({ a: a.id, b: b.id });\n }\n }\n }\n return out;\n}\n\nfunction asciiGrid(nodes: NodeOutput[], edges: EdgeOutput[], options: PrintLayoutOptions): string {\n if (nodes.length === 0) return '';\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const n of nodes) {\n if (n.x < minX) minX = n.x;\n if (n.y < minY) minY = n.y;\n if (n.x + n.width > maxX) maxX = n.x + n.width;\n if (n.y + n.height > maxY) maxY = n.y + n.height;\n }\n for (const e of edges) for (const p of e.points) {\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 targetW = options.gridWidth ?? 80;\n const layoutW = Math.max(1, maxX - minX);\n const layoutH = Math.max(1, maxY - minY);\n const scaleX = options.gridScale ?? targetW / layoutW;\n // Characters are roughly twice as tall as wide -> halve Y scale.\n const scaleY = scaleX * 0.5;\n\n const w = Math.max(1, Math.ceil(layoutW * scaleX) + 1);\n const h = Math.max(1, Math.ceil(layoutH * scaleY) + 1);\n\n if (h > 80) return '(grid suppressed: too tall — pass {grid:false} to skip)';\n\n const grid: string[][] = Array.from({ length: h }, () => Array.from({ length: w }, () => ' '));\n\n const compoundIds = new Set<string>();\n for (const n of nodes) if (n.parentId) compoundIds.add(n.parentId);\n\n // Draw nodes\n for (const n of nodes) {\n const x0 = Math.round((n.x - minX) * scaleX);\n const y0 = Math.round((n.y - minY) * scaleY);\n const x1 = Math.max(x0, Math.round((n.x + n.width - minX) * scaleX) - 1);\n const y1 = Math.max(y0, Math.round((n.y + n.height - minY) * scaleY) - 1);\n const isCompound = compoundIds.has(n.id);\n const ch = isCompound ? '.' : '#';\n for (let y = y0; y <= y1 && y < h; y++) {\n for (let x = x0; x <= x1 && x < w; x++) {\n if (y < 0 || x < 0) continue;\n if (y === y0 || y === y1 || x === x0 || x === x1) grid[y][x] = ch;\n else if (isCompound) {\n // empty interior for compounds\n } else grid[y][x] = ch;\n }\n }\n // Label: first letters of id, centered top-left of box\n const label = n.id.slice(0, Math.min(n.id.length, Math.max(2, x1 - x0 - 1)));\n const lx = Math.max(0, x0 + 1);\n const ly = Math.max(0, y0);\n for (let i = 0; i < label.length && lx + i < w; i++) {\n if (ly < h) grid[ly][lx + i] = label[i];\n }\n }\n\n return grid.map(row => row.join('')).join('\\n');\n}\n"],"mappings":";AAsMA,IAAM,mBAA0D;AAAA,EAC9D,OAAO;AAAA,IACL,gCAAgC;AAAA,IAChC,kCAAkC;AAAA,IAClC,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,gCAAgC;AAAA,IAChC,kCAAkC;AAAA,IAClC,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,gCAAgC;AAAA,IAChC,kCAAkC;AAAA,IAClC,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,eAAe,SAA0C;AACvE,QAAM,UAAyB,SAAS,WAAW;AACnD,QAAM,UAAU,iBAAiB,OAAO;AACxC,SAAO;AAAA,IACL,WAAW,SAAS,aAAa;AAAA,IACjC;AAAA,IACA,aAAa,SAAS,eAAe;AAAA,IACrC,cAAc,SAAS,gBAAgB;AAAA,IACvC,gCACE,SAAS,kCAAkC,QAAQ;AAAA,IACrD,kCACE,SAAS,oCAAoC,QAAQ;AAAA,IACvD,eAAe,SAAS,iBAAiB,QAAQ;AAAA,IACjD,YAAY,SAAS,cAAc;AAAA,IACnC,eAAe,SAAS,aAAa,WAAW;AAAA,IAChD,YAAY,SAAS,aAAa,QAAQ;AAAA,IAC1C,gBAAgB,SAAS,kBAAkB;AAAA,IAC3C,iBAAiB,SAAS,mBAAmB;AAAA,IAC7C,YAAY,SAAS;AAAA,EACvB;AACF;;;AC7MO,IAAM,QAAN,MAAY;AAAA,EAAZ;AACL,iBAAmC,oBAAI,IAAI;AAC3C,iBAAmC,oBAAI,IAAI;AAC3C,oBAAqC,oBAAI,IAAI;AAC7C,mBAAoC,oBAAI,IAAI;AAAA;AAAA,EAE5C,QAAQ,MAA0B;AAChC,SAAK,MAAM,IAAI,KAAK,IAAI,IAAI;AAC5B,QAAI,CAAC,KAAK,SAAS,IAAI,KAAK,EAAE,EAAG,MAAK,SAAS,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AACrE,QAAI,CAAC,KAAK,QAAQ,IAAI,KAAK,EAAE,EAAG,MAAK,QAAQ,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AAAA,EACrE;AAAA,EAEA,QAAQ,MAA0B;AAChC,SAAK,MAAM,IAAI,KAAK,IAAI,IAAI;AAC5B,QAAI,CAAC,KAAK,SAAS,IAAI,KAAK,IAAI,EAAG,MAAK,SAAS,IAAI,KAAK,MAAM,oBAAI,IAAI,CAAC;AACzE,QAAI,CAAC,KAAK,QAAQ,IAAI,KAAK,EAAE,EAAG,MAAK,QAAQ,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AACnE,SAAK,SAAS,IAAI,KAAK,IAAI,EAAG,IAAI,KAAK,EAAE;AACzC,SAAK,QAAQ,IAAI,KAAK,EAAE,EAAG,IAAI,KAAK,EAAE;AAAA,EACxC;AAAA,EAEA,WAAW,QAAsB;AAC/B,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM;AACX,SAAK,SAAS,IAAI,KAAK,IAAI,GAAG,OAAO,MAAM;AAC3C,SAAK,QAAQ,IAAI,KAAK,EAAE,GAAG,OAAO,MAAM;AACxC,SAAK,MAAM,OAAO,MAAM;AAAA,EAC1B;AAAA,EAEA,WAAW,QAAsB;AAC/B,UAAM,aAAa,CAAC,GAAI,KAAK,SAAS,IAAI,MAAM,KAAK,CAAC,CAAE;AACxD,UAAM,YAAY,CAAC,GAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC,CAAE;AACtD,eAAW,OAAO,WAAY,MAAK,WAAW,GAAG;AACjD,eAAW,OAAO,UAAW,MAAK,WAAW,GAAG;AAChD,SAAK,MAAM,OAAO,MAAM;AACxB,SAAK,SAAS,OAAO,MAAM;AAC3B,SAAK,QAAQ,OAAO,MAAM;AAAA,EAC5B;AAAA,EAEA,aAAa,QAA0B;AACrC,UAAM,SAAmB,CAAC;AAC1B,UAAM,YAAY,KAAK,QAAQ,IAAI,MAAM;AACzC,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,YAAI,KAAM,QAAO,KAAK,KAAK,IAAI;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,QAA0B;AACnC,UAAM,SAAmB,CAAC;AAC1B,UAAM,aAAa,KAAK,SAAS,IAAI,MAAM;AAC3C,QAAI,YAAY;AACd,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,YAAI,KAAM,QAAO,KAAK,KAAK,EAAE;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAOO,SAAS,WACd,OACA,OACA,MAAyB,EAAE,eAAe,GAAG,YAAY,KAAK,GACvD;AACP,QAAM,QAAQ,IAAI,MAAM;AAExB,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ;AAAA,MACZ,IAAI,KAAK;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,QAAQ,EAAE,UAAU,IAAI,EAAE;AAAA,MAClE,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU,KAAK;AAAA,MACf,YAAY;AAAA,MACZ,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAiB,KAAK,QAAQ;AACpC,UAAM,gBAAgB,SAAS,YAAY,IAAI,gBAAgB,IAAI;AACnE,UAAM,QAAQ;AAAA,MACZ,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,UAAU;AAAA,MACV,YAAY,KAAK;AAAA,MACjB;AAAA,MACA,QAAQ,KAAK,UAAU;AAAA,IACzB,CAAC;AAAA,EACH;AAMA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,UAAM,MAAM,MAAM,QAAQ,IAAI,MAAM;AACpC,UAAM,OAAO,MAAM,SAAS,IAAI,MAAM;AACtC,QAAI,aAAa;AACjB,QAAI,KAAK;AACP,iBAAW,OAAO,KAAK;AACrB,YAAI,MAAM,MAAM,IAAI,GAAG,GAAG,SAAS,WAAW;AAAE,uBAAa;AAAM;AAAA,QAAO;AAAA,MAC5E;AAAA,IACF;AACA,QAAI,CAAC,cAAc,MAAM;AACvB,iBAAW,OAAO,MAAM;AACtB,YAAI,MAAM,MAAM,IAAI,GAAG,GAAG,SAAS,WAAW;AAAE,uBAAa;AAAM;AAAA,QAAO;AAAA,MAC5E;AAAA,IACF;AACA,UAAM,iBAAiB,KAAK,QAAQ,MAAM,MAAM,QAAQ;AACxD,SAAK,UAAU,CAAC,cAAc,gBAAgB;AAAA,EAChD;AAEA,SAAO;AACT;AAGO,SAAS,kBAAkB,MAAoB,UAAyB;AAC7E,QAAM,SAAS,KAAK,QAAQ,KAAK,OAAK,EAAE,OAAO,QAAQ;AACvD,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,GAAG,KAAK,IAAI,KAAK,QAAQ,GAAG,GAAG,KAAK,IAAI,KAAK,SAAS,EAAE;AAAA,EACnE;AAEA,QAAM,SAAS,OAAO,UAAU;AAEhC,UAAQ,OAAO,UAAU;AAAA,IACvB,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO,GAAG,KAAK,EAAE;AAAA,IACtD,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO,GAAG,KAAK,IAAI,KAAK,OAAO;AAAA,IACpE,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO;AAAA,IACvD,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,KAAK,OAAO,GAAG,KAAK,IAAI,SAAS,KAAK,OAAO;AAAA,EACtE;AACF;AAGO,SAAS,mBAAmB,MAAyB;AAC1D,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAO,aAAO,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACjC,KAAK;AAAU,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACnC,KAAK;AAAQ,aAAO,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IAClC,KAAK;AAAS,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACpC;AACF;;;AC1LO,SAAS,YAAY,OAA2B;AACrD,QAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ;AACnC,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,WAAW,oBAAI,IAAY;AAEjC,aAAW,UAAU,MAAM,MAAM,KAAK,GAAG;AACvC,UAAM,IAAI,QAAQ,KAAK;AAAA,EACzB;AAGA,QAAM,UAAU,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACrD,UAAM,SAAS,MAAM,SAAS,IAAI,CAAC,GAAG,QAAQ,MAAM,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ;AAClF,UAAM,SAAS,MAAM,SAAS,IAAI,CAAC,GAAG,QAAQ,MAAM,MAAM,QAAQ,IAAI,CAAC,GAAG,QAAQ;AAClF,WAAO,QAAQ;AAAA,EACjB,CAAC;AAED,WAAS,IAAI,QAAsB;AACjC,UAAM,IAAI,QAAQ,IAAI;AAEtB,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,YAAY;AACd,iBAAW,UAAU,YAAY;AAC/B,cAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAI,CAAC,KAAM;AAEX,cAAM,cAAc,MAAM,IAAI,KAAK,EAAE;AACrC,YAAI,gBAAgB,MAAM;AACxB,mBAAS,IAAI,MAAM;AAAA,QACrB,WAAW,gBAAgB,OAAO;AAChC,cAAI,KAAK,EAAE;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI,QAAQ,KAAK;AAAA,EACzB;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,MAAM,IAAI,MAAM,MAAM,OAAO;AAC/B,UAAI,MAAM;AAAA,IACZ;AAAA,EACF;AAGA,aAAW,UAAU,UAAU;AAC7B,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,CAAC,KAAM;AAEX,UAAM,WAAW,MAAM;AACvB,UAAM,QAAQ;AAAA,MACZ,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,UAAU,CAAC,KAAK;AAAA,IAClB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACtDO,SAAS,aAAa,OAA0B;AACrD,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,WAAW,oBAAI,IAAY;AAGjC,WAAS,aAAa,QAAwB;AAC5C,QAAI,OAAO,IAAI,MAAM,EAAG,QAAO,OAAO,IAAI,MAAM;AAChD,QAAI,SAAS,IAAI,MAAM,EAAG,QAAO;AAEjC,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,CAAC,QAAQ,KAAK,QAAS,QAAO;AAElC,aAAS,IAAI,MAAM;AAEnB,UAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,QAAI,eAAe;AACnB,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,QAAQ,KAAK,SAAS,UAAW;AACtC,cAAM,OAAO,MAAM,MAAM,IAAI,KAAK,IAAI;AACtC,YAAI,CAAC,QAAQ,KAAK,QAAS;AAC3B,uBAAe,KAAK,IAAI,cAAc,aAAa,KAAK,IAAI,CAAC;AAAA,MAC/D;AAAA,IACF;AAEA,UAAM,QAAQ,eAAe;AAC7B,WAAO,IAAI,QAAQ,KAAK;AACxB,SAAK,QAAQ;AACb,aAAS,OAAO,MAAM;AACtB,WAAO;AAAA,EACT;AAEA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,KAAK,QAAS,cAAa,MAAM;AAAA,EACxC;AAGA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,iBAA2B,CAAC;AAElC,UAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,MAAM,MAAM,MAAM,IAAI,KAAK,IAAI;AACrC,YAAI,OAAO,CAAC,IAAI,WAAW,OAAO,IAAI,KAAK,IAAI,GAAG;AAChD,yBAAe,KAAK,OAAO,IAAI,KAAK,IAAI,CAAE;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,YAAY;AACd,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,MAAM,MAAM,MAAM,IAAI,KAAK,EAAE;AACnC,YAAI,OAAO,CAAC,IAAI,WAAW,OAAO,IAAI,KAAK,EAAE,GAAG;AAC9C,yBAAe,KAAK,OAAO,IAAI,KAAK,EAAE,CAAE;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,eAAe,SAAS,GAAG;AAC7B,qBAAe,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACnC,cAAQ,eAAe,KAAK,MAAM,eAAe,SAAS,CAAC,CAAC;AAAA,IAC9D,OAAO;AACL,cAAQ;AAAA,IACV;AACA,WAAO,IAAI,QAAQ,KAAK;AACxB,SAAK,QAAQ;AAAA,EACf;AAGA,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,OAAO,IAAI,MAAM,GAAG;AACvB,aAAO,IAAI,QAAQ,CAAC;AACpB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAGA,MAAI,WAAW;AACf,MAAI,WAAW;AACf,aAAW,KAAK,OAAO,OAAO,GAAG;AAC/B,QAAI,IAAI,SAAU,YAAW;AAC7B,QAAI,IAAI,SAAU,YAAW;AAAA,EAC/B;AACA,MAAI,CAAC,SAAS,QAAQ,EAAG,QAAO,CAAC;AACjC,MAAI,aAAa,GAAG;AAClB,eAAW,CAAC,IAAI,CAAC,KAAK,QAAQ;AAC5B,YAAM,MAAM,IAAI;AAChB,aAAO,IAAI,IAAI,GAAG;AAClB,YAAM,IAAI,MAAM,MAAM,IAAI,EAAE;AAC5B,UAAI,EAAG,GAAE,QAAQ;AAAA,IACnB;AACA,gBAAY;AAAA,EACd;AAEA,QAAM,cAA0B,MAAM,KAAK,EAAE,QAAQ,WAAW,EAAE,GAAG,MAAM,CAAC,CAAC;AAC7E,aAAW,CAAC,QAAQ,KAAK,KAAK,QAAQ;AACpC,gBAAY,KAAK,EAAE,KAAK,MAAM;AAAA,EAChC;AAEA,SAAO;AACT;AAOO,SAAS,iBAAiB,OAAc,QAAgC;AAC7E,MAAI,eAAe;AACnB,QAAM,iBAAiB,CAAC,GAAG,MAAM,MAAM,OAAO,CAAC;AAE/C,aAAW,QAAQ,gBAAgB;AACjC,QAAI,KAAK,SAAS,UAAW;AAE7B,UAAM,WAAW,MAAM,MAAM,IAAI,KAAK,IAAI;AAC1C,UAAM,SAAS,MAAM,MAAM,IAAI,KAAK,EAAE;AACtC,QAAI,CAAC,YAAY,CAAC,OAAQ;AAE1B,UAAM,YAAY,SAAS;AAC3B,UAAM,UAAU,OAAO;AACvB,UAAM,OAAO,UAAU;AAEvB,QAAI,QAAQ,EAAG;AAEf,UAAM,WAAW,KAAK,EAAE;AAExB,QAAI,aAAa,KAAK;AACtB,QAAI,eAAe,KAAK;AAExB,aAAS,IAAI,YAAY,GAAG,IAAI,SAAS,KAAK;AAC5C,YAAM,UAAU,WAAW,cAAc;AAEzC,YAAM,QAAQ;AAAA,QACZ,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,EAAE,IAAI,MAAM,MAAM,SAAS,UAAU,OAAO,QAAQ,IAAI;AAAA,UACxD,EAAE,IAAI,OAAO,MAAM,UAAU,UAAU,UAAU,QAAQ,IAAI;AAAA,QAC/D;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,QACP,GAAG;AAAA,QACH,GAAG;AAAA,QACH,YAAY;AAAA,QACZ,SAAS;AAAA,MACX,CAAC;AAED,aAAO,CAAC,EAAE,KAAK,OAAO;AAEtB,YAAM,QAAQ;AAAA,QACZ,IAAI,WAAW,YAAY,IAAI,CAAC;AAAA,QAChC,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,MAAM,KAAK;AAAA,QACX,QAAQ,KAAK;AAAA,MACf,CAAC;AAED,mBAAa;AACb,qBAAe;AAAA,IACjB;AAEA,UAAM,QAAQ;AAAA,MACZ,IAAI,WAAW,YAAY;AAAA,MAC3B,MAAM;AAAA,MACN,IAAI,KAAK;AAAA,MACT,YAAY;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,MACjB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACnMO,SAAS,kBACd,OACA,QACA,YACA,qBAA8B,OAClB;AACZ,MAAI,OAAO,UAAU,EAAG,QAAO;AAE/B,QAAM,aAAa,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAG1D,QAAM,gBAAgB,aAAa,MAC/B,KAAK,IAAI,YAAY,CAAC,IACtB,aAAa,MACX,KAAK,IAAI,YAAY,EAAE,IACvB;AAGN,QAAM,gBAAgB,sBAAsB,aAAa;AAGzD,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,aAAS,IAAI,GAAG,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK;AACzC,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;AACzC,UAAI,KAAM,MAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,aAAa,OAAO,IAAI,OAAK,CAAC,GAAG,CAAC,CAAC;AACvC,MAAI,gBAAgB,kBAAkB,OAAO,MAAM;AACnD,MAAI,qBAAqB;AAEzB,WAAS,OAAO,GAAG,OAAO,eAAe,QAAQ;AAE/C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,wBAAkB,OAAO,QAAQ,GAAG,IAAI;AAAA,IAC1C;AAGA,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,wBAAkB,OAAO,QAAQ,GAAG,MAAM;AAAA,IAC5C;AAGA,QAAI,CAAC,eAAe;AAClB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAI,OAAO,CAAC,EAAE,UAAU,KAAK;AAC3B,2BAAiB,OAAO,QAAQ,CAAC;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,kBAAkB,OAAO,MAAM;AACjD,QAAI,YAAY,eAAe;AAC7B,sBAAgB;AAChB,mBAAa,OAAO,IAAI,OAAK,CAAC,GAAG,CAAC,CAAC;AACnC,2BAAqB;AAAA,IACvB,OAAO;AACL;AAAA,IACF;AAEA,QAAI,cAAc,KAAK,sBAAsB,EAAG;AAAA,EAClD;AAGA,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,WAAO,CAAC,IAAI,WAAW,CAAC;AACxB,aAAS,IAAI,GAAG,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK;AACzC,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC;AACzC,UAAI,KAAM,MAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBACP,OACA,QACA,YACA,WACM;AACN,QAAM,QAAQ,OAAO,UAAU;AAC/B,QAAM,gBAAgB,cAAc,OAAO,aAAa,IAAI,aAAa;AAEzE,MAAI,gBAAgB,KAAK,iBAAiB,OAAO,OAAQ;AAMzD,QAAM,IAAI,MAAM;AAChB,QAAM,OAAO,IAAI,aAAa,CAAC;AAE/B,MAAI,cAAc,MAAM;AACtB,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,SAAS,MAAM,CAAC;AACtB,UAAI,MAAM;AACV,UAAI,QAAQ;AACZ,YAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,UAAI,WAAW;AACb,mBAAW,OAAO,WAAW;AAC3B,gBAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,cAAI,CAAC,KAAM;AACX,gBAAM,WAAW,MAAM,MAAM,IAAI,KAAK,IAAI;AAC1C,cAAI,YAAY,SAAS,UAAU,eAAe;AAChD,mBAAO,SAAS;AAChB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,WAAK,CAAC,IAAI,QAAQ,IAAI,MAAM,QAAQ;AAAA,IACtC;AAAA,EACF,OAAO;AACL,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,SAAS,MAAM,CAAC;AACtB,UAAI,MAAM;AACV,UAAI,QAAQ;AACZ,YAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,UAAI,YAAY;AACd,mBAAW,OAAO,YAAY;AAC5B,gBAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,cAAI,CAAC,KAAM;AACX,gBAAM,WAAW,MAAM,MAAM,IAAI,KAAK,EAAE;AACxC,cAAI,YAAY,SAAS,UAAU,eAAe;AAChD,mBAAO,SAAS;AAChB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,WAAK,CAAC,IAAI,QAAQ,IAAI,MAAM,QAAQ;AAAA,IACtC;AAAA,EACF;AAIA,QAAM,UAAU,IAAI,MAAc,CAAC;AACnC,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,SAAQ,CAAC,IAAI;AACzC,UAAQ,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;AAGxC,QAAM,YAAY,IAAI,MAAc,CAAC;AACrC,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,WAAU,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC;AAC3D,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,CAAC,IAAI,UAAU,CAAC;AACtB,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM,CAAC,CAAC;AACrC,QAAI,KAAM,MAAK,QAAQ;AAAA,EACzB;AACF;AAEA,SAAS,iBAAiB,OAAc,QAAoB,YAA0B;AACpF,QAAM,QAAQ,OAAO,UAAU;AAC/B,MAAI,MAAM,UAAU,EAAG;AAEvB,MAAI,WAAW;AACf,MAAI,SAAS;AAEb,SAAO,YAAY,SAAS,GAAG;AAC7B,eAAW;AACX;AACA,aAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,YAAM,QAAQ,MAAM,CAAC;AACrB,YAAM,QAAQ,MAAM,IAAI,CAAC;AAEzB,YAAM,kBAAkB,mBAAmB,OAAO,QAAQ,YAAY,OAAO,KAAK;AAGlF,YAAM,CAAC,IAAI;AACX,YAAM,IAAI,CAAC,IAAI;AACf,YAAM,KAAK,MAAM,MAAM,IAAI,KAAK;AAChC,YAAM,KAAK,MAAM,MAAM,IAAI,KAAK;AAChC,UAAI,GAAI,IAAG,QAAQ,IAAI;AACvB,UAAI,GAAI,IAAG,QAAQ;AAEnB,YAAM,iBAAiB,mBAAmB,OAAO,QAAQ,YAAY,OAAO,KAAK;AAEjF,UAAI,iBAAiB,iBAAiB;AACpC,mBAAW;AAAA,MACb,OAAO;AAEL,cAAM,CAAC,IAAI;AACX,cAAM,IAAI,CAAC,IAAI;AACf,YAAI,GAAI,IAAG,QAAQ;AACnB,YAAI,GAAI,IAAG,QAAQ,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAM,YAAsB,CAAC;AAC7B,IAAM,YAAsB,CAAC;AAO7B,SAAS,mBACP,OACA,QACA,YACA,OACA,OACQ;AACR,MAAI,YAAY;AAGhB,MAAI,aAAa,GAAG;AAClB,UAAM,WAAW,aAAa;AAE9B,cAAU,SAAS;AACnB,cAAU,SAAS;AAEnB,UAAM,MAAM,MAAM,QAAQ,IAAI,KAAK;AACnC,QAAI,KAAK;AACP,iBAAW,OAAO,KAAK;AACrB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,IAAI,MAAM,MAAM,IAAI,KAAK,IAAI;AACnC,YAAI,KAAK,EAAE,UAAU,SAAU,WAAU,KAAK,EAAE,KAAK;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,QAAQ,IAAI,KAAK;AACnC,QAAI,KAAK;AACP,iBAAW,OAAO,KAAK;AACrB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,IAAI,MAAM,MAAM,IAAI,KAAK,IAAI;AACnC,YAAI,KAAK,EAAE,UAAU,SAAU,WAAU,KAAK,EAAE,KAAK;AAAA,MACvD;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,KAAK,UAAU,CAAC;AACtB,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAI,KAAK,UAAU,CAAC,EAAG;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,aAAa,OAAO,SAAS,GAAG;AAClC,UAAM,WAAW,aAAa;AAE9B,cAAU,SAAS;AACnB,cAAU,SAAS;AAEnB,UAAM,OAAO,MAAM,SAAS,IAAI,KAAK;AACrC,QAAI,MAAM;AACR,iBAAW,OAAO,MAAM;AACtB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,IAAI,MAAM,MAAM,IAAI,KAAK,EAAE;AACjC,YAAI,KAAK,EAAE,UAAU,SAAU,WAAU,KAAK,EAAE,KAAK;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,SAAS,IAAI,KAAK;AACrC,QAAI,MAAM;AACR,iBAAW,OAAO,MAAM;AACtB,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,IAAI,MAAM,MAAM,IAAI,KAAK,EAAE;AACjC,YAAI,KAAK,EAAE,UAAU,SAAU,WAAU,KAAK,EAAE,KAAK;AAAA,MACvD;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,KAAK,UAAU,CAAC;AACtB,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAI,KAAK,UAAU,CAAC,EAAG;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,kBAAkB,OAAc,QAA4B;AAC1E,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC1C,aAAS,oBAAoB,OAAO,OAAO,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAAA,EAC9D;AACA,SAAO;AACT;AAMA,SAAS,oBACP,OACA,YACA,YACQ;AACR,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,QAAQ,CAAC,IAAI,QAAQ,SAAS,IAAI,IAAI,GAAG,CAAC;AAGrD,QAAM,YAAgC,CAAC;AACvC,WAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ;AACnD,UAAM,SAAS,WAAW,IAAI;AAC9B,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,CAAC,WAAY;AACjB,eAAW,OAAO,YAAY;AAC5B,YAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,UAAI,CAAC,KAAM;AACX,YAAM,KAAK,SAAS,IAAI,KAAK,EAAE;AAC/B,UAAI,OAAO,QAAW;AACpB,kBAAU,KAAK,CAAC,MAAM,EAAE,CAAC;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,UAAU,EAAG,QAAO;AAGlC,YAAU,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAGnD,QAAM,iBAAiB,UAAU,IAAI,OAAK,EAAE,CAAC,CAAC;AAC9C,SAAO,eAAe,cAAc;AACtC;AAOA,SAAS,eAAe,KAAuB;AAC7C,QAAM,IAAI,IAAI;AACd,MAAI,KAAK,EAAG,QAAO;AAEnB,MAAI,MAAM,IAAI,MAAc,CAAC;AAC7B,MAAI,MAAM;AACV,MAAI,MAAM;AACV,MAAI,QAAQ;AAEZ,WAAS,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG;AAC1C,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK,SAAS,GAAG;AACtC,YAAM,OAAO;AACb,YAAM,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC;AACjC,YAAM,QAAQ,KAAK,IAAI,KAAK,SAAS,IAAI,CAAC;AAC1C,UAAI,IAAI,MAAM,IAAI,KAAK,IAAI;AAC3B,aAAO,IAAI,OAAO,IAAI,OAAO;AAC3B,YAAI,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG;AACpB,cAAI,GAAG,IAAI,IAAI,GAAG;AAAA,QACpB,OAAO;AACL,mBAAS,MAAM;AACf,cAAI,GAAG,IAAI,IAAI,GAAG;AAAA,QACpB;AAAA,MACF;AACA,aAAO,IAAI,IAAK,KAAI,GAAG,IAAI,IAAI,GAAG;AAClC,aAAO,IAAI,MAAO,KAAI,GAAG,IAAI,IAAI,GAAG;AAAA,IACtC;AACA,UAAM,MAAM;AACZ,UAAM;AACN,UAAM;AAAA,EACR;AAIA,MAAI,QAAQ,KAAK;AACf,aAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,CAAC,IAAI,IAAI,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;;;ACnXO,SAAS,kBACd,OACA,QACA,SACM;AACN,QAAM,eAAe,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AACzE,QAAM,aAAa,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAEvE,sBAAoB,OAAO,QAAQ,SAAS,cAAc,UAAU;AACpE,uBAAqB,OAAO,QAAQ,SAAS,YAAY;AACzD,oBAAkB,OAAO,QAAQ,SAAS,YAAY;AACxD;AAKA,SAAS,oBACP,OACA,QACA,SACA,cACA,YACM;AAEN,QAAM,aAAuB,CAAC;AAC9B,aAAW,SAAS,QAAQ;AAC1B,QAAI,UAAU;AACd,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,OAAO,eAAe,KAAK,QAAQ,KAAK;AAC9C,gBAAU,KAAK,IAAI,SAAS,IAAI;AAAA,IAClC;AACA,eAAW,KAAK,OAAO;AAAA,EACzB;AAGA,QAAM,iBAA2B,CAAC;AAClC,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,mBAAe,KAAK,GAAG;AACvB,WAAO,WAAW,CAAC,IAAI,QAAQ;AAAA,EACjC;AAGA,MAAI,YAAY;AACd,UAAM,YAAY,MAAM,QAAQ;AAChC,aAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,qBAAe,CAAC,IAAI,YAAY,eAAe,CAAC,IAAI,WAAW,CAAC;AAAA,IAClE;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,eAAW,UAAU,OAAO,CAAC,GAAG;AAC9B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,WAAW,eAAe,KAAK,QAAQ,KAAK;AAClD,YAAM,UAAU,WAAW,CAAC,IAAI,YAAY;AAE5C,UAAI,cAAc;AAChB,aAAK,IAAI,eAAe,CAAC,IAAI;AAAA,MAC/B,OAAO;AACL,aAAK,IAAI,eAAe,CAAC,IAAI;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,qBACP,OACA,QACA,SACA,cACM;AACN,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM;AAEV,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,OAAO,eAAe,KAAK,SAAS,KAAK;AAE/C,UAAI,cAAc;AAChB,aAAK,IAAI;AAAA,MACX,OAAO;AACL,aAAK,IAAI;AAAA,MACX;AAEA,aAAO,OAAO,QAAQ;AAAA,IACxB;AAGA,UAAM,YAAY,MAAM,QAAQ;AAChC,UAAM,eAAe,CAAC,YAAY;AAElC,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,UAAI,cAAc;AAChB,aAAK,KAAK;AAAA,MACZ,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,kBACP,OACA,QACA,SACA,cACM;AACN,WAAS,OAAO,GAAG,OAAO,QAAQ,kCAAkC,QAAQ;AAE1E,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,oBAAc,OAAO,OAAO,CAAC,GAAG,SAAS,YAAY;AAAA,IACvD;AAGA,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,oBAAc,OAAO,OAAO,CAAC,GAAG,SAAS,YAAY;AAAA,IACvD;AAAA,EACF;AAEA,kBAAgB,OAAO,QAAQ,YAAY;AAC7C;AAIA,IAAI,eAA6B,IAAI,aAAa,EAAE;AACpD,IAAI,cAA4B,IAAI,aAAa,EAAE;AAEnD,SAAS,cAAc,MAAoB;AACzC,MAAI,aAAa,SAAS,KAAM,gBAAe,IAAI,aAAa,OAAO,CAAC;AACxE,MAAI,YAAY,SAAS,KAAM,eAAc,IAAI,aAAa,OAAO,CAAC;AACxE;AAEA,SAAS,cACP,OACA,OACA,SACA,cACM;AACN,QAAM,IAAI,MAAM;AAChB,MAAI,MAAM,EAAG;AAGb,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,KAAK,MAAM,CAAC;AAClB,UAAM,KAAK,MAAM,QAAQ,IAAI,EAAE,GAAG,QAAQ,MAAM,MAAM,SAAS,IAAI,EAAE,GAAG,QAAQ;AAChF,QAAI,IAAI,UAAW,aAAY;AAAA,EACjC;AACA,gBAAc,KAAK,IAAI,GAAG,SAAS,CAAC;AACpC,QAAM,UAAU;AAGhB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,UAAU;AAEd,UAAM,YAAY,MAAM,QAAQ,IAAI,MAAM;AAC1C,QAAI,WAAW;AACb,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,IAAI,MAAM,MAAM,IAAI,KAAK,IAAI;AACnC,YAAI,CAAC,EAAG;AACR,qBAAa,SAAS,IAAI,YAAY,GAAG,YAAY,IAAI,aAAa,GAAG,YAAY,IAAI;AAAA,MAC3F;AAAA,IACF;AACA,UAAM,aAAa,MAAM,SAAS,IAAI,MAAM;AAC5C,QAAI,YAAY;AACd,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,KAAM;AACX,cAAM,IAAI,MAAM,MAAM,IAAI,KAAK,EAAE;AACjC,YAAI,CAAC,EAAG;AACR,qBAAa,SAAS,IAAI,YAAY,GAAG,YAAY,IAAI,aAAa,GAAG,YAAY,IAAI;AAAA,MAC3F;AAAA,IACF;AAEA,QAAI,YAAY,GAAG;AACjB,cAAQ,CAAC,IAAI,YAAY,MAAM,YAAY;AAC3C;AAAA,IACF;AAGA,eAAW,cAAc,OAAO;AAEhC,UAAM,WAAW,aAAa,MAAM,YAAY;AAChD,UAAM,UAAU,UAAU,OAAO,KAC5B,cAAc,WAAW,KAAK,CAAC,IAAI,aAAa,WAAW,CAAC,KAAK,IAClE,aAAa,WAAW,CAAC;AAE7B,YAAQ,CAAC,IAAI,SAAS,WAAW;AAAA,EACnC;AAGA,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,QAAI,aAAa,QAAQ,CAAC;AAE1B,QAAI,IAAI,GAAG;AACT,YAAM,SAAS,MAAM,IAAI,CAAC;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,UAAU,YAAY,MAAM,YAAY,IAAI,aAAa,MAAM,YAAY;AACjF,UAAI,aAAa,UAAU,QAAQ,YAAa,cAAa,UAAU,QAAQ;AAAA,IACjF;AAEA,gBAAY,MAAM,cAAc,UAAU;AAAA,EAC5C;AAGA,WAAS,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;AAC/B,UAAM,SAAS,MAAM,CAAC;AACtB,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,UAAM,SAAS,MAAM,IAAI,CAAC;AAC1B,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AAEnC,UAAM,UAAU,YAAY,MAAM,YAAY,IAAI,aAAa,MAAM,YAAY;AACjF,UAAM,YAAY,YAAY,MAAM,YAAY;AAEhD,QAAI,UAAU,QAAQ,cAAc,WAAW;AAC7C,kBAAY,MAAM,cAAc,YAAY,QAAQ,cAAc,aAAa,MAAM,YAAY,CAAC;AAAA,IACpG;AAAA,EACF;AACF;AAIA,SAAS,WAAW,KAAmB,OAAqB;AAC1D,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,IAAI,IAAI,CAAC;AACf,QAAI,IAAI,IAAI;AACZ,WAAO,KAAK,KAAK,IAAI,CAAC,IAAI,GAAG;AAC3B,UAAI,IAAI,CAAC,IAAI,IAAI,CAAC;AAClB;AAAA,IACF;AACA,QAAI,IAAI,CAAC,IAAI;AAAA,EACf;AACF;AAEA,SAAS,gBACP,OACA,QACA,cACM;AACN,MAAI,OAAO,WAAW,EAAG;AAGzB,MAAI,YAAY;AAChB,MAAI,YAAY;AAEhB,aAAW,SAAS,QAAQ;AAC1B,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,MAAM,YAAY,MAAM,YAAY;AAC1C,YAAM,OAAO,aAAa,MAAM,YAAY;AAC5C,kBAAY,KAAK,IAAI,WAAW,GAAG;AACnC,kBAAY,KAAK,IAAI,WAAW,MAAM,IAAI;AAAA,IAC5C;AAAA,EACF;AAGA,QAAM,SAAS,CAAC;AAChB,aAAW,SAAS,QAAQ;AAC1B,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,kBAAY,MAAM,cAAc,YAAY,MAAM,YAAY,IAAI,MAAM;AAAA,IAC1E;AAAA,EACF;AAGA,MAAI,UAAU;AACd,aAAW,SAAS,QAAQ;AAC1B,eAAW,UAAU,OAAO;AAC1B,YAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAM,MAAM,eAAe,KAAK,IAAI,KAAK;AACzC,gBAAU,KAAK,IAAI,SAAS,GAAG;AAAA,IACjC;AAAA,EACF;AAEA,MAAI,YAAY,GAAG;AACjB,eAAW,SAAS,QAAQ;AAC1B,iBAAW,UAAU,OAAO;AAC1B,cAAM,OAAO,MAAM,MAAM,IAAI,MAAM;AACnC,YAAI,cAAc;AAChB,eAAK,KAAK;AAAA,QACZ,OAAO;AACL,eAAK,KAAK;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,YAAY,MAAgC,cAA+B;AAClF,SAAO,eAAe,KAAK,IAAI,KAAK;AACtC;AAEA,SAAS,YAAY,MAAgC,cAAuB,OAAqB;AAC/F,MAAI,cAAc;AAChB,SAAK,IAAI;AAAA,EACX,OAAO;AACL,SAAK,IAAI;AAAA,EACX;AACF;AAEA,SAAS,aAAa,MAAyC,cAA+B;AAC5F,SAAO,eAAe,KAAK,SAAS,KAAK;AAC3C;;;AClTO,SAAS,mBACd,OACA,QACA,SACM;AACN,QAAM,eAAe,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAOzE,QAAM,cAA4B,CAAC;AACnC,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,CAAC,KAAK,WAAW,KAAK,QAAS;AAEnC,UAAM,WAAW,qBAAqB,OAAO,MAAM;AACnD,QAAI,UAAU;AACZ,kBAAY,KAAK,EAAE,SAAS,QAAQ,YAAY,SAAS,CAAC;AAAA,IAC5D,OAAO;AACL,mBAAa,KAAK,MAAM;AAAA,IAC1B;AAAA,EACF;AAGA,QAAM,aAAa,oBAAI,IAAsB;AAC7C,aAAW,EAAE,SAAS,WAAW,KAAK,aAAa;AACjD,UAAM,MAAM,WAAW,IAAI,UAAU,KAAK,CAAC;AAC3C,QAAI,KAAK,OAAO;AAChB,eAAW,IAAI,YAAY,GAAG;AAAA,EAChC;AAGA,aAAW,CAAC,YAAY,IAAI,KAAK,YAAY;AAC3C,UAAM,WAAW,MAAM,MAAM,IAAI,UAAU;AAC3C,QAAI,CAAC,SAAU;AAEf,UAAM,EAAE,YAAY,UAAU,IAAI,kBAAkB,OAAO,YAAY,MAAM,YAAY;AAEzF,QAAI,cAAc;AAEhB,YAAM,WAAW,SAAS,IAAI,SAAS,QAAQ;AAC/C,UAAI,UAAU,SAAS;AACvB,iBAAW,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,UAAU,QAAQ,cAAc,EAAE;AACxC,UAAE,IAAI,WAAW,EAAE,QAAQ;AAC3B,kBAAU,EAAE;AAAA,MACd;AACA,UAAI,aAAa,SAAS,IAAI,SAAS;AACvC,iBAAW,OAAO,WAAW;AAC3B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,aAAa,QAAQ;AAC3B,UAAE,IAAI,WAAW,EAAE,QAAQ;AAC3B,qBAAa,EAAE,IAAI,EAAE;AAAA,MACvB;AAAA,IACF,OAAO;AAEL,YAAM,WAAW,SAAS,IAAI,SAAS,SAAS;AAChD,UAAI,WAAW,SAAS;AACxB,iBAAW,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,WAAW,QAAQ,cAAc,EAAE;AACzC,UAAE,IAAI,WAAW,EAAE,SAAS;AAC5B,mBAAW,EAAE;AAAA,MACf;AACA,UAAI,YAAY,SAAS,IAAI,SAAS;AACtC,iBAAW,OAAO,WAAW;AAC3B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,CAAC,EAAG;AACR,UAAE,IAAI,YAAY,QAAQ;AAC1B,UAAE,IAAI,WAAW,EAAE,SAAS;AAC5B,oBAAY,EAAE,IAAI,EAAE;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAIA,MAAI,UAAU,GAAG,UAAU;AAC3B,aAAW,YAAY,cAAc;AACnC,UAAM,IAAI,MAAM,MAAM,IAAI,QAAQ;AAClC,QAAI,CAAC,EAAG;AACR,MAAE,IAAI;AACN,MAAE,IAAI;AACN,QAAI,aAAc,YAAW,EAAE,QAAQ,QAAQ;AAAA,QAC1C,YAAW,EAAE,SAAS,QAAQ;AAAA,EACrC;AACF;AAMA,SAAS,qBAAqB,OAAc,SAAgC;AAC1E,QAAM,SAAS,oBAAI,IAAoB;AAEvC,QAAM,OAAO,MAAM,SAAS,IAAI,OAAO;AACvC,MAAI,MAAM;AACR,eAAW,OAAO,MAAM;AACtB,YAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,UAAI,CAAC,KAAM;AACX,YAAM,QAAQ,MAAM,MAAM,IAAI,KAAK,EAAE;AACrC,UAAI,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,SAAS;AAC7C,eAAO,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACA,QAAM,MAAM,MAAM,QAAQ,IAAI,OAAO;AACrC,MAAI,KAAK;AACP,eAAW,OAAO,KAAK;AACrB,YAAM,OAAO,MAAM,MAAM,IAAI,GAAG;AAChC,UAAI,CAAC,KAAM;AACX,YAAM,QAAQ,MAAM,MAAM,IAAI,KAAK,IAAI;AACvC,UAAI,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,SAAS;AAC7C,eAAO,IAAI,KAAK,OAAO,OAAO,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAwB;AAC5B,MAAI,YAAY;AAChB,aAAW,CAAC,IAAI,KAAK,KAAK,QAAQ;AAChC,QAAI,QAAQ,aAAc,UAAU,aAAa,WAAW,QAAQ,KAAK,QAAS;AAChF,eAAS;AACT,kBAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;AAYA,SAAS,kBACP,OACA,YACA,UACA,cAC+C;AAC/C,QAAM,WAAW,MAAM,MAAM,IAAI,UAAU;AAC3C,MAAI,CAAC,SAAU,QAAO,EAAE,YAAY,CAAC,GAAG,QAAQ,EAAE,KAAK,GAAG,WAAW,CAAC,EAAE;AAGxE,QAAM,QAAgB,CAAC;AAEvB,aAAW,OAAO,UAAU;AAC1B,QAAI,OAAqB;AACzB,QAAI,SAAS;AAEb,UAAM,gBAAgB,CAAC,aAAiC;AACtD,UAAI,CAAC,SAAU;AACf,YAAM,SAAS,SAAS,QAAQ,KAAK,OAAK,EAAE,OAAO,QAAQ;AAC3D,UAAI,CAAC,OAAQ;AACb,eAAS,OAAO,UAAU;AAC1B,UAAI,cAAc;AAChB,YAAI,OAAO,aAAa,MAAO,QAAO;AAAA,iBAC7B,OAAO,aAAa,SAAU,QAAO;AAAA,MAChD,OAAO;AACL,YAAI,OAAO,aAAa,OAAQ,QAAO;AAAA,iBAC9B,OAAO,aAAa,QAAS,QAAO;AAAA,MAC/C;AAAA,IACF;AAGA,UAAM,OAAO,MAAM,SAAS,IAAI,GAAG;AACnC,QAAI,KAAM,YAAW,OAAO,MAAM;AAChC,YAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,UAAI,KAAK,EAAE,OAAO,YAAY;AAAE,sBAAc,EAAE,QAAQ;AAAG;AAAA,MAAO;AAAA,IACpE;AACA,QAAI,SAAS,WAAW;AACtB,YAAM,MAAM,MAAM,QAAQ,IAAI,GAAG;AACjC,UAAI,IAAK,YAAW,OAAO,KAAK;AAC9B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,KAAK,EAAE,SAAS,YAAY;AAAE,wBAAc,EAAE,UAAU;AAAG;AAAA,QAAO;AAAA,MACxE;AAAA,IACF;AAEA,UAAM,KAAK,EAAE,IAAI,KAAK,MAAM,OAAO,CAAC;AAAA,EACtC;AAEA,QAAM,SAAS,MAAM,OAAO,OAAK,EAAE,SAAS,QAAQ;AACpD,QAAM,QAAQ,MAAM,OAAO,OAAK,EAAE,SAAS,OAAO;AAClD,QAAM,UAAU,MAAM,OAAO,OAAK,EAAE,SAAS,SAAS;AAGtD,aAAW,KAAK,SAAS;AACvB,QAAI,OAAO,UAAU,MAAM,OAAQ,QAAO,KAAK,CAAC;AAAA,QAC3C,OAAM,KAAK,CAAC;AAAA,EACnB;AAIA,QAAM,MAAM,CAAC,GAAS,MAAa,EAAE,SAAS,EAAE,WAAY,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI;AACjG,SAAO,KAAK,GAAG;AACf,QAAM,KAAK,GAAG;AAEd,SAAO;AAAA,IACL,YAAY,OAAO,IAAI,OAAK,EAAE,EAAE;AAAA,IAChC,WAAW,MAAM,IAAI,OAAK,EAAE,EAAE;AAAA,EAChC;AACF;AAWO,SAAS,WAAW,QAAoB,OAA0B;AACvE,SAAO,OAAO;AAAA,IAAI,WAChB,MAAM,OAAO,QAAM;AACjB,YAAM,IAAI,MAAM,MAAM,IAAI,EAAE;AAC5B,aAAO,KAAK,CAAC,EAAE;AAAA,IACjB,CAAC;AAAA,EACH;AACF;;;ACxOO,SAAS,WACd,OACA,WACA,YACc;AACd,QAAM,SAAS,kBAAkB,KAAK;AACtC,QAAM,SAAuB,CAAC;AAE9B,aAAW,SAAS,QAAQ;AAC1B,WAAO,KAAK,WAAW,OAAO,OAAO,WAAW,UAAU,CAAC;AAAA,EAC7D;AAEA,SAAO;AACT;AAaA,SAAS,kBAAkB,OAA2B;AACpD,QAAM,SAAsB,CAAC;AAC7B,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,CAAC,QAAQ,IAAI,KAAK,MAAM,OAAO;AACxC,QAAI,QAAQ,IAAI,MAAM,EAAG;AAEzB,UAAM,WAAW,MAAM,MAAM,IAAI,KAAK,IAAI;AAC1C,QAAI,CAAC,YAAY,SAAS,QAAS;AAEnC,UAAM,aAAuB,CAAC;AAC9B,QAAI,cAAc;AAClB,YAAQ,IAAI,MAAM;AAElB,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,MAAM,IAAI,YAAY,EAAE;AAC7C,UAAI,CAAC,UAAU,CAAC,OAAO,QAAS;AAEhC,iBAAW,KAAK,YAAY,EAAE;AAE9B,YAAM,aAAa,MAAM,SAAS,IAAI,YAAY,EAAE;AACpD,UAAI,CAAC,cAAc,WAAW,SAAS,EAAG;AAE1C,UAAI,WAAW;AACf,iBAAW,OAAO,YAAY;AAC5B,cAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AAC7B,YAAI,KAAK,EAAE,eAAe,KAAK,YAAY;AACzC,qBAAW;AACX,kBAAQ,IAAI,GAAG;AACf;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,UAAU;AACb,cAAM,MAAM,WAAW,OAAO,EAAE,KAAK,EAAE;AACvC,YAAI,CAAC,IAAK;AACV,mBAAW,MAAM,MAAM,IAAI,GAAG;AAC9B,YAAI,CAAC,SAAU;AACf,gBAAQ,IAAI,GAAG;AAAA,MACjB;AAEA,oBAAc;AAAA,IAChB;AAEA,WAAO,KAAK;AAAA,MACV,YAAY,KAAK;AAAA,MACjB,MAAM,KAAK;AAAA,MACX,IAAI,YAAY;AAAA,MAChB,YAAY,KAAK;AAAA,MACjB,UAAU,YAAY;AAAA,MACtB;AAAA,MACA,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,WACP,OACA,OACA,WACA,QACY;AACZ,QAAM,WAAW,MAAM,MAAM,IAAI,MAAM,IAAI;AAC3C,QAAM,SAAS,MAAM,MAAM,IAAI,MAAM,EAAE;AAEvC,QAAM,aAAa,MAAM,WAAW,MAAM,KAAK,MAAM;AACrD,QAAM,WAAW,MAAM,WAAW,MAAM,OAAO,MAAM;AACrD,QAAM,mBAAmB,MAAM,WAAW,MAAM,WAAW,MAAM;AACjE,QAAM,iBAAiB,MAAM,WAAW,MAAM,aAAa,MAAM;AAEjE,QAAM,aAAa,MAAM,WAAW,SAAS;AAC7C,QAAM,aAAa,MAAM,WAAW,WAAW;AAE/C,QAAM,YAAY,kBAAkB,YAAY,gBAAgB;AAChE,QAAM,YAAY,kBAAkB,YAAY,cAAc;AAE9D,QAAM,eAAe,WAAW,QAAQ,KAAK,OAAK,EAAE,OAAO,gBAAgB;AAC3E,QAAM,eAAe,WAAW,QAAQ,KAAK,OAAK,EAAE,OAAO,cAAc;AAEzE,QAAM,aAAa,cAAc,YAAY,qBAAqB,SAAS;AAC3E,QAAM,aAAa,cAAc,YAAY,qBAAqB,SAAS;AAE3E,QAAM,YAAqB,CAAC;AAE5B,YAAU,KAAK,SAAS;AAExB,QAAM,UAAU,mBAAmB,UAAU;AAC7C,YAAU,KAAK;AAAA,IACb,GAAG,UAAU,IAAI,QAAQ,IAAI;AAAA,IAC7B,GAAG,UAAU,IAAI,QAAQ,IAAI;AAAA,EAC/B,CAAC;AAED,QAAM,UAAU,MAAM,WAAW,CAAC,GAAG,MAAM,UAAU,EAAE,QAAQ,IAAI,MAAM;AACzE,aAAW,WAAW,SAAS;AAC7B,UAAM,QAAQ,MAAM,MAAM,IAAI,OAAO;AACrC,cAAU,KAAK,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAAA,EAC3C;AAEA,QAAM,WAAW,mBAAmB,UAAU;AAC9C,YAAU,KAAK;AAAA,IACb,GAAG,UAAU,IAAI,SAAS,IAAI;AAAA,IAC9B,GAAG,UAAU,IAAI,SAAS,IAAI;AAAA,EAChC,CAAC;AAED,YAAU,KAAK,SAAS;AAExB,QAAM,SAAS,eAAe,WAAW,SAAS;AAElD,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,YAAY;AAAA,IACZ,UAAU;AAAA,IACV;AAAA,IACA,MAAM,MAAM;AAAA,EACd;AACF;AAEA,SAAS,eAAe,QAAiB,WAAqC;AAC5E,MAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,QAAM,SAAkB,CAAC,OAAO,CAAC,CAAC;AAClC,QAAM,iBAAiB,cAAc,QAAQ,cAAc;AAE3D,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,UAAM,OAAO,OAAO,CAAC;AAErB,UAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AACnC,UAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAEnC,QAAI,KAAK,QAAQ,KAAK,MAAM;AAC1B,aAAO,KAAK,IAAI;AAChB;AAAA,IACF;AAEA,QAAI,gBAAgB;AAClB,YAAM,QAAQ,KAAK,IAAI,KAAK,KAAK;AACjC,aAAO,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,CAAC;AAClC,aAAO,KAAK,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,CAAC;AAAA,IACpC,OAAO;AACL,YAAM,QAAQ,KAAK,IAAI,KAAK,KAAK;AACjC,aAAO,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;AAClC,aAAO,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;AAAA,IACpC;AAEA,WAAO,KAAK,IAAI;AAAA,EAClB;AAEA,SAAO,cAAc,MAAM;AAC7B;AAEA,SAAS,cAAc,QAA0B;AAC/C,MAAI,OAAO,UAAU,EAAG,QAAO;AAE/B,QAAM,SAAkB,CAAC,OAAO,CAAC,CAAC;AAElC,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC1C,UAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,UAAM,OAAO,OAAO,CAAC;AACrB,UAAM,OAAO,OAAO,IAAI,CAAC;AAEzB,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI;AAC9E,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI;AAE9E,QAAI,CAAC,SAAS,CAAC,OAAO;AACpB,aAAO,KAAK,IAAI;AAAA,IAClB,WAAW,SAAS,OAAO;AACzB;AAAA,IACF,OAAO;AACL,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,KAAK,OAAO,OAAO,SAAS,CAAC,CAAC;AACrC,SAAO;AACT;AAEA,SAAS,qBAAqB,WAAwC;AACpE,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;AAEA,SAAS,qBAAqB,WAAwC;AACpE,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;;;ACzOO,SAAS,eACd,OACA,OACA,SACM;AACN,MAAI,MAAM,WAAW,EAAG;AAGxB,QAAM,WAAW,oBAAI,IAAwB;AAC7C,aAAW,KAAK,MAAO,UAAS,IAAI,EAAE,IAAI,CAAC;AAC3C,QAAM,SAAS,oBAAI,IAAoB;AACvC,WAAS,YAAY,IAAoB;AACvC,QAAI,OAAO,IAAI,EAAE,EAAG,QAAO,OAAO,IAAI,EAAE;AACxC,UAAM,IAAI,SAAS,IAAI,EAAE;AACzB,QAAI,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,SAAS,IAAI,EAAE,QAAQ,GAAG;AAClD,aAAO,IAAI,IAAI,EAAE;AACjB,aAAO;AAAA,IACT;AACA,UAAM,IAAI,YAAY,EAAE,QAAQ;AAChC,WAAO,IAAI,IAAI,CAAC;AAChB,WAAO;AAAA,EACT;AACA,aAAW,KAAK,MAAO,aAAY,EAAE,EAAE;AAIvC,QAAM,SAAS,oBAAI,IAAoB;AACvC,WAAS,KAAK,GAAmB;AAC/B,QAAI,MAAM;AACV,WAAO,OAAO,IAAI,GAAG,MAAM,KAAK;AAC9B,YAAM,IAAI,OAAO,IAAI,GAAG;AACxB,aAAO,IAAI,KAAK,OAAO,IAAI,CAAC,CAAE;AAC9B,YAAM,OAAO,IAAI,GAAG;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AACA,WAAS,MAAM,GAAW,GAAiB;AACzC,UAAM,KAAK,KAAK,CAAC;AACjB,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,OAAO,GAAI,QAAO,IAAI,IAAI,EAAE;AAAA,EAClC;AACA,aAAW,KAAK,MAAO,QAAO,IAAI,YAAY,EAAE,EAAE,GAAG,YAAY,EAAE,EAAE,CAAC;AACtE,aAAW,KAAK,OAAO;AACrB,UAAM,KAAK,YAAY,EAAE,IAAI;AAC7B,UAAM,KAAK,YAAY,EAAE,EAAE;AAC3B,QAAI,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,EAAG,OAAM,IAAI,EAAE;AAAA,EACxD;AAGA,QAAM,SAAS,oBAAI,IAA0B;AAC7C,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,YAAY,EAAE,EAAE;AAC7B,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC;AACjC,QAAI,KAAK,CAAC;AACV,WAAO,IAAI,MAAM,GAAG;AAAA,EACtB;AAEA,MAAI,OAAO,QAAQ,EAAG;AAEtB,QAAM,eAAe,QAAQ,cAAc,QAAQ,QAAQ,cAAc;AAGzE,QAAM,cAAc,oBAAI,IAA0B;AAClD,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,YAAY,EAAE,IAAI;AAC/B,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,MAAM,YAAY,IAAI,IAAI,KAAK,CAAC;AACtC,QAAI,KAAK,CAAC;AACV,gBAAY,IAAI,MAAM,GAAG;AAAA,EAC3B;AAYA,QAAM,QAAmB,CAAC;AAC1B,aAAW,CAAC,QAAQ,KAAK,KAAK,QAAQ;AACpC,QAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,eAAW,KAAK,OAAO;AACrB,UAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,UAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,UAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,UAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,IAC5C;AACA,UAAM,YAAY,YAAY,IAAI,MAAM,KAAK,CAAC;AAC9C,eAAW,KAAK,WAAW;AACzB,iBAAW,KAAK,EAAE,QAAQ;AACxB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,YAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AAAA,MAC3B;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,QAAQ,OAAO,OAAO,OAAO,WAAW,MAAM,MAAM,MAAM,KAAK,CAAC;AAAA,EACnF;AAGA,QAAM,KAAK,CAAC,GAAG,MAAM;AACnB,UAAM,QAAQ,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;AAC1D,UAAM,QAAQ,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;AAC1D,WAAO,QAAQ;AAAA,EACjB,CAAC;AAED,QAAM,MAAM,QAAQ;AACpB,MAAI,SAAS;AACb,aAAW,OAAO,OAAO;AACvB,QAAI,cAAc;AAEhB,YAAM,KAAK,SAAS,IAAI;AACxB,YAAM,KAAK,CAAC,IAAI;AAChB,iBAAW,KAAK,IAAI,OAAO;AACzB,UAAE,KAAK;AACP,UAAE,KAAK;AACP,mBAAW,KAAK,EAAE,SAAS;AACzB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,iBAAW,KAAK,IAAI,OAAO;AACzB,mBAAW,KAAK,EAAE,QAAQ;AACxB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,gBAAW,IAAI,OAAO,IAAI,OAAQ;AAAA,IACpC,OAAO;AAEL,YAAM,KAAK,SAAS,IAAI;AACxB,YAAM,KAAK,CAAC,IAAI;AAChB,iBAAW,KAAK,IAAI,OAAO;AACzB,UAAE,KAAK;AACP,UAAE,KAAK;AACP,mBAAW,KAAK,EAAE,SAAS;AACzB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,iBAAW,KAAK,IAAI,OAAO;AACzB,mBAAW,KAAK,EAAE,QAAQ;AACxB,YAAE,KAAK;AACP,YAAE,KAAK;AAAA,QACT;AAAA,MACF;AACA,gBAAW,IAAI,OAAO,IAAI,OAAQ;AAAA,IACpC;AAAA,EACF;AACF;;;ACjIO,SAAS,uBAAuB,OAAoB,SAAuC;AAChG,MAAI,CAAC,QAAQ,WAAY,QAAO;AAEhC,QAAM,YAAY,IAAI,IAAuB,MAAM,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAE5E,QAAM,WAAW,MAAM,MAAM,IAAI,UAAQ;AACvC,UAAM,OAAO,aAAa,MAAM,MAAM,KAAK;AAC3C,UAAM,WAAW,iBAAiB,MAAM,MAAM,MAAM,OAAO,WAAW,QAAQ,SAAS;AAEvF,UAAM,WAAW,gBAAgB,MAAM,UAAU,QAAQ,WAAW,IAAI;AACxE,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,WAAW,QAAQ,WAAY,QAAQ;AAC7C,WAAO,YAAY;AAAA,EACrB,CAAC;AAED,SAAO,EAAE,OAAO,UAAU,OAAO,MAAM,MAAM;AAC/C;AAOA,SAAS,aAAa,MAAiB,OAA8B;AACnE,QAAM,WAAW,MAAM,OAAO,OAAK,EAAE,SAAS,KAAK,MAAM,EAAE,OAAO,KAAK,EAAE;AACzE,MAAI,SAAS,WAAW,EAAG,QAAO,EAAE,MAAM,WAAW;AAErD,QAAM,UAAU,SAAS,MAAM,QAAM,EAAE,QAAQ,eAAe,MAAM;AACpE,MAAI,CAAC,QAAS,QAAO,EAAE,MAAM,OAAO;AAMpC,aAAW,KAAK,UAAU;AACxB,UAAM,aAAa,EAAE,SAAS,KAAK,KAAK,EAAE,KAAK,EAAE;AACjD,UAAM,mBAAmB,EAAE,SAAS,KAAK,KAAK,EAAE,WAAW,EAAE;AAC7D,UAAM,WAAW;AAAA,MAAmB;AAAA,MAAY;AAAA,MAAkB;AAAA;AAAA,MAAuB;AAAA,IAAK;AAC9F,QAAI,SAAU,QAAO,EAAE,MAAM,SAAS,cAAc,SAAS;AAAA,EAC/D;AACA,SAAO,EAAE,MAAM,SAAS,cAAc,KAAK;AAC7C;AAEA,SAAS,mBACP,aACA,WACA,QACA,YACmB;AAInB,SAAO;AACT;AAEA,SAAS,iBACP,MACA,MACA,OACA,OACA,WAC2C;AAC3C,MAAI,KAAK,SAAS,cAAc,KAAK,SAAS,QAAQ;AACpD,WAAO,EAAE,OAAO,aAAa,SAAS,GAAG,QAAQ,cAAc,SAAS,EAAE;AAAA,EAC5E;AAGA,QAAM,qBAAqB,uBAAuB,MAAM,OAAO,KAAK;AACpE,MAAI,CAAC,oBAAoB;AACvB,WAAO,EAAE,OAAO,aAAa,SAAS,GAAG,QAAQ,cAAc,SAAS,EAAE;AAAA,EAC5E;AAaA,QAAM,iBAAiB,cAAc,QAAQ,cAAc;AAE3D,MAAI;AACJ,MAAI,gBAAgB;AAClB,QAAI,uBAAuB,OAAQ,cAAa;AAAA,aACvC,uBAAuB,QAAS,cAAa;AAAA,QACjD,cAAa;AAAA,EACpB,OAAO;AACL,QAAI,uBAAuB,MAAO,cAAa;AAAA,aACtC,uBAAuB,SAAU,cAAa;AAAA,QAClD,cAAa;AAAA,EACpB;AAEA,SAAO,EAAE,OAAO,YAAY,QAAQ,WAAW;AACjD;AAEA,SAAS,uBACP,OACA,OACA,OACmB;AACnB,aAAW,KAAK,OAAO;AACrB,UAAM,cAAc,EAAE,SAAS,MAAM;AACrC,UAAM,YAAY,EAAE,OAAO,MAAM;AACjC,QAAI,CAAC,eAAe,CAAC,UAAW;AAEhC,UAAM,aAAa,cAAc,EAAE,KAAK,EAAE;AAC1C,UAAM,WAAW,MAAM,IAAI,UAAU;AACrC,QAAI,CAAC,SAAU;AAEf,UAAM,mBAAmB,cAAc,EAAE,WAAW,EAAE;AACtD,UAAM,iBAAiB,SAAS,QAAQ,KAAK,OAAK,EAAE,OAAO,gBAAgB;AAC3E,QAAI,eAAgB,QAAO,eAAe;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,gBACP,MACA,UACA,WACA,MACyC;AACzC,MAAI,KAAK,QAAQ,WAAW,EAAG,QAAO;AACtC,QAAM,eAAe,MAAM,KAAK,SAAS,QAAQ;AACjD,MAAI,aAAa,cAAc,EAAG,QAAO;AAEzC,QAAM,aAA8E,CAAC;AACrF,aAAW,OAAO,CAAC,IAAI,KAAK,GAAG,GAAY;AACzC,UAAM,UAAU,cAAc,KAAK,SAAS,GAAG;AAC/C,eAAW,KAAK,EAAE,UAAU,KAAK,OAAO,MAAM,SAAS,QAAQ,EAAE,CAAC;AAAA,EACpE;AAEA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,aAAa,EAAE,MAAM,UAAU;AACjE,QAAM,OAAO,WAAW,CAAC;AACzB,MAAI,KAAK,MAAM,cAAc,aAAa,WAAY,QAAO;AAE7D,SAAO,cAAc,MAAM,KAAK,UAAU,cAAc,KAAK,OAAO,WAAW,UAAU,IAAI;AAC/F;AAEA,SAAS,cACP,MACA,UACA,SACA,eACA,WACA,UACA,MACA;AACA,QAAM,WAAsB,EAAE,GAAG,MAAM,SAAS,cAAc,KAAK,SAAS,QAAQ,EAAE;AACtF,QAAM,WAAW,KAAK,SAAS,UAC3B,0BAA0B,SAAS,MAAM,wDACzC,aAAa,SAAS,sBAAsB,SAAS,KAAK,mBAAmB,SAAS,MAAM;AAChG,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,QAAQ,GAAG,QAAQ,KAAK,QAAQ,OAAO,IAAI,QAAQ,KAAK,mBAAmB,cAAc,OAAO,IAAI,cAAc,KAAK;AAAA,EACzH;AACF;AAEA,SAAS,aAAa,WAAwC;AAC5D,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;AAEA,SAAS,cAAc,WAAwC;AAC7D,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAM,aAAO;AAAA,EACpB;AACF;AAEA,SAAS,MACP,SACA,UACwD;AACxD,MAAI,UAAU;AACd,MAAI,QAAQ;AACZ,aAAW,KAAK,SAAS;AACvB;AACA,QAAI,EAAE,SAAS,WAAW,EAAE,aAAa,SAAS,MAAO;AAAA,aAChD,EAAE,SAAS,YAAY,EAAE,aAAa,SAAS,OAAQ;AAAA,EAClE;AACA,SAAO,EAAE,SAAS,OAAO,YAAY,UAAU,IAAI,IAAI,UAAU,MAAM;AACzE;AAcO,SAAS,uBACd,OACA,SACA,SACa;AACb,MAAI,CAAC,QAAQ,WAAY,QAAO;AAEhC,QAAM,eAAe,IAAI,IAAwB,QAAQ,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClF,QAAM,aAAa,IAAI,IAAuB,MAAM,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAE7E,QAAM,WAAW,MAAM,MAAM,IAAI,UAAQ;AACvC,UAAM,WAAW,wBAAwB,MAAM,MAAM,OAAO,YAAY,cAAc,QAAQ,SAAS;AACvG,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,WAAW,QAAQ,WAAY,QAAQ;AAC7C,WAAO,YAAY;AAAA,EACrB,CAAC;AAED,SAAO,EAAE,OAAO,UAAU,OAAO,MAAM,MAAM;AAC/C;AAoBA,SAAS,wBACP,MACA,OACA,YACA,cACA,WACgC;AAChC,QAAM,cAAc,aAAa,IAAI,KAAK,EAAE;AAC5C,MAAI,CAAC,YAAa,QAAO;AACzB,MAAI,KAAK,QAAQ,WAAW,EAAG,QAAO;AAEtC,QAAM,eAAe,cAAc,QAAQ,cAAc;AAGzD,QAAM,UAAU,eAAe,YAAY,IAAI,YAAY;AAC3D,QAAM,UAAU,eAAe,YAAY,IAAI,YAAY,QAAQ,YAAY,IAAI,YAAY;AAC/F,QAAM,WAAW,eAAe,YAAY,IAAI,YAAY;AAC5D,QAAM,WAAW,eAAe,YAAY,IAAI,YAAY,SAAS,YAAY,IAAI,YAAY;AACjG,QAAM,eAAe,WAAW,YAAY;AAE5C,QAAM,gBAAgB,oBAAI,IAAY;AACtC,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,SAAS,KAAK,GAAI,eAAc,IAAI,EAAE,UAAU;AACtD,QAAI,EAAE,OAAO,KAAK,GAAI,eAAc,IAAI,EAAE,QAAQ;AAAA,EACpD;AACA,MAAI,cAAc,SAAS,EAAG,QAAO;AAGrC,QAAM,gBAAgB,oBAAI,IAA2B;AAErD,aAAW,KAAK,OAAO;AACrB,UAAM,SAAS,EAAE,SAAS,KAAK;AAC/B,UAAM,OAAO,EAAE,OAAO,KAAK;AAC3B,QAAI,CAAC,UAAU,CAAC,KAAM;AAEtB,UAAM,WAAW,SAAS,EAAE,aAAa,EAAE;AAC3C,UAAM,aAAa,SAAS,EAAE,KAAK,EAAE;AACrC,UAAM,KAAK,aAAa,IAAI,UAAU;AACtC,QAAI,CAAC,GAAI;AAET,UAAM,aAAa,eAAe,GAAG,IAAI,GAAG;AAC5C,UAAM,aAAa,eAAe,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG;AAC9D,UAAM,UAAU,KAAK,IAAI,SAAS,UAAU,IAAI,KAAK,IAAI,SAAS,UAAU;AAC5E,UAAM,SAAS,WAAW;AAE1B,UAAM,YAAY,eAAe,GAAG,IAAI,GAAG,SAAS,IAAI,GAAG,IAAI,GAAG,QAAQ;AAC1E,UAAM,WAAW,eAAe,GAAG,IAAI,GAAG,QAAQ,IAAI,GAAG,IAAI,GAAG,SAAS;AACzE,UAAM,YAAY,eAAe,YAAY,IAAI,YAAY,QAAQ,IAAI,YAAY,IAAI,YAAY,SAAS;AAG9G,UAAM,cAAc,cAAc,WAAY,WAAW,KAAK,WAAW;AACzE,UAAM,WAAuB,eACxB,cAAc,SAAS,UACvB,cAAc,QAAQ;AAG3B,UAAM,IAAI,YAAY;AACtB,UAAM,WAAuB,eACxB,KAAK,IAAI,WAAW,QACpB,KAAK,IAAI,UAAU;AAExB,UAAM,SAAqB,YAAY,WAAW,IAAI,YAAY,WAAW,KAAK;AAElF,UAAM,OAAO,KAAK,MAAM,WAAW,WAAW,YAAY,WAAW;AACrE,UAAM,SAAS,OAAO,IAAI,IAAI,OAAO;AAErC,UAAM,MAAM,cAAc,IAAI,QAAQ,KAAK,CAAC;AAC5C,QAAI,KAAK,EAAE,QAAQ,QAAQ,UAAU,UAAU,YAAY,WAAW,WAAW,UAAU,OAAO,CAAC;AACnG,kBAAc,IAAI,UAAU,GAAG;AAAA,EACjC;AAIA,QAAM,WAAW,oBAAI,IAAsB;AAC3C,aAAW,CAAC,UAAU,KAAK,KAAK,eAAe;AAC7C,QAAI,MAAM,WAAW,EAAG;AAGxB,UAAM,UAAsC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE;AACnF,QAAI,MAAM,MAAM,CAAC;AACjB,eAAW,KAAK,OAAO;AACrB,cAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,KAAK,EAAE;AACjD,UAAI,EAAE,SAAS,IAAI,OAAQ,OAAM;AAAA,IACnC;AACA,UAAM,OAAQ,OAAO,QAAQ,OAAO,EACjC,OAAO,CAAC,KAAK,QAAS,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,MAAM,KAAM,CAAC,OAAqB,SAAS,CAAC,EAAE,CAAC;AAC1F,aAAS,IAAI,UAAU;AAAA,MACrB;AAAA,MAAM,QAAQ,IAAI;AAAA,MAAQ,UAAU,IAAI;AAAA,MAAU,UAAU,IAAI;AAAA,MAChE,YAAY,IAAI;AAAA,MAAY,WAAW,IAAI;AAAA,MAAW,QAAQ,IAAI;AAAA,IACpE,CAAC;AAAA,EACH;AAUA,aAAW,YAAY,CAAC,OAAO,UAAU,QAAQ,OAAO,GAAmB;AACzE,UAAM,QAAQ,CAAC,GAAG,SAAS,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,QAAQ;AACvF,QAAI,MAAM,SAAS,EAAG;AACtB,QAAI,UAAU,OAAO,WAAW;AAChC,eAAW,CAAC,EAAE,CAAC,KAAK,OAAO;AACzB,UAAI,EAAE,aAAa,YAAa,WAAU;AAAA,eACjC,EAAE,aAAa,YAAa,YAAW;AAAA,IAClD;AAGA,QAAI,WAAW,SAAU;AAQzB,UAAM,SAAS,CAAC,OAAgB,KAAK,WAAW,KAAK,WAAW,WAAW;AAC3E,UAAM,iBAAiB,CAAC,GAAG,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EACrG,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,IAAI,OAAO,CAAC,CAAC;AACvC,QAAI,eAAe,UAAU,GAAG;AAC9B,YAAM,OAAO,eAAe,CAAC;AAC7B,iBAAW,CAAC,EAAE,CAAC,KAAK,OAAO;AACzB,YAAI,EAAE,WAAW,KAAK,EAAE,eAAe,KAAM,GAAE,OAAO,EAAE;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAGA,QAAM,cAAoE,CAAC;AAC3E,QAAM,cAAc,oBAAI,IAAwB;AAChD,aAAW,KAAK,KAAK,SAAS;AAC5B,UAAM,IAAI,SAAS,IAAI,EAAE,EAAE;AAC3B,QAAI,CAAC,EAAG;AACR,gBAAY,IAAI,EAAE,IAAI,EAAE,IAAI;AAC5B,QAAI,EAAE,SAAS,EAAE,SAAU,aAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,IAAI,EAAE,KAAK;AAAA,EAChF;AAMA,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,QAAM,SAAS,oBAAI,IAA0B;AAC7C,aAAW,CAAC,KAAK,CAAC,KAAK,UAAU;AAC/B,UAAM,MAAM,OAAO,IAAI,EAAE,IAAI,KAAK,CAAC;AACnC,QAAI,KAAK,GAAG;AACZ,WAAO,IAAI,EAAE,MAAM,GAAG;AAAA,EACxB;AACA,aAAW,CAAC,MAAM,SAAS,KAAK,QAAQ;AACtC,QAAI,UAAU,SAAS,EAAG;AAC1B,UAAM,UAAU,UACb,IAAI,SAAO,KAAK,QAAQ,KAAK,OAAK,EAAE,OAAO,GAAG,EAAG,UAAU,GAAG,EAC9D,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAIvB,UAAM,iBAAiB,SAAS,SAAS,SAAS;AAClD,UAAM,UAAU,CAAC,QAAwB;AACvC,YAAM,IAAI,SAAS,IAAI,GAAG;AAG1B,UAAI,cAAc;AAIhB,eAAO,iBAAiB,EAAE,YAAY,EAAE;AAAA,MAC1C;AACA,aAAO,iBAAiB,EAAE,aAAa,EAAE;AAAA,IAC3C;AACA,UAAM,gBAAgB,CAAC,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,MAAM;AAClD,YAAM,KAAK,QAAQ,CAAC,GAAG,KAAK,QAAQ,CAAC;AACrC,aAAO,KAAK,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,IAC9C,CAAC;AACD,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,oBAAc,IAAI,cAAc,CAAC,GAAG,QAAQ,CAAC,CAAC;AAAA,IAChD;AAAA,EACF;AAGA,MAAI,UAAU;AACd,QAAM,aAAa,KAAK,QAAQ,IAAI,OAAK;AACvC,UAAM,OAAO,YAAY,IAAI,EAAE,EAAE,KAAK,EAAE;AACxC,UAAM,SAAS,cAAc,IAAI,EAAE,EAAE,IAAI,cAAc,IAAI,EAAE,EAAE,IAAM,EAAE,UAAU;AACjF,QAAI,SAAS,EAAE,YAAY,YAAY,EAAE,UAAU,MAAM;AACvD,gBAAU;AACV,aAAO,EAAE,GAAG,GAAG,UAAU,MAAM,OAAO;AAAA,IACxC;AACA,WAAO;AAAA,EACT,CAAC;AAED,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,WAAsB,EAAE,GAAG,MAAM,SAAS,WAAW;AAC3D,QAAM,cAAc,OAAO,QAAQ,WAAW,EAC3C,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,SAAI,EAAE,EAAE,EAAE,EAC3C,KAAK,IAAI;AACZ,QAAM,SAAS,cACX,GAAG,OAAO,KAAK,WAAW,EAAE,MAAM,kDAAkD,WAAW,MAC/F;AAEJ,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,SAAS;AAAA,IACT;AAAA,IACA,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,cAAc,SAAwB,KAAoC;AACxF,QAAM,aAAa,CAAC,MAA8B;AAChD,QAAI,QAAQ,KAAK;AACf,aAAO,MAAM,QAAQ,WAAW,MAAM,WAAW,QAAQ,MAAM,SAAS,UAAU;AAAA,IACpF;AACA,QAAI,QAAQ,IAAI;AACd,aAAO,MAAM,QAAQ,UAAU,MAAM,UAAU,WAAW,MAAM,WAAW,SAAS;AAAA,IACtF;AACA,WAAO,MAAM,QAAQ,SAAS,MAAM,SAAS,WAAW,MAAM,WAAW,UAAU;AAAA,EACrF;AACA,SAAO,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,UAAU,WAAW,EAAE,QAAQ,EAAE,EAAE;AACtE;;;ACxeA,IAAM,kBAAkB;AAMjB,SAAS,OAAO,OAAoB,SAAuC;AAChF,QAAM,WAAW,eAAe,OAAO;AACvC,MAAI,MAAM,MAAM,WAAW,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAG5D,MAAI,WAAW,uBAAuB,OAAO,QAAQ;AAKrD,MAAI,SAAS,YAAY;AACvB,UAAM,iBAAkC,EAAE,GAAG,UAAU,YAAY,OAAU;AAC7E,UAAM,UAAU,eAAe,UAAU,cAAc;AACvD,eAAW,uBAAuB,UAAU,SAAS,QAAQ;AAAA,EAC/D;AAEA,SAAO,eAAe,UAAU,QAAQ;AAC1C;AAGO,SAAS,cAAc,OAAc,SAAwC;AAClF,MAAI,MAAM,MAAM,SAAS,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE;AAE1D,cAAY,KAAK;AAEjB,MAAI,SAAS,aAAa,KAAK;AAC/B,WAAS,iBAAiB,OAAO,MAAM;AAGvC,MAAI,OAAO,WAAW,QAAQ,KAAK;AACnC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,oBAAkB,OAAO,MAAM,OAAO;AAGtC,qBAAmB,OAAO,QAAQ,OAAO;AAEzC,QAAM,cAAc,WAAW,OAAO,QAAQ,WAAW,QAAQ,UAAU;AAC3E,SAAO,YAAY,OAAO,WAAW;AACvC;AAEA,SAAS,YAAY,OAAc,aAA0D;AAC3F,QAAM,QAAsB,CAAC;AAC7B,QAAM,QAAsB,CAAC;AAE7B,aAAW,CAAC,EAAE,IAAI,KAAK,MAAM,OAAO;AAClC,QAAI,KAAK,QAAS;AAElB,UAAM,UAA0B,KAAK,QAAQ,IAAI,OAAK;AACpD,YAAM,MAAM,kBAAkB,MAAM,EAAE,EAAE;AACxC,aAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AAAA,IAC5E,CAAC;AAED,UAAM,KAAK;AAAA,MACT,IAAI,KAAK;AAAA,MACT,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,aAAW,SAAS,aAAa;AAC/B,UAAM,KAAK;AAAA,MACT,IAAI,MAAM;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,IAAI,MAAM;AAAA,MACV,YAAY,MAAM;AAAA,MAClB,UAAU,MAAM;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,MAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,OAAO,MAAM;AACxB;AAMA,SAAS,eAAe,OAAoB,SAAwC;AAClF,QAAM,UAAU,IAAI,IAAI,MAAM,MAAM,IAAI,OAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEvD,QAAM,mBAAmB,oBAAI,IAAyB;AACtD,QAAM,YAAyB,CAAC;AAChC,aAAW,KAAK,MAAM,OAAO;AAC3B,QAAI,EAAE,YAAY,QAAQ,IAAI,EAAE,QAAQ,GAAG;AACzC,YAAM,MAAM,iBAAiB,IAAI,EAAE,QAAQ,KAAK,CAAC;AACjD,UAAI,KAAK,CAAC;AACV,uBAAiB,IAAI,EAAE,UAAU,GAAG;AAAA,IACtC,OAAO;AACL,gBAAU,KAAK,CAAC;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,cAAc,IAAI,IAAI,iBAAiB,KAAK,CAAC;AAGnD,QAAM,aAAa,oBAAI,IAAoB;AAC3C,WAAS,QAAQ,IAAoB;AACnC,QAAI,WAAW,IAAI,EAAE,EAAG,QAAO,WAAW,IAAI,EAAE;AAChD,UAAM,IAAI,QAAQ,IAAI,EAAE;AACxB,UAAM,IAAI,GAAG,YAAY,QAAQ,IAAI,EAAE,QAAQ,IAAI,QAAQ,EAAE,QAAQ,IAAI,IAAI;AAC7E,eAAW,IAAI,IAAI,CAAC;AACpB,WAAO;AAAA,EACT;AACA,aAAW,KAAK,MAAM,MAAO,SAAQ,EAAE,EAAE;AAEzC,QAAM,kBAAkB,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC;AAG/E,QAAM,aAAa,oBAAI,IAA0B;AAEjD,QAAM,eAAe,oBAAI,IAA+C;AAExE,aAAW,cAAc,iBAAiB;AACxC,UAAM,WAAW,iBAAiB,IAAI,UAAU,KAAK,CAAC;AACtD,QAAI,SAAS,WAAW,EAAG;AAE3B,UAAM,aAAa,IAAI,IAAI,SAAS,IAAI,OAAK,EAAE,EAAE,CAAC;AAClD,UAAM,WAAW,MAAM,MAAM,OAAO,OAAK,WAAW,IAAI,EAAE,IAAI,KAAK,WAAW,IAAI,EAAE,EAAE,CAAC;AAGvF,UAAM,gBAAgB,SAAS,IAAI,OAAK;AACtC,YAAM,KAAK,aAAa,IAAI,EAAE,EAAE;AAChC,aAAO,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,IAAI;AAAA,IAC7D,CAAC;AAID,UAAM,aAA8B,EAAE,GAAG,SAAS,gBAAgB,MAAM;AACxE,UAAM,WAAwB,EAAE,OAAO,cAAc,IAAI,WAAW,GAAG,OAAO,SAAS;AACvF,UAAM,YAAY,WAAW,UAAU,UAAU;AACjD,eAAW,IAAI,YAAY,SAAS;AAGpC,UAAM,OAAO,mBAAmB,UAAU,KAAK;AAC/C,UAAM,SAAS,KAAK,QAAQ,QAAQ,kBAAkB;AACtD,UAAM,SAAS,KAAK,SAAS,QAAQ,kBAAkB,IAAI;AAE3D,UAAM,WAAW,QAAQ,IAAI,UAAU;AACvC,iBAAa,IAAI,YAAY;AAAA,MAC3B,OAAO,KAAK,IAAI,QAAQ,SAAS,KAAK;AAAA,MACtC,QAAQ,KAAK,IAAI,QAAQ,SAAS,MAAM;AAAA,IAC1C,CAAC;AAAA,EACH;AAGA,QAAM,iBAAiB,UAAU,IAAI,OAAK;AACxC,UAAM,KAAK,aAAa,IAAI,EAAE,EAAE;AAChC,WAAO,KAAK,EAAE,GAAG,GAAG,OAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,IAAI;AAAA,EAC7D,CAAC;AACD,QAAM,YAAY,IAAI,IAAI,UAAU,IAAI,OAAK,EAAE,EAAE,CAAC;AAClD,QAAM,YAAY,MAAM,MAAM,OAAO,OAAK;AAExC,WAAO,UAAU,IAAI,EAAE,IAAI,KAAK,UAAU,IAAI,EAAE,EAAE;AAAA,EACpD,CAAC;AAED,QAAM,aAAa,WAAW,EAAE,OAAO,eAAe,IAAI,WAAW,GAAG,OAAO,UAAU,GAAG,OAAO;AAInG,QAAM,aAA2B,CAAC;AAClC,QAAM,aAA2B,CAAC;AAGlC,aAAW,KAAK,WAAW,OAAO;AAChC,UAAM,cAAc,YAAY,IAAI,EAAE,EAAE;AACxC,eAAW,KAAK;AAAA,MACd,GAAG;AAAA,MACH,UAAU,QAAQ,IAAI,EAAE,EAAE,GAAG;AAAA,IAC/B,CAAC;AACD,QAAI,aAAa;AACf,4BAAsB,GAAG,gBAAc,WAAW,IAAI,UAAU,GAAG,YAAY,YAAY,SAAS,OAAO;AAAA,IAC7G;AAAA,EACF;AACA,aAAW,KAAK,GAAG,WAAW,KAAK;AAEnC,MAAI,QAAQ,gBAAgB;AAC1B,mBAAe,YAAY,YAAY,OAAO;AAAA,EAChD;AAEA,SAAO,EAAE,OAAO,YAAY,OAAO,WAAW;AAChD;AAMA,SAAS,sBACP,QACA,QACA,YACA,YACA,SACA,SACM;AACN,QAAM,MAAM,OAAO,OAAO,EAAE;AAC5B,MAAI,CAAC,IAAK;AAEV,QAAM,OAAO,mBAAmB,IAAI,KAAK;AAEzC,QAAM,KAAK,OAAO,IAAI,QAAQ,kBAAkB,KAAK;AACrD,QAAM,KAAK,OAAO,IAAI,QAAQ,kBAAkB,kBAAkB,KAAK;AAIvE,QAAM,aAAa,OAAO,QAAQ,QAAQ,kBAAkB;AAC5D,QAAM,UAAU,aAAa,KAAK,SAAS;AAC3C,QAAM,aAAa,OAAO,SAAS,QAAQ,kBAAkB,IAAI;AACjE,QAAM,UAAU,aAAa,KAAK,UAAU;AAC5C,QAAM,KAAK,KAAK,KAAK,IAAI,GAAG,MAAM;AAClC,QAAM,KAAK,KAAK,KAAK,IAAI,GAAG,MAAM;AAElC,aAAW,SAAS,IAAI,OAAO;AAC7B,UAAM,SAAqB;AAAA,MACzB,GAAG;AAAA,MACH,GAAG,MAAM,IAAI;AAAA,MACb,GAAG,MAAM,IAAI;AAAA,MACb,SAAS,MAAM,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE;AAAA,MACpE,UAAU,QAAQ,IAAI,MAAM,EAAE,GAAG,YAAY,OAAO;AAAA,IACtD;AACA,eAAW,KAAK,MAAM;AACtB,QAAI,OAAO,MAAM,EAAE,GAAG;AACpB,4BAAsB,QAAQ,QAAQ,YAAY,YAAY,SAAS,OAAO;AAAA,IAChF;AAAA,EACF;AAEA,aAAW,QAAQ,IAAI,OAAO;AAC5B,eAAW,KAAK;AAAA,MACd,GAAG;AAAA,MACH,QAAQ,KAAK,OAAO,IAAI,QAAM,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE;AAAA,IAC7D,CAAC;AAAA,EACH;AACF;AAGA,SAAS,YAAY,GAAyB;AAC5C,QAAM,EAAE,UAAU,UAAU,GAAG,KAAK,IAAI;AACxC,SAAO;AACT;AAEA,SAAS,WAAW,OAAoB,SAAwC;AAC9E,QAAM,QAAQ,WAAW,MAAM,OAAO,MAAM,OAAO;AAAA,IACjD,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ;AAAA,EACtB,CAAC;AACD,SAAO,cAAc,OAAO,OAAO;AACrC;AAEA,SAAS,mBACP,OAC2F;AAC3F,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,QAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EAC5C;AACA,MAAI,CAAC,SAAS,IAAI,GAAG;AACnB,WAAO;AAAG,WAAO;AAAG,WAAO;AAAG,WAAO;AAAA,EACvC;AACA,SAAO,EAAE,MAAM,MAAM,MAAM,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AAC3E;;;ACzRO,IAAM,oBAAN,MAAwB;AAAA,EAQ7B,YAAY,SAAyB;AALrC,SAAQ,aAAqC,oBAAI,IAAI;AACrD,SAAQ,aAAqC,oBAAI,IAAI;AACrD,SAAQ,aAAkC;AAC1C,SAAQ,gBAAuD,oBAAI,IAAI;AAGrE,SAAK,UAAU;AACf,SAAK,kBAAkB,eAAe,OAAO;AAAA,EAC/C;AAAA,EAEA,SAAS,OAAkC;AACzC,SAAK,WAAW,MAAM;AACtB,SAAK,WAAW,MAAM;AACtB,eAAW,QAAQ,MAAM,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AACjE,eAAW,QAAQ,MAAM,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AACjE,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,SAAS,OAAoB,OAAmC;AAC9D,eAAW,QAAQ,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AAC3D,QAAI,MAAO,YAAW,QAAQ,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AACtE,WAAO,KAAK,uBAAuB,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,EAAE,CAAC,CAAC;AAAA,EAClE;AAAA,EAEA,YAAY,SAAiC;AAC3C,UAAM,aAAa,IAAI,IAAI,OAAO;AAClC,eAAW,MAAM,QAAS,MAAK,WAAW,OAAO,EAAE;AACnD,eAAW,CAAC,QAAQ,IAAI,KAAK,KAAK,YAAY;AAC5C,UAAI,WAAW,IAAI,KAAK,IAAI,KAAK,WAAW,IAAI,KAAK,EAAE,GAAG;AACxD,aAAK,WAAW,OAAO,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,eAAW,MAAM,QAAS,MAAK,cAAc,OAAO,EAAE;AACtD,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,SAAS,OAAkC;AACzC,eAAW,QAAQ,MAAO,MAAK,WAAW,IAAI,KAAK,IAAI,IAAI;AAC3D,WAAO,KAAK,uBAAuB,oBAAI,IAAY,CAAC;AAAA,EACtD;AAAA,EAEA,YAAY,SAAiC;AAC3C,eAAW,MAAM,QAAS,MAAK,WAAW,OAAO,EAAE;AACnD,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,YAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,YAA0B;AAChC,UAAM,QAAqB;AAAA,MACzB,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,MACnC,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,IACrC;AACA,SAAK,aAAa,OAAO,OAAO,KAAK,OAAO;AAC5C,SAAK,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,uBAAuB,YAAuC;AACpE,UAAM,QAAqB;AAAA,MACzB,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,MACnC,OAAO,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC;AAAA,IACrC;AAEA,UAAM,QAAQ,OAAO,OAAO,KAAK,OAAO;AACxC,SAAK,aAAa,KAAK,eAAe,OAAO,UAAU;AACvD,SAAK,eAAe;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,OAAqB,YAAuC;AACjF,QAAI,KAAK,cAAc,SAAS,EAAG,QAAO;AAC1C,UAAM,mBAAmB;AAEzB,UAAM,UAAwB;AAAA,MAC5B,OAAO,MAAM,MAAM,IAAI,OAAK;AAC1B,YAAI,WAAW,IAAI,EAAE,EAAE,EAAG,QAAO;AACjC,cAAM,MAAM,KAAK,cAAc,IAAI,EAAE,EAAE;AACvC,YAAI,CAAC,IAAK,QAAO;AACjB,cAAM,KAAK,IAAI,IAAI,EAAE;AACrB,cAAM,KAAK,IAAI,IAAI,EAAE;AACrB,cAAM,IAAI,EAAE,IAAI,KAAK;AACrB,cAAM,IAAI,EAAE,IAAI,KAAK;AACrB,cAAM,MAAM,IAAI,EAAE;AAClB,cAAM,MAAM,IAAI,EAAE;AAClB,eAAO;AAAA,UACL,GAAG;AAAA,UACH;AAAA,UACA;AAAA,UACA,SAAS,EAAE,QAAQ,IAAI,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,IAAI,EAAE;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,MACD,OAAO,MAAM;AAAA,IACf;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,WAAY;AACtB,SAAK,cAAc,MAAM;AACzB,eAAW,QAAQ,KAAK,WAAW,OAAO;AACxC,WAAK,cAAc,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;;;AChHO,SAAS,YAAY,QAAsB,UAA8B,CAAC,GAAW;AAC1F,QAAM,QAAkB,CAAC;AACzB,QAAM,EAAE,OAAO,MAAM,IAAI;AAEzB,MAAI,MAAM,WAAW,EAAG,QAAO;AAG/B,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,QAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EAC5C;AACA,QAAM,KAAK,cAAc,MAAM,MAAM,WAAW,MAAM,MAAM,YAAY;AACxE,QAAM,KAAK,YAAY,KAAK,QAAQ,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,OAAO,OAAO,MAAM,QAAQ,CAAC,CAAC,OAAO,OAAO,MAAM,QAAQ,CAAC,CAAC,GAAG;AAGpK,QAAM,MAAM,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5D,QAAM,QAAwB,CAAC;AAC/B,aAAW,KAAK,KAAK;AACnB,UAAM,SAAS,MAAM,KAAK,OAAK,KAAK,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC;AACzD,QAAI,OAAQ,QAAO,KAAK,CAAC;AAAA,QACpB,OAAM,KAAK,CAAC,CAAC,CAAC;AAAA,EACrB;AAEA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,iBAAiB;AAC5B,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AACjD,UAAM,UAAU,OAAO,IAAI,OAAK;AAC9B,YAAM,IAAI,EAAE,WAAW,IAAI,EAAE,QAAQ,OAAO;AAC5C,aAAO,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM;AAAA,IAChF,CAAC,EAAE,KAAK,IAAI;AACZ,UAAM,KAAK,OAAO,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,OAAO,EAAE;AAAA,EACpE;AAGA,QAAM,WAAW,oBAAI,IAAsC;AAC3D,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,EAAE;AACd,UAAM,MAAM,SAAS,IAAI,GAAG,KAAK,CAAC;AAClC,QAAI,KAAK,CAAC;AACV,aAAS,IAAI,KAAK,GAAG;AAAA,EACvB;AACA,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,SAAS,KAAK,GAAG;AAC/B,QAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,CAAC,EAAG,aAAY,IAAI,CAAC;AAAA,EACzD;AACA,MAAI,YAAY,OAAO,GAAG;AAGxB,QAASA,gBAAT,SAAsB,IAAwB,OAAe;AAC3D,YAAM,WAAW,SAAS,IAAI,EAAE,KAAK,CAAC;AACtC,iBAAW,KAAK,UAAU;AACxB,cAAM,SAAS,KAAK,OAAO,KAAK;AAChC,cAAM,MAAM,YAAY,IAAI,EAAE,EAAE,IAAI,gBAAgB;AACpD,cAAM,KAAK,GAAG,MAAM,KAAK,EAAE,EAAE,GAAG,GAAG,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,QAAQ,CAAC,CAAC,GAAG;AACjJ,YAAI,YAAY,IAAI,EAAE,EAAE,EAAG,CAAAA,cAAa,EAAE,IAAI,QAAQ,CAAC;AAAA,MACzD;AAAA,IACF;AARS,uBAAAA;AAFT,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mBAAmB;AAU9B,IAAAA,cAAa,QAAW,CAAC;AAAA,EAC3B;AAGA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,eAAe;AAC1B,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,EAAE,OAAO,CAAC;AACvB,UAAM,OAAO,EAAE,OAAO,EAAE,OAAO,SAAS,CAAC;AACzC,UAAM,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,IAAI,IAAI,EAAE,UAAU,WAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,MAAM,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC,aAAQ,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC,UAAU,EAAE,OAAO,MAAM,MAAM;AAAA,EACrM;AAGA,QAAM,WAAW,aAAa,KAAK;AACnC,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,6BAA6B;AACxC,eAAW,KAAK,UAAU;AACxB,YAAM,KAAK,KAAK,EAAE,CAAC,aAAa,EAAE,CAAC,EAAE;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,OAAO;AAC1B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,UAAU,OAAO,OAAO,OAAO,CAAC;AAAA,EAC7C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,OAAiD;AACrE,QAAM,MAAkC,CAAC;AACzC,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,MAAO,KAAI,EAAE,SAAU,aAAY,IAAI,EAAE,QAAQ;AAEjE,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,aAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,YAAM,IAAI,MAAM,CAAC;AACjB,YAAM,IAAI,MAAM,CAAC;AAEjB,UAAI,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAU;AAEhD,YAAM,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;AACtD,YAAM,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE;AACvD,UAAI,YAAY,UAAU;AACxB,YAAI,KAAK,EAAE,GAAG,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,UAAU,OAAqB,OAAqB,SAAqC;AAChG,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,OAAO;AAC/D,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,QAAQ,KAAM,QAAO,EAAE,IAAI,EAAE;AACzC,QAAI,EAAE,IAAI,EAAE,SAAS,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EAC5C;AACA,aAAW,KAAK,MAAO,YAAW,KAAK,EAAE,QAAQ;AAC/C,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AAAA,EAC3B;AAEA,QAAM,UAAU,QAAQ,aAAa;AACrC,QAAM,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI;AACvC,QAAM,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI;AACvC,QAAM,SAAS,QAAQ,aAAa,UAAU;AAE9C,QAAM,SAAS,SAAS;AAExB,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,MAAM,IAAI,CAAC;AACrD,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,MAAM,IAAI,CAAC;AAErD,MAAI,IAAI,GAAI,QAAO;AAEnB,QAAM,OAAmB,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC;AAE7F,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,MAAO,KAAI,EAAE,SAAU,aAAY,IAAI,EAAE,QAAQ;AAGjE,aAAW,KAAK,OAAO;AACrB,UAAM,KAAK,KAAK,OAAO,EAAE,IAAI,QAAQ,MAAM;AAC3C,UAAM,KAAK,KAAK,OAAO,EAAE,IAAI,QAAQ,MAAM;AAC3C,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO,EAAE,IAAI,EAAE,QAAQ,QAAQ,MAAM,IAAI,CAAC;AACvE,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO,EAAE,IAAI,EAAE,SAAS,QAAQ,MAAM,IAAI,CAAC;AACxE,UAAM,aAAa,YAAY,IAAI,EAAE,EAAE;AACvC,UAAM,KAAK,aAAa,MAAM;AAC9B,aAAS,IAAI,IAAI,KAAK,MAAM,IAAI,GAAG,KAAK;AACtC,eAAS,IAAI,IAAI,KAAK,MAAM,IAAI,GAAG,KAAK;AACtC,YAAI,IAAI,KAAK,IAAI,EAAG;AACpB,YAAI,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,GAAI,MAAK,CAAC,EAAE,CAAC,IAAI;AAAA,iBACtD,YAAY;AAAA,QAErB,MAAO,MAAK,CAAC,EAAE,CAAC,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,QAAQ,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,EAAE,GAAG,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;AAC3E,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AAC7B,UAAM,KAAK,KAAK,IAAI,GAAG,EAAE;AACzB,aAAS,IAAI,GAAG,IAAI,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK;AACnD,UAAI,KAAK,EAAG,MAAK,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,KAAK,IAAI,SAAO,IAAI,KAAK,EAAE,CAAC,EAAE,KAAK,IAAI;AAChD;","names":["printSubtree"]}
|