));\n const second = this.uniquePort(id, new RegExp(`^${b} vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit ));\n if (first \u0026\u0026 second \u0026\u0026 first !== second \u0026\u0026 !hasHint(first, new RegExp(`^${b} vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit )) \u0026\u0026 !hasHint(second, new RegExp(`^${a} vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit )))\n return [first, second];\n }\n }\n hasGroundedDriver(anodeNet, cathodeNet) {\n return (this.index.portsByNet.get(anodeNet) ?? []).some((p) =\u003e {\n const id = p.source_component_id;\n const component = this.index.components.get(id);\n if (component?.ftype !== \"simple_chip\" \u0026\u0026 !(component?.ftype === \"simple_transistor\" \u0026\u0026 component.transistor_type === \"npn\"))\n return false;\n if (this.index.portsByComponent.get(id)?.length !== 3)\n return false;\n const c = this.uniquePort(id, /^(?:C|COLLECTOR)$/);\n const e = this.uniquePort(id, /^(?:E|EMITTER)$/);\n const b = this.uniquePort(id, /^(?:B|BASE)$/);\n if (!c || !e || !b || new Set([c, e, b]).size !== 3 || [c, e, b].some((p2) =\u003e p2.do_not_connect) || c.source_port_id !== p.source_port_id)\n return false;\n const emitterNet = this.index.connected(e.source_port_id), baseNet = this.index.connected(b.source_port_id);\n return this.index.groundNets.has(emitterNet) \u0026\u0026 !this.index.powerNets.has(emitterNet) \u0026\u0026 new Set([anodeNet, cathodeNet, emitterNet, baseNet]).size === 4;\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"relayName\", issue.relaySchematicBox.sourceComponentName);\n addAttr(attrs, \"diodeName\", issue.diodeSchematicBox.sourceComponentName);\n addAttr(attrs, \"distanceFromCoilPins\", issue.distanceFromCoilPins);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cFlybackDiodeSeparatedFromRelayCoil ${attrs.join(\" \")} /\u003e`;\n }\n}\nfunction hasHint(port, pattern) {\n return [port.name, ...port.port_hints ?? []].some((hint) =\u003e pattern.test(hint.toUpperCase().replace(/[\\s_]/g, \"\")));\n}\n\n// ../../work/placement-analysis/lib/solvers/CurrentSenseShuntPlacementSolver/CurrentSenseShuntPlacementSolver.ts\nvar EPSILON = 0.01;\n\nclass CurrentSenseShuntPlacementSolver extends BaseSolver {\n params;\n index;\n hostIds;\n traces;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n this.index = new PlacementNetworkIndex(params.ctx);\n this.hostIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_chip\").map((component) =\u003e component.source_component_id);\n this.traces = params.ctx.circuitJson.filter((element) =\u003e element.type === \"schematic_trace\");\n this.solved = this.hostIds.length === 0;\n }\n _step() {\n const hostId = this.hostIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.hostIds.length;\n if (!hostId)\n return;\n const index = this.index;\n const host = index.placement(hostId);\n const ports = index.portsByComponent.get(hostId) ?? [];\n const positive = ports.filter((port) =\u003e inputRole(port) === \"positive\");\n const negative = ports.filter((port) =\u003e inputRole(port) === \"negative\");\n const outputs = ports.filter((port) =\u003e hasHint2(port, /^(?:OUT|VOUT|OUTPUT)$/));\n if (!host || positive.length !== 1 || negative.length !== 1 || outputs.length !== 1 || !ports.some((port) =\u003e hasHint2(port, /^(?:VS|VCC|VDD)$/)) || !ports.some((port) =\u003e hasHint2(port, /^(?:GND|GROUND|VSS)$/)))\n return;\n const inputs = [positive[0], negative[0]];\n const nets = inputs.map((port) =\u003e index.connected(port.source_port_id));\n if (inputs.some((port) =\u003e port.do_not_connect) || nets[0] === nets[1] || nets.includes(index.connected(outputs[0].source_port_id)))\n return;\n const pins = inputs.map((port) =\u003e index.port(port));\n const [positivePin, negativePin] = pins;\n if (!positivePin || !negativePin || !positivePin.facing_direction || positivePin.facing_direction !== negativePin.facing_direction || pins.some((pin) =\u003e pin.schematic_sheet_id !== host.schematicSheetId))\n return;\n const resistorIds = new Set((index.portsByNet.get(nets[0]) ?? []).filter((port) =\u003e index.components.get(port.source_component_id)?.ftype === \"simple_resistor\").map((port) =\u003e port.source_component_id).filter((id) =\u003e index.twoTerminalNets(id)?.includes(nets[1])));\n if (resistorIds.size !== 1)\n return;\n const shuntId = [...resistorIds][0];\n const component = index.components.get(shuntId);\n if (component?.ftype !== \"simple_resistor\" || !Number.isFinite(component.resistance) || component.resistance \u003c= 0 || component.resistance \u003e 1)\n return;\n if (nets.some((net) =\u003e (index.portsByNet.get(net) ?? []).some((port) =\u003e port.source_component_id !== hostId \u0026\u0026 inputRole(port) !== undefined \u0026\u0026 index.components.get(port.source_component_id)?.ftype === \"simple_chip\")))\n return;\n const shunt = index.placement(shuntId);\n if (!shunt || !index.sameLocalScope(host, shunt))\n return;\n const shuntPorts = index.portsByComponent.get(shuntId);\n if (shuntPorts.some((port) =\u003e port.do_not_connect))\n return;\n const shuntPins = nets.map((net) =\u003e index.port(shuntPorts.find((port) =\u003e index.connected(port.source_port_id) === net)));\n if (shuntPins.some((pin) =\u003e !pin || pin.schematic_sheet_id !== host.schematicSheetId))\n return;\n const horizontalInputs = positivePin.facing_direction === \"left\" || positivePin.facing_direction === \"right\";\n const across = (point) =\u003e horizontalInputs ? point.y : point.x;\n const first = across(positivePin.center), second = across(negativePin.center);\n const span = Math.abs(first - second);\n if (span \u003c EPSILON)\n return;\n const shuntAcross = horizontalInputs ? shunt.schY : shunt.schX;\n const halfSize = (horizontalInputs ? shunt.height : shunt.width) / 2;\n const inputBandGap = Math.max(Math.min(first, second) - (shuntAcross + halfSize), shuntAcross - halfSize - Math.max(first, second));\n if (inputBandGap \u003c= Math.max(1.5, 2 * span) || Math.hypot(shunt.schX - host.schX, shunt.schY - host.schY) \u003e Math.max(8, 4 * Math.max(host.width, host.height)))\n return;\n const visible = pins.map((pin, i) =\u003e this.hasVisibleConnection(shuntPins[i], pin, nets[i]));\n if (visible[0] === visible[1])\n return;\n const labeledIndex = visible[0] ? 1 : 0;\n const labeledNet = nets[labeledIndex];\n if (!this.params.ctx.circuitJson.some((element) =\u003e {\n if (element.type !== \"schematic_net_label\" || element.schematic_sheet_id !== host.schematicSheetId)\n return false;\n if (element.source_net_id \u0026\u0026 (index.connected(element.source_net_id) === labeledNet || index.connected(`connectivity:${element.source_net_id}`) === labeledNet))\n return true;\n const pin = shuntPins[labeledIndex].center;\n if (element.anchor_position \u0026\u0026 Math.hypot(element.anchor_position.x - pin.x, element.anchor_position.y - pin.y) \u003c EPSILON)\n return true;\n return element.source_trace_id !== undefined \u0026\u0026 this.sourceTraceTouchesNet(element.source_trace_id, labeledNet);\n }))\n return;\n this.params.issues.push({\n lineItemType: \"CurrentSenseShuntSeparatedFromInputs\",\n amplifierSchematicBox: host,\n shuntSchematicBox: shunt,\n positiveInputSourcePortId: inputs[0].source_port_id,\n negativeInputSourcePortId: inputs[1].source_port_id,\n inputBandGap,\n message: `Place ${shunt.sourceComponentName ?? shuntId} near ${host.sourceComponentName ?? hostId}.${inputs[0].name}/${inputs[1].name}, so both sense connections can be read together. Move or rotate the shunt as needed; preserve all pin connections and leave room for labels.`\n });\n }\n hasVisibleConnection(from, to, net) {\n const edges = this.traces.filter((trace) =\u003e {\n if (trace.schematic_sheet_id !== from.schematic_sheet_id)\n return false;\n if (trace.subcircuit_connectivity_map_key)\n return this.index.connected(`connectivity:${trace.subcircuit_connectivity_map_key}`) === net;\n if (this.sourceTraceTouchesNet(trace.source_trace_id, net))\n return true;\n const endpoints = [trace.edges[0]?.from, trace.edges.at(-1)?.to];\n const endpointNets = new Set(this.params.ctx.circuitJson.flatMap((element) =\u003e element.type === \"schematic_port\" \u0026\u0026 element.source_port_id \u0026\u0026 element.schematic_sheet_id === trace.schematic_sheet_id \u0026\u0026 endpoints.some((point) =\u003e point \u0026\u0026 Math.hypot(point.x - element.center.x, point.y - element.center.y) \u003c EPSILON) ? [this.index.connected(element.source_port_id)] : []));\n return endpointNets.size === 1 \u0026\u0026 endpointNets.has(net);\n }).flatMap((trace) =\u003e trace.edges);\n const reached = edges.filter((edge) =\u003e onSegment(from.center, edge.from, edge.to));\n const visited = new Set;\n for (let i = 0;i \u003c reached.length; i++) {\n const current = reached[i];\n if (onSegment(to.center, current.from, current.to))\n return true;\n for (const [edgeIndex, edge] of edges.entries()) {\n if (visited.has(edgeIndex) || ![current.from, current.to].some((point) =\u003e onSegment(point, edge.from, edge.to)) \u0026\u0026 ![edge.from, edge.to].some((point) =\u003e onSegment(point, current.from, current.to)))\n continue;\n visited.add(edgeIndex);\n reached.push(edge);\n }\n }\n return false;\n }\n sourceTraceTouchesNet(traceId, net) {\n if (!traceId)\n return false;\n const source = this.params.ctx.circuitJson.find((element) =\u003e element.type === \"source_trace\" \u0026\u0026 element.source_trace_id === traceId);\n return source?.type === \"source_trace\" \u0026\u0026 source.connected_source_port_ids.some((id) =\u003e this.index.connected(id) === net);\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"amplifierName\", issue.amplifierSchematicBox.sourceComponentName);\n addAttr(attrs, \"shuntName\", issue.shuntSchematicBox.sourceComponentName);\n addAttr(attrs, \"inputBandGap\", issue.inputBandGap);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cCurrentSenseShuntSeparatedFromInputs ${attrs.join(\" \")} /\u003e`;\n }\n}\nfunction hasHint2(port, pattern) {\n return [port.name, ...port.port_hints ?? []].some((hint) =\u003e pattern.test(hint.toUpperCase().replace(/[\\s_]/g, \"\")));\n}\nfunction inputRole(port) {\n const positive = hasHint2(port, /^(?:IN\\+|VIN\\+|INPOS|VINPOS)$/);\n const negative = hasHint2(port, /^(?:IN-|VIN-|INNEG|VINNEG)$/);\n return positive === negative ? undefined : positive ? \"positive\" : \"negative\";\n}\nfunction onSegment(point, from, to) {\n const dx = to.x - from.x, dy = to.y - from.y;\n const length = Math.hypot(dx, dy);\n if (length \u003c EPSILON)\n return Math.hypot(point.x - from.x, point.y - from.y) \u003c EPSILON;\n const projection = ((point.x - from.x) * dx + (point.y - from.y) * dy) / length;\n return projection \u003e= -EPSILON \u0026\u0026 projection \u003c= length + EPSILON \u0026\u0026 Math.abs((point.x - from.x) * dy - (point.y - from.y) * dx) / length \u003c EPSILON;\n}\n\n// ../../work/placement-analysis/lib/solvers/VoltageDividerPlacementSolver/VoltageDividerPlacementSolver.ts\nclass VoltageDividerPlacementSolver extends BaseSolver {\n params;\n index;\n positiveNets = new Set;\n resistorIds;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n this.index = new PlacementNetworkIndex(params.ctx);\n this.resistorIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_resistor\").map((component) =\u003e component.source_component_id);\n for (const element of params.ctx.circuitJson) {\n if (element.type === \"source_net\" \u0026\u0026 element.is_positive_voltage_source)\n this.positiveNets.add(this.index.connected(element.source_net_id));\n }\n this.solved = this.resistorIds.length === 0;\n }\n _step() {\n const supplyId = this.resistorIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.resistorIds.length;\n if (!supplyId || !this.isResistor(supplyId))\n return;\n const index = this.index;\n const nets = index.twoTerminalNets(supplyId);\n if (!nets)\n return;\n const rails = nets.filter((net) =\u003e index.isRail(net));\n if (rails.length !== 1)\n return;\n const supplyNet = rails[0];\n if (!this.positiveNets.has(supplyNet) || index.groundNets.has(supplyNet))\n return;\n const tap = nets.find((net) =\u003e net !== supplyNet);\n const tapPorts = index.portsByNet.get(tap) ?? [];\n const resistorIds = new Set(tapPorts.filter((port) =\u003e index.components.get(port.source_component_id)?.ftype === \"simple_resistor\").map((port) =\u003e port.source_component_id));\n if (resistorIds.size !== 2)\n return;\n const groundId = [...resistorIds].find((id) =\u003e id !== supplyId);\n if (!this.isResistor(groundId))\n return;\n const groundNets = index.twoTerminalNets(groundId);\n const groundNet = groundNets?.find((net) =\u003e net !== tap);\n if (!groundNets?.includes(tap) || !groundNet || !index.groundNets.has(groundNet) || index.powerNets.has(groundNet) || !tapPorts.some((port) =\u003e !resistorIds.has(port.source_component_id)))\n return;\n const supply = index.placement(supplyId);\n const ground = index.placement(groundId);\n if (!supply || !ground || !index.sameLocalScope(supply, ground))\n return;\n const supplyTap = this.getDownwardResistorPorts(supplyId, supplyNet, tap);\n const groundTap = this.getDownwardResistorPorts(groundId, tap, groundNet);\n if (!supplyTap || !groundTap)\n return;\n const reversedBodyGap = ground.schY - ground.height / 2 - (supply.schY + supply.height / 2);\n if (reversedBodyGap \u003c= 1.5)\n return;\n this.params.issues.push({\n lineItemType: \"VoltageDividerSupplyResistorBelowGroundResistor\",\n supplyResistorSchematicBox: supply,\n groundResistorSchematicBox: ground,\n supplyTapSourcePortId: supplyTap.bottom.source_port_id,\n groundTapSourcePortId: groundTap.top.source_port_id,\n reversedBodyGap,\n message: `Place ${supply.sourceComponentName ?? supplyId} above ${ground.sourceComponentName ?? groundId}, close enough to read their shared divider tap. Preserve all connections and leave room for labels; exact alignment is not required.`\n });\n }\n isResistor(id) {\n const component = this.index.components.get(id);\n return component?.ftype === \"simple_resistor\" \u0026\u0026 Number.isFinite(component.resistance) \u0026\u0026 component.resistance \u003e 0;\n }\n getDownwardResistorPorts(id, topNet, bottomNet) {\n const index = this.index;\n const placement = index.placement(id);\n const ports = index.portsByComponent.get(id);\n if (ports.some((port) =\u003e port.do_not_connect))\n return;\n const top = ports.find((port) =\u003e index.connected(port.source_port_id) === topNet);\n const bottom = ports.find((port) =\u003e index.connected(port.source_port_id) === bottomNet);\n if (!top || !bottom)\n return;\n const topPin = index.port(top);\n const bottomPin = index.port(bottom);\n if (!topPin || !bottomPin || topPin.schematic_sheet_id !== placement.schematicSheetId || bottomPin.schematic_sheet_id !== placement.schematicSheetId || topPin.facing_direction !== \"up\" || bottomPin.facing_direction !== \"down\" || topPin.center.y \u003c= bottomPin.center.y)\n return;\n return { top, bottom };\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"supplyResistorName\", issue.supplyResistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"groundResistorName\", issue.groundResistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"reversedBodyGap\", issue.reversedBodyGap);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cVoltageDividerSupplyResistorBelowGroundResistor ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/RegulatorInputOutputCapacitorPlacementSolver/RegulatorInputOutputCapacitorPlacementSolver.ts\nclass RegulatorInputOutputCapacitorPlacementSolver extends BaseSolver {\n params;\n index;\n hostIds;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n this.index = new PlacementNetworkIndex(params.ctx);\n this.hostIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_chip\").map((component) =\u003e component.source_component_id);\n this.solved = this.hostIds.length === 0;\n }\n _step() {\n const hostId = this.hostIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.hostIds.length;\n if (!hostId)\n return;\n const index = this.index;\n const host = index.placement(hostId);\n const ports = index.portsByComponent.get(hostId) ?? [];\n if (!host || ports.some((port) =\u003e !portRole(port)))\n return;\n const inputs = ports.filter((port) =\u003e portRole(port) === \"input\");\n const outputs = ports.filter((port) =\u003e portRole(port) === \"output\");\n const grounds = ports.filter((port) =\u003e portRole(port) === \"ground\");\n if (inputs.length !== 1 || outputs.length !== 1 || !grounds.length)\n return;\n const input = inputs[0];\n const output = outputs[0];\n if ([input, output, ...grounds].some((port) =\u003e port.do_not_connect))\n return;\n const inputNet = index.connected(input.source_port_id);\n const outputNet = index.connected(output.source_port_id);\n const groundNets = new Set(grounds.map((port) =\u003e index.connected(port.source_port_id)));\n if (groundNets.size !== 1)\n return;\n const groundNet = [...groundNets][0];\n if (new Set([inputNet, outputNet, groundNet]).size !== 3 || !(index.groundNets.has(groundNet) || grounds.some((port) =\u003e port.requires_ground || port.provides_ground)) || !(index.powerNets.has(inputNet) || input.requires_power) || !(index.powerNets.has(outputNet) || output.provides_power))\n return;\n const inputPin = index.port(input);\n const outputPin = index.port(output);\n if (!inputPin || !outputPin || inputPin.schematic_sheet_id !== host.schematicSheetId || outputPin.schematic_sheet_id !== host.schematicSheetId)\n return;\n const horizontal = inputPin.facing_direction === \"left\" \u0026\u0026 outputPin.facing_direction === \"right\" || inputPin.facing_direction === \"right\" \u0026\u0026 outputPin.facing_direction === \"left\";\n const vertical = inputPin.facing_direction === \"up\" \u0026\u0026 outputPin.facing_direction === \"down\" || inputPin.facing_direction === \"down\" \u0026\u0026 outputPin.facing_direction === \"up\";\n if (!horizontal \u0026\u0026 !vertical)\n return;\n const sign = outputPin.facing_direction === \"right\" || outputPin.facing_direction === \"up\" ? 1 : -1;\n const pinSeparation = sign * (horizontal ? outputPin.center.x - inputPin.center.x : outputPin.center.y - inputPin.center.y);\n if (pinSeparation \u003c= 0.01)\n return;\n const inputCap = this.localCapacitor(host, inputNet, groundNet);\n const outputCap = this.localCapacitor(host, outputNet, groundNet);\n if (!inputCap || !outputCap)\n return;\n const beyondOppositeSide = (cap, side) =\u003e {\n const distance = side * sign * (horizontal ? cap.schX - host.schX : cap.schY - host.schY);\n const halfBodies = horizontal ? (host.width + cap.width) / 2 : (host.height + cap.height) / 2;\n return distance \u003e halfBodies + 0.2;\n };\n if (!beyondOppositeSide(inputCap, 1) || !beyondOppositeSide(outputCap, -1))\n return;\n const name = host.sourceComponentName ?? hostId;\n this.params.issues.push({\n lineItemType: \"RegulatorCapacitorsOnWrongSides\",\n regulatorSchematicBox: host,\n inputCapacitorSchematicBox: inputCap,\n outputCapacitorSchematicBox: outputCap,\n inputSourcePortId: input.source_port_id,\n outputSourcePortId: output.source_port_id,\n message: `Place ${inputCap.sourceComponentName} near ${name}.${input.name} on the ${inputPin.facing_direction} side and ${outputCap.sourceComponentName} near ${name}.${output.name} on the ${outputPin.facing_direction} side. Preserve all connections and leave room for labels; exact alignment is not required.`\n });\n }\n localCapacitor(host, rail, ground) {\n const index = this.index;\n const candidates = [];\n const maxDistance = Math.max(6, 4 * Math.max(host.width, host.height));\n const ids = new Set((index.portsByNet.get(rail) ?? []).map((port) =\u003e port.source_component_id));\n for (const id of ids) {\n if (index.components.get(id)?.ftype !== \"simple_capacitor\")\n continue;\n const nets = index.twoTerminalNets(id);\n const cap = index.placement(id);\n if (!nets?.includes(ground) || !cap || !index.sameLocalScope(host, cap))\n continue;\n if (Math.hypot(cap.schX - host.schX, cap.schY - host.schY) \u003e maxDistance)\n continue;\n const ports = index.portsByComponent.get(id);\n if (ports.some((port) =\u003e port.do_not_connect || !index.port(port) || index.port(port).schematic_sheet_id !== host.schematicSheetId))\n continue;\n candidates.push(cap);\n }\n return candidates.length === 1 ? candidates[0] : undefined;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"regulatorName\", issue.regulatorSchematicBox.sourceComponentName);\n addAttr(attrs, \"inputCapacitorName\", issue.inputCapacitorSchematicBox.sourceComponentName);\n addAttr(attrs, \"outputCapacitorName\", issue.outputCapacitorSchematicBox.sourceComponentName);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cRegulatorCapacitorsOnWrongSides ${attrs.join(\" \")} /\u003e`;\n }\n}\nfunction portRole(port) {\n const roles = new Set;\n for (const hint of [port.name, ...port.port_hints ?? []]) {\n const name = hint.toUpperCase().replace(/[ _-]/g, \"\");\n if (/^(?:VIN|IN|INPUT)$/.test(name))\n roles.add(\"input\");\n else if (/^(?:VOUT|OUT|OUTPUT)$/.test(name))\n roles.add(\"output\");\n else if (/^(?:GND\\d*|VSS)$/.test(name))\n roles.add(\"ground\");\n else if (/^(?:EN|ENABLE|CE|SHDN|NC\\d*|EP|PAD|ADJ|FB|BYP|BYPASS|NR|PG|PGOOD)$/.test(name))\n roles.add(\"control\");\n }\n return roles.size === 1 ? [...roles][0] : undefined;\n}\n\n// ../../work/placement-analysis/lib/utils/geometry.ts\nfunction centeredRect(cx, cy, w, h) {\n return {\n left: cx - w / 2,\n right: cx + w / 2,\n top: cy + h / 2,\n bottom: cy - h / 2\n };\n}\nfunction rectOverlap(a, b) {\n const ow = Math.min(a.right, b.right) - Math.max(a.left, b.left);\n const oh = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);\n return ow \u003e 0 \u0026\u0026 oh \u003e 0 ? { ow, oh } : null;\n}\n\n// ../../work/placement-analysis/lib/solvers/ConnectorPlacementSolver/ConnectorPlacementSolver.ts\nvar EPSILON2 = 0.01;\nvar directions = {\n right: { x: 1, y: 0 },\n left: { x: -1, y: 0 },\n up: { x: 0, y: 1 },\n down: { x: 0, y: -1 }\n};\nvar dot = (a, b) =\u003e a.x * b.x + a.y * b.y;\nvar distance = (a, b) =\u003e Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\nvar near = (a, b) =\u003e distance(a, b) \u003c= EPSILON2;\nvar round2 = (value) =\u003e Math.round(value * 100) / 100;\n\nclass ConnectorPlacementSolver extends BaseSolver {\n params;\n constructor(params) {\n super();\n this.params = params;\n }\n _step() {\n const { ctx, issues } = this.params;\n const index = new PlacementNetworkIndex(ctx);\n for (const ports of index.portsByComponent.values()) {\n for (const port of ports) {\n const net = index.connected(port.source_port_id);\n if (port.requires_ground || port.provides_ground)\n index.groundNets.add(net);\n if (port.requires_power || port.provides_power)\n index.powerNets.add(net);\n }\n }\n const allTraces = ctx.circuitJson.filter((e) =\u003e e.type === \"schematic_trace\");\n for (const [id, source] of index.components) {\n if (source.ftype !== \"simple_pin_header\" \u0026\u0026 source.ftype !== \"simple_connector\")\n continue;\n const connector = index.placement(id);\n const sourcePorts = index.portsByComponent.get(id) ?? [];\n if (!connector || sourcePorts.length \u003c 2)\n continue;\n const pins = sourcePorts.map((p) =\u003e index.port(p));\n const facing = pins[0]?.facing_direction;\n if (!facing || pins.some((p) =\u003e !p || p.facing_direction !== facing))\n continue;\n const along = directions[facing];\n const across = { x: -along.y, y: along.x };\n const traces = allTraces.filter((t) =\u003e t.schematic_sheet_id === connector.schematicSheetId);\n const railLabels = ctx.circuitJson.filter((e) =\u003e e.type === \"schematic_net_label\" \u0026\u0026 e.schematic_sheet_id === connector.schematicSheetId);\n const connections = [];\n let ambiguous = false;\n for (const sourcePort of sourcePorts) {\n const pin = index.port(sourcePort);\n const net = index.connected(sourcePort.source_port_id);\n const peers = (index.portsByNet.get(net) ?? []).filter((p) =\u003e p.source_port_id !== sourcePort.source_port_id);\n const incidentTraces = traces.filter((t) =\u003e t.edges.some((edge) =\u003e near(edge.from, pin.center) || near(edge.to, pin.center)));\n if (index.isRail(net)) {\n if (incidentTraces.some((t) =\u003e !railLabels.some((label) =\u003e label.anchor_position \u0026\u0026 joins(t, pin.center, label.anchor_position))))\n ambiguous = true;\n continue;\n }\n if (peers.length === 0) {\n if (incidentTraces.length \u003e 0)\n ambiguous = true;\n continue;\n }\n const peer = peers.length === 1 ? index.port(peers[0]) : undefined;\n const component = peers.length === 1 ? index.placement(peers[0].source_component_id) : undefined;\n if (!peer?.facing_direction || !component || !index.sameLocalScope(connector, component) || dot(directions[peer.facing_direction], along) !== -1) {\n ambiguous = true;\n break;\n }\n connections.push({ pin, peer, component });\n }\n if (ambiguous || connections.length \u003c 2)\n continue;\n if (connections.some((c) =\u003e dot(c.peer.center, along) \u003e= dot(c.pin.center, along) - 2))\n continue;\n const detouredConnections = connections.map((c) =\u003e traces.filter((t) =\u003e joins(t, c.pin.center, c.peer.center) \u0026\u0026 bendCount(t) \u003e= 3)).filter((t) =\u003e t.length \u003e 0);\n if (detouredConnections.length \u003c 2)\n continue;\n const detours = detouredConnections.flat();\n const ordered = [...connections].sort((a, b) =\u003e dot(a.pin.center, across) - dot(b.pin.center, across));\n if (ordered.some((c, i) =\u003e i \u003e 0 \u0026\u0026 dot(c.peer.center, across) \u003c= dot(ordered[i - 1].peer.center, across) + EPSILON2))\n continue;\n const center = { x: connector.schX, y: connector.schY };\n const pinOffset = Math.max(...connections.map((c) =\u003e dot(c.pin.center, along) - dot(center, along)));\n const targetAlong = Math.min(...connections.map((c) =\u003e dot(c.peer.center, along))) - 2 - pinOffset;\n const offsets = connections.map((c) =\u003e dot(c.peer.center, across) - dot(c.pin.center, across) + dot(center, across)).sort((a, b) =\u003e a - b);\n const targetAcross = offsets[Math.floor(offsets.length / 2)];\n const target = {\n x: round2(along.x * targetAlong + across.x * targetAcross),\n y: round2(along.y * targetAlong + across.y * targetAcross)\n };\n const delta = { x: target.x - center.x, y: target.y - center.y };\n const movedPin = (pin) =\u003e ({\n x: pin.center.x + delta.x,\n y: pin.center.y + delta.y\n });\n if (connections.some((c) =\u003e distance(movedPin(c.pin), c.peer.center) \u003e distance(c.pin.center, c.peer.center) + EPSILON2))\n continue;\n const before = connections.reduce((sum, c) =\u003e sum + distance(c.pin.center, c.peer.center), 0);\n const after = connections.reduce((sum, c) =\u003e sum + distance(movedPin(c.pin), c.peer.center), 0);\n if (before - after \u003c 4 || after \u003e before * 0.75)\n continue;\n const obstacles = ctx.componentPlacements.filter((p) =\u003e p.schematicSheetId === connector.schematicSheetId \u0026\u0026 p.schematicComponentId !== connector.schematicComponentId);\n const targetBounds = centeredRect(target.x, target.y, connector.width + 0.4, connector.height + 0.4);\n if (obstacles.some((p) =\u003e rectOverlap(targetBounds, centeredRect(p.schX, p.schY, p.width, p.height))))\n continue;\n if (connections.some((c) =\u003e {\n const start = movedPin(c.pin);\n const end = c.peer.center;\n const middleAlong = (dot(start, along) + dot(end, along)) / 2;\n const points = [\n start,\n {\n x: along.x * middleAlong + across.x * dot(start, across),\n y: along.y * middleAlong + across.y * dot(start, across)\n },\n {\n x: along.x * middleAlong + across.x * dot(end, across),\n y: along.y * middleAlong + across.y * dot(end, across)\n },\n end\n ];\n return obstacles.some((p) =\u003e p.schematicComponentId !== c.component.schematicComponentId \u0026\u0026 points.slice(1).some((point, i) =\u003e segmentCrossesBox(points[i], point, p)));\n }))\n continue;\n const connectedComponents = [\n ...new Map(connections.map((c) =\u003e [\n c.component.schematicComponentId,\n c.component\n ])).values()\n ];\n const name = connector.sourceComponentName ?? connector.schematicComponentId;\n issues.push({\n lineItemType: \"ConnectorPositionCausesTraceDetours\",\n connectorSchematicBox: connector,\n connectedComponents,\n schematicTraceIds: [\n ...new Set(detours.map((t) =\u003e t.schematic_trace_id))\n ],\n evaluatedSignalCount: connections.length,\n newSchX: target.x,\n newSchY: target.y,\n deltaSchX: round2(delta.x),\n deltaSchY: round2(delta.y),\n currentTotalSignalDistance: round2(before),\n suggestedTotalSignalDistance: round2(after),\n message: `Move ${name} to schX=${target.x}, schY=${target.y} so its signal pins face ${connectedComponents.map((p) =\u003e p.sourceComponentName ?? p.schematicComponentId).join(\", \")}. Preserve rotation and pin assignments; reroute the connections and attached rail labels.`\n });\n }\n this.solved = true;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"connectorComponentName\", issue.connectorSchematicBox.sourceComponentName);\n addAttr(attrs, \"connectedComponents\", issue.connectedComponents.map((p) =\u003e p.sourceComponentName ?? p.schematicComponentId).join(\",\"));\n for (const key of [\n \"evaluatedSignalCount\",\n \"newSchX\",\n \"newSchY\",\n \"deltaSchX\",\n \"deltaSchY\",\n \"currentTotalSignalDistance\",\n \"suggestedTotalSignalDistance\"\n ])\n addAttr(attrs, key, issue[key]);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cConnectorPositionCausesTraceDetours ${attrs.join(\" \")} /\u003e`;\n }\n}\nfunction joins(trace, a, b) {\n const first = trace.edges[0]?.from;\n const last = trace.edges.at(-1)?.to;\n return !!first \u0026\u0026 !!last \u0026\u0026 (near(first, a) \u0026\u0026 near(last, b) || near(first, b) \u0026\u0026 near(last, a));\n}\nfunction bendCount(trace) {\n let previousAxis;\n let bends = 0;\n for (let i = 0;i \u003c trace.edges.length; i++) {\n const edge = trace.edges[i];\n if (i \u003e 0 \u0026\u0026 !near(trace.edges[i - 1].to, edge.from))\n return 0;\n if (near(edge.from, edge.to))\n continue;\n const axis = Math.abs(edge.from.y - edge.to.y) \u003c EPSILON2 ? \"x\" : Math.abs(edge.from.x - edge.to.x) \u003c EPSILON2 ? \"y\" : undefined;\n if (!axis)\n return 0;\n if (previousAxis \u0026\u0026 previousAxis !== axis)\n bends++;\n previousAxis = axis;\n }\n return bends;\n}\nfunction segmentCrossesBox(a, b, box) {\n const bounds = centeredRect(box.schX, box.schY, box.width + 0.2, box.height + 0.2);\n return Math.max(a.x, b.x) \u003e bounds.left \u0026\u0026 Math.min(a.x, b.x) \u003c bounds.right \u0026\u0026 Math.max(a.y, b.y) \u003e bounds.bottom \u0026\u0026 Math.min(a.y, b.y) \u003c bounds.top;\n}\n\n// ../../work/placement-analysis/lib/solvers/LowSideTransistorPlacementSolver/LowSideTransistorPlacementSolver.ts\nclass LowSideTransistorPlacementSolver extends BaseSolver {\n index;\n positiveNets = new Set;\n transistorIds;\n issues;\n currentIndex = 0;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.issues = issues;\n this.index = new PlacementNetworkIndex(ctx);\n for (const element of ctx.circuitJson) {\n if (element.type === \"source_net\" \u0026\u0026 element.is_positive_voltage_source)\n this.positiveNets.add(this.index.connected(element.source_net_id));\n }\n this.transistorIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_transistor\" \u0026\u0026 component.transistor_type === \"npn\").map((component) =\u003e component.source_component_id);\n this.solved = this.transistorIds.length === 0;\n }\n _step() {\n const id = this.transistorIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.transistorIds.length;\n if (!id)\n return;\n const index = this.index;\n const transistor = index.placement(id);\n if (!transistor || index.portsByComponent.get(id)?.length !== 3)\n return;\n const base = index.namedPort(id, \"base\");\n const collector = index.namedPort(id, \"collector\");\n const emitter = index.namedPort(id, \"emitter\");\n if (!base || !collector || !emitter)\n return;\n const baseNet = index.connected(base.source_port_id);\n const collectorNet = index.connected(collector.source_port_id);\n const emitterNet = index.connected(emitter.source_port_id);\n if (new Set([baseNet, collectorNet, emitterNet]).size !== 3 || !index.groundNets.has(emitterNet) || index.powerNets.has(emitterNet) || index.isRail(baseNet) || index.isRail(collectorNet))\n return;\n const basePeers = (index.portsByNet.get(baseNet) ?? []).filter((port) =\u003e port.source_component_id !== id);\n if (basePeers.length !== 1)\n return;\n const resistorId = basePeers[0].source_component_id;\n const resistor = index.components.get(resistorId);\n const baseResistor = index.placement(resistorId);\n const resistorNets = index.twoTerminalNets(resistorId);\n const inputNet = resistorNets?.find((net) =\u003e net !== baseNet);\n if (resistor?.ftype !== \"simple_resistor\" || resistor.resistance \u003c= 0 || !baseResistor || !index.sameLocalScope(transistor, baseResistor) || !inputNet || index.isRail(inputNet) || inputNet === collectorNet)\n return;\n const collectorPeers = (index.portsByNet.get(collectorNet) ?? []).filter((port) =\u003e port.source_component_id !== id);\n const loadPeers = collectorPeers.filter((port) =\u003e {\n const type = index.components.get(port.source_component_id)?.ftype;\n return type === \"simple_chip\";\n });\n if (loadPeers.length !== 1)\n return;\n const loadId = loadPeers[0].source_component_id;\n const load = index.placement(loadId);\n const loadNets = index.twoTerminalNets(loadId);\n const supplyNet = loadNets?.find((net) =\u003e net !== collectorNet);\n if (!load || !index.sameLocalScope(transistor, load) || !supplyNet || !this.positiveNets.has(supplyNet) || index.groundNets.has(supplyNet))\n return;\n const clampPeers = collectorPeers.filter((port) =\u003e port.source_component_id !== loadId);\n if (clampPeers.length !== 1)\n return;\n const clampId = clampPeers[0].source_component_id;\n const clamp = index.placement(clampId);\n const anode = index.namedPort(clampId, \"anode\");\n const cathode = index.namedPort(clampId, \"cathode\");\n if (index.components.get(clampId)?.ftype !== \"simple_diode\" || !index.twoTerminalNets(clampId) || !anode || !cathode || index.connected(anode.source_port_id) !== collectorNet || index.connected(cathode.source_port_id) !== supplyNet || !clamp || !index.sameLocalScope(transistor, clamp))\n return;\n const collectorPin = index.port(collector);\n const emitterPin = index.port(emitter);\n const basePin = index.port(base);\n if (!collectorPin || !emitterPin || !basePin)\n return;\n const collectorFacingDirection = collectorPin.facing_direction;\n const emitterFacingDirection = emitterPin.facing_direction;\n if (!collectorFacingDirection || !emitterFacingDirection)\n return;\n const placementProblems = [];\n if (transistor.schY \u003e= load.schY)\n placementProblems.push(\"transistor_not_below_load\");\n if (collectorFacingDirection !== \"up\")\n placementProblems.push(\"collector_not_up\");\n if (emitterFacingDirection !== \"down\")\n placementProblems.push(\"emitter_not_down\");\n if (placementProblems.length === 0)\n return;\n const name = transistor.sourceComponentName ?? id;\n const loadName = load.sourceComponentName ?? loadId;\n this.issues.push({\n lineItemType: \"LowSideTransistorNotAlignedWithLoad\",\n transistorSchematicBox: transistor,\n loadSchematicBox: load,\n baseResistorSchematicBox: baseResistor,\n clampDiodeSchematicBox: clamp,\n collectorSourcePortId: collector.source_port_id,\n emitterSourcePortId: emitter.source_port_id,\n collectorFacingDirection,\n emitterFacingDirection,\n placementProblems,\n message: `Arrange ${name} below ${loadName}, with its collector facing up toward the load and emitter facing down toward ground; place ${baseResistor.sourceComponentName ?? resistorId} beside the base. Preserve all pin connections and reroute affected traces.`\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"transistorName\", issue.transistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"loadName\", issue.loadSchematicBox.sourceComponentName);\n addAttr(attrs, \"baseResistorName\", issue.baseResistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"clampDiodeName\", issue.clampDiodeSchematicBox.sourceComponentName);\n addAttr(attrs, \"placementProblems\", issue.placementProblems.join(\",\"));\n addAttr(attrs, \"collectorFacingDirection\", issue.collectorFacingDirection);\n addAttr(attrs, \"emitterFacingDirection\", issue.emitterFacingDirection);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cLowSideTransistorNotAlignedWithLoad ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/UsbSeriesResistorPlacementSolver/UsbSeriesResistorPlacementSolver.ts\nclass UsbSeriesResistorPlacementSolver extends BaseSolver {\n params;\n index;\n hostIds;\n reportedPairs = new Set;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n this.index = new PlacementNetworkIndex(params.ctx);\n this.hostIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_chip\").map((component) =\u003e component.source_component_id);\n this.solved = this.hostIds.length === 0;\n }\n _step() {\n const hostId = this.hostIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.hostIds.length;\n if (!hostId)\n return;\n const ports = this.index.portsByComponent.get(hostId) ?? [];\n const positivePorts = ports.filter((port) =\u003e usbRole(port) === \"positive\");\n const negativePorts = ports.filter((port) =\u003e usbRole(port) === \"negative\");\n if (positivePorts.length !== 1 || negativePorts.length !== 1)\n return;\n const positivePort = positivePorts[0];\n const negativePort = negativePorts[0];\n const positive = this.seriesResistor(positivePort);\n const negative = this.seriesResistor(negativePort);\n if (!positive || !negative || positive.axis !== negative.axis || !this.index.sameLocalScope(positive.placement, negative.placement) || new Set([\n positive.hostNet,\n negative.hostNet,\n positive.interfaceNet,\n negative.interfaceNet\n ]).size !== 4 || !this.shareInterface(positive, negative, hostId))\n return;\n const pairKey = [positive.id, negative.id].sort().join(\"\\x00\");\n if (this.reportedPairs.has(pairKey))\n return;\n const a = positive.placement;\n const b = negative.placement;\n const horizontal = positive.axis === \"horizontal\";\n const along = Math.abs(horizontal ? a.schX - b.schX : a.schY - b.schY);\n const across = Math.abs(horizontal ? a.schY - b.schY : a.schX - b.schX);\n const alongA = horizontal ? a.width : a.height;\n const alongB = horizontal ? b.width : b.height;\n const acrossA = horizontal ? a.height : a.width;\n const acrossB = horizontal ? b.height : b.width;\n const bodyGap2 = along - (alongA + alongB) / 2;\n if (bodyGap2 \u003c Math.max(alongA, alongB) || across \u003e= (acrossA + acrossB) / 2 - 0.01)\n return;\n this.reportedPairs.add(pairKey);\n const positiveName = a.sourceComponentName ?? positive.id;\n const negativeName = b.sourceComponentName ?? negative.id;\n this.params.issues.push({\n lineItemType: \"UsbSeriesResistorsNotAligned\",\n positiveResistorSchematicBox: a,\n negativeResistorSchematicBox: b,\n hostSourceComponentId: hostId,\n positiveSourcePortId: positivePort.source_port_id,\n negativeSourcePortId: negativePort.source_port_id,\n signalAxis: positive.axis,\n message: `Place ${positiveName} (D+) and ${negativeName} (D−) near each other and draw clear traces to their corresponding USB ports. Exact alignment is not required; preserve pin assignments and leave space for labels.`\n });\n }\n seriesResistor(hostPort) {\n const index = this.index;\n const hostNet = index.connected(hostPort.source_port_id);\n if (index.isRail(hostNet))\n return;\n const candidates = new Set((index.portsByNet.get(hostNet) ?? []).filter((port) =\u003e index.components.get(port.source_component_id)?.ftype === \"simple_resistor\").map((port) =\u003e port.source_component_id));\n if (candidates.size !== 1)\n return;\n const id = [...candidates][0];\n const nets = index.twoTerminalNets(id);\n const interfaceNet = nets?.find((net) =\u003e net !== hostNet);\n const placement = index.placement(id);\n if (!interfaceNet || index.isRail(interfaceNet) || !placement)\n return;\n if ((index.portsByNet.get(interfaceNet) ?? []).some((port) =\u003e port.source_component_id !== id \u0026\u0026 index.components.get(port.source_component_id)?.ftype === \"simple_resistor\"))\n return;\n const pins = index.portsByComponent.get(id).map((port) =\u003e index.port(port));\n const [first, second] = pins;\n if (!first || !second)\n return;\n const facing = new Set([first.facing_direction, second.facing_direction]);\n let axis;\n if (facing.has(\"left\") \u0026\u0026 facing.has(\"right\") \u0026\u0026 Math.abs(first.center.y - second.center.y) \u003c 0.01)\n axis = \"horizontal\";\n else if (facing.has(\"up\") \u0026\u0026 facing.has(\"down\") \u0026\u0026 Math.abs(first.center.x - second.center.x) \u003c 0.01)\n axis = \"vertical\";\n else\n return;\n return { id, placement, hostNet, interfaceNet, axis };\n }\n shareInterface(positive, negative, hostId) {\n const peerIds = (net) =\u003e new Set((this.index.portsByNet.get(net) ?? []).map((port) =\u003e port.source_component_id).filter((id) =\u003e id !== hostId \u0026\u0026 id !== positive.id \u0026\u0026 id !== negative.id \u0026\u0026 (this.index.portsByComponent.get(id)?.length ?? 0) \u003e 2));\n const positivePeers = peerIds(positive.interfaceNet);\n return [...peerIds(negative.interfaceNet)].some((id) =\u003e positivePeers.has(id));\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"positiveResistorName\", issue.positiveResistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"negativeResistorName\", issue.negativeResistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"signalAxis\", issue.signalAxis);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cUsbSeriesResistorsNotAligned ${attrs.join(\" \")} /\u003e`;\n }\n}\nfunction usbRole(port) {\n const roles = new Set;\n for (const hint of [port.name, ...port.port_hints ?? []]) {\n const name = hint.toUpperCase();\n if (/^(?:USB_?)?D(?:P|\\+|_POS)$/.test(name))\n roles.add(\"positive\");\n if (/^(?:USB_?)?D(?:M|N|-|_NEG)$/.test(name))\n roles.add(\"negative\");\n }\n return roles.size === 1 ? [...roles][0] : undefined;\n}\n\n// ../../work/placement-analysis/lib/utils/graphics.ts\nfunction mergeGraphicsObjects(objects) {\n return objects.filter((o) =\u003e o !== undefined).reduce((acc, o) =\u003e mergeGraphics(acc, o), {});\n}\nfunction highlightPlacement(placement, color, label) {\n return {\n rects: [\n {\n center: { x: placement.schX, y: placement.schY },\n width: placement.width,\n height: placement.height,\n stroke: color,\n fill: color.replace(\"0.95\", \"0.15\"),\n label\n }\n ]\n };\n}\nfunction visualizeCircuitJson(circuitJson) {\n const rects = circuitJson.filter((el) =\u003e el.type === \"schematic_box\").map((el) =\u003e {\n const box = el;\n return {\n center: { x: box.x, y: box.y },\n width: box.width,\n height: box.height,\n stroke: \"hsl(0,0%,60%)\"\n };\n });\n return { rects };\n}\n\n// ../../work/placement-analysis/lib/solvers/CapacitorOrientationSolver/CapacitorOrientationSolver.ts\nclass CapacitorOrientationSolver extends BaseSolver {\n static EPSILON = 0.01;\n static ORIENTATION_MESSAGE = 'Use schOrientation=\"vertical\" on this capacitor to fix the symbol orientation';\n ctx;\n out;\n schematicComponentById;\n sourceComponentById;\n capacitorPlacements;\n feedbackCapacitorIds;\n currentPlacementIndex = 0;\n horizontalSymbolNames = new Set([\n \"capacitor_left\",\n \"capacitor_right\"\n ]);\n constructor({\n ctx,\n issues: out\n }) {\n super();\n this.ctx = ctx;\n this.out = out;\n this.schematicComponentById = this.buildSchematicComponentById(ctx.circuitJson);\n this.sourceComponentById = this.buildSourceComponentById(ctx.circuitJson);\n this.capacitorPlacements = this.getCapacitorPlacements();\n const networks = new PlacementNetworkIndex(ctx);\n this.feedbackCapacitorIds = new Set(this.capacitorPlacements.flatMap((capacitor) =\u003e capacitor.sourceComponentId \u0026\u0026 networks.isDirectOpAmpFeedback(capacitor.sourceComponentId) ? [capacitor.sourceComponentId] : []));\n this.solved = this.capacitorPlacements.length === 0;\n }\n getCapacitorPlacements() {\n return this.ctx.componentPlacements.filter((p) =\u003e p.sourceComponentId !== undefined \u0026\u0026 this.sourceComponentById.get(p.sourceComponentId)?.ftype === \"simple_capacitor\").map((p) =\u003e ({\n schX: p.schX,\n schY: p.schY,\n width: p.width,\n height: p.height,\n sourceComponentId: p.sourceComponentId,\n sourceComponentName: p.sourceComponentName,\n schematicComponentId: p.schematicComponentId,\n schematicSheetId: p.schematicSheetId,\n schematicSheetName: p.schematicSheetName\n }));\n }\n _step() {\n const currentPlacement = this.capacitorPlacements[this.currentPlacementIndex];\n if (!currentPlacement) {\n this.solved = true;\n return;\n }\n this.currentPlacementIndex += 1;\n this.solved = this.currentPlacementIndex \u003e= this.capacitorPlacements.length;\n const issue = this.getIssueForPlacement(currentPlacement);\n if (issue)\n this.out.push(issue);\n }\n visualize() {\n const focusedPlacement = this.getFocusedPlacement();\n return mergeGraphicsObjects([\n visualizeCircuitJson(this.ctx.circuitJson),\n focusedPlacement ? highlightPlacement(focusedPlacement, \"hsl(210, 100%, 50%, 0.95)\", \"capacitorOrientation\") : undefined\n ]);\n }\n getFocusedPlacement() {\n if (this.capacitorPlacements.length === 0)\n return;\n const index = this.iterations === 0 ? this.currentPlacementIndex : Math.max(0, this.currentPlacementIndex - 1);\n return this.capacitorPlacements[index];\n }\n buildSchematicComponentById(circuitJson) {\n return new Map(circuitJson.filter((el) =\u003e el.type === \"schematic_component\").map((sc) =\u003e [sc.schematic_component_id, sc]));\n }\n buildSourceComponentById(circuitJson) {\n return new Map(circuitJson.flatMap((el) =\u003e {\n if (el.type !== \"source_component\" || !(\"source_component_id\" in el) || typeof el.source_component_id !== \"string\")\n return [];\n return [\n {\n type: \"source_component\",\n source_component_id: el.source_component_id,\n ftype: \"ftype\" in el \u0026\u0026 typeof el.ftype === \"string\" ? el.ftype : undefined\n }\n ];\n }).map((sc) =\u003e [sc.source_component_id, sc]));\n }\n createIssuePlacement(placement) {\n return {\n positionAnchor: \"center\",\n schX: placement.schX,\n schY: placement.schY,\n width: placement.width,\n height: placement.height,\n sourceComponentId: placement.sourceComponentId,\n sourceComponentName: placement.sourceComponentName,\n schematicComponentId: placement.schematicComponentId,\n schematicSheetId: placement.schematicSheetId,\n schematicSheetName: placement.schematicSheetName\n };\n }\n getIssueForPlacement(placement) {\n if (!placement.schematicComponentId || !placement.sourceComponentId)\n return;\n const schematicComponent = this.schematicComponentById.get(placement.schematicComponentId);\n if (!schematicComponent)\n return;\n if (!this.horizontalSymbolNames.has(schematicComponent.symbol_name ?? \"\"))\n return;\n if (this.feedbackCapacitorIds.has(placement.sourceComponentId))\n return;\n if (this.isInlineWithHorizontalTraces(placement.schematicComponentId))\n return;\n return {\n lineItemType: \"CapacitorSymbolHorizontal\",\n schematicBox: this.createIssuePlacement(placement),\n message: CapacitorOrientationSolver.ORIENTATION_MESSAGE\n };\n }\n isInlineWithHorizontalTraces(schematicComponentId) {\n const ports = this.ctx.circuitJson.filter((element) =\u003e element.type === \"schematic_port\" \u0026\u0026 element.schematic_component_id === schematicComponentId);\n if (ports.length !== 2)\n return false;\n const traces = ports.map((port) =\u003e this.getOutwardHorizontalTrace(port));\n return traces.every((trace) =\u003e trace !== undefined) \u0026\u0026 traces.some((trace) =\u003e trace !== undefined \u0026\u0026 trace.edges.every((edge) =\u003e Math.abs(edge.from.y - edge.to.y) \u003c= CapacitorOrientationSolver.EPSILON));\n }\n getOutwardHorizontalTrace(port) {\n if (port.facing_direction !== \"left\" \u0026\u0026 port.facing_direction !== \"right\")\n return;\n return this.ctx.circuitJson.find((element) =\u003e element.type === \"schematic_trace\" \u0026\u0026 element.schematic_sheet_id === port.schematic_sheet_id \u0026\u0026 element.edges.some((edge) =\u003e {\n const other = this.pointsEqual(edge.from, port.center) ? edge.to : this.pointsEqual(edge.to, port.center) ? edge.from : undefined;\n return other !== undefined \u0026\u0026 Math.abs(other.y - port.center.y) \u003c= CapacitorOrientationSolver.EPSILON \u0026\u0026 (port.facing_direction === \"left\" ? other.x \u003c port.center.x - CapacitorOrientationSolver.EPSILON : other.x \u003e port.center.x + CapacitorOrientationSolver.EPSILON);\n }));\n }\n pointsEqual(first, second) {\n return Math.abs(first.x - second.x) \u003c= CapacitorOrientationSolver.EPSILON \u0026\u0026 Math.abs(first.y - second.y) \u003c= CapacitorOrientationSolver.EPSILON;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"componentName\", issue.schematicBox.sourceComponentName);\n addAttr(attrs, \"schX\", issue.schematicBox.schX);\n addAttr(attrs, \"schY\", issue.schematicBox.schY);\n addAttr(attrs, \"width\", issue.schematicBox.width);\n addAttr(attrs, \"height\", issue.schematicBox.height);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cCapacitorSymbolHorizontal ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/DecouplingCapacitorGroupingSolver/DecouplingCapacitorGroupingSolver.ts\nclass DecouplingCapacitorGroupingSolver extends BaseSolver {\n params;\n static MIN_BODY_GAP = 4;\n banks = [];\n netNames = new Map;\n bankIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n const index = new PlacementNetworkIndex(params.ctx);\n const powerNets = new Set(index.powerNets);\n const groundNets = new Set(index.groundNets);\n for (const element of params.ctx.circuitJson) {\n if (element.type === \"source_net\") {\n const net = index.connected(element.source_net_id);\n if (!this.netNames.has(net))\n this.netNames.set(net, element.name);\n }\n }\n for (const ports of index.portsByComponent.values()) {\n for (const port of ports) {\n if (port.do_not_connect)\n continue;\n const net = index.connected(port.source_port_id);\n if (port.provides_power || port.requires_power)\n powerNets.add(net);\n if (port.provides_ground || port.requires_ground)\n groundNets.add(net);\n if ((powerNets.has(net) || groundNets.has(net)) \u0026\u0026 !this.netNames.has(net))\n this.netNames.set(net, port.name);\n }\n }\n for (const component of index.components.values()) {\n if (component.ftype !== \"simple_capacitor\")\n continue;\n const id = component.source_component_id;\n const placement = index.placement(id);\n const nets = index.twoTerminalNets(id);\n const ports = index.portsByComponent.get(id);\n if (!placement || !nets || !ports || ports.some((port) =\u003e {\n const schematicPort = index.port(port);\n return port.do_not_connect || !schematicPort || schematicPort.schematic_sheet_id !== placement.schematicSheetId;\n }))\n continue;\n const power = nets.find((net) =\u003e powerNets.has(net) \u0026\u0026 !groundNets.has(net));\n const ground = nets.find((net) =\u003e groundNets.has(net) \u0026\u0026 !powerNets.has(net));\n if (!power || !ground)\n continue;\n const bank = this.banks.find((candidate) =\u003e candidate.power === power \u0026\u0026 candidate.ground === ground \u0026\u0026 index.sameLocalScope(candidate.capacitors[0], placement));\n if (bank)\n bank.capacitors.push(placement);\n else\n this.banks.push({ power, ground, capacitors: [placement] });\n }\n this.solved = this.banks.length === 0;\n }\n _step() {\n const bank = this.banks[this.bankIndex++];\n this.solved = this.bankIndex \u003e= this.banks.length;\n if (bank.capacitors.length \u003c 2)\n return;\n const maxRecommendedBodyGap = Math.max(DecouplingCapacitorGroupingSolver.MIN_BODY_GAP, ...bank.capacitors.map((box) =\u003e 3 * Math.max(box.width, box.height)));\n let maxBodyGap = 0;\n for (let i = 0;i \u003c bank.capacitors.length; i++) {\n for (const b of bank.capacitors.slice(i + 1)) {\n const a = bank.capacitors[i];\n const gap = Math.hypot(Math.max(0, Math.abs(a.schX - b.schX) - (a.width + b.width) / 2), Math.max(0, Math.abs(a.schY - b.schY) - (a.height + b.height) / 2));\n maxBodyGap = Math.max(maxBodyGap, gap);\n }\n }\n if (maxBodyGap \u003c= maxRecommendedBodyGap + 0.000001)\n return;\n const railName = this.netNames.get(bank.power) ?? bank.power;\n const groundName = this.netNames.get(bank.ground) ?? bank.ground;\n this.params.issues.push({\n lineItemType: \"DecouplingCapacitorsNotCloseTogether\",\n railName,\n groundName,\n capacitorSchematicBoxes: bank.capacitors,\n maxBodyGap,\n maxRecommendedBodyGap,\n message: `Group the decoupling capacitors between ${railName} and ${groundName} closer together in this schematic block. Preserve their net connections.`\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"rail\", issue.railName);\n addAttr(attrs, \"ground\", issue.groundName);\n addAttr(attrs, \"capacitorNames\", issue.capacitorSchematicBoxes.map((box) =\u003e box.sourceComponentName ?? box.schematicComponentId).join(\", \"));\n addAttr(attrs, \"maxBodyGap\", issue.maxBodyGap);\n addAttr(attrs, \"maxRecommendedBodyGap\", issue.maxRecommendedBodyGap);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cDecouplingCapacitorsNotCloseTogether ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/utils/net-label-bounds.ts\nfunction getNetLabelBounds(label) {\n const anchorSide = label.anchor_side;\n const isVertical = anchorSide === \"top\" || anchorSide === \"bottom\";\n if (isVertical) {\n const anchorY = label.anchor_position?.y ?? label.center.y;\n const textHalfExtent = (label.text?.length ?? 8) * 0.13 / 2 + 0.1;\n const left = label.center.x - 0.1;\n const right = label.center.x + 0.1;\n if (anchorSide === \"top\") {\n return {\n left,\n right,\n top: anchorY,\n bottom: anchorY - textHalfExtent * 2\n };\n }\n return { left, right, top: anchorY + textHalfExtent * 2, bottom: anchorY };\n }\n const anchorX = label.anchor_position?.x ?? label.center.x;\n const halfWidth = Math.abs(label.center.x - anchorX);\n const farHalfWidth = halfWidth + 0.1;\n const top = label.center.y + 0.1;\n const bottom = label.center.y - 0.1;\n if (label.center.x \u003e= anchorX) {\n return {\n left: anchorX,\n right: label.center.x + farHalfWidth,\n top,\n bottom\n };\n }\n return { left: label.center.x - farHalfWidth, right: anchorX, top, bottom };\n}\n\n// ../../work/placement-analysis/lib/solvers/ComponentNetLabelCollisionSolver/ComponentNetLabelCollisionSolver.ts\nclass ComponentNetLabelCollisionSolver extends BaseSolver {\n params;\n placements;\n netLabelsByComponentId;\n rawCollisions = [];\n firstIndex = 0;\n secondIndex = 1;\n constructor(params) {\n super();\n this.params = params;\n this.placements = params.ctx.componentPlacements;\n this.netLabelsByComponentId = this.buildNetLabelsByComponentId(params.ctx.circuitJson);\n this.solved = this.placements.length \u003c 2;\n }\n _step() {\n if (this.firstIndex \u003e= this.placements.length - 1) {\n this.buildAndPushIssues();\n this.solved = true;\n return;\n }\n const compA = this.placements[this.firstIndex];\n const compB = this.placements[this.secondIndex];\n this.detectPair(compA, compB);\n this.secondIndex++;\n if (this.secondIndex \u003e= this.placements.length) {\n this.firstIndex++;\n this.secondIndex = this.firstIndex + 1;\n }\n }\n detectPair(compA, compB) {\n if (compA.schematicSheetId !== compB.schematicSheetId)\n return;\n this.rawCollisions.push(...this.detectLabelLabel(compA, compB));\n this.rawCollisions.push(...this.detectBoxLabel(compA, compB));\n this.rawCollisions.push(...this.detectBoxLabel(compB, compA));\n }\n detectLabelLabel(firstComponent, secondComponent) {\n let leftComp = firstComponent;\n let rightComp = secondComponent;\n if (firstComponent.schX \u003e secondComponent.schX) {\n leftComp = secondComponent;\n rightComp = firstComponent;\n }\n const leftId = leftComp.schematicComponentId;\n const rightId = rightComp.schematicComponentId;\n if (!leftId || !rightId)\n return [];\n const leftLabels = this.netLabelsByComponentId.get(leftId) ?? [];\n const rightLabels = this.netLabelsByComponentId.get(rightId) ?? [];\n if (leftLabels.length === 0 || rightLabels.length === 0)\n return [];\n const hits = [];\n for (const leftLabel of leftLabels) {\n for (const rightLabel of rightLabels) {\n const leftBounds = getNetLabelBounds(leftLabel);\n const rightBounds = getNetLabelBounds(rightLabel);\n if (rectOverlap(leftBounds, rightBounds)) {\n hits.push({\n type: \"label-label\",\n bounds: {\n left: Math.max(leftBounds.left, rightBounds.left),\n right: Math.min(leftBounds.right, rightBounds.right),\n top: Math.min(leftBounds.top, rightBounds.top),\n bottom: Math.max(leftBounds.bottom, rightBounds.bottom)\n },\n leftComp,\n rightComp,\n leftId,\n rightId,\n xSeparation: leftBounds.right - rightBounds.left + 0.1\n });\n }\n }\n }\n return hits;\n }\n detectBoxLabel(boxComp, labelComp) {\n const boxId = boxComp.schematicComponentId;\n const labelId = labelComp.schematicComponentId;\n if (!boxId || !labelId)\n return [];\n const labels = this.netLabelsByComponentId.get(labelId) ?? [];\n if (labels.length === 0)\n return [];\n const boxBounds = centeredRect(boxComp.schX, boxComp.schY, boxComp.width, boxComp.height);\n const boxIsLeft = boxComp.schX \u003c= labelComp.schX;\n const hits = [];\n for (const label of labels) {\n const labelBounds = getNetLabelBounds(label);\n if (!rectOverlap(boxBounds, labelBounds))\n continue;\n let xSeparation;\n if (boxIsLeft) {\n xSeparation = boxBounds.right - labelBounds.left + 0.1;\n } else {\n xSeparation = labelBounds.right - boxBounds.left + 0.1;\n }\n hits.push({\n type: \"box-label\",\n bounds: {\n left: Math.max(boxBounds.left, labelBounds.left),\n right: Math.min(boxBounds.right, labelBounds.right),\n top: Math.min(boxBounds.top, labelBounds.top),\n bottom: Math.max(boxBounds.bottom, labelBounds.bottom)\n },\n boxComp,\n labelComp,\n boxId,\n labelId,\n xSeparation\n });\n }\n return hits;\n }\n buildAndPushIssues() {\n if (this.rawCollisions.length === 0)\n return;\n const collisionsBySheet = new Map;\n for (const collision of this.rawCollisions) {\n const placement = collision.type === \"label-label\" ? collision.leftComp : collision.boxComp;\n const sheetKey = placement.schematicSheetId ?? \"\";\n const sheetCollisions = collisionsBySheet.get(sheetKey);\n if (sheetCollisions)\n sheetCollisions.push(collision);\n else\n collisionsBySheet.set(sheetKey, [collision]);\n }\n for (const collisions of collisionsBySheet.values()) {\n this.buildAndPushIssueForSheet(collisions);\n }\n }\n buildAndPushIssueForSheet(collisions) {\n const globalFixes = this.computeGlobalFixes(collisions);\n if (globalFixes.size === 0)\n return;\n const seenPairs = new Set;\n const pairs = [];\n for (const collision of collisions) {\n let comp1Name;\n let comp2Name;\n if (collision.type === \"label-label\") {\n comp1Name = collision.leftComp.sourceComponentName ?? \"\";\n comp2Name = collision.rightComp.sourceComponentName ?? \"\";\n } else {\n comp1Name = collision.boxComp.sourceComponentName ?? \"\";\n comp2Name = collision.labelComp.sourceComponentName ?? \"\";\n }\n const key = `${comp1Name}/${comp2Name}`;\n if (!seenPairs.has(key)) {\n seenPairs.add(key);\n pairs.push({ comp1Name, comp2Name });\n }\n }\n const firstCollision = collisions[0];\n const firstPlacement = firstCollision.type === \"label-label\" ? firstCollision.leftComp : firstCollision.boxComp;\n this.params.issues.push({\n lineItemType: \"NetLabelCollision\",\n schematicSheetId: firstPlacement.schematicSheetId,\n schematicSheetName: firstPlacement.schematicSheetName,\n pairs,\n collisionBounds: collisions.map((collision) =\u003e collision.bounds),\n moves: Array.from(globalFixes.values())\n });\n }\n computeGlobalFixes(collisions) {\n const compById = new Map;\n for (const placement of this.placements) {\n if (placement.schematicComponentId)\n compById.set(placement.schematicComponentId, placement);\n }\n const constraintMap = new Map;\n const addConstraint = (leftId, rightId, xSeparation) =\u003e {\n const leftComp = compById.get(leftId);\n const rightComp = compById.get(rightId);\n if (!leftComp || !rightComp)\n return;\n const minSep = rightComp.schX - leftComp.schX + xSeparation;\n const key = `${leftId}|${rightId}`;\n constraintMap.set(key, Math.max(constraintMap.get(key) ?? 0, minSep));\n };\n for (const collision of collisions) {\n if (collision.type === \"label-label\") {\n addConstraint(collision.leftId, collision.rightId, collision.xSeparation);\n } else if (collision.boxComp.schX \u003c= collision.labelComp.schX) {\n addConstraint(collision.boxId, collision.labelId, collision.xSeparation);\n } else {\n addConstraint(collision.labelId, collision.boxId, collision.xSeparation);\n }\n }\n const constraints = [...constraintMap.entries()].map(([key, minSep]) =\u003e {\n const pipeIndex = key.indexOf(\"|\");\n return {\n leftId: key.slice(0, pipeIndex),\n rightId: key.slice(pipeIndex + 1),\n minSep\n };\n });\n const allIds = new Set;\n const adjacency = new Map;\n for (const { leftId, rightId } of constraints) {\n allIds.add(leftId);\n allIds.add(rightId);\n if (!adjacency.has(leftId))\n adjacency.set(leftId, new Set);\n if (!adjacency.has(rightId))\n adjacency.set(rightId, new Set);\n adjacency.get(leftId).add(rightId);\n adjacency.get(rightId).add(leftId);\n }\n const visited = new Set;\n const result = new Map;\n for (const startId of allIds) {\n if (visited.has(startId))\n continue;\n const group = [];\n const queue = [startId];\n visited.add(startId);\n while (queue.length) {\n const compId = queue.shift();\n group.push(compId);\n for (const neighbor of adjacency.get(compId) ?? []) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n queue.push(neighbor);\n }\n }\n }\n group.sort((idA, idB) =\u003e (compById.get(idA)?.schX ?? 0) - (compById.get(idB)?.schX ?? 0));\n const groupIds = new Set(group);\n const groupConstraints = constraints.filter((c) =\u003e groupIds.has(c.leftId) \u0026\u0026 groupIds.has(c.rightId));\n const assigned = new Map;\n for (const compId of group) {\n let newX = compById.get(compId)?.schX ?? 0;\n for (const { leftId, rightId, minSep } of groupConstraints) {\n if (rightId === compId \u0026\u0026 assigned.has(leftId)) {\n newX = Math.max(newX, assigned.get(leftId) + minSep);\n }\n }\n assigned.set(compId, newX);\n }\n const totalPush = [...assigned.entries()].reduce((sum, [compId, newX]) =\u003e sum + (newX - (compById.get(compId)?.schX ?? 0)), 0);\n if (totalPush \u003e 0.000000001) {\n const pullBack = totalPush / group.length;\n const shifted = new Map;\n for (const compId of group) {\n let newX = (compById.get(compId)?.schX ?? 0) - pullBack;\n for (const { leftId, rightId, minSep } of groupConstraints) {\n if (rightId === compId \u0026\u0026 shifted.has(leftId)) {\n newX = Math.max(newX, shifted.get(leftId) + minSep);\n }\n }\n shifted.set(compId, newX);\n }\n const maxDisplacement = (positions) =\u003e [...positions.entries()].reduce((currentMax, [compId, newX]) =\u003e Math.max(currentMax, Math.abs(newX - (compById.get(compId)?.schX ?? 0))), 0);\n if (maxDisplacement(shifted) \u003c maxDisplacement(assigned)) {\n for (const [compId, newX] of shifted)\n assigned.set(compId, newX);\n }\n }\n for (const [compId, newX] of assigned) {\n const comp = compById.get(compId);\n if (!comp || Math.abs(newX - comp.schX) \u003c 0.000000001)\n continue;\n result.set(compId, {\n componentName: comp.sourceComponentName ?? compId,\n newSchX: Math.round(newX * 100) / 100,\n newSchY: Math.round(comp.schY * 100) / 100\n });\n }\n }\n return result;\n }\n buildNetLabelsByComponentId(circuitJson) {\n const MATCH_EPSILON = 0.0001;\n const portPositions = [];\n for (const element of circuitJson) {\n if (element.type !== \"schematic_port\")\n continue;\n const port = element;\n if (!port.schematic_component_id)\n continue;\n portPositions.push({\n componentId: port.schematic_component_id,\n cx: port.center.x,\n cy: port.center.y,\n schematicSheetId: port.schematic_sheet_id\n });\n }\n const result = new Map;\n for (const element of circuitJson) {\n if (element.type !== \"schematic_net_label\")\n continue;\n const label = element;\n if (!label.anchor_position)\n continue;\n const { x: anchorX, y: anchorY } = label.anchor_position;\n const matches = portPositions.filter((port) =\u003e port.schematicSheetId === label.schematic_sheet_id \u0026\u0026 Math.hypot(port.cx - anchorX, port.cy - anchorY) \u003c MATCH_EPSILON);\n if (matches.length === 0)\n continue;\n const componentIds = new Set(matches.map((match) =\u003e match.componentId));\n if (componentIds.size !== 1)\n continue;\n const componentId = matches[0].componentId;\n const labels = result.get(componentId) ?? [];\n labels.push(label);\n result.set(componentId, labels);\n }\n return result;\n }\n static netLabelCollisionToString(issue) {\n const pairAttrs = issue.pairs.map((pair, i) =\u003e `pair${i + 1}=\"${pair.comp1Name}/${pair.comp2Name}\"`).join(\" \");\n const moves = issue.moves.map((move) =\u003e ` \u003cMove componentName=\"${move.componentName}\" newSchX=\"${move.newSchX}\" newSchY=\"${move.newSchY}\" /\u003e`);\n return [\n `\u003cComponentNetLabelCollision ${pairAttrs}\u003e`,\n ` \u003cSuggestedFix note=\"Apply all moves simultaneously. Set schAutoLayoutEnabled on your circuit.\"\u003e`,\n ...moves,\n ` \u003c/SuggestedFix\u003e`,\n `\u003c/ComponentNetLabelCollision\u003e`\n ].join(`\n`);\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/ComponentPinAlignmentSolver/ComponentPinAlignmentSolver.ts\nclass ComponentPinAlignmentSolver extends BaseSolver {\n static ALIGNMENT_EPSILON = 0.01;\n ctx;\n out;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.ctx = ctx;\n this.out = issues;\n }\n _step() {\n const portsById = new Map(this.ctx.circuitJson.filter((el) =\u003e el.type === \"schematic_port\").map((port) =\u003e [port.schematic_port_id, port]));\n const placementBySchematicComponentId = new Map(this.ctx.componentPlacements.flatMap((placement) =\u003e placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));\n const pinPairsByComponentPair = new Map;\n for (const trace of this.ctx.circuitJson.filter((el) =\u003e el.type === \"schematic_trace\")) {\n const pinPair = this.getTracePinPair(trace, portsById);\n if (!pinPair)\n continue;\n const firstComponentId = pinPair.firstPort.schematic_component_id;\n const secondComponentId = pinPair.secondPort.schematic_component_id;\n if (!firstComponentId || !secondComponentId || firstComponentId === secondComponentId) {\n continue;\n }\n const orderedPair = firstComponentId \u003c secondComponentId ? pinPair : {\n firstPort: pinPair.secondPort,\n secondPort: pinPair.firstPort\n };\n const key = [firstComponentId, secondComponentId].sort().join(\"\\x00\");\n const pairs = pinPairsByComponentPair.get(key) ?? [];\n const isDuplicate = pairs.some((pair) =\u003e pair.firstPort.schematic_port_id === orderedPair.firstPort.schematic_port_id \u0026\u0026 pair.secondPort.schematic_port_id === orderedPair.secondPort.schematic_port_id);\n if (!isDuplicate)\n pairs.push(orderedPair);\n pinPairsByComponentPair.set(key, pairs);\n }\n for (const pinPairs of pinPairsByComponentPair.values()) {\n const issue = this.findVerticalShiftIssue(pinPairs, placementBySchematicComponentId);\n if (issue)\n this.out.push(issue);\n }\n this.solved = true;\n }\n getTracePinPair(trace, portsById) {\n const firstEdge = trace.edges?.[0];\n const lastEdge = trace.edges?.at(-1);\n if (!firstEdge || !lastEdge)\n return;\n const firstPortId = firstEdge.from_schematic_port_id ?? firstEdge.to_schematic_port_id;\n const secondPortId = lastEdge.to_schematic_port_id ?? lastEdge.from_schematic_port_id;\n const ports = [...portsById.values()];\n const firstPort = firstPortId ? portsById.get(firstPortId) : this.findPortAtPoint(ports, firstEdge.from, trace.schematic_sheet_id);\n const secondPort = secondPortId ? portsById.get(secondPortId) : this.findPortAtPoint(ports, lastEdge.to, trace.schematic_sheet_id);\n if (!firstPort || !secondPort)\n return;\n if (firstPort.schematic_port_id === secondPort.schematic_port_id)\n return;\n if (firstPort.schematic_sheet_id !== secondPort.schematic_sheet_id)\n return;\n return { firstPort, secondPort };\n }\n findPortAtPoint(ports, point, schematicSheetId) {\n const { ALIGNMENT_EPSILON } = ComponentPinAlignmentSolver;\n return ports.find((port) =\u003e port.schematic_sheet_id === schematicSheetId \u0026\u0026 Math.abs(port.center.x - point.x) \u003c= ALIGNMENT_EPSILON \u0026\u0026 Math.abs(port.center.y - point.y) \u003c= ALIGNMENT_EPSILON);\n }\n findVerticalShiftIssue(pinPairs, placementBySchematicComponentId) {\n const firstPair = pinPairs[0];\n if (!firstPair)\n return;\n const firstPlacement = placementBySchematicComponentId.get(firstPair.firstPort.schematic_component_id);\n const secondPlacement = placementBySchematicComponentId.get(firstPair.secondPort.schematic_component_id);\n if (!firstPlacement || !secondPlacement)\n return;\n const [leftPlacement, rightPlacement] = firstPlacement.schX \u003c= secondPlacement.schX ? [firstPlacement, secondPlacement] : [secondPlacement, firstPlacement];\n const horizontalPairs = pinPairs.flatMap((pair) =\u003e {\n const [leftPort, rightPort] = pair.firstPort.center.x \u003c= pair.secondPort.center.x ? [pair.firstPort, pair.secondPort] : [pair.secondPort, pair.firstPort];\n return leftPort.facing_direction === \"right\" \u0026\u0026 rightPort.facing_direction === \"left\" ? [{ leftPort, rightPort }] : [];\n });\n if (horizontalPairs.length \u003c 2)\n return;\n const { ALIGNMENT_EPSILON } = ComponentPinAlignmentSolver;\n const currentlyAlignedPinCount = horizontalPairs.filter(({ leftPort, rightPort }) =\u003e Math.abs(leftPort.center.y - rightPort.center.y) \u003c= ALIGNMENT_EPSILON).length;\n const candidateGroups = [];\n for (const pair of horizontalPairs) {\n const deltaSchY2 = pair.leftPort.center.y - pair.rightPort.center.y;\n if (Math.abs(deltaSchY2) \u003c= ALIGNMENT_EPSILON)\n continue;\n const group = candidateGroups.find((candidate) =\u003e Math.abs(candidate.deltaSchY - deltaSchY2) \u003c= ALIGNMENT_EPSILON);\n if (group)\n group.pairs.push(pair);\n else\n candidateGroups.push({ deltaSchY: deltaSchY2, pairs: [pair] });\n }\n const bestCandidate = candidateGroups.sort((a, b) =\u003e b.pairs.length - a.pairs.length || Math.abs(a.deltaSchY) - Math.abs(b.deltaSchY))[0];\n if (!bestCandidate || bestCandidate.pairs.length \u003c 2 || bestCandidate.pairs.length \u003c= currentlyAlignedPinCount) {\n return;\n }\n const targetName = rightPlacement.sourceComponentName ?? rightPlacement.schematicComponentId ?? \"component\";\n const deltaSchY = bestCandidate.deltaSchY;\n const newSchY = rightPlacement.schY + deltaSchY;\n return {\n lineItemType: \"ComponentPinsWouldAlignWithVerticalShift\",\n firstComponent: leftPlacement,\n secondComponent: rightPlacement,\n targetComponent: rightPlacement,\n deltaSchY,\n newSchY,\n currentlyAlignedPinCount,\n alignedPinCount: bestCandidate.pairs.length,\n alignedPinPairs: bestCandidate.pairs.map(({ leftPort, rightPort }) =\u003e ({\n firstPin: this.getPinLabel(leftPort),\n secondPin: this.getPinLabel(rightPort)\n })),\n message: `shift ${targetName} vertically by ${fmtDelta(deltaSchY)} to align ${bestCandidate.pairs.length} connected pin pairs`\n };\n }\n getPinLabel(port) {\n return port.display_pin_label ?? port.pin_number?.toString();\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"firstComponentName\", issue.firstComponent.sourceComponentName);\n addAttr(attrs, \"secondComponentName\", issue.secondComponent.sourceComponentName);\n addAttr(attrs, \"targetComponentName\", issue.targetComponent.sourceComponentName);\n addAttr(attrs, \"deltaSchY\", issue.deltaSchY);\n addAttr(attrs, \"newSchY\", issue.newSchY);\n addAttr(attrs, \"currentlyAlignedPinCount\", issue.currentlyAlignedPinCount);\n addAttr(attrs, \"alignedPinCount\", issue.alignedPinCount);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cComponentPinsWouldAlignWithVerticalShift ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/CrystalLoadCapacitorPlacementSolver/CrystalLoadCapacitorPlacementSolver.ts\nclass CrystalLoadCapacitorPlacementSolver extends BaseSolver {\n static ALIGNMENT_TOLERANCE = 0.1;\n issues;\n networks;\n currentNetworkIndex = 0;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.issues = issues;\n this.networks = this.findCrystalLoadNetworks(ctx);\n this.solved = this.networks.length === 0;\n }\n _step() {\n const network = this.networks[this.currentNetworkIndex];\n if (!network) {\n this.solved = true;\n return;\n }\n this.currentNetworkIndex += 1;\n this.solved = this.currentNetworkIndex \u003e= this.networks.length;\n const deltaSchX = round3(network.newSchX - network.crystal.schX);\n const deltaSchY = round3(network.newSchY - network.crystal.schY);\n if (Math.abs(deltaSchX) \u003c= CrystalLoadCapacitorPlacementSolver.ALIGNMENT_TOLERANCE \u0026\u0026 Math.abs(deltaSchY) \u003c= CrystalLoadCapacitorPlacementSolver.ALIGNMENT_TOLERANCE) {\n return;\n }\n const crystalName = network.crystal.sourceComponentName ?? \"the crystal\";\n const firstCapacitorName = network.firstLoadCapacitor.sourceComponentName ?? \"the first load capacitor\";\n const secondCapacitorName = network.secondLoadCapacitor.sourceComponentName ?? \"the second load capacitor\";\n this.issues.push({\n lineItemType: \"CrystalNotCenteredOverLoadCapacitors\",\n crystalSchematicBox: network.crystal,\n firstLoadCapacitorSchematicBox: network.firstLoadCapacitor,\n secondLoadCapacitorSchematicBox: network.secondLoadCapacitor,\n deltaSchX,\n deltaSchY,\n newSchX: network.newSchX,\n newSchY: network.newSchY,\n message: `move ${crystalName} to schX=${network.newSchX}, schY=${network.newSchY} so it is centered between ${firstCapacitorName} and ${secondCapacitorName} and aligned with their load-side pins`\n });\n }\n findCrystalLoadNetworks(ctx) {\n const sourceComponents = new Map;\n const sourcePortsByComponentId = new Map;\n const schematicPortsBySourcePortId = new Map;\n const placementBySourceComponentId = new Map(ctx.componentPlacements.flatMap((placement) =\u003e placement.sourceComponentId ? [[placement.sourceComponentId, placement]] : []));\n for (const element of ctx.circuitJson) {\n if (element.type === \"source_component\") {\n sourceComponents.set(element.source_component_id, {\n sourceComponentId: element.source_component_id,\n ftype: \"ftype\" in element \u0026\u0026 typeof element.ftype === \"string\" ? element.ftype : undefined\n });\n }\n if (element.type === \"source_port\" \u0026\u0026 typeof element.source_component_id === \"string\" \u0026\u0026 typeof element.subcircuit_connectivity_map_key === \"string\") {\n const sourcePort = {\n sourcePortId: element.source_port_id,\n sourceComponentId: element.source_component_id,\n connectivityKey: element.subcircuit_connectivity_map_key\n };\n const componentPorts = sourcePortsByComponentId.get(element.source_component_id) ?? [];\n componentPorts.push(sourcePort);\n sourcePortsByComponentId.set(element.source_component_id, componentPorts);\n }\n if (element.type === \"schematic_port\" \u0026\u0026 element.source_port_id) {\n schematicPortsBySourcePortId.set(element.source_port_id, element);\n }\n }\n const capacitorConnectionsByConnectivityKey = new Map;\n for (const sourceComponent of sourceComponents.values()) {\n if (sourceComponent.ftype !== \"simple_capacitor\")\n continue;\n const capacitorPorts = sourcePortsByComponentId.get(sourceComponent.sourceComponentId) ?? [];\n if (capacitorPorts.length !== 2)\n continue;\n const firstCapacitorPort = capacitorPorts[0];\n const secondCapacitorPort = capacitorPorts[1];\n const capacitorPlacement = placementBySourceComponentId.get(sourceComponent.sourceComponentId);\n if (!capacitorPlacement)\n continue;\n for (const [loadPort, returnPort] of [\n [firstCapacitorPort, secondCapacitorPort],\n [secondCapacitorPort, firstCapacitorPort]\n ]) {\n const schematicLoadPort = schematicPortsBySourcePortId.get(loadPort.sourcePortId);\n if (!schematicLoadPort)\n continue;\n const connections = capacitorConnectionsByConnectivityKey.get(loadPort.connectivityKey) ?? [];\n connections.push({\n capacitor: capacitorPlacement,\n loadPort: schematicLoadPort,\n returnConnectivityKey: returnPort.connectivityKey\n });\n capacitorConnectionsByConnectivityKey.set(loadPort.connectivityKey, connections);\n }\n }\n const networks = [];\n for (const sourceComponent of sourceComponents.values()) {\n if (sourceComponent.ftype !== \"simple_crystal\" \u0026\u0026 sourceComponent.ftype !== \"simple_chip\") {\n continue;\n }\n const crystalPorts = sourcePortsByComponentId.get(sourceComponent.sourceComponentId) ?? [];\n if (crystalPorts.length !== 2 || crystalPorts[0].connectivityKey === crystalPorts[1].connectivityKey) {\n continue;\n }\n const firstCrystalConnectivityKey = crystalPorts[0].connectivityKey;\n const secondCrystalConnectivityKey = crystalPorts[1].connectivityKey;\n const hasOscillatorHost = [...sourcePortsByComponentId.entries()].some(([sourceComponentId, sourcePorts]) =\u003e sourceComponentId !== sourceComponent.sourceComponentId \u0026\u0026 sourcePorts.length \u003e 2 \u0026\u0026 sourcePorts.some((port) =\u003e port.connectivityKey === firstCrystalConnectivityKey) \u0026\u0026 sourcePorts.some((port) =\u003e port.connectivityKey === secondCrystalConnectivityKey));\n if (!hasOscillatorHost)\n continue;\n const crystalPlacement = placementBySourceComponentId.get(sourceComponent.sourceComponentId);\n if (!crystalPlacement)\n continue;\n const firstConnections = capacitorConnectionsByConnectivityKey.get(crystalPorts[0].connectivityKey) ?? [];\n const secondConnections = capacitorConnectionsByConnectivityKey.get(crystalPorts[1].connectivityKey) ?? [];\n const candidatePairs = firstConnections.flatMap((firstConnection) =\u003e secondConnections.flatMap((secondConnection) =\u003e {\n if (firstConnection.capacitor.sourceComponentId === secondConnection.capacitor.sourceComponentId || firstConnection.returnConnectivityKey !== secondConnection.returnConnectivityKey || firstConnection.returnConnectivityKey === firstCrystalConnectivityKey || firstConnection.returnConnectivityKey === secondCrystalConnectivityKey || firstConnection.capacitor.schematicSheetId !== crystalPlacement.schematicSheetId || secondConnection.capacitor.schematicSheetId !== crystalPlacement.schematicSheetId) {\n return [];\n }\n return [{ firstConnection, secondConnection }];\n }));\n if (candidatePairs.length === 0)\n continue;\n const bestPair = candidatePairs.toSorted((a, b) =\u003e pairDistance(a, crystalPlacement) - pairDistance(b, crystalPlacement))[0];\n const loadPorts = [\n bestPair.firstConnection.loadPort,\n bestPair.secondConnection.loadPort\n ];\n const capacitors = [\n bestPair.firstConnection.capacitor,\n bestPair.secondConnection.capacitor\n ].toSorted((a, b) =\u003e a.schX - b.schX);\n networks.push({\n crystal: crystalPlacement,\n firstLoadCapacitor: capacitors[0],\n secondLoadCapacitor: capacitors[1],\n newSchX: round3((loadPorts[0].center.x + loadPorts[1].center.x) / 2),\n newSchY: round3((loadPorts[0].center.y + loadPorts[1].center.y) / 2)\n });\n }\n return networks;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"crystalName\", issue.crystalSchematicBox.sourceComponentName);\n addAttr(attrs, \"firstLoadCapacitorName\", issue.firstLoadCapacitorSchematicBox.sourceComponentName);\n addAttr(attrs, \"secondLoadCapacitorName\", issue.secondLoadCapacitorSchematicBox.sourceComponentName);\n addAttr(attrs, \"newSchX\", issue.newSchX);\n addAttr(attrs, \"newSchY\", issue.newSchY);\n addAttr(attrs, \"deltaSchX\", issue.deltaSchX, { formatDelta: true });\n addAttr(attrs, \"deltaSchY\", issue.deltaSchY, { formatDelta: true });\n addAttr(attrs, \"message\", issue.message);\n return `\u003cCrystalNotCenteredOverLoadCapacitors ${attrs.join(\" \")} /\u003e`;\n }\n}\nvar pairDistance = (pair, crystal) =\u003e distance2(pair.firstConnection.capacitor, crystal) + distance2(pair.secondConnection.capacitor, crystal);\nvar distance2 = (first, second) =\u003e Math.hypot(first.schX - second.schX, first.schY - second.schY);\nvar round3 = (value) =\u003e Math.round(value * 100) / 100;\n\n// ../../work/placement-analysis/node_modules/circuit-json-to-connectivity-map/dist/index.js\nfunction findConnectedNetworks(connections) {\n const networks = /* @__PURE__ */ new Map;\n let netCounter = 0;\n function getOrCreateNetwork(nodeId) {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network;\n }\n }\n const newNetwork = /* @__PURE__ */ new Set;\n networks.set(`connectivity_net${netCounter++}`, newNetwork);\n return newNetwork;\n }\n for (const connection of connections) {\n let network = null;\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId);\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId);\n if (existingNetwork !== network) {\n for (const node of existingNetwork) {\n network.add(node);\n }\n networks.delete(Array.from(networks.entries()).find(([, net]) =\u003e net === existingNetwork)[0]);\n }\n }\n network.add(nodeId);\n }\n }\n return Object.fromEntries(Array.from(networks.entries()).map(([netId, connectedNodes]) =\u003e [\n netId,\n Array.from(connectedNodes)\n ]));\n}\nvar ConnectivityMap = class {\n netMap;\n idToNetMap;\n constructor(netMap) {\n this.netMap = netMap;\n this.idToNetMap = {};\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId;\n }\n }\n }\n addConnections(connections) {\n for (const connection of connections) {\n const existingNets = /* @__PURE__ */ new Set;\n for (const id of connection) {\n const existingNetId = this.idToNetMap[id];\n if (existingNetId) {\n existingNets.add(existingNetId);\n }\n }\n let targetNetId;\n if (existingNets.size === 0) {\n targetNetId = `connectivity_net${Object.keys(this.netMap).length}`;\n this.netMap[targetNetId] = [];\n } else if (existingNets.size === 1) {\n targetNetId = existingNets.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;\n } else {\n targetNetId = existingNets.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;\n for (const netId of existingNets) {\n if (netId !== targetNetId) {\n this.netMap[targetNetId].push(...this.netMap[netId]);\n this.netMap[netId] = this.netMap[targetNetId];\n for (const id of this.netMap[targetNetId]) {\n this.idToNetMap[id] = targetNetId;\n }\n }\n }\n }\n for (const id of connection) {\n if (!this.netMap[targetNetId].includes(id)) {\n this.netMap[targetNetId].push(id);\n }\n this.idToNetMap[id] = targetNetId;\n }\n }\n }\n getIdsConnectedToNet(netId) {\n return this.netMap[netId] || [];\n }\n getNetConnectedToId(id) {\n return this.idToNetMap[id];\n }\n areIdsConnected(id1, id2) {\n if (id1 === id2)\n return true;\n const netId1 = this.getNetConnectedToId(id1);\n if (!netId1)\n return false;\n const netId2 = this.getNetConnectedToId(id2);\n if (!netId2)\n return false;\n return netId1 === netId2 || netId2 === id1 || netId2 === id1;\n }\n areAllIdsConnected(ids) {\n const netId = this.getNetConnectedToId(ids[0]);\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id);\n if (nextNetId === undefined) {\n return false;\n }\n if (nextNetId !== netId) {\n return false;\n }\n }\n return true;\n }\n};\nvar getSourcePortConnectivityMapFromCircuitJson = (circuitJson) =\u003e {\n const connections = [];\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...element.connected_source_port_ids ?? [],\n ...element.connected_source_net_ids ?? []\n ]);\n } else if (element.type === \"source_component\") {\n if (element.internally_connected_source_port_ids) {\n for (const portGroup of element.internally_connected_source_port_ids) {\n connections.push(portGroup);\n }\n }\n } else if (element.type === \"source_component_internal_connection\") {\n connections.push(element.source_port_ids);\n }\n }\n const netMap = findConnectedNetworks(connections);\n return new ConnectivityMap(netMap);\n};\n\n// ../../work/placement-analysis/lib/solvers/DiodeResistorAlignmentSolver/DiodeResistorAlignmentSolver.ts\nclass DiodeResistorAlignmentSolver extends BaseSolver {\n static DIODE_FTYPES = new Set([\"simple_led\", \"simple_diode\"]);\n ctx;\n out;\n schematicTraces;\n currentIndex = 0;\n sourceConnectivity;\n sourceComponentFtypeById;\n sourceComponentIdBySourcePortId;\n schematicPorts;\n schematicBoxBySourceComponentId;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.ctx = ctx;\n this.out = issues;\n const { circuitJson } = ctx;\n this.sourceConnectivity = getSourcePortConnectivityMapFromCircuitJson(circuitJson);\n this.sourceComponentFtypeById = this.buildSourceComponentFtypeById(circuitJson);\n this.sourceComponentIdBySourcePortId = this.buildSourceComponentIdBySourcePortId(circuitJson);\n this.schematicPorts = circuitJson.filter((el) =\u003e el.type === \"schematic_port\");\n this.schematicBoxBySourceComponentId = this.buildSchematicBoxBySourceComponentId();\n this.schematicTraces = circuitJson.filter((el) =\u003e el.type === \"schematic_trace\");\n this.solved = this.schematicTraces.length === 0;\n }\n _step() {\n const trace = this.schematicTraces[this.currentIndex];\n if (!trace) {\n this.solved = true;\n return;\n }\n this.currentIndex++;\n this.solved = this.currentIndex \u003e= this.schematicTraces.length;\n if (!trace.edges || trace.edges.length === 0)\n return;\n const firstEdge = trace.edges[0];\n const lastEdge = trace.edges[trace.edges.length - 1];\n if (!firstEdge || !lastEdge)\n return;\n const start = firstEdge.from;\n const end = lastEdge.to;\n const schematicSheetId = trace.schematic_sheet_id;\n const startSourceCompId = this.findSourceComponentIdNearPoint(start, schematicSheetId);\n const endSourceCompId = this.findSourceComponentIdNearPoint(end, schematicSheetId);\n if (!startSourceCompId || !endSourceCompId)\n return;\n const startFtype = this.sourceComponentFtypeById.get(startSourceCompId);\n const endFtype = this.sourceComponentFtypeById.get(endSourceCompId);\n const { DIODE_FTYPES } = DiodeResistorAlignmentSolver;\n const isDiodeResistorPair = DIODE_FTYPES.has(startFtype) \u0026\u0026 endFtype === \"simple_resistor\" || startFtype === \"simple_resistor\" \u0026\u0026 DIODE_FTYPES.has(endFtype);\n if (!isDiodeResistorPair)\n return;\n const diodeCompId = DIODE_FTYPES.has(startFtype) ? startSourceCompId : endSourceCompId;\n const resistorCompId = startFtype === \"simple_resistor\" ? startSourceCompId : endSourceCompId;\n const diodeBox = this.schematicBoxBySourceComponentId.get(diodeCompId);\n const resistorBox = this.schematicBoxBySourceComponentId.get(resistorCompId);\n if (!diodeBox || !resistorBox)\n return;\n const diodePort = this.findNearestPort(DIODE_FTYPES.has(startFtype) ? start : end, schematicSheetId);\n const resistorPort = this.findNearestPort(startFtype === \"simple_resistor\" ? start : end, schematicSheetId);\n if (!diodePort?.center || !resistorPort?.center)\n return;\n if (!this.sourceConnectivity.areIdsConnected(diodePort.source_port_id, resistorPort.source_port_id))\n return;\n const diodeName = diodeBox.sourceComponentName ?? diodeCompId;\n const resistorName = resistorBox.sourceComponentName ?? resistorCompId;\n const diodePin = diodePort?.display_pin_label ?? diodePort?.pin_number?.toString();\n const resistorPin = resistorPort?.display_pin_label ?? resistorPort?.pin_number?.toString();\n const diodeFacing = diodePort?.facing_direction;\n const resistorFacing = resistorPort?.facing_direction;\n const diodePinDesc = diodePin ? `${diodeName}.${diodePin}` : diodeName;\n const resistorPinDesc = resistorPin ? `${resistorName}.${resistorPin}` : resistorName;\n const makeIssue = (message) =\u003e ({\n lineItemType: \"DiodeResistorNotAligned\",\n diodeSchematicBox: diodeBox,\n resistorSchematicBox: resistorBox,\n diodePin,\n resistorPin,\n diodePinFacingDirection: diodeFacing,\n resistorPinFacingDirection: resistorFacing,\n message\n });\n if (!DiodeResistorAlignmentSolver.isCoLinear(diodePort.center, resistorPort.center)) {\n this.out.push(makeIssue(`trace has corners — align ${diodeName} and ${resistorName} on same axis and rotate so ${diodePinDesc} faces ${resistorPinDesc}`));\n return;\n }\n if (diodeFacing \u0026\u0026 resistorFacing \u0026\u0026 !DiodeResistorAlignmentSolver.pinsFacingEachOther(diodePort.center, diodeFacing, resistorPort.center, resistorFacing)) {\n this.out.push(makeIssue(`${diodePinDesc} and ${resistorPinDesc} face away from each other — rotate ${diodeName} so ${diodePinDesc} faces ${resistorPinDesc}`));\n }\n }\n static isCoLinear(a, b, epsilon = 0.01) {\n return Math.abs(a.x - b.x) \u003c epsilon || Math.abs(a.y - b.y) \u003c epsilon;\n }\n static pinsFacingEachOther(aCenter, aFacing, bCenter, bFacing) {\n const dx = bCenter.x - aCenter.x;\n const dy = bCenter.y - aCenter.y;\n const aToward = aFacing === \"right\" \u0026\u0026 dx \u003e 0 || aFacing === \"left\" \u0026\u0026 dx \u003c 0 || aFacing === \"up\" \u0026\u0026 dy \u003e 0 || aFacing === \"down\" \u0026\u0026 dy \u003c 0;\n const bToward = bFacing === \"right\" \u0026\u0026 dx \u003c 0 || bFacing === \"left\" \u0026\u0026 dx \u003e 0 || bFacing === \"up\" \u0026\u0026 dy \u003c 0 || bFacing === \"down\" \u0026\u0026 dy \u003e 0;\n return aToward \u0026\u0026 bToward;\n }\n static dist(a, b) {\n return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);\n }\n findNearestPort(point, schematicSheetId) {\n let nearest;\n let minDist = Infinity;\n for (const port of this.schematicPorts) {\n if (port.schematic_sheet_id !== schematicSheetId)\n continue;\n if (!port.center)\n continue;\n const d = DiodeResistorAlignmentSolver.dist(point, port.center);\n if (d \u003c minDist) {\n minDist = d;\n nearest = port;\n }\n }\n return nearest;\n }\n findSourceComponentIdNearPoint(point, schematicSheetId) {\n const nearest = this.findNearestPort(point, schematicSheetId);\n if (!nearest || !nearest.source_port_id)\n return;\n return this.sourceComponentIdBySourcePortId.get(nearest.source_port_id);\n }\n buildSourceComponentFtypeById(circuitJson) {\n const map = new Map;\n for (const el of circuitJson) {\n if (el.type === \"source_component\" \u0026\u0026 \"source_component_id\" in el \u0026\u0026 \"ftype\" in el \u0026\u0026 typeof el.ftype === \"string\") {\n map.set(el.source_component_id, el.ftype);\n }\n }\n return map;\n }\n buildSourceComponentIdBySourcePortId(circuitJson) {\n const map = new Map;\n for (const el of circuitJson) {\n if (el.type === \"source_port\" \u0026\u0026 \"source_port_id\" in el \u0026\u0026 \"source_component_id\" in el \u0026\u0026 typeof el.source_port_id === \"string\" \u0026\u0026 typeof el.source_component_id === \"string\") {\n map.set(el.source_port_id, el.source_component_id);\n }\n }\n return map;\n }\n buildSchematicBoxBySourceComponentId() {\n const map = new Map;\n for (const placement of this.ctx.componentPlacements) {\n if (placement.sourceComponentId) {\n map.set(placement.sourceComponentId, placement);\n }\n }\n return map;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"diodeComponentName\", issue.diodeSchematicBox.sourceComponentName);\n addAttr(attrs, \"diodePin\", issue.diodePin);\n addAttr(attrs, \"resistorComponentName\", issue.resistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"resistorPin\", issue.resistorPin);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cDiodeResistorNotAligned ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/FeedbackNetworkPlacementSolver/FeedbackNetworkPlacementSolver.ts\nclass FeedbackNetworkPlacementSolver extends BaseSolver {\n static MIN_BODY_GAP = 4;\n index;\n amplifierIds;\n issues;\n currentIndex = 0;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.issues = issues;\n this.index = new PlacementNetworkIndex(ctx);\n this.amplifierIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_op_amp\").map((component) =\u003e component.source_component_id);\n this.solved = this.amplifierIds.length === 0;\n }\n _step() {\n const id = this.amplifierIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.amplifierIds.length;\n if (!id)\n return;\n const index = this.index;\n const amplifier = index.placement(id);\n const output = index.namedPort(id, \"output\");\n const input = index.namedPort(id, \"inverting_input\");\n if (!amplifier || !output || !input || !index.port(output) || !index.port(input))\n return;\n const outputNet = index.connected(output.source_port_id);\n const inputNet = index.connected(input.source_port_id);\n if (outputNet === inputNet || index.isRail(outputNet) || index.isRail(inputNet))\n return;\n if ((index.portsByNet.get(inputNet) ?? []).some((port) =\u003e port.source_component_id !== id \u0026\u0026 index.components.get(port.source_component_id)?.ftype === \"simple_op_amp\"))\n return;\n const feedbackComponents = [];\n const seen = new Set;\n for (const port of index.portsByNet.get(outputNet) ?? []) {\n const componentId = port.source_component_id;\n if (seen.has(componentId))\n continue;\n seen.add(componentId);\n const component = index.components.get(componentId);\n if (component?.ftype !== \"simple_resistor\" \u0026\u0026 component?.ftype !== \"simple_capacitor\")\n continue;\n if (component.ftype === \"simple_resistor\" \u0026\u0026 !(component.resistance \u003e 0))\n continue;\n const nets = index.twoTerminalNets(componentId);\n if (!nets?.includes(inputNet) || !nets.includes(outputNet))\n continue;\n const placement = index.placement(componentId);\n if (!placement || !index.sameLocalScope(amplifier, placement))\n return;\n feedbackComponents.push(placement);\n }\n const distantComponents = feedbackComponents.flatMap((schematicBox) =\u003e {\n const bodyGap2 = distanceBetweenBoxes(amplifier, schematicBox);\n const maxRecommendedBodyGap = Math.max(FeedbackNetworkPlacementSolver.MIN_BODY_GAP, 3 * Math.max(schematicBox.width, schematicBox.height));\n return bodyGap2 \u003e maxRecommendedBodyGap ? [{ schematicBox, bodyGap: bodyGap2, maxRecommendedBodyGap }] : [];\n });\n if (distantComponents.length === 0)\n return;\n const names = distantComponents.map(({ schematicBox }) =\u003e schematicBox.sourceComponentName ?? schematicBox.sourceComponentId).join(\", \");\n this.issues.push({\n lineItemType: \"FeedbackNetworkNotCompact\",\n amplifierSchematicBox: amplifier,\n feedbackComponents,\n distantComponents,\n outputSourcePortId: output.source_port_id,\n invertingInputSourcePortId: input.source_port_id,\n message: `consider grouping ${names} closer to ${amplifier.sourceComponentName ?? id}, with a compact feedback return path above or below the amplifier`\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"amplifierName\", issue.amplifierSchematicBox.sourceComponentName);\n addAttr(attrs, \"feedbackComponentNames\", issue.feedbackComponents.map((box) =\u003e box.sourceComponentName ?? box.sourceComponentId).join(\", \"));\n addAttr(attrs, \"distantComponentNames\", issue.distantComponents.map(({ schematicBox }) =\u003e schematicBox.sourceComponentName ?? schematicBox.sourceComponentId).join(\", \"));\n addAttr(attrs, \"message\", issue.message);\n return `\u003cFeedbackNetworkNotCompact ${attrs.join(\" \")} /\u003e`;\n }\n}\nfunction distanceBetweenBoxes(a, b) {\n return Math.hypot(Math.max(0, Math.abs(a.schX - b.schX) - (a.width + b.width) / 2), Math.max(0, Math.abs(a.schY - b.schY) - (a.height + b.height) / 2));\n}\n\n// ../../work/placement-analysis/lib/utils/switch-pull-resistor-pairs.ts\nfunction getSwitchPullResistorPairs(index) {\n const pairs = [];\n const isHorizontal = (id) =\u003e {\n const ports = index.portsByComponent.get(id);\n if (ports?.length !== 2)\n return false;\n const a = index.port(ports[0]);\n const b = index.port(ports[1]);\n return !!a \u0026\u0026 !!b \u0026\u0026 Math.abs(a.center.y - b.center.y) \u003c 0.01 \u0026\u0026 Math.abs(a.center.x - b.center.x) \u003e 0.01;\n };\n for (const component of index.components.values()) {\n if (component.ftype !== \"simple_resistor\" || component.resistance \u003c= 0)\n continue;\n const id = component.source_component_id;\n const nets = index.twoTerminalNets(id);\n if (!nets || nets.filter((net) =\u003e index.isRail(net)).length !== 1)\n continue;\n const rail = nets.find((net) =\u003e index.isRail(net));\n if (index.powerNets.has(rail) \u0026\u0026 index.groundNets.has(rail))\n continue;\n const signal = nets.find((net) =\u003e net !== rail);\n const peers = index.portsByNet.get(signal) ?? [];\n const switches = peers.filter((port) =\u003e {\n const type = index.components.get(port.source_component_id)?.ftype;\n return type === \"simple_switch\" || type === \"simple_push_button\";\n });\n if (switches.length !== 1 || peers.filter((port) =\u003e index.components.get(port.source_component_id)?.ftype === \"simple_resistor\").length !== 1)\n continue;\n const signalPort = switches[0];\n const switchId = signalPort.source_component_id;\n const switchType = index.components.get(switchId)?.ftype;\n const switchNets = index.twoTerminalNets(switchId);\n const otherRail = switchNets?.find((net) =\u003e net !== signal);\n if (!otherRail)\n continue;\n const pullDirection = index.powerNets.has(rail) ? \"up\" : \"down\";\n if (pullDirection === \"up\" ? !index.groundNets.has(otherRail) || index.powerNets.has(otherRail) : !index.powerNets.has(otherRail) || index.groundNets.has(otherRail))\n continue;\n if ([id, switchId].some((componentId) =\u003e index.portsByComponent.get(componentId)?.some((port) =\u003e port.do_not_connect)))\n continue;\n const resistor = index.placement(id);\n const switchBox = index.placement(switchId);\n const pin = index.port(signalPort);\n if (!resistor || !switchBox || !pin || !index.sameLocalScope(resistor, switchBox))\n continue;\n pairs.push({\n resistor,\n switchBox,\n signalPort,\n signalSchY: pin.center.y,\n pullDirection,\n horizontalPushbutton: switchType === \"simple_push_button\" \u0026\u0026 isHorizontal(id) \u0026\u0026 isHorizontal(switchId)\n });\n }\n return pairs;\n}\nfunction getHorizontalPushbuttonComponentIds(index) {\n return new Set(getSwitchPullResistorPairs(index).flatMap((pair) =\u003e pair.horizontalPushbutton ? [pair.resistor.sourceComponentId, pair.switchBox.sourceComponentId] : []));\n}\n\n// ../../work/placement-analysis/lib/solvers/PullResistorPlacementSolver/PullResistorPlacementSolver.ts\nclass PullResistorPlacementSolver extends BaseSolver {\n static MIN_WRONG_SIDE_GAP = 1.5;\n index;\n resistorIds;\n horizontalPushbuttonComponentIds;\n issues;\n currentIndex = 0;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.issues = issues;\n this.index = new PlacementNetworkIndex(ctx);\n this.horizontalPushbuttonComponentIds = getHorizontalPushbuttonComponentIds(this.index);\n this.resistorIds = [...this.index.components.values()].filter((component) =\u003e component.ftype === \"simple_resistor\" \u0026\u0026 component.resistance \u003e 0).map((component) =\u003e component.source_component_id);\n this.solved = this.resistorIds.length === 0;\n }\n _step() {\n const id = this.resistorIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.resistorIds.length;\n if (!id)\n return;\n if (this.horizontalPushbuttonComponentIds.has(id))\n return;\n const index = this.index;\n const resistor = index.placement(id);\n const nets = index.twoTerminalNets(id);\n if (!resistor || !nets)\n return;\n const rails = nets.filter((net) =\u003e index.isRail(net));\n if (rails.length !== 1)\n return;\n const rail = rails[0];\n if (index.powerNets.has(rail) \u0026\u0026 index.groundNets.has(rail))\n return;\n const pullDirection = index.groundNets.has(rail) ? \"down\" : \"up\";\n const signal = nets.find((net) =\u003e net !== rail);\n const signalPorts = index.portsByNet.get(signal) ?? [];\n const requiringPorts = signalPorts.filter((port) =\u003e port.needs_external_pullup || port.needs_external_pulldown);\n if (requiringPorts.length !== 1)\n return;\n const signalPort = requiringPorts[0];\n if (signalPort.needs_external_pullup \u0026\u0026 signalPort.needs_external_pulldown)\n return;\n if (pullDirection === \"up\" ? !signalPort.needs_external_pullup : !signalPort.needs_external_pulldown)\n return;\n const host = index.placement(signalPort.source_component_id);\n const schematicPin = index.port(signalPort);\n if (!host || !schematicPin || !index.sameLocalScope(host, resistor))\n return;\n if (signalPorts.some((port) =\u003e {\n const otherId = port.source_component_id;\n if (otherId === id || otherId === signalPort.source_component_id)\n return false;\n const type = index.components.get(otherId)?.ftype;\n if (type !== \"simple_capacitor\")\n return true;\n const capacitorNets = index.twoTerminalNets(otherId);\n const returnNet = capacitorNets?.find((net) =\u003e net !== signal);\n if (!returnNet || !index.groundNets.has(returnNet) || index.powerNets.has(returnNet))\n return true;\n const capacitor = index.placement(otherId);\n return !capacitor || !index.sameLocalScope(host, capacitor);\n }))\n return;\n const signalSchY = schematicPin.center.y;\n const wrongSideGap = pullDirection === \"up\" ? signalSchY - (resistor.schY + resistor.height / 2) : resistor.schY - resistor.height / 2 - signalSchY;\n if (wrongSideGap \u003c= PullResistorPlacementSolver.MIN_WRONG_SIDE_GAP)\n return;\n const preferredSide = pullDirection === \"up\" ? \"above\" : \"below\";\n this.issues.push({\n lineItemType: \"PullResistorOnWrongSide\",\n resistorSchematicBox: resistor,\n hostSchematicBox: host,\n signalSourcePortId: signalPort.source_port_id,\n signalPinName: signalPort.name,\n signalSchY,\n pullDirection,\n preferredSide,\n wrongSideGap,\n maxRecommendedWrongSideGap: PullResistorPlacementSolver.MIN_WRONG_SIDE_GAP,\n message: `consider placing ${resistor.sourceComponentName ?? id} ${preferredSide} ${host.sourceComponentName ?? signalPort.source_component_id}.${signalPort.name} so the pull-${pullDirection} branch reads toward ${pullDirection === \"up\" ? \"power\" : \"ground\"}`\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"resistorName\", issue.resistorSchematicBox.sourceComponentName);\n addAttr(attrs, \"hostName\", issue.hostSchematicBox.sourceComponentName);\n addAttr(attrs, \"signalPin\", issue.signalPinName);\n addAttr(attrs, \"pullDirection\", issue.pullDirection);\n addAttr(attrs, \"preferredSide\", issue.preferredSide);\n addAttr(attrs, \"signalSchY\", issue.signalSchY);\n addAttr(attrs, \"wrongSideGap\", issue.wrongSideGap);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cPullResistorOnWrongSide ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/TwoPinComponentRailOrientationSolver/TwoPinComponentRailOrientationSolver.ts\nclass TwoPinComponentRailOrientationSolver extends BaseSolver {\n static EPSILON = 0.01;\n index;\n powerNets;\n groundNets;\n positiveVoltageNets = new Set;\n componentIds;\n horizontalPushbuttonComponentIds;\n issues;\n currentIndex = 0;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.issues = issues;\n this.index = new PlacementNetworkIndex(ctx);\n this.horizontalPushbuttonComponentIds = getHorizontalPushbuttonComponentIds(this.index);\n this.powerNets = new Set(this.index.powerNets);\n this.groundNets = new Set(this.index.groundNets);\n for (const element of ctx.circuitJson) {\n if (element.type === \"source_net\" \u0026\u0026 element.is_positive_voltage_source)\n this.positiveVoltageNets.add(this.index.connected(element.source_net_id));\n if (element.type !== \"source_port\")\n continue;\n const net = this.index.connected(element.source_port_id);\n if (element.provides_power || element.requires_power)\n this.powerNets.add(net);\n if (element.provides_ground || element.requires_ground)\n this.groundNets.add(net);\n }\n this.componentIds = [...this.index.components.keys()].filter((id) =\u003e this.index.portsByComponent.get(id)?.length === 2);\n this.solved = this.componentIds.length === 0;\n }\n _step() {\n const id = this.componentIds[this.currentIndex++];\n this.solved = this.currentIndex \u003e= this.componentIds.length;\n if (!id)\n return;\n const index = this.index;\n const component = index.placement(id);\n const sourceComponent = index.components.get(id);\n const nets = index.twoTerminalNets(id);\n if (!component || !nets)\n return;\n if (sourceComponent?.ftype === \"simple_inductor\" \u0026\u0026 !nets.some((net) =\u003e this.groundNets.has(net)))\n return;\n if (sourceComponent?.ftype === \"simple_diode\" \u0026\u0026 nets.every((net) =\u003e this.powerNets.has(net)))\n return;\n if (nets.some((net) =\u003e this.powerNets.has(net) \u0026\u0026 this.groundNets.has(net)))\n return;\n const railTypes = nets.map((net) =\u003e this.powerNets.has(net) ? \"power\" : this.groundNets.has(net) ? \"ground\" : undefined);\n if (railTypes.every((type) =\u003e type === undefined))\n return;\n const railType = railTypes.includes(\"power\") ? \"power\" : \"ground\";\n const candidates = nets.flatMap((net, i) =\u003e railTypes[i] === railType ? [{ net, index: i }] : []);\n const railIndex = (candidates.find(({ net }) =\u003e index.portsByNet.get(net)?.some((port) =\u003e railType === \"power\" ? port.provides_power : port.provides_ground)) ?? candidates.find(({ net }) =\u003e (railType === \"power\" ? index.powerNets : index.groundNets).has(net)) ?? candidates[0]).index;\n const rail = nets[railIndex];\n const sourcePorts = index.portsByComponent.get(id);\n const railSourcePort = sourcePorts.find((port) =\u003e index.connected(port.source_port_id) === rail);\n const otherSourcePort = sourcePorts.find((port) =\u003e port !== railSourcePort);\n const railPort = index.port(railSourcePort);\n const otherPort = index.port(otherSourcePort);\n if (!railPort || !otherPort)\n return;\n const otherNet = index.connected(otherSourcePort.source_port_id);\n const otherIsGround = this.groundNets.has(otherNet);\n const isSupplyToSignalResistor = sourceComponent?.ftype === \"simple_resistor\" \u0026\u0026 !this.powerNets.has(otherNet) \u0026\u0026 !otherIsGround;\n const invertedRails = this.positiveVoltageNets.has(rail) \u0026\u0026 (otherIsGround || isSupplyToSignalResistor) \u0026\u0026 Math.abs(railPort.center.x - otherPort.center.x) \u003c= TwoPinComponentRailOrientationSolver.EPSILON \u0026\u0026 railPort.center.y \u003c otherPort.center.y - TwoPinComponentRailOrientationSolver.EPSILON \u0026\u0026 railPort.facing_direction === \"down\" \u0026\u0026 otherPort.facing_direction === \"up\";\n if (invertedRails) {\n this.issues.push({\n lineItemType: \"TwoPinComponentHasInvertedRails\",\n schematicBox: component,\n railSourcePortId: railSourcePort.source_port_id,\n railPinName: railSourcePort.name,\n railType: \"power\",\n deltaSchRotation: 180,\n suggestedRailFacingDirection: \"up\",\n message: `rotate ${component.sourceComponentName ?? id} by 180° so its positive-supply pin faces up and its ${otherIsGround ? \"ground\" : \"signal\"} pin faces down; preserve pin connections and reroute attached traces`\n });\n return;\n }\n const horizontal = Math.abs(railPort.center.y - otherPort.center.y) \u003c= TwoPinComponentRailOrientationSolver.EPSILON \u0026\u0026 Math.abs(railPort.center.x - otherPort.center.x) \u003e TwoPinComponentRailOrientationSolver.EPSILON \u0026\u0026 (railPort.facing_direction === \"left\" \u0026\u0026 otherPort.facing_direction === \"right\" || railPort.facing_direction === \"right\" \u0026\u0026 otherPort.facing_direction === \"left\");\n if (!horizontal)\n return;\n if (this.horizontalPushbuttonComponentIds.has(id))\n return;\n const suggestedRailFacingDirection = railType === \"power\" ? \"up\" : \"down\";\n const deltaSchRotation = railPort.facing_direction === \"left\" === (railType === \"power\") ? -90 : 90;\n this.issues.push({\n lineItemType: \"TwoPinComponentShouldBeVertical\",\n schematicBox: component,\n railSourcePortId: railSourcePort.source_port_id,\n railPinName: railSourcePort.name,\n railType,\n deltaSchRotation,\n suggestedRailFacingDirection,\n message: `rotate ${component.sourceComponentName ?? id} by ${deltaSchRotation}° so its ${railType}-connected pin faces ${suggestedRailFacingDirection} and the component is vertical`\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"componentName\", issue.schematicBox.sourceComponentName);\n addAttr(attrs, \"railPin\", issue.railPinName);\n addAttr(attrs, \"railType\", issue.railType);\n addAttr(attrs, \"deltaSchRotation\", issue.deltaSchRotation);\n addAttr(attrs, \"suggestedRailFacingDirection\", issue.suggestedRailFacingDirection);\n addAttr(attrs, \"message\", issue.message);\n return `\u003c${issue.lineItemType} ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/utils/schematic-box-components.ts\nfunction getSchematicBoxComponentIds(circuitJson) {\n return new Set(circuitJson.flatMap((element) =\u003e element.type === \"schematic_component\" \u0026\u0026 element.is_box_with_pins !== false \u0026\u0026 !element.symbol_name \u0026\u0026 !element.schematic_symbol_id ? [element.schematic_component_id] : []));\n}\n\n// ../../work/placement-analysis/lib/solvers/SchematicBoxInnerLabelCollisionSolver/SchematicBoxInnerLabelCollisionSolver.ts\nclass SchematicBoxInnerLabelCollisionSolver extends BaseSolver {\n params;\n MESSAGE = \"Inner labels are colliding. Increase the schWidth or schHeight.\";\n PIN_LABEL_EDGE_PADDING = 0.1;\n PIN_LABEL_TEXT_HEIGHT = 0.15;\n PIN_NAME_CHARACTER_WIDTH = 0.095;\n FALLBACK_CHARACTER_WIDTH = 0.13;\n INNER_LABEL_COLLISION_PADDING = 0.02;\n COLLISION_COMPARISON_EPSILON = 0.000000001;\n entries;\n placementById;\n sourcePortById;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n const { circuitJson, componentPlacements } = params.ctx;\n this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);\n this.sourcePortById = this.getSourcePortById(circuitJson);\n const boxIds = getSchematicBoxComponentIds(circuitJson);\n this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson)).filter(([id]) =\u003e boxIds.has(id));\n this.solved = this.entries.length === 0;\n }\n _step() {\n const entry = this.entries[this.currentIndex++];\n if (!entry) {\n this.solved = true;\n return;\n }\n this.solved = this.currentIndex \u003e= this.entries.length;\n const [schematicComponentId, ports] = entry;\n const schematicBox = this.placementById.get(schematicComponentId);\n if (!schematicBox)\n return;\n const bounds = this.getCenteredRectBounds(schematicBox);\n const labelRects = this.getLabelRects(bounds, ports, this.sourcePortById);\n if (labelRects.length === 0)\n return;\n const collisionSummary = this.getCollisionSummary(labelRects);\n if (collisionSummary.overlappingSides.length === 0)\n return;\n this.params.issues.push({\n lineItemType: \"SchematicBoxInnerLabelCollision\",\n schematicBox,\n overlappingSides: collisionSummary.overlappingSides,\n message: this.MESSAGE\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"message\", issue.message);\n addAttr(attrs, \"componentName\", issue.schematicBox.sourceComponentName);\n addAttr(attrs, \"currentSchWidth\", issue.schematicBox.width);\n addAttr(attrs, \"currentSchHeight\", issue.schematicBox.height);\n addAttr(attrs, \"overlappingSides\", issue.overlappingSides.join(\",\"));\n return `\u003cSchematicBoxInnerLabelCollision ${attrs.join(\" \")} /\u003e`;\n }\n isSchematicPort(el) {\n return el.type === \"schematic_port\";\n }\n isSourcePort(el) {\n return el.type === \"source_port\";\n }\n isSchematicSide(side) {\n return side === \"left\" || side === \"right\" || side === \"top\" || side === \"bottom\";\n }\n isPinNameLabel(label, sourcePort) {\n if (!sourcePort)\n return false;\n return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);\n }\n estimateLabelLength(label, sourcePort) {\n return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);\n }\n hasCollision(requiredGrowth) {\n return requiredGrowth \u003e this.COLLISION_COMPARISON_EPSILON;\n }\n getCenteredRectBounds(box) {\n return {\n left: box.schX - box.width / 2,\n right: box.schX + box.width / 2,\n top: box.schY + box.height / 2,\n bottom: box.schY - box.height / 2\n };\n }\n getSourcePortById(circuitJson) {\n return new Map(circuitJson.filter((el) =\u003e this.isSourcePort(el)).map((sp) =\u003e [sp.source_port_id, sp]));\n }\n getPlacementBySchematicComponentId(componentPlacements) {\n return new Map(componentPlacements.filter((p) =\u003e p.schematicComponentId).map((p) =\u003e [p.schematicComponentId, p]));\n }\n getPortsBySchematicComponentId(circuitJson) {\n const map = new Map;\n for (const port of circuitJson.filter((el) =\u003e this.isSchematicPort(el))) {\n if (!port.schematic_component_id)\n continue;\n if (!this.isSchematicSide(port.side_of_component))\n continue;\n const ports = map.get(port.schematic_component_id);\n if (ports)\n ports.push(port);\n else\n map.set(port.schematic_component_id, [port]);\n }\n return map;\n }\n getLabelRects(bounds, ports, sourcePortById) {\n const rects = [];\n for (const port of ports) {\n if (!this.isSchematicSide(port.side_of_component))\n continue;\n if (!port.display_pin_label)\n continue;\n const labelLength = this.estimateLabelLength(port.display_pin_label, sourcePortById.get(port.source_port_id));\n const halfTextHeight = this.PIN_LABEL_TEXT_HEIGHT / 2;\n switch (port.side_of_component) {\n case \"left\": {\n const xMin = bounds.left + this.PIN_LABEL_EDGE_PADDING;\n rects.push({\n side: port.side_of_component,\n xMin,\n xMax: xMin + labelLength,\n yMin: port.center.y - halfTextHeight,\n yMax: port.center.y + halfTextHeight\n });\n break;\n }\n case \"right\": {\n const xMax = bounds.right - this.PIN_LABEL_EDGE_PADDING;\n rects.push({\n side: port.side_of_component,\n xMin: xMax - labelLength,\n xMax,\n yMin: port.center.y - halfTextHeight,\n yMax: port.center.y + halfTextHeight\n });\n break;\n }\n case \"top\": {\n const yMax = bounds.top - this.PIN_LABEL_EDGE_PADDING;\n rects.push({\n side: port.side_of_component,\n xMin: port.center.x - halfTextHeight,\n xMax: port.center.x + halfTextHeight,\n yMin: yMax - labelLength,\n yMax\n });\n break;\n }\n case \"bottom\": {\n const yMin = bounds.bottom + this.PIN_LABEL_EDGE_PADDING;\n rects.push({\n side: port.side_of_component,\n xMin: port.center.x - halfTextHeight,\n xMax: port.center.x + halfTextHeight,\n yMin,\n yMax: yMin + labelLength\n });\n break;\n }\n }\n }\n return rects;\n }\n getCollisionSummary(rects) {\n const overlappingSides = new Set;\n for (let i = 0;i \u003c rects.length; i++) {\n for (let j = i + 1;j \u003c rects.length; j++) {\n const a = rects[i];\n const b = rects[j];\n if (a.side === b.side)\n continue;\n if (!this.rectsOverlap(a, b))\n continue;\n overlappingSides.add(a.side);\n overlappingSides.add(b.side);\n }\n }\n return {\n overlappingSides: this.sortSides(Array.from(overlappingSides))\n };\n }\n rectsOverlap(a, b) {\n return this.hasCollision(Math.min(a.xMax, b.xMax) - Math.max(a.xMin, b.xMin) + this.INNER_LABEL_COLLISION_PADDING) \u0026\u0026 this.hasCollision(Math.min(a.yMax, b.yMax) - Math.max(a.yMin, b.yMin) + this.INNER_LABEL_COLLISION_PADDING);\n }\n sortSides(sides) {\n const order = {\n left: 0,\n right: 1,\n top: 2,\n bottom: 3\n };\n return sides.sort((a, b) =\u003e order[a] - order[b]);\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/SchematicBoxOverlapSolver/SchematicBoxOverlapSolver.ts\nclass SchematicBoxOverlapSolver extends BaseSolver {\n params;\n placements;\n firstIndex = 0;\n secondIndex = 1;\n constructor(params) {\n super();\n this.params = params;\n this.placements = params.ctx.componentPlacements;\n this.solved = this.placements.length \u003c 2;\n }\n _step() {\n if (this.firstIndex \u003e= this.placements.length - 1) {\n this.solved = true;\n return;\n }\n const overlap = this.getComponentOverlap(this.placements[this.firstIndex], this.placements[this.secondIndex]);\n if (overlap)\n this.params.issues.push(overlap);\n this.secondIndex++;\n if (this.secondIndex \u003e= this.placements.length) {\n this.firstIndex++;\n this.secondIndex = this.firstIndex + 1;\n }\n this.solved = this.firstIndex \u003e= this.placements.length - 1;\n }\n getCenteredRectBounds(box) {\n return {\n left: box.schX - box.width / 2,\n right: box.schX + box.width / 2,\n top: box.schY - box.height / 2,\n bottom: box.schY + box.height / 2\n };\n }\n getOverlapCorrectionSuggestions({\n firstComponent,\n secondComponent,\n overlapWidth,\n overlapHeight\n }) {\n const firstArea = firstComponent.width * firstComponent.height;\n const secondArea = secondComponent.width * secondComponent.height;\n const target = firstArea \u003c= secondArea ? firstComponent : secondComponent;\n const other = target === firstComponent ? secondComponent : firstComponent;\n const deltaSchX = target.schX \u003c= other.schX ? -overlapWidth : overlapWidth;\n const deltaSchY = target.schY \u003c= other.schY ? -overlapHeight : overlapHeight;\n return [\n {\n targetComponentName: target.sourceComponentName,\n deltaSchX,\n deltaSchY: 0,\n newSchX: target.schX + deltaSchX,\n newSchY: target.schY\n },\n {\n targetComponentName: target.sourceComponentName,\n deltaSchX: 0,\n deltaSchY,\n newSchX: target.schX,\n newSchY: target.schY + deltaSchY\n }\n ];\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"component1Name\", issue.firstComponent.sourceComponentName);\n addAttr(attrs, \"component2Name\", issue.secondComponent.sourceComponentName);\n addAttr(attrs, \"component1SchX\", issue.firstComponent.schX);\n addAttr(attrs, \"component1SchY\", issue.firstComponent.schY);\n addAttr(attrs, \"component2SchX\", issue.secondComponent.schX);\n addAttr(attrs, \"component2SchY\", issue.secondComponent.schY);\n addAttr(attrs, \"overlapWidth\", issue.overlapWidth);\n addAttr(attrs, \"overlapHeight\", issue.overlapHeight);\n return [\n `\u003cComponentOverlap ${attrs.join(\" \")}\u003e`,\n ...issue.correctionSuggestions.map(SchematicBoxOverlapSolver.correctionSuggestionToString),\n \"\u003c/ComponentOverlap\u003e\"\n ].join(`\n`);\n }\n static correctionSuggestionToString(suggestion) {\n const attrs = [];\n addAttr(attrs, \"target\", suggestion.targetComponentName);\n if (suggestion.deltaSchX !== 0) {\n addAttr(attrs, \"newSchX\", suggestion.newSchX);\n addAttr(attrs, \"deltaSchX\", suggestion.deltaSchX, { formatDelta: true });\n }\n if (suggestion.deltaSchY !== 0) {\n addAttr(attrs, \"newSchY\", suggestion.newSchY);\n addAttr(attrs, \"deltaSchY\", suggestion.deltaSchY, { formatDelta: true });\n }\n return `\u003cOverlapCorrectionSuggestion ${attrs.join(\" \")} /\u003e`;\n }\n getComponentOverlap(firstComponent, secondComponent) {\n if (firstComponent.schematicSheetId !== secondComponent.schematicSheetId)\n return null;\n const a = this.getCenteredRectBounds(firstComponent);\n const b = this.getCenteredRectBounds(secondComponent);\n const overlapWidth = Math.min(a.right, b.right) - Math.max(a.left, b.left);\n const overlapHeight = Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top);\n if (overlapWidth \u003c= 0 || overlapHeight \u003c= 0)\n return null;\n return {\n lineItemType: \"ComponentOverlap\",\n firstComponent,\n secondComponent,\n overlapWidth,\n overlapHeight,\n correctionSuggestions: this.getOverlapCorrectionSuggestions({\n firstComponent,\n secondComponent,\n overlapWidth,\n overlapHeight\n })\n };\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/SchematicBoxTooWideSolver/SchematicBoxTooWideSolver.ts\nclass SchematicBoxTooWideSolver extends BaseSolver {\n params;\n SCHEMATIC_BOX_TOO_WIDE_MESSAGE = \"Shrink schematic box width\";\n PIN_HEADER_MAX_ALLOWED_GAP = 0.1;\n GENERIC_MAX_ALLOWED_GAP = 1;\n PIN_LABEL_EDGE_PADDING = 0.1;\n PIN_NAME_CHARACTER_WIDTH = 0.095;\n FALLBACK_CHARACTER_WIDTH = 0.13;\n GAP_COMPARISON_EPSILON = 0.000000001;\n entries;\n placementById;\n sourcePortById;\n sourceComponentById;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n const { circuitJson, componentPlacements } = params.ctx;\n this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);\n this.sourcePortById = this.getSourcePortById(circuitJson);\n this.sourceComponentById = this.getSourceComponentById(circuitJson);\n const boxIds = getSchematicBoxComponentIds(circuitJson);\n this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson)).filter(([id]) =\u003e boxIds.has(id));\n this.solved = this.entries.length === 0;\n }\n _step() {\n const entry = this.entries[this.currentIndex++];\n if (!entry) {\n this.solved = true;\n return;\n }\n this.solved = this.currentIndex \u003e= this.entries.length;\n const [schematicComponentId, ports] = entry;\n const schematicBox = this.placementById.get(schematicComponentId);\n if (!schematicBox)\n return;\n const sourceComponent = schematicBox.sourceComponentId ? this.sourceComponentById.get(schematicBox.sourceComponentId) : undefined;\n if (sourceComponent?.ftype === \"simple_connector\" \u0026\u0026 sourceComponent.standard === \"usb_c\")\n return;\n const bounds = this.getCenteredRectBounds(schematicBox);\n const leftCol = this.getLabelColumn(\"left\", ports, this.sourcePortById);\n const rightCol = this.getLabelColumn(\"right\", ports, this.sourcePortById);\n const ftype = this.getSourceComponentFtype(schematicBox, this.sourceComponentById);\n let measuredSpace;\n if (leftCol \u0026\u0026 rightCol) {\n measuredSpace = this.getInnerLabelEdge(bounds, rightCol) - this.getInnerLabelEdge(bounds, leftCol);\n } else if (leftCol \u0026\u0026 leftCol.labelCount \u003e= 4) {\n measuredSpace = bounds.right - this.getInnerLabelEdge(bounds, leftCol);\n } else if (rightCol \u0026\u0026 rightCol.labelCount \u003e= 4) {\n measuredSpace = this.getInnerLabelEdge(bounds, rightCol) - bounds.left;\n }\n if (measuredSpace === undefined)\n return;\n const maxAllowed = ftype === \"simple_pin_header\" ? this.PIN_HEADER_MAX_ALLOWED_GAP : this.GENERIC_MAX_ALLOWED_GAP;\n if (!this.exceedsMaxAllowedGap(measuredSpace, maxAllowed))\n return;\n const suggestedSchWidth = this.getSuggestedWidth({\n measuredInnerLabelHorizontalEmptySpace: measuredSpace,\n maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,\n currentWidth: schematicBox.width\n });\n if (ftype === \"simple_pin_header\") {\n this.params.issues.push({\n lineItemType: \"PinHeaderSchematicBoxTooWide\",\n schematicBox,\n measuredInnerLabelHorizontalEmptySpace: measuredSpace,\n maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,\n suggestedSchWidth,\n message: this.SCHEMATIC_BOX_TOO_WIDE_MESSAGE\n });\n } else {\n this.params.issues.push({\n lineItemType: \"GenericSchematicBoxTooWide\",\n schematicBox,\n measuredInnerLabelHorizontalEmptySpace: measuredSpace,\n maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,\n suggestedSchWidth,\n message: this.SCHEMATIC_BOX_TOO_WIDE_MESSAGE\n });\n }\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"message\", issue.message);\n addAttr(attrs, \"componentName\", issue.schematicBox.sourceComponentName);\n addAttr(attrs, \"currentSchWidth\", issue.schematicBox.width);\n addAttr(attrs, \"measuredInnerLabelHorizontalEmptySpace\", issue.measuredInnerLabelHorizontalEmptySpace);\n addAttr(attrs, \"maxAllowedInnerLabelHorizontalEmptySpace\", issue.maxAllowedInnerLabelHorizontalEmptySpace);\n addAttr(attrs, \"suggestedSchWidth\", issue.suggestedSchWidth);\n return `\u003c${issue.lineItemType} ${attrs.join(\" \")} /\u003e`;\n }\n isSchematicPort(el) {\n return el.type === \"schematic_port\";\n }\n isSourcePort(el) {\n return el.type === \"source_port\";\n }\n isHorizontalSide(side) {\n return side === \"left\" || side === \"right\";\n }\n getSourceComponentWithFtype(el) {\n if (el.type !== \"source_component\" || !(\"source_component_id\" in el) || typeof el.source_component_id !== \"string\")\n return null;\n return {\n type: \"source_component\",\n source_component_id: el.source_component_id,\n standard: \"standard\" in el \u0026\u0026 typeof el.standard === \"string\" ? el.standard : undefined,\n ftype: \"ftype\" in el \u0026\u0026 typeof el.ftype === \"string\" ? el.ftype : undefined\n };\n }\n isPinNameLabel(label, sourcePort) {\n if (!sourcePort)\n return false;\n return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);\n }\n estimateLabelWidth(label, sourcePort) {\n return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);\n }\n exceedsMaxAllowedGap(measured, maxAllowed) {\n return measured - maxAllowed \u003e this.GAP_COMPARISON_EPSILON;\n }\n getCenteredRectBounds(box) {\n return {\n left: box.schX - box.width / 2,\n right: box.schX + box.width / 2,\n top: box.schY + box.height / 2,\n bottom: box.schY - box.height / 2\n };\n }\n getSourcePortById(circuitJson) {\n return new Map(circuitJson.filter((el) =\u003e this.isSourcePort(el)).map((sp) =\u003e [sp.source_port_id, sp]));\n }\n getSourceComponentById(circuitJson) {\n return new Map(circuitJson.flatMap((el) =\u003e {\n const sc = this.getSourceComponentWithFtype(el);\n return sc ? [sc] : [];\n }).map((sc) =\u003e [sc.source_component_id, sc]));\n }\n getPlacementBySchematicComponentId(componentPlacements) {\n return new Map(componentPlacements.filter((p) =\u003e p.schematicComponentId).map((p) =\u003e [p.schematicComponentId, p]));\n }\n getPortsBySchematicComponentId(circuitJson) {\n const map = new Map;\n for (const port of circuitJson.filter((el) =\u003e this.isSchematicPort(el))) {\n if (!port.schematic_component_id)\n continue;\n if (!this.isHorizontalSide(port.side_of_component))\n continue;\n const ports = map.get(port.schematic_component_id);\n if (ports)\n ports.push(port);\n else\n map.set(port.schematic_component_id, [port]);\n }\n return map;\n }\n getSourceComponentFtype(schematicBox, sourceComponentById) {\n return schematicBox.sourceComponentId ? sourceComponentById.get(schematicBox.sourceComponentId)?.ftype : undefined;\n }\n getLabelColumn(side, ports, sourcePortById) {\n const widths = ports.filter((p) =\u003e p.side_of_component === side).flatMap((p) =\u003e p.display_pin_label ? [\n this.estimateLabelWidth(p.display_pin_label, sourcePortById.get(p.source_port_id))\n ] : []);\n if (widths.length === 0)\n return null;\n return {\n side,\n labelCount: widths.length,\n maxLabelWidth: Math.max(...widths)\n };\n }\n getInnerLabelEdge(bounds, col) {\n return col.side === \"left\" ? bounds.left + this.PIN_LABEL_EDGE_PADDING + col.maxLabelWidth : bounds.right - this.PIN_LABEL_EDGE_PADDING - col.maxLabelWidth;\n }\n getSuggestedWidth(input) {\n return input.currentWidth - input.measuredInnerLabelHorizontalEmptySpace + input.maxAllowedInnerLabelHorizontalEmptySpace;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/SchematicPinPaddingToEdgeSolver/SchematicPinPaddingToEdgeSolver.ts\nclass SchematicPinPaddingToEdgeSolver extends BaseSolver {\n params;\n MESSAGE = \"Move schematic pins closer to the box edge or change the schematic box\";\n PIN_NAME_CHARACTER_WIDTH = 0.095;\n FALLBACK_CHARACTER_WIDTH = 0.13;\n GAP_COMPARISON_EPSILON = 0.000000001;\n entries;\n placementById;\n schematicComponentById;\n sourcePortById;\n currentIndex = 0;\n constructor(params) {\n super();\n this.params = params;\n const { circuitJson, componentPlacements } = params.ctx;\n this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);\n this.schematicComponentById = this.getSchematicComponentById(circuitJson);\n this.sourcePortById = this.getSourcePortById(circuitJson);\n const boxIds = getSchematicBoxComponentIds(circuitJson);\n this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson)).filter(([id]) =\u003e boxIds.has(id));\n this.solved = this.entries.length === 0;\n }\n _step() {\n const entry = this.entries[this.currentIndex++];\n if (!entry) {\n this.solved = true;\n return;\n }\n this.solved = this.currentIndex \u003e= this.entries.length;\n const [schematicComponentId, ports] = entry;\n const schematicBox = this.placementById.get(schematicComponentId);\n if (!schematicBox)\n return;\n const pinSpacing = this.getPinSpacing(schematicBox, this.schematicComponentById);\n if (pinSpacing === null)\n return;\n const maxLabelLengthBySide = this.getMaxLabelLengthBySide(ports, this.sourcePortById);\n const portsBySide = new Map;\n for (const port of ports) {\n if (!this.isSchematicSide(port.side_of_component))\n continue;\n const sidePorts = portsBySide.get(port.side_of_component) ?? [];\n sidePorts.push(port);\n portsBySide.set(port.side_of_component, sidePorts);\n }\n const useLabelAwareMaxPadding = this.hasPinsOnAllSides(portsBySide);\n const candidates = [];\n for (const [pinSide, sidePorts] of portsBySide) {\n if (sidePorts.length === 1)\n continue;\n for (const edgeSide of this.getBoxEdgeSidesForPinSide(pinSide)) {\n const outerPin = this.getOuterPinBySide(edgeSide, sidePorts);\n if (!outerPin)\n continue;\n const measuredPadding = this.getPinPaddingToEdge(schematicBox, outerPin, edgeSide);\n const maxAllowedPadding = useLabelAwareMaxPadding ? this.getMaxAllowedPinPadding(pinSpacing, edgeSide, maxLabelLengthBySide) : pinSpacing;\n if (!this.exceedsMaxAllowedGap(measuredPadding, maxAllowedPadding + pinSpacing))\n continue;\n candidates.push({\n schematicBox,\n pinSide,\n edgeSide,\n pinName: this.getPinName(outerPin, this.sourcePortById),\n measuredPadding,\n maxAllowedPadding\n });\n }\n }\n if (!candidates.length)\n return;\n const details = candidates.map((candidate) =\u003e this.createIssue(candidate));\n const representative = details.reduce((a, b) =\u003e b.excessPadding \u003e a.excessPadding ? b : a);\n const widths = details.flatMap((detail) =\u003e detail.suggestedSchWidth === undefined ? [] : [detail.suggestedSchWidth]);\n const heights = details.flatMap((detail) =\u003e detail.suggestedSchHeight === undefined ? [] : [detail.suggestedSchHeight]);\n const dimensions = [\n widths.length ? \"width\" : \"\",\n heights.length ? \"height\" : \"\"\n ].filter(Boolean).join(\" and \");\n this.params.issues.push({\n ...representative,\n paddingDetails: details.map(({\n pinSide,\n edgeSide,\n pinName,\n measuredPadding,\n maxAllowedPadding,\n excessPadding\n }) =\u003e ({\n pinSide,\n edgeSide,\n pinName,\n measuredPadding,\n maxAllowedPadding,\n excessPadding\n })),\n suggestedSchWidth: widths.length ? Math.max(...widths) : undefined,\n suggestedSchHeight: heights.length ? Math.max(...heights) : undefined,\n message: `${this.MESSAGE} ${dimensions}`\n });\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"message\", issue.message);\n addAttr(attrs, \"componentName\", issue.schematicBox.sourceComponentName);\n if (issue.paddingDetails) {\n addAttr(attrs, \"pinSides\", [...new Set(issue.paddingDetails.map((detail) =\u003e detail.pinSide))].join(\",\"));\n addAttr(attrs, \"edgeSides\", [\n ...new Set(issue.paddingDetails.map((detail) =\u003e detail.edgeSide))\n ].join(\",\"));\n } else {\n addAttr(attrs, \"pinSide\", issue.pinSide);\n addAttr(attrs, \"edgeSide\", issue.edgeSide);\n addAttr(attrs, \"pinName\", issue.pinName);\n addAttr(attrs, \"measuredPadding\", issue.measuredPadding);\n addAttr(attrs, \"maxAllowedPadding\", issue.maxAllowedPadding);\n addAttr(attrs, \"excessPadding\", issue.excessPadding);\n }\n addAttr(attrs, \"suggestedSchWidth\", issue.suggestedSchWidth);\n addAttr(attrs, \"suggestedSchHeight\", issue.suggestedSchHeight);\n return `\u003cSchematicPinPaddingToEdgeTooLarge ${attrs.join(\" \")} /\u003e`;\n }\n isSchematicPort(el) {\n return el.type === \"schematic_port\";\n }\n isSourcePort(el) {\n return el.type === \"source_port\";\n }\n isSchematicComponent(el) {\n return el.type === \"schematic_component\";\n }\n isHorizontalSide(side) {\n return side === \"left\" || side === \"right\";\n }\n isVerticalSide(side) {\n return side === \"top\" || side === \"bottom\";\n }\n isSchematicSide(side) {\n return this.isHorizontalSide(side) || this.isVerticalSide(side);\n }\n isPinNameLabel(label, sourcePort) {\n if (!sourcePort)\n return false;\n return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);\n }\n estimateLabelWidth(label, sourcePort) {\n return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);\n }\n exceedsMaxAllowedGap(measured, maxAllowed) {\n return measured - maxAllowed \u003e this.GAP_COMPARISON_EPSILON;\n }\n getCenteredRectBounds(box) {\n return {\n left: box.schX - box.width / 2,\n right: box.schX + box.width / 2,\n top: box.schY + box.height / 2,\n bottom: box.schY - box.height / 2\n };\n }\n getSourcePortById(circuitJson) {\n return new Map(circuitJson.filter((el) =\u003e this.isSourcePort(el)).map((sp) =\u003e [sp.source_port_id, sp]));\n }\n getSchematicComponentById(circuitJson) {\n return new Map(circuitJson.filter((el) =\u003e this.isSchematicComponent(el)).map((sc) =\u003e [sc.schematic_component_id, sc]));\n }\n getPlacementBySchematicComponentId(componentPlacements) {\n return new Map(componentPlacements.filter((p) =\u003e p.schematicComponentId).map((p) =\u003e [p.schematicComponentId, p]));\n }\n getPortsBySchematicComponentId(circuitJson) {\n const map = new Map;\n for (const port of circuitJson.filter((el) =\u003e this.isSchematicPort(el))) {\n if (!port.schematic_component_id)\n continue;\n if (!this.isSchematicSide(port.side_of_component))\n continue;\n const ports = map.get(port.schematic_component_id);\n if (ports)\n ports.push(port);\n else\n map.set(port.schematic_component_id, [port]);\n }\n return map;\n }\n getPinSpacing(schematicBox, schematicComponentById) {\n if (!schematicBox.schematicComponentId)\n return null;\n const sc = schematicComponentById.get(schematicBox.schematicComponentId);\n return typeof sc?.pin_spacing === \"number\" ? sc.pin_spacing : null;\n }\n getPinName(port, sourcePortById) {\n const sp = sourcePortById.get(port.source_port_id);\n if (sp?.name)\n return sp.name;\n if (port.display_pin_label)\n return port.display_pin_label;\n if (sp?.pin_number !== undefined)\n return String(sp.pin_number);\n return;\n }\n getMaxLabelLengthBySide(ports, sourcePortById) {\n const result = {\n left: 0,\n right: 0,\n top: 0,\n bottom: 0\n };\n for (const port of ports) {\n if (!this.isSchematicSide(port.side_of_component))\n continue;\n if (!port.display_pin_label)\n continue;\n result[port.side_of_component] = Math.max(result[port.side_of_component], this.estimateLabelWidth(port.display_pin_label, sourcePortById.get(port.source_port_id)));\n }\n return result;\n }\n getOuterPinBySide(edgeSide, ports) {\n if (ports.length === 0)\n return null;\n switch (edgeSide) {\n case \"top\":\n return ports.reduce((a, b) =\u003e b.center.y \u003e a.center.y ? b : a);\n case \"bottom\":\n return ports.reduce((a, b) =\u003e b.center.y \u003c a.center.y ? b : a);\n case \"left\":\n return ports.reduce((a, b) =\u003e b.center.x \u003c a.center.x ? b : a);\n case \"right\":\n return ports.reduce((a, b) =\u003e b.center.x \u003e a.center.x ? b : a);\n }\n }\n getPinPaddingToEdge(schematicBox, port, edgeSide) {\n const bounds = this.getCenteredRectBounds(schematicBox);\n switch (edgeSide) {\n case \"top\":\n return Math.max(0, bounds.top - port.center.y);\n case \"bottom\":\n return Math.max(0, port.center.y - bounds.bottom);\n case \"left\":\n return Math.max(0, port.center.x - bounds.left);\n case \"right\":\n return Math.max(0, bounds.right - port.center.x);\n }\n }\n getBoxEdgeSidesForPinSide(pinSide) {\n return this.isHorizontalSide(pinSide) ? [\"top\", \"bottom\"] : [\"left\", \"right\"];\n }\n hasPinsOnAllSides(portsBySide) {\n return portsBySide.has(\"left\") \u0026\u0026 portsBySide.has(\"right\") \u0026\u0026 portsBySide.has(\"top\") \u0026\u0026 portsBySide.has(\"bottom\");\n }\n getMaxAllowedPinPadding(spacing, edgeSide, maxLabelLengthBySide) {\n const sides = this.isHorizontalSide(edgeSide) ? [\"left\", \"right\"] : [\"top\", \"bottom\"];\n return (maxLabelLengthBySide[sides[0]] + maxLabelLengthBySide[sides[1]] + spacing) / 2;\n }\n createIssue(candidate) {\n const excessPadding = Math.max(0, candidate.measuredPadding - candidate.maxAllowedPadding);\n const reduction = excessPadding * 2;\n return {\n lineItemType: \"SchematicPinPaddingToEdgeTooLarge\",\n pinSide: candidate.pinSide,\n edgeSide: candidate.edgeSide,\n pinName: candidate.pinName,\n schematicBox: candidate.schematicBox,\n measuredPadding: candidate.measuredPadding,\n maxAllowedPadding: candidate.maxAllowedPadding,\n excessPadding,\n suggestedSchWidth: this.isHorizontalSide(candidate.pinSide) ? undefined : Math.max(0, candidate.schematicBox.width - reduction),\n suggestedSchHeight: this.isHorizontalSide(candidate.pinSide) ? Math.max(0, candidate.schematicBox.height - reduction) : undefined,\n message: this.isHorizontalSide(candidate.pinSide) ? `${this.MESSAGE} height` : `${this.MESSAGE} width`\n };\n }\n}\n\n// ../../work/placement-analysis/node_modules/circuit-json/dist/index.mjs\nvar exports_dist = {};\n__export(exports_dist, {\n wave_shape: () =\u003e wave_shape,\n voltage: () =\u003e voltage,\n visible_layer: () =\u003e visible_layer,\n unknown_error_finding_part: () =\u003e unknown_error_finding_part,\n timestamp: () =\u003e timestamp,\n time: () =\u003e time,\n supplier_name: () =\u003e supplier_name,\n supplier_footprint_mismatch_warning: () =\u003e supplier_footprint_mismatch_warning,\n spice_simulation_options: () =\u003e spice_simulation_options,\n source_unnamed_trace_warning: () =\u003e source_unnamed_trace_warning,\n source_trace_not_connected_error: () =\u003e source_trace_not_connected_error,\n source_trace: () =\u003e source_trace,\n source_simple_voltage_source: () =\u003e source_simple_voltage_source,\n source_simple_voltage_probe: () =\u003e source_simple_voltage_probe,\n source_simple_transistor: () =\u003e source_simple_transistor,\n source_simple_test_point: () =\u003e source_simple_test_point,\n source_simple_switch: () =\u003e source_simple_switch,\n source_simple_resonator: () =\u003e source_simple_resonator,\n source_simple_resistor: () =\u003e source_simple_resistor,\n source_simple_push_button: () =\u003e source_simple_push_button,\n source_simple_power_source: () =\u003e source_simple_power_source,\n source_simple_potentiometer: () =\u003e source_simple_potentiometer,\n source_simple_pinout: () =\u003e source_simple_pinout,\n source_simple_pin_header: () =\u003e source_simple_pin_header,\n source_simple_op_amp: () =\u003e source_simple_op_amp,\n source_simple_mosfet: () =\u003e source_simple_mosfet,\n source_simple_led: () =\u003e source_simple_led,\n source_simple_inductor: () =\u003e source_simple_inductor,\n source_simple_ground: () =\u003e source_simple_ground,\n source_simple_fiducial: () =\u003e source_simple_fiducial,\n source_simple_diode: () =\u003e source_simple_diode,\n source_simple_current_source: () =\u003e source_simple_current_source,\n source_simple_crystal: () =\u003e source_simple_crystal,\n source_simple_connector: () =\u003e source_simple_connector,\n source_simple_chip: () =\u003e source_simple_chip,\n source_simple_capacitor: () =\u003e source_simple_capacitor,\n source_simple_battery: () =\u003e source_simple_battery,\n source_simple_ammeter: () =\u003e source_simple_ammeter,\n source_property_ignored_warning: () =\u003e source_property_ignored_warning,\n source_project_metadata: () =\u003e source_project_metadata,\n source_port: () =\u003e source_port,\n source_pin_must_be_connected_error: () =\u003e source_pin_must_be_connected_error,\n source_pin_missing_trace_warning: () =\u003e source_pin_missing_trace_warning,\n source_pin_attributes: () =\u003e source_pin_attributes,\n source_pcb_ground_plane: () =\u003e source_pcb_ground_plane,\n source_no_power_pin_defined_warning: () =\u003e source_no_power_pin_defined_warning,\n source_no_ground_pin_defined_warning: () =\u003e source_no_ground_pin_defined_warning,\n source_net: () =\u003e source_net,\n source_missing_property_error: () =\u003e source_missing_property_error,\n source_missing_manufacturer_part_number_warning: () =\u003e source_missing_manufacturer_part_number_warning,\n source_manually_placed_via: () =\u003e source_manually_placed_via,\n source_invalid_component_property_error: () =\u003e source_invalid_component_property_error,\n source_interconnect: () =\u003e source_interconnect,\n source_i2c_misconfigured_error: () =\u003e source_i2c_misconfigured_error,\n source_group: () =\u003e source_group,\n source_failed_to_create_component_error: () =\u003e source_failed_to_create_component_error,\n source_component_pins_underspecified_warning: () =\u003e source_component_pins_underspecified_warning,\n source_component_misconfigured_error: () =\u003e source_component_misconfigured_error,\n source_component_internal_connection: () =\u003e source_component_internal_connection,\n source_component_base: () =\u003e source_component_base,\n source_board: () =\u003e source_board,\n source_ambiguous_port_reference: () =\u003e source_ambiguous_port_reference,\n size: () =\u003e size,\n simulation_voltage_source: () =\u003e simulation_voltage_source,\n simulation_voltage_probe: () =\u003e simulation_voltage_probe,\n simulation_unknown_experiment_error: () =\u003e simulation_unknown_experiment_error,\n simulation_transient_voltage_graph: () =\u003e simulation_transient_voltage_graph,\n simulation_transient_current_graph: () =\u003e simulation_transient_current_graph,\n simulation_switch: () =\u003e simulation_switch,\n simulation_spice_subcircuit: () =\u003e simulation_spice_subcircuit,\n simulation_oscilloscope_trace: () =\u003e simulation_oscilloscope_trace,\n simulation_op_amp: () =\u003e simulation_op_amp,\n simulation_experiment: () =\u003e simulation_experiment,\n simulation_dc_voltage_source: () =\u003e simulation_dc_voltage_source,\n simulation_dc_current_source: () =\u003e simulation_dc_current_source,\n simulation_current_source: () =\u003e simulation_current_source,\n simulation_current_probe: () =\u003e simulation_current_probe,\n simulation_ac_voltage_source: () =\u003e simulation_ac_voltage_source,\n simulation_ac_current_source: () =\u003e simulation_ac_current_source,\n schematic_voltage_probe: () =\u003e schematic_voltage_probe,\n schematic_trace: () =\u003e schematic_trace,\n schematic_text: () =\u003e schematic_text,\n schematic_table_cell: () =\u003e schematic_table_cell,\n schematic_table: () =\u003e schematic_table,\n schematic_symbol: () =\u003e schematic_symbol,\n schematic_sheet: () =\u003e schematic_sheet,\n schematic_rect: () =\u003e schematic_rect,\n schematic_port: () =\u003e schematic_port,\n schematic_pin_styles: () =\u003e schematic_pin_styles,\n schematic_path: () =\u003e schematic_path,\n schematic_net_label: () =\u003e schematic_net_label,\n schematic_manual_edit_conflict_warning: () =\u003e schematic_manual_edit_conflict_warning,\n schematic_line: () =\u003e schematic_line,\n schematic_layout_error: () =\u003e schematic_layout_error,\n schematic_group: () =\u003e schematic_group,\n schematic_error: () =\u003e schematic_error,\n schematic_debug_rect: () =\u003e schematic_debug_rect,\n schematic_debug_point: () =\u003e schematic_debug_point,\n schematic_debug_object_base: () =\u003e schematic_debug_object_base,\n schematic_debug_object: () =\u003e schematic_debug_object,\n schematic_debug_line: () =\u003e schematic_debug_line,\n schematic_component_port_arrangement_by_size: () =\u003e schematic_component_port_arrangement_by_size,\n schematic_component_port_arrangement_by_sides: () =\u003e schematic_component_port_arrangement_by_sides,\n schematic_component: () =\u003e schematic_component,\n schematic_circle: () =\u003e schematic_circle,\n schematic_box: () =\u003e schematic_box,\n schematic_arc: () =\u003e schematic_arc,\n route_hint_point: () =\u003e route_hint_point,\n rotation: () =\u003e rotation,\n ring: () =\u003e ring,\n resistance: () =\u003e resistance,\n position3: () =\u003e position3,\n position: () =\u003e position,\n port_arrangement: () =\u003e port_arrangement,\n point_with_bulge: () =\u003e point_with_bulge,\n point3: () =\u003e point3,\n point: () =\u003e point,\n pcb_via_trace_clearance_error: () =\u003e pcb_via_trace_clearance_error,\n pcb_via_clearance_error: () =\u003e pcb_via_clearance_error,\n pcb_via: () =\u003e pcb_via,\n pcb_trace_warning: () =\u003e pcb_trace_warning,\n pcb_trace_route_point_wire: () =\u003e pcb_trace_route_point_wire,\n pcb_trace_route_point_via: () =\u003e pcb_trace_route_point_via,\n pcb_trace_route_point_through_pad: () =\u003e pcb_trace_route_point_through_pad,\n pcb_trace_route_point: () =\u003e pcb_trace_route_point,\n pcb_trace_missing_error: () =\u003e pcb_trace_missing_error,\n pcb_trace_hint: () =\u003e pcb_trace_hint,\n pcb_trace_error: () =\u003e pcb_trace_error,\n pcb_trace: () =\u003e pcb_trace,\n pcb_thermal_spoke: () =\u003e pcb_thermal_spoke,\n pcb_text: () =\u003e pcb_text,\n pcb_solder_paste: () =\u003e pcb_solder_paste,\n pcb_smtpad_pill: () =\u003e pcb_smtpad_pill,\n pcb_smtpad: () =\u003e pcb_smtpad,\n pcb_silkscreen_text: () =\u003e pcb_silkscreen_text,\n pcb_silkscreen_rect: () =\u003e pcb_silkscreen_rect,\n pcb_silkscreen_pill: () =\u003e pcb_silkscreen_pill,\n pcb_silkscreen_path: () =\u003e pcb_silkscreen_path,\n pcb_silkscreen_oval: () =\u003e pcb_silkscreen_oval,\n pcb_silkscreen_line: () =\u003e pcb_silkscreen_line,\n pcb_silkscreen_graphic_brep: () =\u003e pcb_silkscreen_graphic_brep,\n pcb_silkscreen_graphic: () =\u003e pcb_silkscreen_graphic,\n pcb_silkscreen_circle: () =\u003e pcb_silkscreen_circle,\n pcb_route_hints: () =\u003e pcb_route_hints,\n pcb_route_hint: () =\u003e pcb_route_hint,\n pcb_port_not_matched_error: () =\u003e pcb_port_not_matched_error,\n pcb_port_not_connected_error: () =\u003e pcb_port_not_connected_error,\n pcb_port: () =\u003e pcb_port,\n pcb_plated_hole: () =\u003e pcb_plated_hole,\n pcb_placement_error: () =\u003e pcb_placement_error,\n pcb_panelization_placement_error: () =\u003e pcb_panelization_placement_error,\n pcb_panel: () =\u003e pcb_panel,\n pcb_pad_trace_clearance_error: () =\u003e pcb_pad_trace_clearance_error,\n pcb_pad_pad_clearance_error: () =\u003e pcb_pad_pad_clearance_error,\n pcb_note_text: () =\u003e pcb_note_text,\n pcb_note_rect: () =\u003e pcb_note_rect,\n pcb_note_path: () =\u003e pcb_note_path,\n pcb_note_line: () =\u003e pcb_note_line,\n pcb_note_dimension: () =\u003e pcb_note_dimension,\n pcb_net: () =\u003e pcb_net,\n pcb_missing_footprint_error: () =\u003e pcb_missing_footprint_error,\n pcb_manual_edit_conflict_warning: () =\u003e pcb_manual_edit_conflict_warning,\n pcb_keepout: () =\u003e pcb_keepout,\n pcb_hole_rotated_pill_shape: () =\u003e pcb_hole_rotated_pill_shape,\n pcb_hole_rect_shape: () =\u003e pcb_hole_rect_shape,\n pcb_hole_pill_shape: () =\u003e pcb_hole_pill_shape,\n pcb_hole_oval_shape: () =\u003e pcb_hole_oval_shape,\n pcb_hole_circle_shape: () =\u003e pcb_hole_circle_shape,\n pcb_hole_circle_or_square_shape: () =\u003e pcb_hole_circle_or_square_shape,\n pcb_hole: () =\u003e pcb_hole,\n pcb_group: () =\u003e pcb_group,\n pcb_ground_plane_region: () =\u003e pcb_ground_plane_region,\n pcb_ground_plane: () =\u003e pcb_ground_plane,\n pcb_footprint_overlap_error: () =\u003e pcb_footprint_overlap_error,\n pcb_fabrication_note_text: () =\u003e pcb_fabrication_note_text,\n pcb_fabrication_note_rect: () =\u003e pcb_fabrication_note_rect,\n pcb_fabrication_note_path: () =\u003e pcb_fabrication_note_path,\n pcb_fabrication_note_dimension: () =\u003e pcb_fabrication_note_dimension,\n pcb_cutout_rect: () =\u003e pcb_cutout_rect,\n pcb_cutout_polygon: () =\u003e pcb_cutout_polygon,\n pcb_cutout_path: () =\u003e pcb_cutout_path,\n pcb_cutout_circle: () =\u003e pcb_cutout_circle,\n pcb_cutout: () =\u003e pcb_cutout,\n pcb_courtyard_rect: () =\u003e pcb_courtyard_rect,\n pcb_courtyard_polygon: () =\u003e pcb_courtyard_polygon,\n pcb_courtyard_pill: () =\u003e pcb_courtyard_pill,\n pcb_courtyard_overlap_error: () =\u003e pcb_courtyard_overlap_error,\n pcb_courtyard_outline: () =\u003e pcb_courtyard_outline,\n pcb_courtyard_circle: () =\u003e pcb_courtyard_circle,\n pcb_copper_text: () =\u003e pcb_copper_text,\n pcb_copper_pour_rect: () =\u003e pcb_copper_pour_rect,\n pcb_copper_pour_polygon: () =\u003e pcb_copper_pour_polygon,\n pcb_copper_pour_brep: () =\u003e pcb_copper_pour_brep,\n pcb_copper_pour: () =\u003e pcb_copper_pour,\n pcb_connector_not_in_accessible_orientation_warning: () =\u003e pcb_connector_not_in_accessible_orientation_warning,\n pcb_component_outside_board_error: () =\u003e pcb_component_outside_board_error,\n pcb_component_not_on_board_edge_error: () =\u003e pcb_component_not_on_board_edge_error,\n pcb_component_invalid_layer_error: () =\u003e pcb_component_invalid_layer_error,\n pcb_component: () =\u003e pcb_component,\n pcb_breakout_point: () =\u003e pcb_breakout_point,\n pcb_board: () =\u003e pcb_board,\n pcb_autorouting_error: () =\u003e pcb_autorouting_error,\n pcbRenderLayer: () =\u003e pcbRenderLayer,\n parseAndConvertSiUnit: () =\u003e parseAndConvertSiUnit,\n ninePointAnchor: () =\u003e ninePointAnchor,\n ms: () =\u003e ms,\n manufacturing_drc_properties: () =\u003e manufacturing_drc_properties,\n length: () =\u003e length,\n layer_string: () =\u003e layer_string,\n layer_ref: () =\u003e layer_ref,\n kicadSymbolProperty: () =\u003e kicadSymbolProperty,\n kicadSymbolProperties: () =\u003e kicadSymbolProperties,\n kicadSymbolPinNumbers: () =\u003e kicadSymbolPinNumbers,\n kicadSymbolPinNames: () =\u003e kicadSymbolPinNames,\n kicadSymbolMetadata: () =\u003e kicadSymbolMetadata,\n kicadSymbolEffects: () =\u003e kicadSymbolEffects,\n kicadProperty: () =\u003e kicadProperty,\n kicadFootprintProperties: () =\u003e kicadFootprintProperties,\n kicadFootprintPad: () =\u003e kicadFootprintPad,\n kicadFootprintModel: () =\u003e kicadFootprintModel,\n kicadFootprintMetadata: () =\u003e kicadFootprintMetadata,\n kicadFootprintAttributes: () =\u003e kicadFootprintAttributes,\n kicadFont: () =\u003e kicadFont,\n kicadEffects: () =\u003e kicadEffects,\n kicadAt: () =\u003e kicadAt,\n inductance: () =\u003e inductance,\n getZodPrefixedIdWithDefault: () =\u003e getZodPrefixedIdWithDefault,\n frequency: () =\u003e frequency,\n external_footprint_load_error: () =\u003e external_footprint_load_error,\n experiment_type: () =\u003e experiment_type,\n duration_ms: () =\u003e duration_ms,\n distance: () =\u003e distance4,\n current: () =\u003e current,\n circuit_json_footprint_load_error: () =\u003e circuit_json_footprint_load_error,\n capacitance: () =\u003e capacitance,\n cad_model_formats: () =\u003e cad_model_formats,\n cad_model_axis_directions: () =\u003e cad_model_axis_directions,\n cad_component: () =\u003e cad_component,\n cadModelDefaultDirectionMap: () =\u003e cadModelDefaultDirectionMap,\n brep_shape: () =\u003e brep_shape,\n battery_capacity: () =\u003e battery_capacity,\n base_circuit_json_error: () =\u003e base_circuit_json_error,\n asset: () =\u003e asset,\n any_source_component: () =\u003e any_source_component,\n any_soup_element: () =\u003e any_soup_element,\n any_circuit_element: () =\u003e any_circuit_element,\n all_layers: () =\u003e all_layers\n});\n\n// ../../work/placement-analysis/node_modules/format-si-unit/dist/index.js\nvar SI_PREFIX_VALUES = /* @__PURE__ */ new Map([\n [\"T\", 1000000000000],\n [\"G\", 1e9],\n [\"M\", 1e6],\n [\"K\", 1000],\n [\"k\", 1000],\n [\"\", 1],\n [\"m\", 0.001],\n [\"µ\", 0.000001],\n [\"u\", 0.000001],\n [\"n\", 0.000000001],\n [\"p\", 0.000000000001],\n [\"f\", 0.000000000000001]\n]);\nvar SI_PREFIXES = [...SI_PREFIX_VALUES.keys()];\nfunction getSiPrefixMultiplier(prefix) {\n return SI_PREFIX_VALUES.get(prefix);\n}\nvar unitMappings = {\n Hz: {\n baseUnit: \"Hz\",\n variants: {\n MHz: 1e6,\n kHz: 1000,\n Hz: 1\n }\n },\n g: {\n baseUnit: \"g\",\n variants: {\n kg: 1000,\n g: 1\n }\n },\n Ω: {\n baseUnit: \"Ω\",\n variants: {\n mΩ: 0.001,\n mohm: 0.001,\n mOhm: 0.001,\n milliohm: 0.001,\n Ω: 1,\n ohm: 1,\n Ohm: 1,\n kΩ: 1000,\n KΩ: 1000,\n kohm: 1000,\n kOhm: 1000,\n KOhm: 1000,\n Kohm: 1000,\n MΩ: 1e6,\n Mohm: 1e6,\n MOhm: 1e6,\n megohm: 1e6,\n Megohm: 1e6,\n GΩ: 1e9,\n Gohm: 1e9,\n GOhm: 1e9,\n TΩ: 1000000000000,\n Tohm: 1000000000000,\n TOhm: 1000000000000\n }\n },\n V: {\n baseUnit: \"V\",\n variants: {\n mV: 0.001,\n V: 1,\n kV: 1000,\n KV: 1000,\n MV: 1e6,\n GV: 1e9,\n TV: 1000000000000\n }\n },\n A: {\n baseUnit: \"A\",\n variants: {\n µA: 0.000001,\n mA: 0.001,\n ma: 0.001,\n A: 1,\n kA: 1000,\n MA: 1e6\n }\n },\n F: {\n baseUnit: \"F\",\n variants: {\n pF: 0.000000000001,\n nF: 0.000000001,\n µF: 0.000001,\n uF: 0.000001,\n mF: 0.001,\n F: 1,\n kF: 1000,\n KF: 1000,\n MF: 1e6\n }\n },\n H: {\n baseUnit: \"H\",\n variants: {\n pH: 0.000000000001,\n nH: 0.000000001,\n µH: 0.000001,\n uH: 0.000001,\n mH: 0.001,\n H: 1,\n kH: 1000,\n KH: 1000,\n MH: 1e6\n }\n },\n ml: {\n baseUnit: \"ml\",\n variants: {\n ml: 1,\n mL: 1,\n l: 1000,\n L: 1000\n }\n },\n deg: {\n baseUnit: \"deg\",\n variants: {\n rad: 180 / Math.PI\n }\n },\n ms: {\n baseUnit: \"ms\",\n variants: {\n fs: 0.000000000001,\n ps: 0.000000001,\n ns: 0.000001,\n us: 0.001,\n µs: 0.001,\n ms: 1,\n s: 1000\n }\n },\n mm: {\n baseUnit: \"mm\",\n variants: {\n nm: 0.000001,\n µm: 0.001,\n um: 0.001,\n mm: 1,\n cm: 10,\n dm: 100,\n m: 1000,\n km: 1e6,\n in: 25.4,\n ft: 304.8,\n IN: 25.4,\n FT: 304.8,\n yd: 914.4,\n mi: 1609344,\n mil: 0.0254\n }\n }\n};\nvar unitMappingAndVariantSuffixes = /* @__PURE__ */ new Set;\nfor (const [baseUnit, info] of Object.entries(unitMappings)) {\n unitMappingAndVariantSuffixes.add(baseUnit);\n for (const variant of Object.keys(info.variants)) {\n unitMappingAndVariantSuffixes.add(variant);\n }\n}\nfunction getBaseTscircuitUnit(unit) {\n for (const info of Object.values(unitMappings)) {\n if (unit in info.variants) {\n return {\n baseUnit: info.baseUnit,\n conversionFactor: info.variants[unit]\n };\n }\n for (const [variant, conversionFactor] of Object.entries(info.variants)) {\n if (!unit.endsWith(variant))\n continue;\n const prefix = unit.slice(0, -variant.length);\n const prefixMultiplier = getSiPrefixMultiplier(prefix);\n if (prefixMultiplier == null)\n continue;\n return {\n baseUnit: info.baseUnit,\n conversionFactor: prefixMultiplier * conversionFactor\n };\n }\n }\n return {\n baseUnit: unit,\n conversionFactor: 1\n };\n}\nfunction parseAndConvertSiUnit(v, unitOfValue) {\n if (v === undefined || v === null)\n return { parsedUnit: null, unitOfValue: null, value: null };\n if (typeof v === \"string\" \u0026\u0026 v.match(/^-?[\\d.]+$/))\n return {\n value: Number.parseFloat(v),\n parsedUnit: null,\n unitOfValue: null\n };\n if (typeof v === \"number\")\n return { value: v, parsedUnit: null, unitOfValue: null };\n if (typeof v === \"object\" \u0026\u0026 \"x\" in v \u0026\u0026 \"y\" in v) {\n const firstResult = parseAndConvertSiUnit(v.x, unitOfValue);\n const xResult = parseAndConvertSiUnit(v.x, unitOfValue);\n const yResult = parseAndConvertSiUnit(v.y, unitOfValue);\n if (xResult.value === null || yResult.value === null) {\n return { parsedUnit: null, unitOfValue: null, value: null };\n }\n return {\n parsedUnit: firstResult.parsedUnit,\n unitOfValue: firstResult.unitOfValue,\n value: {\n x: xResult.value,\n y: yResult.value\n }\n };\n }\n const reversedInputString = v.toString().split(\"\").reverse().join(\"\");\n const unitReversed = reversedInputString.match(/[^\\d\\s]+/)?.[0];\n if (!unitReversed) {\n throw new Error(`Could not determine unit: \"${v}\"`);\n }\n const unit = unitReversed.split(\"\").reverse().join(\"\");\n const numberPart = v.slice(0, -unit.length);\n const bareSiPrefixMultiplier = getSiPrefixMultiplier(unit);\n if (unitOfValue \u0026\u0026 bareSiPrefixMultiplier != null) {\n return {\n parsedUnit: null,\n unitOfValue,\n value: Number.parseFloat(numberPart) * bareSiPrefixMultiplier\n };\n }\n if (bareSiPrefixMultiplier != null \u0026\u0026 !unitMappingAndVariantSuffixes.has(unit)) {\n return {\n parsedUnit: null,\n unitOfValue: null,\n value: Number.parseFloat(numberPart) * bareSiPrefixMultiplier\n };\n }\n const { baseUnit, conversionFactor } = getBaseTscircuitUnit(unit);\n return {\n parsedUnit: unit,\n unitOfValue: baseUnit,\n value: conversionFactor * Number.parseFloat(numberPart)\n };\n}\nvar SI_PREFIX_PATTERN = SI_PREFIXES.filter((prefix) =\u003e prefix !== \"\").sort((a, b) =\u003e b.length - a.length).map((prefix) =\u003e prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$\u0026\")).join(\"|\");\nvar SI_UNIT_PATTERN = new RegExp(`^([+-]?(?:\\\\d+(?:\\\\.\\\\d*)?|\\\\.\\\\d+)(?:[eE][+-]?\\\\d+)?)(?:(${SI_PREFIX_PATTERN}))? vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit );\nvar SI_PREFIXES2 = [\n { value: 1000000000000, symbol: \"T\" },\n { value: 1e9, symbol: \"G\" },\n { value: 1e6, symbol: \"M\" },\n { value: 1000, symbol: \"k\" },\n { value: 1, symbol: \"\" },\n { value: 0.001, symbol: \"m\" },\n { value: 0.000001, symbol: \"µ\" },\n { value: 0.000000001, symbol: \"n\" },\n { value: 0.000000000001, symbol: \"p\" }\n];\nvar FALLBACK_PREFIX = SI_PREFIXES2[SI_PREFIXES2.length - 1];\n\n// ../../work/placement-analysis/node_modules/zod/v3/external.js\nvar exports_external = {};\n__export(exports_external, {\n void: () =\u003e voidType,\n util: () =\u003e util,\n unknown: () =\u003e unknownType,\n union: () =\u003e unionType,\n undefined: () =\u003e undefinedType,\n tuple: () =\u003e tupleType,\n transformer: () =\u003e effectsType,\n symbol: () =\u003e symbolType,\n string: () =\u003e stringType,\n strictObject: () =\u003e strictObjectType,\n setErrorMap: () =\u003e setErrorMap,\n set: () =\u003e setType,\n record: () =\u003e recordType,\n quotelessJson: () =\u003e quotelessJson,\n promise: () =\u003e promiseType,\n preprocess: () =\u003e preprocessType,\n pipeline: () =\u003e pipelineType,\n ostring: () =\u003e ostring,\n optional: () =\u003e optionalType,\n onumber: () =\u003e onumber,\n oboolean: () =\u003e oboolean,\n objectUtil: () =\u003e objectUtil,\n object: () =\u003e objectType,\n number: () =\u003e numberType,\n nullable: () =\u003e nullableType,\n null: () =\u003e nullType,\n never: () =\u003e neverType,\n nativeEnum: () =\u003e nativeEnumType,\n nan: () =\u003e nanType,\n map: () =\u003e mapType,\n makeIssue: () =\u003e makeIssue,\n literal: () =\u003e literalType,\n lazy: () =\u003e lazyType,\n late: () =\u003e late,\n isValid: () =\u003e isValid,\n isDirty: () =\u003e isDirty,\n isAsync: () =\u003e isAsync,\n isAborted: () =\u003e isAborted,\n intersection: () =\u003e intersectionType,\n instanceof: () =\u003e instanceOfType,\n getParsedType: () =\u003e getParsedType,\n getErrorMap: () =\u003e getErrorMap,\n function: () =\u003e functionType,\n enum: () =\u003e enumType,\n effect: () =\u003e effectsType,\n discriminatedUnion: () =\u003e discriminatedUnionType,\n defaultErrorMap: () =\u003e en_default,\n datetimeRegex: () =\u003e datetimeRegex,\n date: () =\u003e dateType,\n custom: () =\u003e custom,\n coerce: () =\u003e coerce,\n boolean: () =\u003e booleanType,\n bigint: () =\u003e bigIntType,\n array: () =\u003e arrayType,\n any: () =\u003e anyType,\n addIssueToContext: () =\u003e addIssueToContext,\n ZodVoid: () =\u003e ZodVoid,\n ZodUnknown: () =\u003e ZodUnknown,\n ZodUnion: () =\u003e ZodUnion,\n ZodUndefined: () =\u003e ZodUndefined,\n ZodType: () =\u003e ZodType,\n ZodTuple: () =\u003e ZodTuple,\n ZodTransformer: () =\u003e ZodEffects,\n ZodSymbol: () =\u003e ZodSymbol,\n ZodString: () =\u003e ZodString,\n ZodSet: () =\u003e ZodSet,\n ZodSchema: () =\u003e ZodType,\n ZodRecord: () =\u003e ZodRecord,\n ZodReadonly: () =\u003e ZodReadonly,\n ZodPromise: () =\u003e ZodPromise,\n ZodPipeline: () =\u003e ZodPipeline,\n ZodParsedType: () =\u003e ZodParsedType,\n ZodOptional: () =\u003e ZodOptional,\n ZodObject: () =\u003e ZodObject,\n ZodNumber: () =\u003e ZodNumber,\n ZodNullable: () =\u003e ZodNullable,\n ZodNull: () =\u003e ZodNull,\n ZodNever: () =\u003e ZodNever,\n ZodNativeEnum: () =\u003e ZodNativeEnum,\n ZodNaN: () =\u003e ZodNaN,\n ZodMap: () =\u003e ZodMap,\n ZodLiteral: () =\u003e ZodLiteral,\n ZodLazy: () =\u003e ZodLazy,\n ZodIssueCode: () =\u003e ZodIssueCode,\n ZodIntersection: () =\u003e ZodIntersection,\n ZodFunction: () =\u003e ZodFunction,\n ZodFirstPartyTypeKind: () =\u003e ZodFirstPartyTypeKind,\n ZodError: () =\u003e ZodError,\n ZodEnum: () =\u003e ZodEnum,\n ZodEffects: () =\u003e ZodEffects,\n ZodDiscriminatedUnion: () =\u003e ZodDiscriminatedUnion,\n ZodDefault: () =\u003e ZodDefault,\n ZodDate: () =\u003e ZodDate,\n ZodCatch: () =\u003e ZodCatch,\n ZodBranded: () =\u003e ZodBranded,\n ZodBoolean: () =\u003e ZodBoolean,\n ZodBigInt: () =\u003e ZodBigInt,\n ZodArray: () =\u003e ZodArray,\n ZodAny: () =\u003e ZodAny,\n Schema: () =\u003e ZodType,\n ParseStatus: () =\u003e ParseStatus,\n OK: () =\u003e OK,\n NEVER: () =\u003e NEVER,\n INVALID: () =\u003e INVALID,\n EMPTY_PATH: () =\u003e EMPTY_PATH,\n DIRTY: () =\u003e DIRTY,\n BRAND: () =\u003e BRAND\n});\n\n// ../../work/placement-analysis/node_modules/zod/v3/helpers/util.js\nvar util;\n(function(util2) {\n util2.assertEqual = (_) =\u003e {};\n function assertIs(_arg) {}\n util2.assertIs = assertIs;\n function assertNever(_x) {\n throw new Error;\n }\n util2.assertNever = assertNever;\n util2.arrayToEnum = (items) =\u003e {\n const obj = {};\n for (const item of items) {\n obj[item] = item;\n }\n return obj;\n };\n util2.getValidEnumValues = (obj) =\u003e {\n const validKeys = util2.objectKeys(obj).filter((k) =\u003e typeof obj[obj[k]] !== \"number\");\n const filtered = {};\n for (const k of validKeys) {\n filtered[k] = obj[k];\n }\n return util2.objectValues(filtered);\n };\n util2.objectValues = (obj) =\u003e {\n return util2.objectKeys(obj).map(function(e) {\n return obj[e];\n });\n };\n util2.objectKeys = typeof Object.keys === \"function\" ? (obj) =\u003e Object.keys(obj) : (object) =\u003e {\n const keys = [];\n for (const key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n keys.push(key);\n }\n }\n return keys;\n };\n util2.find = (arr, checker) =\u003e {\n for (const item of arr) {\n if (checker(item))\n return item;\n }\n return;\n };\n util2.isInteger = typeof Number.isInteger === \"function\" ? (val) =\u003e Number.isInteger(val) : (val) =\u003e typeof val === \"number\" \u0026\u0026 Number.isFinite(val) \u0026\u0026 Math.floor(val) === val;\n function joinValues(array, separator = \" | \") {\n return array.map((val) =\u003e typeof val === \"string\" ? `'${val}'` : val).join(separator);\n }\n util2.joinValues = joinValues;\n util2.jsonStringifyReplacer = (_, value) =\u003e {\n if (typeof value === \"bigint\") {\n return value.toString();\n }\n return value;\n };\n})(util || (util = {}));\nvar objectUtil;\n(function(objectUtil2) {\n objectUtil2.mergeShapes = (first, second) =\u003e {\n return {\n ...first,\n ...second\n };\n };\n})(objectUtil || (objectUtil = {}));\nvar ZodParsedType = util.arrayToEnum([\n \"string\",\n \"nan\",\n \"number\",\n \"integer\",\n \"float\",\n \"boolean\",\n \"date\",\n \"bigint\",\n \"symbol\",\n \"function\",\n \"undefined\",\n \"null\",\n \"array\",\n \"object\",\n \"unknown\",\n \"promise\",\n \"void\",\n \"never\",\n \"map\",\n \"set\"\n]);\nvar getParsedType = (data) =\u003e {\n const t = typeof data;\n switch (t) {\n case \"undefined\":\n return ZodParsedType.undefined;\n case \"string\":\n return ZodParsedType.string;\n case \"number\":\n return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;\n case \"boolean\":\n return ZodParsedType.boolean;\n case \"function\":\n return ZodParsedType.function;\n case \"bigint\":\n return ZodParsedType.bigint;\n case \"symbol\":\n return ZodParsedType.symbol;\n case \"object\":\n if (Array.isArray(data)) {\n return ZodParsedType.array;\n }\n if (data === null) {\n return ZodParsedType.null;\n }\n if (data.then \u0026\u0026 typeof data.then === \"function\" \u0026\u0026 data.catch \u0026\u0026 typeof data.catch === \"function\") {\n return ZodParsedType.promise;\n }\n if (typeof Map !== \"undefined\" \u0026\u0026 data instanceof Map) {\n return ZodParsedType.map;\n }\n if (typeof Set !== \"undefined\" \u0026\u0026 data instanceof Set) {\n return ZodParsedType.set;\n }\n if (typeof Date !== \"undefined\" \u0026\u0026 data instanceof Date) {\n return ZodParsedType.date;\n }\n return ZodParsedType.object;\n default:\n return ZodParsedType.unknown;\n }\n};\n\n// ../../work/placement-analysis/node_modules/zod/v3/ZodError.js\nvar ZodIssueCode = util.arrayToEnum([\n \"invalid_type\",\n \"invalid_literal\",\n \"custom\",\n \"invalid_union\",\n \"invalid_union_discriminator\",\n \"invalid_enum_value\",\n \"unrecognized_keys\",\n \"invalid_arguments\",\n \"invalid_return_type\",\n \"invalid_date\",\n \"invalid_string\",\n \"too_small\",\n \"too_big\",\n \"invalid_intersection_types\",\n \"not_multiple_of\",\n \"not_finite\"\n]);\nvar quotelessJson = (obj) =\u003e {\n const json = JSON.stringify(obj, null, 2);\n return json.replace(/\"([^\"]+)\":/g, \"$1:\");\n};\n\nclass ZodError extends Error {\n get errors() {\n return this.issues;\n }\n constructor(issues) {\n super();\n this.issues = [];\n this.addIssue = (sub) =\u003e {\n this.issues = [...this.issues, sub];\n };\n this.addIssues = (subs = []) =\u003e {\n this.issues = [...this.issues, ...subs];\n };\n const actualProto = new.target.prototype;\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(this, actualProto);\n } else {\n this.__proto__ = actualProto;\n }\n this.name = \"ZodError\";\n this.issues = issues;\n }\n format(_mapper) {\n const mapper = _mapper || function(issue) {\n return issue.message;\n };\n const fieldErrors = { _errors: [] };\n const processError = (error) =\u003e {\n for (const issue of error.issues) {\n if (issue.code === \"invalid_union\") {\n issue.unionErrors.map(processError);\n } else if (issue.code === \"invalid_return_type\") {\n processError(issue.returnTypeError);\n } else if (issue.code === \"invalid_arguments\") {\n processError(issue.argumentsError);\n } else if (issue.path.length === 0) {\n fieldErrors._errors.push(mapper(issue));\n } else {\n let curr = fieldErrors;\n let i = 0;\n while (i \u003c issue.path.length) {\n const el = issue.path[i];\n const terminal = i === issue.path.length - 1;\n if (!terminal) {\n curr[el] = curr[el] || { _errors: [] };\n } else {\n curr[el] = curr[el] || { _errors: [] };\n curr[el]._errors.push(mapper(issue));\n }\n curr = curr[el];\n i++;\n }\n }\n }\n };\n processError(this);\n return fieldErrors;\n }\n static assert(value) {\n if (!(value instanceof ZodError)) {\n throw new Error(`Not a ZodError: ${value}`);\n }\n }\n toString() {\n return this.message;\n }\n get message() {\n return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);\n }\n get isEmpty() {\n return this.issues.length === 0;\n }\n flatten(mapper = (issue) =\u003e issue.message) {\n const fieldErrors = {};\n const formErrors = [];\n for (const sub of this.issues) {\n if (sub.path.length \u003e 0) {\n const firstEl = sub.path[0];\n fieldErrors[firstEl] = fieldErrors[firstEl] || [];\n fieldErrors[firstEl].push(mapper(sub));\n } else {\n formErrors.push(mapper(sub));\n }\n }\n return { formErrors, fieldErrors };\n }\n get formErrors() {\n return this.flatten();\n }\n}\nZodError.create = (issues) =\u003e {\n const error = new ZodError(issues);\n return error;\n};\n\n// ../../work/placement-analysis/node_modules/zod/v3/locales/en.js\nvar errorMap = (issue, _ctx) =\u003e {\n let message;\n switch (issue.code) {\n case ZodIssueCode.invalid_type:\n if (issue.received === ZodParsedType.undefined) {\n message = \"Required\";\n } else {\n message = `Expected ${issue.expected}, received ${issue.received}`;\n }\n break;\n case ZodIssueCode.invalid_literal:\n message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;\n break;\n case ZodIssueCode.unrecognized_keys:\n message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, \", \")}`;\n break;\n case ZodIssueCode.invalid_union:\n message = `Invalid input`;\n break;\n case ZodIssueCode.invalid_union_discriminator:\n message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;\n break;\n case ZodIssueCode.invalid_enum_value:\n message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;\n break;\n case ZodIssueCode.invalid_arguments:\n message = `Invalid function arguments`;\n break;\n case ZodIssueCode.invalid_return_type:\n message = `Invalid function return type`;\n break;\n case ZodIssueCode.invalid_date:\n message = `Invalid date`;\n break;\n case ZodIssueCode.invalid_string:\n if (typeof issue.validation === \"object\") {\n if (\"includes\" in issue.validation) {\n message = `Invalid input: must include \"${issue.validation.includes}\"`;\n if (typeof issue.validation.position === \"number\") {\n message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;\n }\n } else if (\"startsWith\" in issue.validation) {\n message = `Invalid input: must start with \"${issue.validation.startsWith}\"`;\n } else if (\"endsWith\" in issue.validation) {\n message = `Invalid input: must end with \"${issue.validation.endsWith}\"`;\n } else {\n util.assertNever(issue.validation);\n }\n } else if (issue.validation !== \"regex\") {\n message = `Invalid ${issue.validation}`;\n } else {\n message = \"Invalid\";\n }\n break;\n case ZodIssueCode.too_small:\n if (issue.type === \"array\")\n message = `Array must contain ${issue.exact ? \"exactly\" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;\n else if (issue.type === \"string\")\n message = `String must contain ${issue.exact ? \"exactly\" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;\n else if (issue.type === \"number\")\n message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;\n else if (issue.type === \"bigint\")\n message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;\n else if (issue.type === \"date\")\n message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;\n else\n message = \"Invalid input\";\n break;\n case ZodIssueCode.too_big:\n if (issue.type === \"array\")\n message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;\n else if (issue.type === \"string\")\n message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;\n else if (issue.type === \"number\")\n message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;\n else if (issue.type === \"bigint\")\n message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;\n else if (issue.type === \"date\")\n message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;\n else\n message = \"Invalid input\";\n break;\n case ZodIssueCode.custom:\n message = `Invalid input`;\n break;\n case ZodIssueCode.invalid_intersection_types:\n message = `Intersection results could not be merged`;\n break;\n case ZodIssueCode.not_multiple_of:\n message = `Number must be a multiple of ${issue.multipleOf}`;\n break;\n case ZodIssueCode.not_finite:\n message = \"Number must be finite\";\n break;\n default:\n message = _ctx.defaultError;\n util.assertNever(issue);\n }\n return { message };\n};\nvar en_default = errorMap;\n\n// ../../work/placement-analysis/node_modules/zod/v3/errors.js\nvar overrideErrorMap = en_default;\nfunction setErrorMap(map) {\n overrideErrorMap = map;\n}\nfunction getErrorMap() {\n return overrideErrorMap;\n}\n// ../../work/placement-analysis/node_modules/zod/v3/helpers/parseUtil.js\nvar makeIssue = (params) =\u003e {\n const { data, path, errorMaps, issueData } = params;\n const fullPath = [...path, ...issueData.path || []];\n const fullIssue = {\n ...issueData,\n path: fullPath\n };\n if (issueData.message !== undefined) {\n return {\n ...issueData,\n path: fullPath,\n message: issueData.message\n };\n }\n let errorMessage = \"\";\n const maps = errorMaps.filter((m) =\u003e !!m).slice().reverse();\n for (const map of maps) {\n errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;\n }\n return {\n ...issueData,\n path: fullPath,\n message: errorMessage\n };\n};\nvar EMPTY_PATH = [];\nfunction addIssueToContext(ctx, issueData) {\n const overrideMap = getErrorMap();\n const issue = makeIssue({\n issueData,\n data: ctx.data,\n path: ctx.path,\n errorMaps: [\n ctx.common.contextualErrorMap,\n ctx.schemaErrorMap,\n overrideMap,\n overrideMap === en_default ? undefined : en_default\n ].filter((x) =\u003e !!x)\n });\n ctx.common.issues.push(issue);\n}\n\nclass ParseStatus {\n constructor() {\n this.value = \"valid\";\n }\n dirty() {\n if (this.value === \"valid\")\n this.value = \"dirty\";\n }\n abort() {\n if (this.value !== \"aborted\")\n this.value = \"aborted\";\n }\n static mergeArray(status, results) {\n const arrayValue = [];\n for (const s of results) {\n if (s.status === \"aborted\")\n return INVALID;\n if (s.status === \"dirty\")\n status.dirty();\n arrayValue.push(s.value);\n }\n return { status: status.value, value: arrayValue };\n }\n static async mergeObjectAsync(status, pairs) {\n const syncPairs = [];\n for (const pair of pairs) {\n const key = await pair.key;\n const value = await pair.value;\n syncPairs.push({\n key,\n value\n });\n }\n return ParseStatus.mergeObjectSync(status, syncPairs);\n }\n static mergeObjectSync(status, pairs) {\n const finalObject = {};\n for (const pair of pairs) {\n const { key, value } = pair;\n if (key.status === \"aborted\")\n return INVALID;\n if (value.status === \"aborted\")\n return INVALID;\n if (key.status === \"dirty\")\n status.dirty();\n if (value.status === \"dirty\")\n status.dirty();\n if (key.value !== \"__proto__\" \u0026\u0026 (typeof value.value !== \"undefined\" || pair.alwaysSet)) {\n finalObject[key.value] = value.value;\n }\n }\n return { status: status.value, value: finalObject };\n }\n}\nvar INVALID = Object.freeze({\n status: \"aborted\"\n});\nvar DIRTY = (value) =\u003e ({ status: \"dirty\", value });\nvar OK = (value) =\u003e ({ status: \"valid\", value });\nvar isAborted = (x) =\u003e x.status === \"aborted\";\nvar isDirty = (x) =\u003e x.status === \"dirty\";\nvar isValid = (x) =\u003e x.status === \"valid\";\nvar isAsync = (x) =\u003e typeof Promise !== \"undefined\" \u0026\u0026 x instanceof Promise;\n// ../../work/placement-analysis/node_modules/zod/v3/helpers/errorUtil.js\nvar errorUtil;\n(function(errorUtil2) {\n errorUtil2.errToObj = (message) =\u003e typeof message === \"string\" ? { message } : message || {};\n errorUtil2.toString = (message) =\u003e typeof message === \"string\" ? message : message?.message;\n})(errorUtil || (errorUtil = {}));\n\n// ../../work/placement-analysis/node_modules/zod/v3/types.js\nclass ParseInputLazyPath {\n constructor(parent, value, path, key) {\n this._cachedPath = [];\n this.parent = parent;\n this.data = value;\n this._path = path;\n this._key = key;\n }\n get path() {\n if (!this._cachedPath.length) {\n if (Array.isArray(this._key)) {\n this._cachedPath.push(...this._path, ...this._key);\n } else {\n this._cachedPath.push(...this._path, this._key);\n }\n }\n return this._cachedPath;\n }\n}\nvar handleResult = (ctx, result) =\u003e {\n if (isValid(result)) {\n return { success: true, data: result.value };\n } else {\n if (!ctx.common.issues.length) {\n throw new Error(\"Validation failed but no issues detected.\");\n }\n return {\n success: false,\n get error() {\n if (this._error)\n return this._error;\n const error = new ZodError(ctx.common.issues);\n this._error = error;\n return this._error;\n }\n };\n }\n};\nfunction processCreateParams(params) {\n if (!params)\n return {};\n const { errorMap: errorMap2, invalid_type_error, required_error, description } = params;\n if (errorMap2 \u0026\u0026 (invalid_type_error || required_error)) {\n throw new Error(`Can't use \"invalid_type_error\" or \"required_error\" in conjunction with custom error map.`);\n }\n if (errorMap2)\n return { errorMap: errorMap2, description };\n const customMap = (iss, ctx) =\u003e {\n const { message } = params;\n if (iss.code === \"invalid_enum_value\") {\n return { message: message ?? ctx.defaultError };\n }\n if (typeof ctx.data === \"undefined\") {\n return { message: message ?? required_error ?? ctx.defaultError };\n }\n if (iss.code !== \"invalid_type\")\n return { message: ctx.defaultError };\n return { message: message ?? invalid_type_error ?? ctx.defaultError };\n };\n return { errorMap: customMap, description };\n}\n\nclass ZodType {\n get description() {\n return this._def.description;\n }\n _getType(input) {\n return getParsedType(input.data);\n }\n _getOrReturnCtx(input, ctx) {\n return ctx || {\n common: input.parent.common,\n data: input.data,\n parsedType: getParsedType(input.data),\n schemaErrorMap: this._def.errorMap,\n path: input.path,\n parent: input.parent\n };\n }\n _processInputParams(input) {\n return {\n status: new ParseStatus,\n ctx: {\n common: input.parent.common,\n data: input.data,\n parsedType: getParsedType(input.data),\n schemaErrorMap: this._def.errorMap,\n path: input.path,\n parent: input.parent\n }\n };\n }\n _parseSync(input) {\n const result = this._parse(input);\n if (isAsync(result)) {\n throw new Error(\"Synchronous parse encountered promise.\");\n }\n return result;\n }\n _parseAsync(input) {\n const result = this._parse(input);\n return Promise.resolve(result);\n }\n parse(data, params) {\n const result = this.safeParse(data, params);\n if (result.success)\n return result.data;\n throw result.error;\n }\n safeParse(data, params) {\n const ctx = {\n common: {\n issues: [],\n async: params?.async ?? false,\n contextualErrorMap: params?.errorMap\n },\n path: params?.path || [],\n schemaErrorMap: this._def.errorMap,\n parent: null,\n data,\n parsedType: getParsedType(data)\n };\n const result = this._parseSync({ data, path: ctx.path, parent: ctx });\n return handleResult(ctx, result);\n }\n \"~validate\"(data) {\n const ctx = {\n common: {\n issues: [],\n async: !!this[\"~standard\"].async\n },\n path: [],\n schemaErrorMap: this._def.errorMap,\n parent: null,\n data,\n parsedType: getParsedType(data)\n };\n if (!this[\"~standard\"].async) {\n try {\n const result = this._parseSync({ data, path: [], parent: ctx });\n return isValid(result) ? {\n value: result.value\n } : {\n issues: ctx.common.issues\n };\n } catch (err) {\n if (err?.message?.toLowerCase()?.includes(\"encountered\")) {\n this[\"~standard\"].async = true;\n }\n ctx.common = {\n issues: [],\n async: true\n };\n }\n }\n return this._parseAsync({ data, path: [], parent: ctx }).then((result) =\u003e isValid(result) ? {\n value: result.value\n } : {\n issues: ctx.common.issues\n });\n }\n async parseAsync(data, params) {\n const result = await this.safeParseAsync(data, params);\n if (result.success)\n return result.data;\n throw result.error;\n }\n async safeParseAsync(data, params) {\n const ctx = {\n common: {\n issues: [],\n contextualErrorMap: params?.errorMap,\n async: true\n },\n path: params?.path || [],\n schemaErrorMap: this._def.errorMap,\n parent: null,\n data,\n parsedType: getParsedType(data)\n };\n const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });\n const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));\n return handleResult(ctx, result);\n }\n refine(check, message) {\n const getIssueProperties = (val) =\u003e {\n if (typeof message === \"string\" || typeof message === \"undefined\") {\n return { message };\n } else if (typeof message === \"function\") {\n return message(val);\n } else {\n return message;\n }\n };\n return this._refinement((val, ctx) =\u003e {\n const result = check(val);\n const setError = () =\u003e ctx.addIssue({\n code: ZodIssueCode.custom,\n ...getIssueProperties(val)\n });\n if (typeof Promise !== \"undefined\" \u0026\u0026 result instanceof Promise) {\n return result.then((data) =\u003e {\n if (!data) {\n setError();\n return false;\n } else {\n return true;\n }\n });\n }\n if (!result) {\n setError();\n return false;\n } else {\n return true;\n }\n });\n }\n refinement(check, refinementData) {\n return this._refinement((val, ctx) =\u003e {\n if (!check(val)) {\n ctx.addIssue(typeof refinementData === \"function\" ? refinementData(val, ctx) : refinementData);\n return false;\n } else {\n return true;\n }\n });\n }\n _refinement(refinement) {\n return new ZodEffects({\n schema: this,\n typeName: ZodFirstPartyTypeKind.ZodEffects,\n effect: { type: \"refinement\", refinement }\n });\n }\n superRefine(refinement) {\n return this._refinement(refinement);\n }\n constructor(def) {\n this.spa = this.safeParseAsync;\n this._def = def;\n this.parse = this.parse.bind(this);\n this.safeParse = this.safeParse.bind(this);\n this.parseAsync = this.parseAsync.bind(this);\n this.safeParseAsync = this.safeParseAsync.bind(this);\n this.spa = this.spa.bind(this);\n this.refine = this.refine.bind(this);\n this.refinement = this.refinement.bind(this);\n this.superRefine = this.superRefine.bind(this);\n this.optional = this.optional.bind(this);\n this.nullable = this.nullable.bind(this);\n this.nullish = this.nullish.bind(this);\n this.array = this.array.bind(this);\n this.promise = this.promise.bind(this);\n this.or = this.or.bind(this);\n this.and = this.and.bind(this);\n this.transform = this.transform.bind(this);\n this.brand = this.brand.bind(this);\n this.default = this.default.bind(this);\n this.catch = this.catch.bind(this);\n this.describe = this.describe.bind(this);\n this.pipe = this.pipe.bind(this);\n this.readonly = this.readonly.bind(this);\n this.isNullable = this.isNullable.bind(this);\n this.isOptional = this.isOptional.bind(this);\n this[\"~standard\"] = {\n version: 1,\n vendor: \"zod\",\n validate: (data) =\u003e this[\"~validate\"](data)\n };\n }\n optional() {\n return ZodOptional.create(this, this._def);\n }\n nullable() {\n return ZodNullable.create(this, this._def);\n }\n nullish() {\n return this.nullable().optional();\n }\n array() {\n return ZodArray.create(this);\n }\n promise() {\n return ZodPromise.create(this, this._def);\n }\n or(option) {\n return ZodUnion.create([this, option], this._def);\n }\n and(incoming) {\n return ZodIntersection.create(this, incoming, this._def);\n }\n transform(transform3) {\n return new ZodEffects({\n ...processCreateParams(this._def),\n schema: this,\n typeName: ZodFirstPartyTypeKind.ZodEffects,\n effect: { type: \"transform\", transform: transform3 }\n });\n }\n default(def) {\n const defaultValueFunc = typeof def === \"function\" ? def : () =\u003e def;\n return new ZodDefault({\n ...processCreateParams(this._def),\n innerType: this,\n defaultValue: defaultValueFunc,\n typeName: ZodFirstPartyTypeKind.ZodDefault\n });\n }\n brand() {\n return new ZodBranded({\n typeName: ZodFirstPartyTypeKind.ZodBranded,\n type: this,\n ...processCreateParams(this._def)\n });\n }\n catch(def) {\n const catchValueFunc = typeof def === \"function\" ? def : () =\u003e def;\n return new ZodCatch({\n ...processCreateParams(this._def),\n innerType: this,\n catchValue: catchValueFunc,\n typeName: ZodFirstPartyTypeKind.ZodCatch\n });\n }\n describe(description) {\n const This = this.constructor;\n return new This({\n ...this._def,\n description\n });\n }\n pipe(target) {\n return ZodPipeline.create(this, target);\n }\n readonly() {\n return ZodReadonly.create(this);\n }\n isOptional() {\n return this.safeParse(undefined).success;\n }\n isNullable() {\n return this.safeParse(null).success;\n }\n}\nvar cuidRegex = /^c[^\\s-]{8,}$/i;\nvar cuid2Regex = /^[0-9a-z]+$/;\nvar ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i;\nvar uuidRegex = /^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$/i;\nvar nanoidRegex = /^[a-z0-9_-]{21}$/i;\nvar jwtRegex = /^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$/;\nvar durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\\d+Y)|(?:[-+]?\\d+[.,]\\d+Y$))?(?:(?:[-+]?\\d+M)|(?:[-+]?\\d+[.,]\\d+M$))?(?:(?:[-+]?\\d+W)|(?:[-+]?\\d+[.,]\\d+W$))?(?:(?:[-+]?\\d+D)|(?:[-+]?\\d+[.,]\\d+D$))?(?:T(?=[\\d+-])(?:(?:[-+]?\\d+H)|(?:[-+]?\\d+[.,]\\d+H$))?(?:(?:[-+]?\\d+M)|(?:[-+]?\\d+[.,]\\d+M$))?(?:[-+]?\\d+(?:[.,]\\d+)?S)?)??$/;\nvar emailRegex = /^(?!\\.)(?!.*\\.\\.)([A-Z0-9_'+\\-\\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\\-]*\\.)+[A-Z]{2,}$/i;\nvar _emojiRegex = `^(\\\\p{Extended_Pictographic}|\\\\p{Emoji_Component})+ vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit ;\nvar emojiRegex;\nvar ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;\nvar ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/(3[0-2]|[12]?[0-9])$/;\nvar ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;\nvar ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;\nvar base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;\nvar base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;\nvar dateRegexSource = `((\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\\\d|30)|(02)-(0[1-9]|1\\\\d|2[0-8])))`;\nvar dateRegex = new RegExp(`^${dateRegexSource} vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit );\nfunction timeRegexSource(args) {\n let secondsRegexSource = `[0-5]\\\\d`;\n if (args.precision) {\n secondsRegexSource = `${secondsRegexSource}\\\\.\\\\d{${args.precision}}`;\n } else if (args.precision == null) {\n secondsRegexSource = `${secondsRegexSource}(\\\\.\\\\d+)?`;\n }\n const secondsQuantifier = args.precision ? \"+\" : \"?\";\n return `([01]\\\\d|2[0-3]):[0-5]\\\\d(:${secondsRegexSource})${secondsQuantifier}`;\n}\nfunction timeRegex(args) {\n return new RegExp(`^${timeRegexSource(args)} vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit );\n}\nfunction datetimeRegex(args) {\n let regex = `${dateRegexSource}T${timeRegexSource(args)}`;\n const opts = [];\n opts.push(args.local ? `Z?` : `Z`);\n if (args.offset)\n opts.push(`([+-]\\\\d{2}:?\\\\d{2})`);\n regex = `${regex}(${opts.join(\"|\")})`;\n return new RegExp(`^${regex} vendor/schematic-style-analysis.js - imrishabh18/rp2040-motor-controller - tscircuit );\n}\nfunction isValidIP(ip, version) {\n if ((version === \"v4\" || !version) \u0026\u0026 ipv4Regex.test(ip)) {\n return true;\n }\n if ((version === \"v6\" || !version) \u0026\u0026 ipv6Regex.test(ip)) {\n return true;\n }\n return false;\n}\nfunction isValidJWT(jwt, alg) {\n if (!jwtRegex.test(jwt))\n return false;\n try {\n const [header] = jwt.split(\".\");\n if (!header)\n return false;\n const base64 = header.replace(/-/g, \"+\").replace(/_/g, \"/\").padEnd(header.length + (4 - header.length % 4) % 4, \"=\");\n const decoded = JSON.parse(atob(base64));\n if (typeof decoded !== \"object\" || decoded === null)\n return false;\n if (\"typ\" in decoded \u0026\u0026 decoded?.typ !== \"JWT\")\n return false;\n if (!decoded.alg)\n return false;\n if (alg \u0026\u0026 decoded.alg !== alg)\n return false;\n return true;\n } catch {\n return false;\n }\n}\nfunction isValidCidr(ip, version) {\n if ((version === \"v4\" || !version) \u0026\u0026 ipv4CidrRegex.test(ip)) {\n return true;\n }\n if ((version === \"v6\" || !version) \u0026\u0026 ipv6CidrRegex.test(ip)) {\n return true;\n }\n return false;\n}\n\nclass ZodString extends ZodType {\n _parse(input) {\n if (this._def.coerce) {\n input.data = String(input.data);\n }\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.string) {\n const ctx2 = this._getOrReturnCtx(input);\n addIssueToContext(ctx2, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.string,\n received: ctx2.parsedType\n });\n return INVALID;\n }\n const status = new ParseStatus;\n let ctx = undefined;\n for (const check of this._def.checks) {\n if (check.kind === \"min\") {\n if (input.data.length \u003c check.value) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n minimum: check.value,\n type: \"string\",\n inclusive: true,\n exact: false,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"max\") {\n if (input.data.length \u003e check.value) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n maximum: check.value,\n type: \"string\",\n inclusive: true,\n exact: false,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"length\") {\n const tooBig = input.data.length \u003e check.value;\n const tooSmall = input.data.length \u003c check.value;\n if (tooBig || tooSmall) {\n ctx = this._getOrReturnCtx(input, ctx);\n if (tooBig) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n maximum: check.value,\n type: \"string\",\n inclusive: true,\n exact: true,\n message: check.message\n });\n } else if (tooSmall) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n minimum: check.value,\n type: \"string\",\n inclusive: true,\n exact: true,\n message: check.message\n });\n }\n status.dirty();\n }\n } else if (check.kind === \"email\") {\n if (!emailRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"email\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"emoji\") {\n if (!emojiRegex) {\n emojiRegex = new RegExp(_emojiRegex, \"u\");\n }\n if (!emojiRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"emoji\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"uuid\") {\n if (!uuidRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"uuid\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"nanoid\") {\n if (!nanoidRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"nanoid\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"cuid\") {\n if (!cuidRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"cuid\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"cuid2\") {\n if (!cuid2Regex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"cuid2\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"ulid\") {\n if (!ulidRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"ulid\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"url\") {\n try {\n new URL(input.data);\n } catch {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"url\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"regex\") {\n check.regex.lastIndex = 0;\n const testResult = check.regex.test(input.data);\n if (!testResult) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"regex\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"trim\") {\n input.data = input.data.trim();\n } else if (check.kind === \"includes\") {\n if (!input.data.includes(check.value, check.position)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_string,\n validation: { includes: check.value, position: check.position },\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"toLowerCase\") {\n input.data = input.data.toLowerCase();\n } else if (check.kind === \"toUpperCase\") {\n input.data = input.data.toUpperCase();\n } else if (check.kind === \"startsWith\") {\n if (!input.data.startsWith(check.value)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_string,\n validation: { startsWith: check.value },\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"endsWith\") {\n if (!input.data.endsWith(check.value)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_string,\n validation: { endsWith: check.value },\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"datetime\") {\n const regex = datetimeRegex(check);\n if (!regex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_string,\n validation: \"datetime\",\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"date\") {\n const regex = dateRegex;\n if (!regex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_string,\n validation: \"date\",\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"time\") {\n const regex = timeRegex(check);\n if (!regex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_string,\n validation: \"time\",\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"duration\") {\n if (!durationRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"duration\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"ip\") {\n if (!isValidIP(input.data, check.version)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"ip\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"jwt\") {\n if (!isValidJWT(input.data, check.alg)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"jwt\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"cidr\") {\n if (!isValidCidr(input.data, check.version)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"cidr\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"base64\") {\n if (!base64Regex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"base64\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"base64url\") {\n if (!base64urlRegex.test(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n validation: \"base64url\",\n code: ZodIssueCode.invalid_string,\n message: check.message\n });\n status.dirty();\n }\n } else {\n util.assertNever(check);\n }\n }\n return { status: status.value, value: input.data };\n }\n _regex(regex, validation, message) {\n return this.refinement((data) =\u003e regex.test(data), {\n validation,\n code: ZodIssueCode.invalid_string,\n ...errorUtil.errToObj(message)\n });\n }\n _addCheck(check) {\n return new ZodString({\n ...this._def,\n checks: [...this._def.checks, check]\n });\n }\n email(message) {\n return this._addCheck({ kind: \"email\", ...errorUtil.errToObj(message) });\n }\n url(message) {\n return this._addCheck({ kind: \"url\", ...errorUtil.errToObj(message) });\n }\n emoji(message) {\n return this._addCheck({ kind: \"emoji\", ...errorUtil.errToObj(message) });\n }\n uuid(message) {\n return this._addCheck({ kind: \"uuid\", ...errorUtil.errToObj(message) });\n }\n nanoid(message) {\n return this._addCheck({ kind: \"nanoid\", ...errorUtil.errToObj(message) });\n }\n cuid(message) {\n return this._addCheck({ kind: \"cuid\", ...errorUtil.errToObj(message) });\n }\n cuid2(message) {\n return this._addCheck({ kind: \"cuid2\", ...errorUtil.errToObj(message) });\n }\n ulid(message) {\n return this._addCheck({ kind: \"ulid\", ...errorUtil.errToObj(message) });\n }\n base64(message) {\n return this._addCheck({ kind: \"base64\", ...errorUtil.errToObj(message) });\n }\n base64url(message) {\n return this._addCheck({\n kind: \"base64url\",\n ...errorUtil.errToObj(message)\n });\n }\n jwt(options) {\n return this._addCheck({ kind: \"jwt\", ...errorUtil.errToObj(options) });\n }\n ip(options) {\n return this._addCheck({ kind: \"ip\", ...errorUtil.errToObj(options) });\n }\n cidr(options) {\n return this._addCheck({ kind: \"cidr\", ...errorUtil.errToObj(options) });\n }\n datetime(options) {\n if (typeof options === \"string\") {\n return this._addCheck({\n kind: \"datetime\",\n precision: null,\n offset: false,\n local: false,\n message: options\n });\n }\n return this._addCheck({\n kind: \"datetime\",\n precision: typeof options?.precision === \"undefined\" ? null : options?.precision,\n offset: options?.offset ?? false,\n local: options?.local ?? false,\n ...errorUtil.errToObj(options?.message)\n });\n }\n date(message) {\n return this._addCheck({ kind: \"date\", message });\n }\n time(options) {\n if (typeof options === \"string\") {\n return this._addCheck({\n kind: \"time\",\n precision: null,\n message: options\n });\n }\n return this._addCheck({\n kind: \"time\",\n precision: typeof options?.precision === \"undefined\" ? null : options?.precision,\n ...errorUtil.errToObj(options?.message)\n });\n }\n duration(message) {\n return this._addCheck({ kind: \"duration\", ...errorUtil.errToObj(message) });\n }\n regex(regex, message) {\n return this._addCheck({\n kind: \"regex\",\n regex,\n ...errorUtil.errToObj(message)\n });\n }\n includes(value, options) {\n return this._addCheck({\n kind: \"includes\",\n value,\n position: options?.position,\n ...errorUtil.errToObj(options?.message)\n });\n }\n startsWith(value, message) {\n return this._addCheck({\n kind: \"startsWith\",\n value,\n ...errorUtil.errToObj(message)\n });\n }\n endsWith(value, message) {\n return this._addCheck({\n kind: \"endsWith\",\n value,\n ...errorUtil.errToObj(message)\n });\n }\n min(minLength, message) {\n return this._addCheck({\n kind: \"min\",\n value: minLength,\n ...errorUtil.errToObj(message)\n });\n }\n max(maxLength, message) {\n return this._addCheck({\n kind: \"max\",\n value: maxLength,\n ...errorUtil.errToObj(message)\n });\n }\n length(len, message) {\n return this._addCheck({\n kind: \"length\",\n value: len,\n ...errorUtil.errToObj(message)\n });\n }\n nonempty(message) {\n return this.min(1, errorUtil.errToObj(message));\n }\n trim() {\n return new ZodString({\n ...this._def,\n checks: [...this._def.checks, { kind: \"trim\" }]\n });\n }\n toLowerCase() {\n return new ZodString({\n ...this._def,\n checks: [...this._def.checks, { kind: \"toLowerCase\" }]\n });\n }\n toUpperCase() {\n return new ZodString({\n ...this._def,\n checks: [...this._def.checks, { kind: \"toUpperCase\" }]\n });\n }\n get isDatetime() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"datetime\");\n }\n get isDate() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"date\");\n }\n get isTime() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"time\");\n }\n get isDuration() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"duration\");\n }\n get isEmail() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"email\");\n }\n get isURL() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"url\");\n }\n get isEmoji() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"emoji\");\n }\n get isUUID() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"uuid\");\n }\n get isNANOID() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"nanoid\");\n }\n get isCUID() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"cuid\");\n }\n get isCUID2() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"cuid2\");\n }\n get isULID() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"ulid\");\n }\n get isIP() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"ip\");\n }\n get isCIDR() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"cidr\");\n }\n get isBase64() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"base64\");\n }\n get isBase64url() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"base64url\");\n }\n get minLength() {\n let min = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"min\") {\n if (min === null || ch.value \u003e min)\n min = ch.value;\n }\n }\n return min;\n }\n get maxLength() {\n let max = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"max\") {\n if (max === null || ch.value \u003c max)\n max = ch.value;\n }\n }\n return max;\n }\n}\nZodString.create = (params) =\u003e {\n return new ZodString({\n checks: [],\n typeName: ZodFirstPartyTypeKind.ZodString,\n coerce: params?.coerce ?? false,\n ...processCreateParams(params)\n });\n};\nfunction floatSafeRemainder(val, step) {\n const valDecCount = (val.toString().split(\".\")[1] || \"\").length;\n const stepDecCount = (step.toString().split(\".\")[1] || \"\").length;\n const decCount = valDecCount \u003e stepDecCount ? valDecCount : stepDecCount;\n const valInt = Number.parseInt(val.toFixed(decCount).replace(\".\", \"\"));\n const stepInt = Number.parseInt(step.toFixed(decCount).replace(\".\", \"\"));\n return valInt % stepInt / 10 ** decCount;\n}\n\nclass ZodNumber extends ZodType {\n constructor() {\n super(...arguments);\n this.min = this.gte;\n this.max = this.lte;\n this.step = this.multipleOf;\n }\n _parse(input) {\n if (this._def.coerce) {\n input.data = Number(input.data);\n }\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.number) {\n const ctx2 = this._getOrReturnCtx(input);\n addIssueToContext(ctx2, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.number,\n received: ctx2.parsedType\n });\n return INVALID;\n }\n let ctx = undefined;\n const status = new ParseStatus;\n for (const check of this._def.checks) {\n if (check.kind === \"int\") {\n if (!util.isInteger(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: \"integer\",\n received: \"float\",\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"min\") {\n const tooSmall = check.inclusive ? input.data \u003c check.value : input.data \u003c= check.value;\n if (tooSmall) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n minimum: check.value,\n type: \"number\",\n inclusive: check.inclusive,\n exact: false,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"max\") {\n const tooBig = check.inclusive ? input.data \u003e check.value : input.data \u003e= check.value;\n if (tooBig) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n maximum: check.value,\n type: \"number\",\n inclusive: check.inclusive,\n exact: false,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"multipleOf\") {\n if (floatSafeRemainder(input.data, check.value) !== 0) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.not_multiple_of,\n multipleOf: check.value,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"finite\") {\n if (!Number.isFinite(input.data)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.not_finite,\n message: check.message\n });\n status.dirty();\n }\n } else {\n util.assertNever(check);\n }\n }\n return { status: status.value, value: input.data };\n }\n gte(value, message) {\n return this.setLimit(\"min\", value, true, errorUtil.toString(message));\n }\n gt(value, message) {\n return this.setLimit(\"min\", value, false, errorUtil.toString(message));\n }\n lte(value, message) {\n return this.setLimit(\"max\", value, true, errorUtil.toString(message));\n }\n lt(value, message) {\n return this.setLimit(\"max\", value, false, errorUtil.toString(message));\n }\n setLimit(kind, value, inclusive, message) {\n return new ZodNumber({\n ...this._def,\n checks: [\n ...this._def.checks,\n {\n kind,\n value,\n inclusive,\n message: errorUtil.toString(message)\n }\n ]\n });\n }\n _addCheck(check) {\n return new ZodNumber({\n ...this._def,\n checks: [...this._def.checks, check]\n });\n }\n int(message) {\n return this._addCheck({\n kind: \"int\",\n message: errorUtil.toString(message)\n });\n }\n positive(message) {\n return this._addCheck({\n kind: \"min\",\n value: 0,\n inclusive: false,\n message: errorUtil.toString(message)\n });\n }\n negative(message) {\n return this._addCheck({\n kind: \"max\",\n value: 0,\n inclusive: false,\n message: errorUtil.toString(message)\n });\n }\n nonpositive(message) {\n return this._addCheck({\n kind: \"max\",\n value: 0,\n inclusive: true,\n message: errorUtil.toString(message)\n });\n }\n nonnegative(message) {\n return this._addCheck({\n kind: \"min\",\n value: 0,\n inclusive: true,\n message: errorUtil.toString(message)\n });\n }\n multipleOf(value, message) {\n return this._addCheck({\n kind: \"multipleOf\",\n value,\n message: errorUtil.toString(message)\n });\n }\n finite(message) {\n return this._addCheck({\n kind: \"finite\",\n message: errorUtil.toString(message)\n });\n }\n safe(message) {\n return this._addCheck({\n kind: \"min\",\n inclusive: true,\n value: Number.MIN_SAFE_INTEGER,\n message: errorUtil.toString(message)\n })._addCheck({\n kind: \"max\",\n inclusive: true,\n value: Number.MAX_SAFE_INTEGER,\n message: errorUtil.toString(message)\n });\n }\n get minValue() {\n let min = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"min\") {\n if (min === null || ch.value \u003e min)\n min = ch.value;\n }\n }\n return min;\n }\n get maxValue() {\n let max = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"max\") {\n if (max === null || ch.value \u003c max)\n max = ch.value;\n }\n }\n return max;\n }\n get isInt() {\n return !!this._def.checks.find((ch) =\u003e ch.kind === \"int\" || ch.kind === \"multipleOf\" \u0026\u0026 util.isInteger(ch.value));\n }\n get isFinite() {\n let max = null;\n let min = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"finite\" || ch.kind === \"int\" || ch.kind === \"multipleOf\") {\n return true;\n } else if (ch.kind === \"min\") {\n if (min === null || ch.value \u003e min)\n min = ch.value;\n } else if (ch.kind === \"max\") {\n if (max === null || ch.value \u003c max)\n max = ch.value;\n }\n }\n return Number.isFinite(min) \u0026\u0026 Number.isFinite(max);\n }\n}\nZodNumber.create = (params) =\u003e {\n return new ZodNumber({\n checks: [],\n typeName: ZodFirstPartyTypeKind.ZodNumber,\n coerce: params?.coerce || false,\n ...processCreateParams(params)\n });\n};\n\nclass ZodBigInt extends ZodType {\n constructor() {\n super(...arguments);\n this.min = this.gte;\n this.max = this.lte;\n }\n _parse(input) {\n if (this._def.coerce) {\n try {\n input.data = BigInt(input.data);\n } catch {\n return this._getInvalidInput(input);\n }\n }\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.bigint) {\n return this._getInvalidInput(input);\n }\n let ctx = undefined;\n const status = new ParseStatus;\n for (const check of this._def.checks) {\n if (check.kind === \"min\") {\n const tooSmall = check.inclusive ? input.data \u003c check.value : input.data \u003c= check.value;\n if (tooSmall) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n type: \"bigint\",\n minimum: check.value,\n inclusive: check.inclusive,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"max\") {\n const tooBig = check.inclusive ? input.data \u003e check.value : input.data \u003e= check.value;\n if (tooBig) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n type: \"bigint\",\n maximum: check.value,\n inclusive: check.inclusive,\n message: check.message\n });\n status.dirty();\n }\n } else if (check.kind === \"multipleOf\") {\n if (input.data % check.value !== BigInt(0)) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.not_multiple_of,\n multipleOf: check.value,\n message: check.message\n });\n status.dirty();\n }\n } else {\n util.assertNever(check);\n }\n }\n return { status: status.value, value: input.data };\n }\n _getInvalidInput(input) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.bigint,\n received: ctx.parsedType\n });\n return INVALID;\n }\n gte(value, message) {\n return this.setLimit(\"min\", value, true, errorUtil.toString(message));\n }\n gt(value, message) {\n return this.setLimit(\"min\", value, false, errorUtil.toString(message));\n }\n lte(value, message) {\n return this.setLimit(\"max\", value, true, errorUtil.toString(message));\n }\n lt(value, message) {\n return this.setLimit(\"max\", value, false, errorUtil.toString(message));\n }\n setLimit(kind, value, inclusive, message) {\n return new ZodBigInt({\n ...this._def,\n checks: [\n ...this._def.checks,\n {\n kind,\n value,\n inclusive,\n message: errorUtil.toString(message)\n }\n ]\n });\n }\n _addCheck(check) {\n return new ZodBigInt({\n ...this._def,\n checks: [...this._def.checks, check]\n });\n }\n positive(message) {\n return this._addCheck({\n kind: \"min\",\n value: BigInt(0),\n inclusive: false,\n message: errorUtil.toString(message)\n });\n }\n negative(message) {\n return this._addCheck({\n kind: \"max\",\n value: BigInt(0),\n inclusive: false,\n message: errorUtil.toString(message)\n });\n }\n nonpositive(message) {\n return this._addCheck({\n kind: \"max\",\n value: BigInt(0),\n inclusive: true,\n message: errorUtil.toString(message)\n });\n }\n nonnegative(message) {\n return this._addCheck({\n kind: \"min\",\n value: BigInt(0),\n inclusive: true,\n message: errorUtil.toString(message)\n });\n }\n multipleOf(value, message) {\n return this._addCheck({\n kind: \"multipleOf\",\n value,\n message: errorUtil.toString(message)\n });\n }\n get minValue() {\n let min = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"min\") {\n if (min === null || ch.value \u003e min)\n min = ch.value;\n }\n }\n return min;\n }\n get maxValue() {\n let max = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"max\") {\n if (max === null || ch.value \u003c max)\n max = ch.value;\n }\n }\n return max;\n }\n}\nZodBigInt.create = (params) =\u003e {\n return new ZodBigInt({\n checks: [],\n typeName: ZodFirstPartyTypeKind.ZodBigInt,\n coerce: params?.coerce ?? false,\n ...processCreateParams(params)\n });\n};\n\nclass ZodBoolean extends ZodType {\n _parse(input) {\n if (this._def.coerce) {\n input.data = Boolean(input.data);\n }\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.boolean) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.boolean,\n received: ctx.parsedType\n });\n return INVALID;\n }\n return OK(input.data);\n }\n}\nZodBoolean.create = (params) =\u003e {\n return new ZodBoolean({\n typeName: ZodFirstPartyTypeKind.ZodBoolean,\n coerce: params?.coerce || false,\n ...processCreateParams(params)\n });\n};\n\nclass ZodDate extends ZodType {\n _parse(input) {\n if (this._def.coerce) {\n input.data = new Date(input.data);\n }\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.date) {\n const ctx2 = this._getOrReturnCtx(input);\n addIssueToContext(ctx2, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.date,\n received: ctx2.parsedType\n });\n return INVALID;\n }\n if (Number.isNaN(input.data.getTime())) {\n const ctx2 = this._getOrReturnCtx(input);\n addIssueToContext(ctx2, {\n code: ZodIssueCode.invalid_date\n });\n return INVALID;\n }\n const status = new ParseStatus;\n let ctx = undefined;\n for (const check of this._def.checks) {\n if (check.kind === \"min\") {\n if (input.data.getTime() \u003c check.value) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n message: check.message,\n inclusive: true,\n exact: false,\n minimum: check.value,\n type: \"date\"\n });\n status.dirty();\n }\n } else if (check.kind === \"max\") {\n if (input.data.getTime() \u003e check.value) {\n ctx = this._getOrReturnCtx(input, ctx);\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n message: check.message,\n inclusive: true,\n exact: false,\n maximum: check.value,\n type: \"date\"\n });\n status.dirty();\n }\n } else {\n util.assertNever(check);\n }\n }\n return {\n status: status.value,\n value: new Date(input.data.getTime())\n };\n }\n _addCheck(check) {\n return new ZodDate({\n ...this._def,\n checks: [...this._def.checks, check]\n });\n }\n min(minDate, message) {\n return this._addCheck({\n kind: \"min\",\n value: minDate.getTime(),\n message: errorUtil.toString(message)\n });\n }\n max(maxDate, message) {\n return this._addCheck({\n kind: \"max\",\n value: maxDate.getTime(),\n message: errorUtil.toString(message)\n });\n }\n get minDate() {\n let min = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"min\") {\n if (min === null || ch.value \u003e min)\n min = ch.value;\n }\n }\n return min != null ? new Date(min) : null;\n }\n get maxDate() {\n let max = null;\n for (const ch of this._def.checks) {\n if (ch.kind === \"max\") {\n if (max === null || ch.value \u003c max)\n max = ch.value;\n }\n }\n return max != null ? new Date(max) : null;\n }\n}\nZodDate.create = (params) =\u003e {\n return new ZodDate({\n checks: [],\n coerce: params?.coerce || false,\n typeName: ZodFirstPartyTypeKind.ZodDate,\n ...processCreateParams(params)\n });\n};\n\nclass ZodSymbol extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.symbol) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.symbol,\n received: ctx.parsedType\n });\n return INVALID;\n }\n return OK(input.data);\n }\n}\nZodSymbol.create = (params) =\u003e {\n return new ZodSymbol({\n typeName: ZodFirstPartyTypeKind.ZodSymbol,\n ...processCreateParams(params)\n });\n};\n\nclass ZodUndefined extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.undefined) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.undefined,\n received: ctx.parsedType\n });\n return INVALID;\n }\n return OK(input.data);\n }\n}\nZodUndefined.create = (params) =\u003e {\n return new ZodUndefined({\n typeName: ZodFirstPartyTypeKind.ZodUndefined,\n ...processCreateParams(params)\n });\n};\n\nclass ZodNull extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.null) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.null,\n received: ctx.parsedType\n });\n return INVALID;\n }\n return OK(input.data);\n }\n}\nZodNull.create = (params) =\u003e {\n return new ZodNull({\n typeName: ZodFirstPartyTypeKind.ZodNull,\n ...processCreateParams(params)\n });\n};\n\nclass ZodAny extends ZodType {\n constructor() {\n super(...arguments);\n this._any = true;\n }\n _parse(input) {\n return OK(input.data);\n }\n}\nZodAny.create = (params) =\u003e {\n return new ZodAny({\n typeName: ZodFirstPartyTypeKind.ZodAny,\n ...processCreateParams(params)\n });\n};\n\nclass ZodUnknown extends ZodType {\n constructor() {\n super(...arguments);\n this._unknown = true;\n }\n _parse(input) {\n return OK(input.data);\n }\n}\nZodUnknown.create = (params) =\u003e {\n return new ZodUnknown({\n typeName: ZodFirstPartyTypeKind.ZodUnknown,\n ...processCreateParams(params)\n });\n};\n\nclass ZodNever extends ZodType {\n _parse(input) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.never,\n received: ctx.parsedType\n });\n return INVALID;\n }\n}\nZodNever.create = (params) =\u003e {\n return new ZodNever({\n typeName: ZodFirstPartyTypeKind.ZodNever,\n ...processCreateParams(params)\n });\n};\n\nclass ZodVoid extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.undefined) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.void,\n received: ctx.parsedType\n });\n return INVALID;\n }\n return OK(input.data);\n }\n}\nZodVoid.create = (params) =\u003e {\n return new ZodVoid({\n typeName: ZodFirstPartyTypeKind.ZodVoid,\n ...processCreateParams(params)\n });\n};\n\nclass ZodArray extends ZodType {\n _parse(input) {\n const { ctx, status } = this._processInputParams(input);\n const def = this._def;\n if (ctx.parsedType !== ZodParsedType.array) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.array,\n received: ctx.parsedType\n });\n return INVALID;\n }\n if (def.exactLength !== null) {\n const tooBig = ctx.data.length \u003e def.exactLength.value;\n const tooSmall = ctx.data.length \u003c def.exactLength.value;\n if (tooBig || tooSmall) {\n addIssueToContext(ctx, {\n code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small,\n minimum: tooSmall ? def.exactLength.value : undefined,\n maximum: tooBig ? def.exactLength.value : undefined,\n type: \"array\",\n inclusive: true,\n exact: true,\n message: def.exactLength.message\n });\n status.dirty();\n }\n }\n if (def.minLength !== null) {\n if (ctx.data.length \u003c def.minLength.value) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n minimum: def.minLength.value,\n type: \"array\",\n inclusive: true,\n exact: false,\n message: def.minLength.message\n });\n status.dirty();\n }\n }\n if (def.maxLength !== null) {\n if (ctx.data.length \u003e def.maxLength.value) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n maximum: def.maxLength.value,\n type: \"array\",\n inclusive: true,\n exact: false,\n message: def.maxLength.message\n });\n status.dirty();\n }\n }\n if (ctx.common.async) {\n return Promise.all([...ctx.data].map((item, i) =\u003e {\n return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i));\n })).then((result2) =\u003e {\n return ParseStatus.mergeArray(status, result2);\n });\n }\n const result = [...ctx.data].map((item, i) =\u003e {\n return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i));\n });\n return ParseStatus.mergeArray(status, result);\n }\n get element() {\n return this._def.type;\n }\n min(minLength, message) {\n return new ZodArray({\n ...this._def,\n minLength: { value: minLength, message: errorUtil.toString(message) }\n });\n }\n max(maxLength, message) {\n return new ZodArray({\n ...this._def,\n maxLength: { value: maxLength, message: errorUtil.toString(message) }\n });\n }\n length(len, message) {\n return new ZodArray({\n ...this._def,\n exactLength: { value: len, message: errorUtil.toString(message) }\n });\n }\n nonempty(message) {\n return this.min(1, message);\n }\n}\nZodArray.create = (schema, params) =\u003e {\n return new ZodArray({\n type: schema,\n minLength: null,\n maxLength: null,\n exactLength: null,\n typeName: ZodFirstPartyTypeKind.ZodArray,\n ...processCreateParams(params)\n });\n};\nfunction deepPartialify(schema) {\n if (schema instanceof ZodObject) {\n const newShape = {};\n for (const key in schema.shape) {\n const fieldSchema = schema.shape[key];\n newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));\n }\n return new ZodObject({\n ...schema._def,\n shape: () =\u003e newShape\n });\n } else if (schema instanceof ZodArray) {\n return new ZodArray({\n ...schema._def,\n type: deepPartialify(schema.element)\n });\n } else if (schema instanceof ZodOptional) {\n return ZodOptional.create(deepPartialify(schema.unwrap()));\n } else if (schema instanceof ZodNullable) {\n return ZodNullable.create(deepPartialify(schema.unwrap()));\n } else if (schema instanceof ZodTuple) {\n return ZodTuple.create(schema.items.map((item) =\u003e deepPartialify(item)));\n } else {\n return schema;\n }\n}\n\nclass ZodObject extends ZodType {\n constructor() {\n super(...arguments);\n this._cached = null;\n this.nonstrict = this.passthrough;\n this.augment = this.extend;\n }\n _getCached() {\n if (this._cached !== null)\n return this._cached;\n const shape = this._def.shape();\n const keys = util.objectKeys(shape);\n this._cached = { shape, keys };\n return this._cached;\n }\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.object) {\n const ctx2 = this._getOrReturnCtx(input);\n addIssueToContext(ctx2, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.object,\n received: ctx2.parsedType\n });\n return INVALID;\n }\n const { status, ctx } = this._processInputParams(input);\n const { shape, keys: shapeKeys } = this._getCached();\n const extraKeys = [];\n if (!(this._def.catchall instanceof ZodNever \u0026\u0026 this._def.unknownKeys === \"strip\")) {\n for (const key in ctx.data) {\n if (!shapeKeys.includes(key)) {\n extraKeys.push(key);\n }\n }\n }\n const pairs = [];\n for (const key of shapeKeys) {\n const keyValidator = shape[key];\n const value = ctx.data[key];\n pairs.push({\n key: { status: \"valid\", value: key },\n value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),\n alwaysSet: key in ctx.data\n });\n }\n if (this._def.catchall instanceof ZodNever) {\n const unknownKeys = this._def.unknownKeys;\n if (unknownKeys === \"passthrough\") {\n for (const key of extraKeys) {\n pairs.push({\n key: { status: \"valid\", value: key },\n value: { status: \"valid\", value: ctx.data[key] }\n });\n }\n } else if (unknownKeys === \"strict\") {\n if (extraKeys.length \u003e 0) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.unrecognized_keys,\n keys: extraKeys\n });\n status.dirty();\n }\n } else if (unknownKeys === \"strip\") {} else {\n throw new Error(`Internal ZodObject error: invalid unknownKeys value.`);\n }\n } else {\n const catchall = this._def.catchall;\n for (const key of extraKeys) {\n const value = ctx.data[key];\n pairs.push({\n key: { status: \"valid\", value: key },\n value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),\n alwaysSet: key in ctx.data\n });\n }\n }\n if (ctx.common.async) {\n return Promise.resolve().then(async () =\u003e {\n const syncPairs = [];\n for (const pair of pairs) {\n const key = await pair.key;\n const value = await pair.value;\n syncPairs.push({\n key,\n value,\n alwaysSet: pair.alwaysSet\n });\n }\n return syncPairs;\n }).then((syncPairs) =\u003e {\n return ParseStatus.mergeObjectSync(status, syncPairs);\n });\n } else {\n return ParseStatus.mergeObjectSync(status, pairs);\n }\n }\n get shape() {\n return this._def.shape();\n }\n strict(message) {\n errorUtil.errToObj;\n return new ZodObject({\n ...this._def,\n unknownKeys: \"strict\",\n ...message !== undefined ? {\n errorMap: (issue, ctx) =\u003e {\n const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError;\n if (issue.code === \"unrecognized_keys\")\n return {\n message: errorUtil.errToObj(message).message ?? defaultError\n };\n return {\n message: defaultError\n };\n }\n } : {}\n });\n }\n strip() {\n return new ZodObject({\n ...this._def,\n unknownKeys: \"strip\"\n });\n }\n passthrough() {\n return new ZodObject({\n ...this._def,\n unknownKeys: \"passthrough\"\n });\n }\n extend(augmentation) {\n return new ZodObject({\n ...this._def,\n shape: () =\u003e ({\n ...this._def.shape(),\n ...augmentation\n })\n });\n }\n merge(merging) {\n const merged = new ZodObject({\n unknownKeys: merging._def.unknownKeys,\n catchall: merging._def.catchall,\n shape: () =\u003e ({\n ...this._def.shape(),\n ...merging._def.shape()\n }),\n typeName: ZodFirstPartyTypeKind.ZodObject\n });\n return merged;\n }\n setKey(key, schema) {\n return this.augment({ [key]: schema });\n }\n catchall(index) {\n return new ZodObject({\n ...this._def,\n catchall: index\n });\n }\n pick(mask) {\n const shape = {};\n for (const key of util.objectKeys(mask)) {\n if (mask[key] \u0026\u0026 this.shape[key]) {\n shape[key] = this.shape[key];\n }\n }\n return new ZodObject({\n ...this._def,\n shape: () =\u003e shape\n });\n }\n omit(mask) {\n const shape = {};\n for (const key of util.objectKeys(this.shape)) {\n if (!mask[key]) {\n shape[key] = this.shape[key];\n }\n }\n return new ZodObject({\n ...this._def,\n shape: () =\u003e shape\n });\n }\n deepPartial() {\n return deepPartialify(this);\n }\n partial(mask) {\n const newShape = {};\n for (const key of util.objectKeys(this.shape)) {\n const fieldSchema = this.shape[key];\n if (mask \u0026\u0026 !mask[key]) {\n newShape[key] = fieldSchema;\n } else {\n newShape[key] = fieldSchema.optional();\n }\n }\n return new ZodObject({\n ...this._def,\n shape: () =\u003e newShape\n });\n }\n required(mask) {\n const newShape = {};\n for (const key of util.objectKeys(this.shape)) {\n if (mask \u0026\u0026 !mask[key]) {\n newShape[key] = this.shape[key];\n } else {\n const fieldSchema = this.shape[key];\n let newField = fieldSchema;\n while (newField instanceof ZodOptional) {\n newField = newField._def.innerType;\n }\n newShape[key] = newField;\n }\n }\n return new ZodObject({\n ...this._def,\n shape: () =\u003e newShape\n });\n }\n keyof() {\n return createZodEnum(util.objectKeys(this.shape));\n }\n}\nZodObject.create = (shape, params) =\u003e {\n return new ZodObject({\n shape: () =\u003e shape,\n unknownKeys: \"strip\",\n catchall: ZodNever.create(),\n typeName: ZodFirstPartyTypeKind.ZodObject,\n ...processCreateParams(params)\n });\n};\nZodObject.strictCreate = (shape, params) =\u003e {\n return new ZodObject({\n shape: () =\u003e shape,\n unknownKeys: \"strict\",\n catchall: ZodNever.create(),\n typeName: ZodFirstPartyTypeKind.ZodObject,\n ...processCreateParams(params)\n });\n};\nZodObject.lazycreate = (shape, params) =\u003e {\n return new ZodObject({\n shape,\n unknownKeys: \"strip\",\n catchall: ZodNever.create(),\n typeName: ZodFirstPartyTypeKind.ZodObject,\n ...processCreateParams(params)\n });\n};\n\nclass ZodUnion extends ZodType {\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n const options = this._def.options;\n function handleResults(results) {\n for (const result of results) {\n if (result.result.status === \"valid\") {\n return result.result;\n }\n }\n for (const result of results) {\n if (result.result.status === \"dirty\") {\n ctx.common.issues.push(...result.ctx.common.issues);\n return result.result;\n }\n }\n const unionErrors = results.map((result) =\u003e new ZodError(result.ctx.common.issues));\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_union,\n unionErrors\n });\n return INVALID;\n }\n if (ctx.common.async) {\n return Promise.all(options.map(async (option) =\u003e {\n const childCtx = {\n ...ctx,\n common: {\n ...ctx.common,\n issues: []\n },\n parent: null\n };\n return {\n result: await option._parseAsync({\n data: ctx.data,\n path: ctx.path,\n parent: childCtx\n }),\n ctx: childCtx\n };\n })).then(handleResults);\n } else {\n let dirty = undefined;\n const issues = [];\n for (const option of options) {\n const childCtx = {\n ...ctx,\n common: {\n ...ctx.common,\n issues: []\n },\n parent: null\n };\n const result = option._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: childCtx\n });\n if (result.status === \"valid\") {\n return result;\n } else if (result.status === \"dirty\" \u0026\u0026 !dirty) {\n dirty = { result, ctx: childCtx };\n }\n if (childCtx.common.issues.length) {\n issues.push(childCtx.common.issues);\n }\n }\n if (dirty) {\n ctx.common.issues.push(...dirty.ctx.common.issues);\n return dirty.result;\n }\n const unionErrors = issues.map((issues2) =\u003e new ZodError(issues2));\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_union,\n unionErrors\n });\n return INVALID;\n }\n }\n get options() {\n return this._def.options;\n }\n}\nZodUnion.create = (types2, params) =\u003e {\n return new ZodUnion({\n options: types2,\n typeName: ZodFirstPartyTypeKind.ZodUnion,\n ...processCreateParams(params)\n });\n};\nvar getDiscriminator = (type) =\u003e {\n if (type instanceof ZodLazy) {\n return getDiscriminator(type.schema);\n } else if (type instanceof ZodEffects) {\n return getDiscriminator(type.innerType());\n } else if (type instanceof ZodLiteral) {\n return [type.value];\n } else if (type instanceof ZodEnum) {\n return type.options;\n } else if (type instanceof ZodNativeEnum) {\n return util.objectValues(type.enum);\n } else if (type instanceof ZodDefault) {\n return getDiscriminator(type._def.innerType);\n } else if (type instanceof ZodUndefined) {\n return [undefined];\n } else if (type instanceof ZodNull) {\n return [null];\n } else if (type instanceof ZodOptional) {\n return [undefined, ...getDiscriminator(type.unwrap())];\n } else if (type instanceof ZodNullable) {\n return [null, ...getDiscriminator(type.unwrap())];\n } else if (type instanceof ZodBranded) {\n return getDiscriminator(type.unwrap());\n } else if (type instanceof ZodReadonly) {\n return getDiscriminator(type.unwrap());\n } else if (type instanceof ZodCatch) {\n return getDiscriminator(type._def.innerType);\n } else {\n return [];\n }\n};\n\nclass ZodDiscriminatedUnion extends ZodType {\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.object) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.object,\n received: ctx.parsedType\n });\n return INVALID;\n }\n const discriminator = this.discriminator;\n const discriminatorValue = ctx.data[discriminator];\n const option = this.optionsMap.get(discriminatorValue);\n if (!option) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_union_discriminator,\n options: Array.from(this.optionsMap.keys()),\n path: [discriminator]\n });\n return INVALID;\n }\n if (ctx.common.async) {\n return option._parseAsync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n });\n } else {\n return option._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n });\n }\n }\n get discriminator() {\n return this._def.discriminator;\n }\n get options() {\n return this._def.options;\n }\n get optionsMap() {\n return this._def.optionsMap;\n }\n static create(discriminator, options, params) {\n const optionsMap = new Map;\n for (const type of options) {\n const discriminatorValues = getDiscriminator(type.shape[discriminator]);\n if (!discriminatorValues.length) {\n throw new Error(`A discriminator value for key \\`${discriminator}\\` could not be extracted from all schema options`);\n }\n for (const value of discriminatorValues) {\n if (optionsMap.has(value)) {\n throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);\n }\n optionsMap.set(value, type);\n }\n }\n return new ZodDiscriminatedUnion({\n typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,\n discriminator,\n options,\n optionsMap,\n ...processCreateParams(params)\n });\n }\n}\nfunction mergeValues(a, b) {\n const aType = getParsedType(a);\n const bType = getParsedType(b);\n if (a === b) {\n return { valid: true, data: a };\n } else if (aType === ZodParsedType.object \u0026\u0026 bType === ZodParsedType.object) {\n const bKeys = util.objectKeys(b);\n const sharedKeys = util.objectKeys(a).filter((key) =\u003e bKeys.indexOf(key) !== -1);\n const newObj = { ...a, ...b };\n for (const key of sharedKeys) {\n const sharedValue = mergeValues(a[key], b[key]);\n if (!sharedValue.valid) {\n return { valid: false };\n }\n newObj[key] = sharedValue.data;\n }\n return { valid: true, data: newObj };\n } else if (aType === ZodParsedType.array \u0026\u0026 bType === ZodParsedType.array) {\n if (a.length !== b.length) {\n return { valid: false };\n }\n const newArray = [];\n for (let index = 0;index \u003c a.length; index++) {\n const itemA = a[index];\n const itemB = b[index];\n const sharedValue = mergeValues(itemA, itemB);\n if (!sharedValue.valid) {\n return { valid: false };\n }\n newArray.push(sharedValue.data);\n }\n return { valid: true, data: newArray };\n } else if (aType === ZodParsedType.date \u0026\u0026 bType === ZodParsedType.date \u0026\u0026 +a === +b) {\n return { valid: true, data: a };\n } else {\n return { valid: false };\n }\n}\n\nclass ZodIntersection extends ZodType {\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n const handleParsed = (parsedLeft, parsedRight) =\u003e {\n if (isAborted(parsedLeft) || isAborted(parsedRight)) {\n return INVALID;\n }\n const merged = mergeValues(parsedLeft.value, parsedRight.value);\n if (!merged.valid) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_intersection_types\n });\n return INVALID;\n }\n if (isDirty(parsedLeft) || isDirty(parsedRight)) {\n status.dirty();\n }\n return { status: status.value, value: merged.data };\n };\n if (ctx.common.async) {\n return Promise.all([\n this._def.left._parseAsync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n }),\n this._def.right._parseAsync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n })\n ]).then(([left, right]) =\u003e handleParsed(left, right));\n } else {\n return handleParsed(this._def.left._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n }), this._def.right._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n }));\n }\n }\n}\nZodIntersection.create = (left, right, params) =\u003e {\n return new ZodIntersection({\n left,\n right,\n typeName: ZodFirstPartyTypeKind.ZodIntersection,\n ...processCreateParams(params)\n });\n};\n\nclass ZodTuple extends ZodType {\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.array) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.array,\n received: ctx.parsedType\n });\n return INVALID;\n }\n if (ctx.data.length \u003c this._def.items.length) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n minimum: this._def.items.length,\n inclusive: true,\n exact: false,\n type: \"array\"\n });\n return INVALID;\n }\n const rest = this._def.rest;\n if (!rest \u0026\u0026 ctx.data.length \u003e this._def.items.length) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n maximum: this._def.items.length,\n inclusive: true,\n exact: false,\n type: \"array\"\n });\n status.dirty();\n }\n const items = [...ctx.data].map((item, itemIndex) =\u003e {\n const schema = this._def.items[itemIndex] || this._def.rest;\n if (!schema)\n return null;\n return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex));\n }).filter((x) =\u003e !!x);\n if (ctx.common.async) {\n return Promise.all(items).then((results) =\u003e {\n return ParseStatus.mergeArray(status, results);\n });\n } else {\n return ParseStatus.mergeArray(status, items);\n }\n }\n get items() {\n return this._def.items;\n }\n rest(rest) {\n return new ZodTuple({\n ...this._def,\n rest\n });\n }\n}\nZodTuple.create = (schemas, params) =\u003e {\n if (!Array.isArray(schemas)) {\n throw new Error(\"You must pass an array of schemas to z.tuple([ ... ])\");\n }\n return new ZodTuple({\n items: schemas,\n typeName: ZodFirstPartyTypeKind.ZodTuple,\n rest: null,\n ...processCreateParams(params)\n });\n};\n\nclass ZodRecord extends ZodType {\n get keySchema() {\n return this._def.keyType;\n }\n get valueSchema() {\n return this._def.valueType;\n }\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.object) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.object,\n received: ctx.parsedType\n });\n return INVALID;\n }\n const pairs = [];\n const keyType = this._def.keyType;\n const valueType = this._def.valueType;\n for (const key in ctx.data) {\n pairs.push({\n key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),\n value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)),\n alwaysSet: key in ctx.data\n });\n }\n if (ctx.common.async) {\n return ParseStatus.mergeObjectAsync(status, pairs);\n } else {\n return ParseStatus.mergeObjectSync(status, pairs);\n }\n }\n get element() {\n return this._def.valueType;\n }\n static create(first, second, third) {\n if (second instanceof ZodType) {\n return new ZodRecord({\n keyType: first,\n valueType: second,\n typeName: ZodFirstPartyTypeKind.ZodRecord,\n ...processCreateParams(third)\n });\n }\n return new ZodRecord({\n keyType: ZodString.create(),\n valueType: first,\n typeName: ZodFirstPartyTypeKind.ZodRecord,\n ...processCreateParams(second)\n });\n }\n}\n\nclass ZodMap extends ZodType {\n get keySchema() {\n return this._def.keyType;\n }\n get valueSchema() {\n return this._def.valueType;\n }\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.map) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.map,\n received: ctx.parsedType\n });\n return INVALID;\n }\n const keyType = this._def.keyType;\n const valueType = this._def.valueType;\n const pairs = [...ctx.data.entries()].map(([key, value], index) =\u003e {\n return {\n key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, \"key\"])),\n value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, \"value\"]))\n };\n });\n if (ctx.common.async) {\n const finalMap = new Map;\n return Promise.resolve().then(async () =\u003e {\n for (const pair of pairs) {\n const key = await pair.key;\n const value = await pair.value;\n if (key.status === \"aborted\" || value.status === \"aborted\") {\n return INVALID;\n }\n if (key.status === \"dirty\" || value.status === \"dirty\") {\n status.dirty();\n }\n finalMap.set(key.value, value.value);\n }\n return { status: status.value, value: finalMap };\n });\n } else {\n const finalMap = new Map;\n for (const pair of pairs) {\n const key = pair.key;\n const value = pair.value;\n if (key.status === \"aborted\" || value.status === \"aborted\") {\n return INVALID;\n }\n if (key.status === \"dirty\" || value.status === \"dirty\") {\n status.dirty();\n }\n finalMap.set(key.value, value.value);\n }\n return { status: status.value, value: finalMap };\n }\n }\n}\nZodMap.create = (keyType, valueType, params) =\u003e {\n return new ZodMap({\n valueType,\n keyType,\n typeName: ZodFirstPartyTypeKind.ZodMap,\n ...processCreateParams(params)\n });\n};\n\nclass ZodSet extends ZodType {\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.set) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.set,\n received: ctx.parsedType\n });\n return INVALID;\n }\n const def = this._def;\n if (def.minSize !== null) {\n if (ctx.data.size \u003c def.minSize.value) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_small,\n minimum: def.minSize.value,\n type: \"set\",\n inclusive: true,\n exact: false,\n message: def.minSize.message\n });\n status.dirty();\n }\n }\n if (def.maxSize !== null) {\n if (ctx.data.size \u003e def.maxSize.value) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.too_big,\n maximum: def.maxSize.value,\n type: \"set\",\n inclusive: true,\n exact: false,\n message: def.maxSize.message\n });\n status.dirty();\n }\n }\n const valueType = this._def.valueType;\n function finalizeSet(elements2) {\n const parsedSet = new Set;\n for (const element of elements2) {\n if (element.status === \"aborted\")\n return INVALID;\n if (element.status === \"dirty\")\n status.dirty();\n parsedSet.add(element.value);\n }\n return { status: status.value, value: parsedSet };\n }\n const elements = [...ctx.data.values()].map((item, i) =\u003e valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)));\n if (ctx.common.async) {\n return Promise.all(elements).then((elements2) =\u003e finalizeSet(elements2));\n } else {\n return finalizeSet(elements);\n }\n }\n min(minSize, message) {\n return new ZodSet({\n ...this._def,\n minSize: { value: minSize, message: errorUtil.toString(message) }\n });\n }\n max(maxSize, message) {\n return new ZodSet({\n ...this._def,\n maxSize: { value: maxSize, message: errorUtil.toString(message) }\n });\n }\n size(size, message) {\n return this.min(size, message).max(size, message);\n }\n nonempty(message) {\n return this.min(1, message);\n }\n}\nZodSet.create = (valueType, params) =\u003e {\n return new ZodSet({\n valueType,\n minSize: null,\n maxSize: null,\n typeName: ZodFirstPartyTypeKind.ZodSet,\n ...processCreateParams(params)\n });\n};\n\nclass ZodFunction extends ZodType {\n constructor() {\n super(...arguments);\n this.validate = this.implement;\n }\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.function) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.function,\n received: ctx.parsedType\n });\n return INVALID;\n }\n function makeArgsIssue(args, error) {\n return makeIssue({\n data: args,\n path: ctx.path,\n errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) =\u003e !!x),\n issueData: {\n code: ZodIssueCode.invalid_arguments,\n argumentsError: error\n }\n });\n }\n function makeReturnsIssue(returns, error) {\n return makeIssue({\n data: returns,\n path: ctx.path,\n errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) =\u003e !!x),\n issueData: {\n code: ZodIssueCode.invalid_return_type,\n returnTypeError: error\n }\n });\n }\n const params = { errorMap: ctx.common.contextualErrorMap };\n const fn = ctx.data;\n if (this._def.returns instanceof ZodPromise) {\n const me = this;\n return OK(async function(...args) {\n const error = new ZodError([]);\n const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) =\u003e {\n error.addIssue(makeArgsIssue(args, e));\n throw error;\n });\n const result = await Reflect.apply(fn, this, parsedArgs);\n const parsedReturns = await me._def.returns._def.type.parseAsync(result, params).catch((e) =\u003e {\n error.addIssue(makeReturnsIssue(result, e));\n throw error;\n });\n return parsedReturns;\n });\n } else {\n const me = this;\n return OK(function(...args) {\n const parsedArgs = me._def.args.safeParse(args, params);\n if (!parsedArgs.success) {\n throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);\n }\n const result = Reflect.apply(fn, this, parsedArgs.data);\n const parsedReturns = me._def.returns.safeParse(result, params);\n if (!parsedReturns.success) {\n throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);\n }\n return parsedReturns.data;\n });\n }\n }\n parameters() {\n return this._def.args;\n }\n returnType() {\n return this._def.returns;\n }\n args(...items) {\n return new ZodFunction({\n ...this._def,\n args: ZodTuple.create(items).rest(ZodUnknown.create())\n });\n }\n returns(returnType) {\n return new ZodFunction({\n ...this._def,\n returns: returnType\n });\n }\n implement(func) {\n const validatedFunc = this.parse(func);\n return validatedFunc;\n }\n strictImplement(func) {\n const validatedFunc = this.parse(func);\n return validatedFunc;\n }\n static create(args, returns, params) {\n return new ZodFunction({\n args: args ? args : ZodTuple.create([]).rest(ZodUnknown.create()),\n returns: returns || ZodUnknown.create(),\n typeName: ZodFirstPartyTypeKind.ZodFunction,\n ...processCreateParams(params)\n });\n }\n}\n\nclass ZodLazy extends ZodType {\n get schema() {\n return this._def.getter();\n }\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n const lazySchema = this._def.getter();\n return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx });\n }\n}\nZodLazy.create = (getter, params) =\u003e {\n return new ZodLazy({\n getter,\n typeName: ZodFirstPartyTypeKind.ZodLazy,\n ...processCreateParams(params)\n });\n};\n\nclass ZodLiteral extends ZodType {\n _parse(input) {\n if (input.data !== this._def.value) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n received: ctx.data,\n code: ZodIssueCode.invalid_literal,\n expected: this._def.value\n });\n return INVALID;\n }\n return { status: \"valid\", value: input.data };\n }\n get value() {\n return this._def.value;\n }\n}\nZodLiteral.create = (value, params) =\u003e {\n return new ZodLiteral({\n value,\n typeName: ZodFirstPartyTypeKind.ZodLiteral,\n ...processCreateParams(params)\n });\n};\nfunction createZodEnum(values, params) {\n return new ZodEnum({\n values,\n typeName: ZodFirstPartyTypeKind.ZodEnum,\n ...processCreateParams(params)\n });\n}\n\nclass ZodEnum extends ZodType {\n _parse(input) {\n if (typeof input.data !== \"string\") {\n const ctx = this._getOrReturnCtx(input);\n const expectedValues = this._def.values;\n addIssueToContext(ctx, {\n expected: util.joinValues(expectedValues),\n received: ctx.parsedType,\n code: ZodIssueCode.invalid_type\n });\n return INVALID;\n }\n if (!this._cache) {\n this._cache = new Set(this._def.values);\n }\n if (!this._cache.has(input.data)) {\n const ctx = this._getOrReturnCtx(input);\n const expectedValues = this._def.values;\n addIssueToContext(ctx, {\n received: ctx.data,\n code: ZodIssueCode.invalid_enum_value,\n options: expectedValues\n });\n return INVALID;\n }\n return OK(input.data);\n }\n get options() {\n return this._def.values;\n }\n get enum() {\n const enumValues = {};\n for (const val of this._def.values) {\n enumValues[val] = val;\n }\n return enumValues;\n }\n get Values() {\n const enumValues = {};\n for (const val of this._def.values) {\n enumValues[val] = val;\n }\n return enumValues;\n }\n get Enum() {\n const enumValues = {};\n for (const val of this._def.values) {\n enumValues[val] = val;\n }\n return enumValues;\n }\n extract(values, newDef = this._def) {\n return ZodEnum.create(values, {\n ...this._def,\n ...newDef\n });\n }\n exclude(values, newDef = this._def) {\n return ZodEnum.create(this.options.filter((opt) =\u003e !values.includes(opt)), {\n ...this._def,\n ...newDef\n });\n }\n}\nZodEnum.create = createZodEnum;\n\nclass ZodNativeEnum extends ZodType {\n _parse(input) {\n const nativeEnumValues = util.getValidEnumValues(this._def.values);\n const ctx = this._getOrReturnCtx(input);\n if (ctx.parsedType !== ZodParsedType.string \u0026\u0026 ctx.parsedType !== ZodParsedType.number) {\n const expectedValues = util.objectValues(nativeEnumValues);\n addIssueToContext(ctx, {\n expected: util.joinValues(expectedValues),\n received: ctx.parsedType,\n code: ZodIssueCode.invalid_type\n });\n return INVALID;\n }\n if (!this._cache) {\n this._cache = new Set(util.getValidEnumValues(this._def.values));\n }\n if (!this._cache.has(input.data)) {\n const expectedValues = util.objectValues(nativeEnumValues);\n addIssueToContext(ctx, {\n received: ctx.data,\n code: ZodIssueCode.invalid_enum_value,\n options: expectedValues\n });\n return INVALID;\n }\n return OK(input.data);\n }\n get enum() {\n return this._def.values;\n }\n}\nZodNativeEnum.create = (values, params) =\u003e {\n return new ZodNativeEnum({\n values,\n typeName: ZodFirstPartyTypeKind.ZodNativeEnum,\n ...processCreateParams(params)\n });\n};\n\nclass ZodPromise extends ZodType {\n unwrap() {\n return this._def.type;\n }\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n if (ctx.parsedType !== ZodParsedType.promise \u0026\u0026 ctx.common.async === false) {\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.promise,\n received: ctx.parsedType\n });\n return INVALID;\n }\n const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data);\n return OK(promisified.then((data) =\u003e {\n return this._def.type.parseAsync(data, {\n path: ctx.path,\n errorMap: ctx.common.contextualErrorMap\n });\n }));\n }\n}\nZodPromise.create = (schema, params) =\u003e {\n return new ZodPromise({\n type: schema,\n typeName: ZodFirstPartyTypeKind.ZodPromise,\n ...processCreateParams(params)\n });\n};\n\nclass ZodEffects extends ZodType {\n innerType() {\n return this._def.schema;\n }\n sourceType() {\n return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects ? this._def.schema.sourceType() : this._def.schema;\n }\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n const effect = this._def.effect || null;\n const checkCtx = {\n addIssue: (arg) =\u003e {\n addIssueToContext(ctx, arg);\n if (arg.fatal) {\n status.abort();\n } else {\n status.dirty();\n }\n },\n get path() {\n return ctx.path;\n }\n };\n checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);\n if (effect.type === \"preprocess\") {\n const processed = effect.transform(ctx.data, checkCtx);\n if (ctx.common.async) {\n return Promise.resolve(processed).then(async (processed2) =\u003e {\n if (status.value === \"aborted\")\n return INVALID;\n const result = await this._def.schema._parseAsync({\n data: processed2,\n path: ctx.path,\n parent: ctx\n });\n if (result.status === \"aborted\")\n return INVALID;\n if (result.status === \"dirty\")\n return DIRTY(result.value);\n if (status.value === \"dirty\")\n return DIRTY(result.value);\n return result;\n });\n } else {\n if (status.value === \"aborted\")\n return INVALID;\n const result = this._def.schema._parseSync({\n data: processed,\n path: ctx.path,\n parent: ctx\n });\n if (result.status === \"aborted\")\n return INVALID;\n if (result.status === \"dirty\")\n return DIRTY(result.value);\n if (status.value === \"dirty\")\n return DIRTY(result.value);\n return result;\n }\n }\n if (effect.type === \"refinement\") {\n const executeRefinement = (acc) =\u003e {\n const result = effect.refinement(acc, checkCtx);\n if (ctx.common.async) {\n return Promise.resolve(result);\n }\n if (result instanceof Promise) {\n throw new Error(\"Async refinement encountered during synchronous parse operation. Use .parseAsync instead.\");\n }\n return acc;\n };\n if (ctx.common.async === false) {\n const inner = this._def.schema._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n });\n if (inner.status === \"aborted\")\n return INVALID;\n if (inner.status === \"dirty\")\n status.dirty();\n executeRefinement(inner.value);\n return { status: status.value, value: inner.value };\n } else {\n return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) =\u003e {\n if (inner.status === \"aborted\")\n return INVALID;\n if (inner.status === \"dirty\")\n status.dirty();\n return executeRefinement(inner.value).then(() =\u003e {\n return { status: status.value, value: inner.value };\n });\n });\n }\n }\n if (effect.type === \"transform\") {\n if (ctx.common.async === false) {\n const base = this._def.schema._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n });\n if (!isValid(base))\n return INVALID;\n const result = effect.transform(base.value, checkCtx);\n if (result instanceof Promise) {\n throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);\n }\n return { status: status.value, value: result };\n } else {\n return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) =\u003e {\n if (!isValid(base))\n return INVALID;\n return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) =\u003e ({\n status: status.value,\n value: result\n }));\n });\n }\n }\n util.assertNever(effect);\n }\n}\nZodEffects.create = (schema, effect, params) =\u003e {\n return new ZodEffects({\n schema,\n typeName: ZodFirstPartyTypeKind.ZodEffects,\n effect,\n ...processCreateParams(params)\n });\n};\nZodEffects.createWithPreprocess = (preprocess, schema, params) =\u003e {\n return new ZodEffects({\n schema,\n effect: { type: \"preprocess\", transform: preprocess },\n typeName: ZodFirstPartyTypeKind.ZodEffects,\n ...processCreateParams(params)\n });\n};\nclass ZodOptional extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType === ZodParsedType.undefined) {\n return OK(undefined);\n }\n return this._def.innerType._parse(input);\n }\n unwrap() {\n return this._def.innerType;\n }\n}\nZodOptional.create = (type, params) =\u003e {\n return new ZodOptional({\n innerType: type,\n typeName: ZodFirstPartyTypeKind.ZodOptional,\n ...processCreateParams(params)\n });\n};\n\nclass ZodNullable extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType === ZodParsedType.null) {\n return OK(null);\n }\n return this._def.innerType._parse(input);\n }\n unwrap() {\n return this._def.innerType;\n }\n}\nZodNullable.create = (type, params) =\u003e {\n return new ZodNullable({\n innerType: type,\n typeName: ZodFirstPartyTypeKind.ZodNullable,\n ...processCreateParams(params)\n });\n};\n\nclass ZodDefault extends ZodType {\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n let data = ctx.data;\n if (ctx.parsedType === ZodParsedType.undefined) {\n data = this._def.defaultValue();\n }\n return this._def.innerType._parse({\n data,\n path: ctx.path,\n parent: ctx\n });\n }\n removeDefault() {\n return this._def.innerType;\n }\n}\nZodDefault.create = (type, params) =\u003e {\n return new ZodDefault({\n innerType: type,\n typeName: ZodFirstPartyTypeKind.ZodDefault,\n defaultValue: typeof params.default === \"function\" ? params.default : () =\u003e params.default,\n ...processCreateParams(params)\n });\n};\n\nclass ZodCatch extends ZodType {\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n const newCtx = {\n ...ctx,\n common: {\n ...ctx.common,\n issues: []\n }\n };\n const result = this._def.innerType._parse({\n data: newCtx.data,\n path: newCtx.path,\n parent: {\n ...newCtx\n }\n });\n if (isAsync(result)) {\n return result.then((result2) =\u003e {\n return {\n status: \"valid\",\n value: result2.status === \"valid\" ? result2.value : this._def.catchValue({\n get error() {\n return new ZodError(newCtx.common.issues);\n },\n input: newCtx.data\n })\n };\n });\n } else {\n return {\n status: \"valid\",\n value: result.status === \"valid\" ? result.value : this._def.catchValue({\n get error() {\n return new ZodError(newCtx.common.issues);\n },\n input: newCtx.data\n })\n };\n }\n }\n removeCatch() {\n return this._def.innerType;\n }\n}\nZodCatch.create = (type, params) =\u003e {\n return new ZodCatch({\n innerType: type,\n typeName: ZodFirstPartyTypeKind.ZodCatch,\n catchValue: typeof params.catch === \"function\" ? params.catch : () =\u003e params.catch,\n ...processCreateParams(params)\n });\n};\n\nclass ZodNaN extends ZodType {\n _parse(input) {\n const parsedType = this._getType(input);\n if (parsedType !== ZodParsedType.nan) {\n const ctx = this._getOrReturnCtx(input);\n addIssueToContext(ctx, {\n code: ZodIssueCode.invalid_type,\n expected: ZodParsedType.nan,\n received: ctx.parsedType\n });\n return INVALID;\n }\n return { status: \"valid\", value: input.data };\n }\n}\nZodNaN.create = (params) =\u003e {\n return new ZodNaN({\n typeName: ZodFirstPartyTypeKind.ZodNaN,\n ...processCreateParams(params)\n });\n};\nvar BRAND = Symbol(\"zod_brand\");\n\nclass ZodBranded extends ZodType {\n _parse(input) {\n const { ctx } = this._processInputParams(input);\n const data = ctx.data;\n return this._def.type._parse({\n data,\n path: ctx.path,\n parent: ctx\n });\n }\n unwrap() {\n return this._def.type;\n }\n}\n\nclass ZodPipeline extends ZodType {\n _parse(input) {\n const { status, ctx } = this._processInputParams(input);\n if (ctx.common.async) {\n const handleAsync = async () =\u003e {\n const inResult = await this._def.in._parseAsync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n });\n if (inResult.status === \"aborted\")\n return INVALID;\n if (inResult.status === \"dirty\") {\n status.dirty();\n return DIRTY(inResult.value);\n } else {\n return this._def.out._parseAsync({\n data: inResult.value,\n path: ctx.path,\n parent: ctx\n });\n }\n };\n return handleAsync();\n } else {\n const inResult = this._def.in._parseSync({\n data: ctx.data,\n path: ctx.path,\n parent: ctx\n });\n if (inResult.status === \"aborted\")\n return INVALID;\n if (inResult.status === \"dirty\") {\n status.dirty();\n return {\n status: \"dirty\",\n value: inResult.value\n };\n } else {\n return this._def.out._parseSync({\n data: inResult.value,\n path: ctx.path,\n parent: ctx\n });\n }\n }\n }\n static create(a, b) {\n return new ZodPipeline({\n in: a,\n out: b,\n typeName: ZodFirstPartyTypeKind.ZodPipeline\n });\n }\n}\n\nclass ZodReadonly extends ZodType {\n _parse(input) {\n const result = this._def.innerType._parse(input);\n const freeze = (data) =\u003e {\n if (isValid(data)) {\n data.value = Object.freeze(data.value);\n }\n return data;\n };\n return isAsync(result) ? result.then((data) =\u003e freeze(data)) : freeze(result);\n }\n unwrap() {\n return this._def.innerType;\n }\n}\nZodReadonly.create = (type, params) =\u003e {\n return new ZodReadonly({\n innerType: type,\n typeName: ZodFirstPartyTypeKind.ZodReadonly,\n ...processCreateParams(params)\n });\n};\nfunction cleanParams(params, data) {\n const p = typeof params === \"function\" ? params(data) : typeof params === \"string\" ? { message: params } : params;\n const p2 = typeof p === \"string\" ? { message: p } : p;\n return p2;\n}\nfunction custom(check, _params = {}, fatal) {\n if (check)\n return ZodAny.create().superRefine((data, ctx) =\u003e {\n const r = check(data);\n if (r instanceof Promise) {\n return r.then((r2) =\u003e {\n if (!r2) {\n const params = cleanParams(_params, data);\n const _fatal = params.fatal ?? fatal ?? true;\n ctx.addIssue({ code: \"custom\", ...params, fatal: _fatal });\n }\n });\n }\n if (!r) {\n const params = cleanParams(_params, data);\n const _fatal = params.fatal ?? fatal ?? true;\n ctx.addIssue({ code: \"custom\", ...params, fatal: _fatal });\n }\n return;\n });\n return ZodAny.create();\n}\nvar late = {\n object: ZodObject.lazycreate\n};\nvar ZodFirstPartyTypeKind;\n(function(ZodFirstPartyTypeKind2) {\n ZodFirstPartyTypeKind2[\"ZodString\"] = \"ZodString\";\n ZodFirstPartyTypeKind2[\"ZodNumber\"] = \"ZodNumber\";\n ZodFirstPartyTypeKind2[\"ZodNaN\"] = \"ZodNaN\";\n ZodFirstPartyTypeKind2[\"ZodBigInt\"] = \"ZodBigInt\";\n ZodFirstPartyTypeKind2[\"ZodBoolean\"] = \"ZodBoolean\";\n ZodFirstPartyTypeKind2[\"ZodDate\"] = \"ZodDate\";\n ZodFirstPartyTypeKind2[\"ZodSymbol\"] = \"ZodSymbol\";\n ZodFirstPartyTypeKind2[\"ZodUndefined\"] = \"ZodUndefined\";\n ZodFirstPartyTypeKind2[\"ZodNull\"] = \"ZodNull\";\n ZodFirstPartyTypeKind2[\"ZodAny\"] = \"ZodAny\";\n ZodFirstPartyTypeKind2[\"ZodUnknown\"] = \"ZodUnknown\";\n ZodFirstPartyTypeKind2[\"ZodNever\"] = \"ZodNever\";\n ZodFirstPartyTypeKind2[\"ZodVoid\"] = \"ZodVoid\";\n ZodFirstPartyTypeKind2[\"ZodArray\"] = \"ZodArray\";\n ZodFirstPartyTypeKind2[\"ZodObject\"] = \"ZodObject\";\n ZodFirstPartyTypeKind2[\"ZodUnion\"] = \"ZodUnion\";\n ZodFirstPartyTypeKind2[\"ZodDiscriminatedUnion\"] = \"ZodDiscriminatedUnion\";\n ZodFirstPartyTypeKind2[\"ZodIntersection\"] = \"ZodIntersection\";\n ZodFirstPartyTypeKind2[\"ZodTuple\"] = \"ZodTuple\";\n ZodFirstPartyTypeKind2[\"ZodRecord\"] = \"ZodRecord\";\n ZodFirstPartyTypeKind2[\"ZodMap\"] = \"ZodMap\";\n ZodFirstPartyTypeKind2[\"ZodSet\"] = \"ZodSet\";\n ZodFirstPartyTypeKind2[\"ZodFunction\"] = \"ZodFunction\";\n ZodFirstPartyTypeKind2[\"ZodLazy\"] = \"ZodLazy\";\n ZodFirstPartyTypeKind2[\"ZodLiteral\"] = \"ZodLiteral\";\n ZodFirstPartyTypeKind2[\"ZodEnum\"] = \"ZodEnum\";\n ZodFirstPartyTypeKind2[\"ZodEffects\"] = \"ZodEffects\";\n ZodFirstPartyTypeKind2[\"ZodNativeEnum\"] = \"ZodNativeEnum\";\n ZodFirstPartyTypeKind2[\"ZodOptional\"] = \"ZodOptional\";\n ZodFirstPartyTypeKind2[\"ZodNullable\"] = \"ZodNullable\";\n ZodFirstPartyTypeKind2[\"ZodDefault\"] = \"ZodDefault\";\n ZodFirstPartyTypeKind2[\"ZodCatch\"] = \"ZodCatch\";\n ZodFirstPartyTypeKind2[\"ZodPromise\"] = \"ZodPromise\";\n ZodFirstPartyTypeKind2[\"ZodBranded\"] = \"ZodBranded\";\n ZodFirstPartyTypeKind2[\"ZodPipeline\"] = \"ZodPipeline\";\n ZodFirstPartyTypeKind2[\"ZodReadonly\"] = \"ZodReadonly\";\n})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));\nvar instanceOfType = (cls, params = {\n message: `Input not instance of ${cls.name}`\n}) =\u003e custom((data) =\u003e data instanceof cls, params);\nvar stringType = ZodString.create;\nvar numberType = ZodNumber.create;\nvar nanType = ZodNaN.create;\nvar bigIntType = ZodBigInt.create;\nvar booleanType = ZodBoolean.create;\nvar dateType = ZodDate.create;\nvar symbolType = ZodSymbol.create;\nvar undefinedType = ZodUndefined.create;\nvar nullType = ZodNull.create;\nvar anyType = ZodAny.create;\nvar unknownType = ZodUnknown.create;\nvar neverType = ZodNever.create;\nvar voidType = ZodVoid.create;\nvar arrayType = ZodArray.create;\nvar objectType = ZodObject.create;\nvar strictObjectType = ZodObject.strictCreate;\nvar unionType = ZodUnion.create;\nvar discriminatedUnionType = ZodDiscriminatedUnion.create;\nvar intersectionType = ZodIntersection.create;\nvar tupleType = ZodTuple.create;\nvar recordType = ZodRecord.create;\nvar mapType = ZodMap.create;\nvar setType = ZodSet.create;\nvar functionType = ZodFunction.create;\nvar lazyType = ZodLazy.create;\nvar literalType = ZodLiteral.create;\nvar enumType = ZodEnum.create;\nvar nativeEnumType = ZodNativeEnum.create;\nvar promiseType = ZodPromise.create;\nvar effectsType = ZodEffects.create;\nvar optionalType = ZodOptional.create;\nvar nullableType = ZodNullable.create;\nvar preprocessType = ZodEffects.createWithPreprocess;\nvar pipelineType = ZodPipeline.create;\nvar ostring = () =\u003e stringType().optional();\nvar onumber = () =\u003e numberType().optional();\nvar oboolean = () =\u003e booleanType().optional();\nvar coerce = {\n string: (arg) =\u003e ZodString.create({ ...arg, coerce: true }),\n number: (arg) =\u003e ZodNumber.create({ ...arg, coerce: true }),\n boolean: (arg) =\u003e ZodBoolean.create({\n ...arg,\n coerce: true\n }),\n bigint: (arg) =\u003e ZodBigInt.create({ ...arg, coerce: true }),\n date: (arg) =\u003e ZodDate.create({ ...arg, coerce: true })\n};\nvar NEVER = INVALID;\n// ../../work/placement-analysis/node_modules/circuit-json/dist/index.mjs\nvar resistance = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v, \"Ω\").value);\nvar capacitance = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v, \"F\").value).transform((value) =\u003e {\n return Number.parseFloat(value.toPrecision(12));\n});\nvar inductance = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v, \"H\").value);\nvar voltage = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v, \"V\").value);\nvar length = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v).value);\nvar frequency = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v, \"Hz\").value);\nvar distance4 = length;\nvar current = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v, \"A\").value);\nvar duration_ms = exports_external.string().or(exports_external.number()).transform((v) =\u003e parseAndConvertSiUnit(v).value);\nvar time = duration_ms;\nvar ms = duration_ms;\nvar timestamp = exports_external.string().datetime();\nvar rotation = exports_external.string().or(exports_external.number()).transform((arg) =\u003e {\n if (typeof arg === \"number\")\n return arg;\n if (arg.endsWith(\"deg\")) {\n return Number.parseFloat(arg.split(\"deg\")[0]);\n }\n if (arg.endsWith(\"rad\")) {\n return Number.parseFloat(arg.split(\"rad\")[0]) * 180 / Math.PI;\n }\n return Number.parseFloat(arg);\n});\nvar battery_capacity = exports_external.number().or(exports_external.string().endsWith(\"mAh\")).transform((v) =\u003e {\n if (typeof v === \"string\") {\n const valString = v.replace(\"mAh\", \"\");\n const num = Number.parseFloat(valString);\n if (Number.isNaN(num)) {\n throw new Error(\"Invalid capacity\");\n }\n return num;\n }\n return v;\n}).describe(\"Battery capacity in mAh\");\nvar expectTypesMatch = (shouldBe) =\u003e {};\nexpectTypesMatch(\"extra props b\");\nexpectTypesMatch(\"missing props b\");\nexpectTypesMatch(true);\nexpectTypesMatch(\"mismatched prop types: a\");\nvar expectStringUnionsMatch = (shouldBe) =\u003e {};\nexpectStringUnionsMatch(true);\nexpectStringUnionsMatch('T1 has extra: \"c\", T2 has extra: \"d\"');\nexpectStringUnionsMatch('T1 has extra: \"c\"');\nexpectStringUnionsMatch('T2 has extra: \"c\"');\nexpectStringUnionsMatch('T1 has extra: \"d\", T2 has extra: \"c\"');\nexpectStringUnionsMatch(true);\nvar point = exports_external.object({\n x: distance4,\n y: distance4\n});\nvar position = point;\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar point3 = exports_external.object({\n x: distance4,\n y: distance4,\n z: distance4\n});\nvar position3 = point3;\nexpectTypesMatch(true);\nvar size = exports_external.object({\n width: exports_external.number(),\n height: exports_external.number()\n});\nexpectTypesMatch(true);\nvar randomId = (length4) =\u003e {\n const chars = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\n return Array.from({ length: length4 }, () =\u003e chars[Math.floor(Math.random() * chars.length)]).join(\"\");\n};\nvar getZodPrefixedIdWithDefault = (prefix) =\u003e {\n return exports_external.string().optional().default(() =\u003e `${prefix}_${randomId(10)}`);\n};\nvar ninePointAnchor = exports_external.enum([\n \"top_left\",\n \"top_center\",\n \"top_right\",\n \"center_left\",\n \"center\",\n \"center_right\",\n \"bottom_left\",\n \"bottom_center\",\n \"bottom_right\"\n]);\nexpectTypesMatch(true);\nvar pcbRenderLayer = exports_external.enum([\n \"top_silkscreen\",\n \"bottom_silkscreen\",\n \"top_copper\",\n \"bottom_copper\",\n \"top_soldermask\",\n \"bottom_soldermask\",\n \"top_fabrication_note\",\n \"bottom_fabrication_note\",\n \"top_user_note\",\n \"bottom_user_note\",\n \"top_courtyard\",\n \"bottom_courtyard\",\n \"inner1_copper\",\n \"inner2_copper\",\n \"inner3_copper\",\n \"inner4_copper\",\n \"inner5_copper\",\n \"inner6_copper\",\n \"edge_cuts\",\n \"drill\"\n]);\nexpectTypesMatch(true);\nvar asset = exports_external.object({\n project_relative_path: exports_external.string(),\n url: exports_external.string(),\n mimetype: exports_external.string()\n});\nexpectTypesMatch(true);\nvar kicadAt = point.extend({\n rotation: rotation.optional()\n});\nexpectTypesMatch(true);\nvar kicadFont = exports_external.object({\n size: point.optional(),\n thickness: distance4.optional()\n});\nexpectTypesMatch(true);\nvar kicadEffects = exports_external.object({\n font: kicadFont.optional()\n});\nexpectTypesMatch(true);\nvar kicadProperty = exports_external.object({\n value: exports_external.string(),\n at: kicadAt.optional(),\n layer: exports_external.string().optional(),\n uuid: exports_external.string().optional(),\n hide: exports_external.boolean().optional(),\n effects: kicadEffects.optional()\n});\nexpectTypesMatch(true);\nvar kicadFootprintProperties = exports_external.object({\n Reference: kicadProperty.optional(),\n Value: kicadProperty.optional(),\n Datasheet: kicadProperty.optional(),\n Description: kicadProperty.optional()\n});\nexpectTypesMatch(true);\nvar kicadFootprintAttributes = exports_external.object({\n through_hole: exports_external.boolean().optional(),\n smd: exports_external.boolean().optional(),\n exclude_from_pos_files: exports_external.boolean().optional(),\n exclude_from_bom: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar kicadFootprintPad = exports_external.object({\n name: exports_external.string(),\n type: exports_external.string(),\n shape: exports_external.string().optional(),\n at: kicadAt.optional(),\n size: point.optional(),\n drill: distance4.optional(),\n layers: exports_external.array(exports_external.string()).optional(),\n removeUnusedLayers: exports_external.boolean().optional(),\n uuid: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar kicadFootprintModel = exports_external.object({\n path: exports_external.string(),\n offset: point3.optional(),\n scale: point3.optional(),\n rotate: point3.optional()\n});\nexpectTypesMatch(true);\nvar kicadFootprintMetadata = exports_external.object({\n footprintName: exports_external.string().optional(),\n version: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n generator: exports_external.string().optional(),\n generatorVersion: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n layer: exports_external.string().optional(),\n properties: kicadFootprintProperties.optional(),\n attributes: kicadFootprintAttributes.optional(),\n pads: exports_external.array(kicadFootprintPad).optional(),\n embeddedFonts: exports_external.boolean().optional(),\n model: kicadFootprintModel.optional()\n});\nexpectTypesMatch(true);\nvar kicadSymbolPinNumbers = exports_external.object({\n hide: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar kicadSymbolPinNames = exports_external.object({\n offset: distance4.optional(),\n hide: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar kicadSymbolEffects = exports_external.object({\n font: kicadFont.optional(),\n justify: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional(),\n hide: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar kicadSymbolProperty = exports_external.object({\n value: exports_external.string(),\n id: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n at: kicadAt.optional(),\n effects: kicadSymbolEffects.optional()\n});\nexpectTypesMatch(true);\nvar kicadSymbolProperties = exports_external.object({\n Reference: kicadSymbolProperty.optional(),\n Value: kicadSymbolProperty.optional(),\n Footprint: kicadSymbolProperty.optional(),\n Datasheet: kicadSymbolProperty.optional(),\n Description: kicadSymbolProperty.optional(),\n ki_keywords: kicadSymbolProperty.optional(),\n ki_fp_filters: kicadSymbolProperty.optional()\n});\nexpectTypesMatch(true);\nvar kicadSymbolMetadata = exports_external.object({\n symbolName: exports_external.string().optional(),\n extends: exports_external.string().optional(),\n pinNumbers: kicadSymbolPinNumbers.optional(),\n pinNames: kicadSymbolPinNames.optional(),\n excludeFromSim: exports_external.boolean().optional(),\n inBom: exports_external.boolean().optional(),\n onBoard: exports_external.boolean().optional(),\n properties: kicadSymbolProperties.optional(),\n embeddedFonts: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar base_circuit_json_error = exports_external.object({\n error_type: exports_external.string(),\n message: exports_external.string(),\n is_fatal: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar supplier_name = exports_external.enum([\n \"jlcpcb\",\n \"macrofab\",\n \"pcbway\",\n \"digikey\",\n \"mouser\",\n \"lcsc\"\n]);\nexpectTypesMatch(true);\nvar source_component_base = exports_external.object({\n type: exports_external.literal(\"source_component\"),\n ftype: exports_external.string().optional(),\n source_component_id: exports_external.string(),\n name: exports_external.string(),\n manufacturer_part_number: exports_external.string().optional(),\n supplier_part_numbers: exports_external.record(supplier_name, exports_external.array(exports_external.string())).optional(),\n display_value: exports_external.string().optional(),\n display_name: exports_external.string().optional(),\n are_pins_interchangeable: exports_external.boolean().optional(),\n internally_connected_source_port_ids: exports_external.array(exports_external.array(exports_external.string())).optional(),\n source_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_simple_capacitor = source_component_base.extend({\n ftype: exports_external.literal(\"simple_capacitor\"),\n capacitance,\n max_voltage_rating: voltage.optional(),\n display_capacitance: exports_external.string().optional(),\n max_decoupling_trace_length: distance4.optional()\n});\nexpectTypesMatch(true);\nvar source_simple_resistor = source_component_base.extend({\n ftype: exports_external.literal(\"simple_resistor\"),\n resistance,\n display_resistance: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_simple_diode = source_component_base.extend({\n ftype: exports_external.literal(\"simple_diode\")\n});\nexpectTypesMatch(true);\nvar source_simple_fiducial = source_component_base.extend({\n ftype: exports_external.literal(\"simple_fiducial\")\n});\nexpectTypesMatch(true);\nvar source_simple_led = source_simple_diode.extend({\n ftype: exports_external.literal(\"simple_led\"),\n color: exports_external.string().optional(),\n wavelength: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_simple_ground = source_component_base.extend({\n ftype: exports_external.literal(\"simple_ground\")\n});\nexpectTypesMatch(true);\nvar source_simple_chip = source_component_base.extend({\n ftype: exports_external.literal(\"simple_chip\")\n});\nexpectTypesMatch(true);\nvar source_simple_power_source = source_component_base.extend({\n ftype: exports_external.literal(\"simple_power_source\"),\n voltage\n});\nexpectTypesMatch(true);\nvar source_simple_current_source = source_component_base.extend({\n ftype: exports_external.literal(\"simple_current_source\"),\n current,\n frequency: frequency.optional(),\n peak_to_peak_current: current.optional(),\n wave_shape: exports_external.enum([\"sine\", \"square\", \"triangle\", \"sawtooth\", \"dc\"]).optional().default(\"dc\"),\n phase: exports_external.number().optional(),\n duty_cycle: exports_external.number().min(0).max(1).optional()\n});\nexpectTypesMatch(true);\nvar source_simple_ammeter = source_component_base.extend({\n ftype: exports_external.literal(\"simple_ammeter\")\n});\nexpectTypesMatch(true);\nvar source_pin_attributes = exports_external.object({\n must_be_connected: exports_external.boolean().optional(),\n provides_power: exports_external.boolean().optional(),\n requires_power: exports_external.boolean().optional(),\n provides_ground: exports_external.boolean().optional(),\n requires_ground: exports_external.boolean().optional(),\n provides_voltage: exports_external.union([exports_external.string(), exports_external.number()]).optional(),\n requires_voltage: exports_external.union([exports_external.string(), exports_external.number()]).optional(),\n do_not_connect: exports_external.boolean().optional(),\n include_in_board_pinout: exports_external.boolean().optional(),\n can_use_internal_pullup: exports_external.boolean().optional(),\n is_using_internal_pullup: exports_external.boolean().optional(),\n needs_external_pullup: exports_external.boolean().optional(),\n can_use_internal_pulldown: exports_external.boolean().optional(),\n is_using_internal_pulldown: exports_external.boolean().optional(),\n needs_external_pulldown: exports_external.boolean().optional(),\n can_use_open_drain: exports_external.boolean().optional(),\n is_using_open_drain: exports_external.boolean().optional(),\n can_use_push_pull: exports_external.boolean().optional(),\n is_using_push_pull: exports_external.boolean().optional(),\n should_have_decoupling_capacitor: exports_external.boolean().optional(),\n recommended_decoupling_capacitor_capacitance: exports_external.union([exports_external.string(), exports_external.number()]).optional(),\n is_configured_for_i2c_sda: exports_external.boolean().optional(),\n is_configured_for_i2c_scl: exports_external.boolean().optional(),\n is_configured_for_spi_mosi: exports_external.boolean().optional(),\n is_configured_for_spi_miso: exports_external.boolean().optional(),\n is_configured_for_spi_sck: exports_external.boolean().optional(),\n is_configured_for_spi_cs: exports_external.boolean().optional(),\n is_configured_for_uart_tx: exports_external.boolean().optional(),\n is_configured_for_uart_rx: exports_external.boolean().optional(),\n supports_i2c_sda: exports_external.boolean().optional(),\n supports_i2c_scl: exports_external.boolean().optional(),\n supports_spi_mosi: exports_external.boolean().optional(),\n supports_spi_miso: exports_external.boolean().optional(),\n supports_spi_sck: exports_external.boolean().optional(),\n supports_spi_cs: exports_external.boolean().optional(),\n supports_uart_tx: exports_external.boolean().optional(),\n supports_uart_rx: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar source_simple_fuse = source_component_base.extend({\n ftype: exports_external.literal(\"simple_fuse\"),\n current_rating_amps: exports_external.number().describe(\"Nominal current in amps the fuse is rated for\"),\n voltage_rating_volts: exports_external.number().describe(\"Voltage rating in volts, e.g. ±5V would be 5\")\n});\nexpectTypesMatch(true);\nvar source_simple_battery = source_component_base.extend({\n ftype: exports_external.literal(\"simple_battery\"),\n capacity: battery_capacity\n});\nexpectTypesMatch(true);\nvar source_simple_inductor = source_component_base.extend({\n ftype: exports_external.literal(\"simple_inductor\"),\n inductance,\n display_inductance: exports_external.string().optional(),\n max_current_rating: exports_external.number().optional()\n});\nexpectTypesMatch(true);\nvar source_simple_push_button = source_component_base.extend({\n ftype: exports_external.literal(\"simple_push_button\")\n});\nexpectTypesMatch(true);\nvar source_simple_potentiometer = source_component_base.extend({\n ftype: exports_external.literal(\"simple_potentiometer\"),\n max_resistance: resistance,\n display_max_resistance: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_simple_crystal = source_component_base.extend({\n ftype: exports_external.literal(\"simple_crystal\"),\n frequency: exports_external.number().describe(\"Frequency in Hz\"),\n load_capacitance: exports_external.number().optional().describe(\"Load capacitance in pF\"),\n pin_variant: exports_external.enum([\"two_pin\", \"four_pin\"]).optional()\n});\nexpectTypesMatch(true);\nvar source_simple_pin_header = source_component_base.extend({\n ftype: exports_external.literal(\"simple_pin_header\"),\n pin_count: exports_external.number(),\n gender: exports_external.enum([\"male\", \"female\"]).optional().default(\"male\")\n});\nexpectTypesMatch(true);\nvar source_simple_connector = source_component_base.extend({\n ftype: exports_external.literal(\"simple_connector\"),\n standard: exports_external.enum([\"usb_c\", \"m2\"]).optional()\n});\nexpectTypesMatch(true);\nvar source_simple_pinout = source_component_base.extend({\n ftype: exports_external.literal(\"simple_pinout\")\n});\nexpectTypesMatch(true);\nvar source_simple_resonator = source_component_base.extend({\n ftype: exports_external.literal(\"simple_resonator\"),\n load_capacitance: capacitance,\n equivalent_series_resistance: resistance.optional(),\n frequency\n});\nexpectTypesMatch(true);\nvar source_simple_transistor = source_component_base.extend({\n ftype: exports_external.literal(\"simple_transistor\"),\n transistor_type: exports_external.enum([\"npn\", \"pnp\"])\n});\nexpectTypesMatch(true);\nvar source_simple_test_point = source_component_base.extend({\n ftype: exports_external.literal(\"simple_test_point\"),\n footprint_variant: exports_external.enum([\"pad\", \"through_hole\"]).optional(),\n pad_shape: exports_external.enum([\"rect\", \"circle\"]).optional(),\n pad_diameter: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n hole_diameter: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n width: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n height: exports_external.union([exports_external.number(), exports_external.string()]).optional()\n});\nexpectTypesMatch(true);\nvar source_simple_mosfet = source_component_base.extend({\n ftype: exports_external.literal(\"simple_mosfet\"),\n channel_type: exports_external.enum([\"n\", \"p\"]),\n mosfet_mode: exports_external.enum([\"enhancement\", \"depletion\"])\n});\nexpectTypesMatch(true);\nvar source_simple_op_amp = source_component_base.extend({\n ftype: exports_external.literal(\"simple_op_amp\")\n});\nexpectTypesMatch(true);\nvar source_simple_switch = source_component_base.extend({\n ftype: exports_external.literal(\"simple_switch\")\n});\nexpectTypesMatch(true);\nvar source_project_metadata = exports_external.object({\n type: exports_external.literal(\"source_project_metadata\"),\n name: exports_external.string().optional(),\n software_used_string: exports_external.string().optional(),\n project_url: exports_external.string().optional(),\n created_at: timestamp.optional()\n});\nexpectTypesMatch(true);\nvar source_missing_property_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_missing_property_error\"),\n source_missing_property_error_id: getZodPrefixedIdWithDefault(\"source_missing_property_error\"),\n source_component_id: exports_external.string(),\n property_name: exports_external.string(),\n subcircuit_id: exports_external.string().optional(),\n error_type: exports_external.literal(\"source_missing_property_error\").default(\"source_missing_property_error\")\n}).describe(\"The source code is missing a property\");\nexpectTypesMatch(true);\nvar source_failed_to_create_component_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_failed_to_create_component_error\"),\n source_failed_to_create_component_error_id: getZodPrefixedIdWithDefault(\"source_failed_to_create_component_error\"),\n error_type: exports_external.literal(\"source_failed_to_create_component_error\").default(\"source_failed_to_create_component_error\"),\n component_name: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n parent_source_component_id: exports_external.string().optional(),\n pcb_center: exports_external.object({\n x: exports_external.number().optional(),\n y: exports_external.number().optional()\n }).optional(),\n schematic_center: exports_external.object({\n x: exports_external.number().optional(),\n y: exports_external.number().optional()\n }).optional()\n}).describe(\"Error emitted when a component fails to be constructed\");\nexpectTypesMatch(true);\nvar source_invalid_component_property_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_invalid_component_property_error\"),\n source_invalid_component_property_error_id: getZodPrefixedIdWithDefault(\"source_invalid_component_property_error\"),\n source_component_id: exports_external.string(),\n property_name: exports_external.string(),\n property_value: exports_external.unknown().optional(),\n expected_format: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n error_type: exports_external.literal(\"source_invalid_component_property_error\").default(\"source_invalid_component_property_error\")\n}).describe(\"The source component property is invalid\");\nexpectTypesMatch(true);\nvar source_trace_not_connected_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_trace_not_connected_error\"),\n source_trace_not_connected_error_id: getZodPrefixedIdWithDefault(\"source_trace_not_connected_error\"),\n error_type: exports_external.literal(\"source_trace_not_connected_error\").default(\"source_trace_not_connected_error\"),\n subcircuit_id: exports_external.string().optional(),\n source_group_id: exports_external.string().optional(),\n source_trace_id: exports_external.string().optional(),\n connected_source_port_ids: exports_external.array(exports_external.string()).optional(),\n selectors_not_found: exports_external.array(exports_external.string()).optional()\n}).describe(\"Occurs when a source trace selector does not match any ports\");\nexpectTypesMatch(true);\nvar source_property_ignored_warning = exports_external.object({\n type: exports_external.literal(\"source_property_ignored_warning\"),\n source_property_ignored_warning_id: getZodPrefixedIdWithDefault(\"source_property_ignored_warning\"),\n source_component_id: exports_external.string(),\n property_name: exports_external.string(),\n subcircuit_id: exports_external.string().optional(),\n error_type: exports_external.literal(\"source_property_ignored_warning\").default(\"source_property_ignored_warning\"),\n message: exports_external.string()\n}).describe(\"The source property was ignored\");\nexpectTypesMatch(true);\nvar source_pin_missing_trace_warning = exports_external.object({\n type: exports_external.literal(\"source_pin_missing_trace_warning\"),\n source_pin_missing_trace_warning_id: getZodPrefixedIdWithDefault(\"source_pin_missing_trace_warning\"),\n warning_type: exports_external.literal(\"source_pin_missing_trace_warning\").default(\"source_pin_missing_trace_warning\"),\n message: exports_external.string(),\n source_component_id: exports_external.string(),\n source_port_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when a source component pin is missing a trace connection\");\nexpectTypesMatch(true);\nvar source_missing_manufacturer_part_number_warning = exports_external.object({\n type: exports_external.literal(\"source_missing_manufacturer_part_number_warning\"),\n source_missing_manufacturer_part_number_warning_id: getZodPrefixedIdWithDefault(\"source_missing_manufacturer_part_number_warning\"),\n warning_type: exports_external.literal(\"source_missing_manufacturer_part_number_warning\").default(\"source_missing_manufacturer_part_number_warning\"),\n message: exports_external.string(),\n source_component_id: exports_external.string(),\n standard: exports_external.string(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when a standard connector is missing manufacturer part number\");\nexpectTypesMatch(true);\nvar source_simple_voltage_probe = source_component_base.extend({\n ftype: exports_external.literal(\"simple_voltage_probe\")\n});\nexpectTypesMatch(true);\nvar source_interconnect = source_component_base.extend({\n ftype: exports_external.literal(\"interconnect\")\n});\nexpectTypesMatch(true);\nvar source_i2c_misconfigured_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_i2c_misconfigured_error\"),\n source_i2c_misconfigured_error_id: getZodPrefixedIdWithDefault(\"source_i2c_misconfigured_error\"),\n error_type: exports_external.literal(\"source_i2c_misconfigured_error\").default(\"source_i2c_misconfigured_error\"),\n source_port_ids: exports_external.array(exports_external.string())\n}).describe(\"Error emitted when incompatible I2C pins (e.g. SDA and SCL) are connected to the same net\");\nexpectTypesMatch(true);\nvar source_component_misconfigured_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_component_misconfigured_error\"),\n source_component_misconfigured_error_id: getZodPrefixedIdWithDefault(\"source_component_misconfigured_error\"),\n error_type: exports_external.literal(\"source_component_misconfigured_error\").default(\"source_component_misconfigured_error\"),\n source_component_ids: exports_external.array(exports_external.string()),\n source_port_ids: exports_external.array(exports_external.string()).optional()\n}).describe(\"Error emitted when one or more source components have an invalid or conflicting configuration\");\nexpectTypesMatch(true);\nvar source_simple_voltage_source = source_component_base.extend({\n ftype: exports_external.literal(\"simple_voltage_source\"),\n voltage,\n frequency: frequency.optional(),\n peak_to_peak_voltage: voltage.optional(),\n wave_shape: exports_external.enum([\"sinewave\", \"square\", \"triangle\", \"sawtooth\"]).optional(),\n phase: rotation.optional(),\n duty_cycle: exports_external.number().optional().describe(\"Duty cycle as a fraction (0 to 1)\"),\n pulse_delay: ms.optional(),\n rise_time: ms.optional(),\n fall_time: ms.optional(),\n pulse_width: ms.optional(),\n period: ms.optional()\n});\nexpectTypesMatch(true);\nvar any_source_component = exports_external.union([\n source_simple_resistor,\n source_simple_capacitor,\n source_simple_diode,\n source_simple_fiducial,\n source_simple_led,\n source_simple_ground,\n source_simple_chip,\n source_simple_power_source,\n source_simple_current_source,\n source_simple_ammeter,\n source_simple_battery,\n source_simple_inductor,\n source_simple_push_button,\n source_simple_potentiometer,\n source_simple_crystal,\n source_simple_pin_header,\n source_simple_connector,\n source_simple_pinout,\n source_simple_resonator,\n source_simple_switch,\n source_simple_transistor,\n source_simple_test_point,\n source_simple_mosfet,\n source_simple_op_amp,\n source_simple_fuse,\n source_simple_voltage_probe,\n source_interconnect,\n source_simple_voltage_source,\n source_project_metadata,\n source_missing_property_error,\n source_invalid_component_property_error,\n source_failed_to_create_component_error,\n source_trace_not_connected_error,\n source_property_ignored_warning,\n source_pin_missing_trace_warning,\n source_missing_manufacturer_part_number_warning,\n source_i2c_misconfigured_error,\n source_component_misconfigured_error\n]);\nexpectTypesMatch(true);\nvar source_port = exports_external.object({\n type: exports_external.literal(\"source_port\"),\n pin_number: exports_external.number().optional(),\n port_hints: exports_external.array(exports_external.string()).optional(),\n name: exports_external.string(),\n source_port_id: exports_external.string(),\n source_component_id: exports_external.string().optional(),\n source_group_id: exports_external.string().optional(),\n most_frequently_referenced_by_name: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional()\n}).merge(source_pin_attributes);\nexpectTypesMatch(true);\nvar source_component_internal_connection = exports_external.object({\n type: exports_external.literal(\"source_component_internal_connection\"),\n source_component_internal_connection_id: exports_external.string(),\n source_component_id: exports_external.string(),\n source_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_trace = exports_external.object({\n type: exports_external.literal(\"source_trace\"),\n source_trace_id: exports_external.string(),\n connected_source_port_ids: exports_external.array(exports_external.string()),\n connected_source_net_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional(),\n max_length: exports_external.number().optional(),\n name: exports_external.string().optional(),\n min_trace_thickness: exports_external.number().optional(),\n display_name: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_group = exports_external.object({\n type: exports_external.literal(\"source_group\"),\n source_group_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional(),\n parent_subcircuit_id: exports_external.string().optional(),\n parent_source_group_id: exports_external.string().optional(),\n is_subcircuit: exports_external.boolean().optional(),\n show_as_schematic_box: exports_external.boolean().optional(),\n name: exports_external.string().optional(),\n was_automatically_named: exports_external.boolean().optional()\n});\nexpectTypesMatch(true);\nvar source_net = exports_external.object({\n type: exports_external.literal(\"source_net\"),\n source_net_id: exports_external.string(),\n name: exports_external.string(),\n member_source_group_ids: exports_external.array(exports_external.string()),\n is_power: exports_external.boolean().optional(),\n is_ground: exports_external.boolean().optional(),\n is_digital_signal: exports_external.boolean().optional(),\n is_analog_signal: exports_external.boolean().optional(),\n is_positive_voltage_source: exports_external.boolean().optional(),\n trace_width: exports_external.number().optional(),\n subcircuit_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar source_board = exports_external.object({\n type: exports_external.literal(\"source_board\"),\n source_board_id: exports_external.string(),\n source_group_id: exports_external.string(),\n title: exports_external.string().optional()\n}).describe(\"Defines a board in the source domain\");\nexpectTypesMatch(true);\nvar source_ambiguous_port_reference = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_ambiguous_port_reference\"),\n source_ambiguous_port_reference_id: getZodPrefixedIdWithDefault(\"source_ambiguous_port_reference\"),\n error_type: exports_external.literal(\"source_ambiguous_port_reference\").default(\"source_ambiguous_port_reference\"),\n source_port_id: exports_external.string().optional(),\n source_component_id: exports_external.string().optional()\n}).describe(\"Error emitted when a port hint matches multiple non-overlapping pads, making the port reference ambiguous\");\nexpectTypesMatch(true);\nvar source_pcb_ground_plane = exports_external.object({\n type: exports_external.literal(\"source_pcb_ground_plane\"),\n source_pcb_ground_plane_id: exports_external.string(),\n source_group_id: exports_external.string(),\n source_net_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a ground plane in the source domain\");\nexpectTypesMatch(true);\nvar all_layers = [\n \"top\",\n \"bottom\",\n \"inner1\",\n \"inner2\",\n \"inner3\",\n \"inner4\",\n \"inner5\",\n \"inner6\"\n];\nvar layer_string = exports_external.enum(all_layers);\nvar layer_ref = layer_string.or(exports_external.object({\n name: layer_string\n})).transform((layer) =\u003e {\n if (typeof layer === \"string\") {\n return layer;\n }\n return layer.name;\n});\nexpectTypesMatch(true);\nvar visible_layer = exports_external.enum([\"top\", \"bottom\"]);\nvar source_manually_placed_via = exports_external.object({\n type: exports_external.literal(\"source_manually_placed_via\"),\n source_manually_placed_via_id: exports_external.string(),\n source_group_id: exports_external.string(),\n source_net_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional(),\n source_trace_id: exports_external.string().optional()\n}).describe(\"Defines a via that is manually placed in the source domain\");\nexpectTypesMatch(true);\nvar source_unnamed_trace_warning = exports_external.object({\n type: exports_external.literal(\"source_unnamed_trace_warning\"),\n source_unnamed_trace_warning_id: getZodPrefixedIdWithDefault(\"source_unnamed_trace_warning\"),\n warning_type: exports_external.literal(\"source_unnamed_trace_warning\").default(\"source_unnamed_trace_warning\"),\n message: exports_external.string(),\n source_trace_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when a source trace is missing a name\");\nexpectTypesMatch(true);\nvar source_no_power_pin_defined_warning = exports_external.object({\n type: exports_external.literal(\"source_no_power_pin_defined_warning\"),\n source_no_power_pin_defined_warning_id: getZodPrefixedIdWithDefault(\"source_no_power_pin_defined_warning\"),\n warning_type: exports_external.literal(\"source_no_power_pin_defined_warning\").default(\"source_no_power_pin_defined_warning\"),\n message: exports_external.string(),\n source_component_id: exports_external.string(),\n source_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when a chip has no source ports with requires_power=true\");\nexpectTypesMatch(true);\nvar source_no_ground_pin_defined_warning = exports_external.object({\n type: exports_external.literal(\"source_no_ground_pin_defined_warning\"),\n source_no_ground_pin_defined_warning_id: getZodPrefixedIdWithDefault(\"source_no_ground_pin_defined_warning\"),\n warning_type: exports_external.literal(\"source_no_ground_pin_defined_warning\").default(\"source_no_ground_pin_defined_warning\"),\n message: exports_external.string(),\n source_component_id: exports_external.string(),\n source_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when a chip has no source ports marked as ground pins\");\nexpectTypesMatch(true);\nvar source_component_pins_underspecified_warning = exports_external.object({\n type: exports_external.literal(\"source_component_pins_underspecified_warning\"),\n source_component_pins_underspecified_warning_id: getZodPrefixedIdWithDefault(\"source_component_pins_underspecified_warning\"),\n warning_type: exports_external.literal(\"source_component_pins_underspecified_warning\").default(\"source_component_pins_underspecified_warning\"),\n message: exports_external.string(),\n source_component_id: exports_external.string(),\n source_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when all ports on a source component are underspecified\");\nexpectTypesMatch(true);\nvar source_pin_must_be_connected_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"source_pin_must_be_connected_error\"),\n source_pin_must_be_connected_error_id: getZodPrefixedIdWithDefault(\"source_pin_must_be_connected_error\"),\n error_type: exports_external.literal(\"source_pin_must_be_connected_error\").default(\"source_pin_must_be_connected_error\"),\n source_component_id: exports_external.string(),\n source_port_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when a pin with mustBeConnected attribute is not connected to any trace\");\nexpectTypesMatch(true);\nvar unknown_error_finding_part = base_circuit_json_error.extend({\n type: exports_external.literal(\"unknown_error_finding_part\"),\n unknown_error_finding_part_id: getZodPrefixedIdWithDefault(\"unknown_error_finding_part\"),\n error_type: exports_external.literal(\"unknown_error_finding_part\").default(\"unknown_error_finding_part\"),\n source_component_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when an unexpected error occurs while finding a part\");\nexpectTypesMatch(true);\nvar schematic_box = exports_external.object({\n type: exports_external.literal(\"schematic_box\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n width: distance4,\n height: distance4,\n is_dashed: exports_external.boolean().default(false),\n x: distance4,\n y: distance4,\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Draws a box on the schematic\");\nexpectTypesMatch(true);\nvar schematic_path = exports_external.object({\n type: exports_external.literal(\"schematic_path\"),\n schematic_path_id: getZodPrefixedIdWithDefault(\"schematic_path\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n fill_color: exports_external.string().optional(),\n is_filled: exports_external.boolean().optional(),\n is_dashed: exports_external.boolean().default(false),\n stroke_width: distance4.nullable().optional(),\n stroke_color: exports_external.string().optional(),\n dash_length: distance4.optional(),\n dash_gap: distance4.optional(),\n points: exports_external.array(point),\n subcircuit_id: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar schematic_pin_styles = exports_external.record(exports_external.object({\n left_margin: length.optional(),\n right_margin: length.optional(),\n top_margin: length.optional(),\n bottom_margin: length.optional()\n}));\nvar schematic_component_port_arrangement_by_size = exports_external.object({\n left_size: exports_external.number(),\n right_size: exports_external.number(),\n top_size: exports_external.number().optional(),\n bottom_size: exports_external.number().optional()\n});\nexpectTypesMatch(true);\nvar schematic_component_port_arrangement_by_sides = exports_external.object({\n left_side: exports_external.object({\n pins: exports_external.array(exports_external.number()),\n direction: exports_external.enum([\"top-to-bottom\", \"bottom-to-top\"]).optional()\n }).optional(),\n right_side: exports_external.object({\n pins: exports_external.array(exports_external.number()),\n direction: exports_external.enum([\"top-to-bottom\", \"bottom-to-top\"]).optional()\n }).optional(),\n top_side: exports_external.object({\n pins: exports_external.array(exports_external.number()),\n direction: exports_external.enum([\"left-to-right\", \"right-to-left\"]).optional()\n }).optional(),\n bottom_side: exports_external.object({\n pins: exports_external.array(exports_external.number()),\n direction: exports_external.enum([\"left-to-right\", \"right-to-left\"]).optional()\n }).optional()\n});\nexpectTypesMatch(true);\nvar port_arrangement = exports_external.union([\n schematic_component_port_arrangement_by_size,\n schematic_component_port_arrangement_by_sides\n]);\nvar schematic_component = exports_external.object({\n type: exports_external.literal(\"schematic_component\"),\n size,\n center: point,\n source_component_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string(),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n pin_spacing: length.optional(),\n pin_styles: schematic_pin_styles.optional(),\n box_width: length.optional(),\n symbol_name: exports_external.string().optional(),\n port_arrangement: port_arrangement.optional(),\n port_labels: exports_external.record(exports_external.string()).optional(),\n symbol_display_value: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n schematic_group_id: exports_external.string().optional(),\n is_schematic_group: exports_external.boolean().optional(),\n source_group_id: exports_external.string().optional(),\n is_box_with_pins: exports_external.boolean().optional().default(true)\n});\nexpectTypesMatch(true);\nvar schematicSymbolMetadata = exports_external.object({\n kicad_symbol: kicadSymbolMetadata.optional()\n}).catchall(exports_external.unknown());\nvar schematic_symbol = exports_external.object({\n type: exports_external.literal(\"schematic_symbol\"),\n schematic_symbol_id: exports_external.string(),\n name: exports_external.string().optional(),\n metadata: schematicSymbolMetadata.optional()\n}).describe(\"Defines a named schematic symbol that can be referenced by components.\");\nexpectTypesMatch(true);\nvar schematic_line = exports_external.object({\n type: exports_external.literal(\"schematic_line\"),\n schematic_line_id: getZodPrefixedIdWithDefault(\"schematic_line\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n x1: distance4,\n y1: distance4,\n x2: distance4,\n y2: distance4,\n stroke_width: distance4.nullable().optional(),\n color: exports_external.string().default(\"#000000\"),\n is_dashed: exports_external.boolean().default(false),\n dash_length: distance4.optional(),\n dash_gap: distance4.optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Draws a styled line on the schematic\");\nexpectTypesMatch(true);\nvar schematic_rect = exports_external.object({\n type: exports_external.literal(\"schematic_rect\"),\n schematic_rect_id: getZodPrefixedIdWithDefault(\"schematic_rect\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n center: point,\n width: distance4,\n height: distance4,\n rotation: rotation.default(0),\n stroke_width: distance4.nullable().optional(),\n color: exports_external.string().default(\"#000000\"),\n is_filled: exports_external.boolean().default(false),\n fill_color: exports_external.string().optional(),\n is_dashed: exports_external.boolean().default(false),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Draws a styled rectangle on the schematic\");\nexpectTypesMatch(true);\nvar schematic_circle = exports_external.object({\n type: exports_external.literal(\"schematic_circle\"),\n schematic_circle_id: getZodPrefixedIdWithDefault(\"schematic_circle\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n center: point,\n radius: distance4,\n stroke_width: distance4.nullable().optional(),\n color: exports_external.string().default(\"#000000\"),\n is_filled: exports_external.boolean().default(false),\n fill_color: exports_external.string().optional(),\n is_dashed: exports_external.boolean().default(false),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Draws a styled circle on the schematic\");\nexpectTypesMatch(true);\nvar schematic_arc = exports_external.object({\n type: exports_external.literal(\"schematic_arc\"),\n schematic_arc_id: getZodPrefixedIdWithDefault(\"schematic_arc\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n center: point,\n radius: distance4,\n start_angle_degrees: rotation,\n end_angle_degrees: rotation,\n direction: exports_external.enum([\"clockwise\", \"counterclockwise\"]).default(\"counterclockwise\"),\n stroke_width: distance4.nullable().optional(),\n color: exports_external.string().default(\"#000000\"),\n is_dashed: exports_external.boolean().default(false),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Draws a styled arc on the schematic\");\nexpectTypesMatch(true);\nvar schematic_trace = exports_external.object({\n type: exports_external.literal(\"schematic_trace\"),\n schematic_trace_id: exports_external.string(),\n schematic_sheet_id: exports_external.string().optional(),\n source_trace_id: exports_external.string().optional(),\n junctions: exports_external.array(exports_external.object({\n x: exports_external.number(),\n y: exports_external.number()\n })),\n edges: exports_external.array(exports_external.object({\n from: exports_external.object({\n x: exports_external.number(),\n y: exports_external.number()\n }),\n to: exports_external.object({\n x: exports_external.number(),\n y: exports_external.number()\n }),\n is_crossing: exports_external.boolean().optional(),\n from_schematic_port_id: exports_external.string().optional(),\n to_schematic_port_id: exports_external.string().optional()\n })),\n subcircuit_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar fivePointAnchor = exports_external.enum([\n \"center\",\n \"left\",\n \"right\",\n \"top\",\n \"bottom\"\n]);\nexpectTypesMatch(true);\nvar schematic_text = exports_external.object({\n type: exports_external.literal(\"schematic_text\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n schematic_symbol_id: exports_external.string().optional(),\n schematic_text_id: exports_external.string(),\n text: exports_external.string(),\n font_size: exports_external.number().default(0.18),\n position: exports_external.object({\n x: distance4,\n y: distance4\n }),\n rotation: exports_external.number().default(0),\n anchor: exports_external.union([fivePointAnchor.describe(\"legacy\"), ninePointAnchor]).default(\"center\"),\n color: exports_external.string().default(\"#000000\"),\n subcircuit_id: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar schematic_port = exports_external.object({\n type: exports_external.literal(\"schematic_port\"),\n schematic_port_id: exports_external.string(),\n source_port_id: exports_external.string(),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n center: point,\n facing_direction: exports_external.enum([\"up\", \"down\", \"left\", \"right\"]).optional(),\n distance_from_component_edge: exports_external.number().optional(),\n side_of_component: exports_external.enum([\"top\", \"bottom\", \"left\", \"right\"]).optional(),\n true_ccw_index: exports_external.number().optional(),\n pin_number: exports_external.number().optional(),\n display_pin_label: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n is_connected: exports_external.boolean().optional(),\n has_input_arrow: exports_external.boolean().optional(),\n has_output_arrow: exports_external.boolean().optional(),\n is_drawn_with_inversion_circle: exports_external.boolean().optional()\n}).describe(\"Defines a port on a schematic component\");\nexpectTypesMatch(true);\nvar schematic_net_label = exports_external.object({\n type: exports_external.literal(\"schematic_net_label\"),\n schematic_net_label_id: getZodPrefixedIdWithDefault(\"schematic_net_label\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_trace_id: exports_external.string().optional(),\n source_trace_id: exports_external.string().optional(),\n source_net_id: exports_external.string(),\n center: point,\n anchor_position: point.optional(),\n anchor_side: exports_external.enum([\"top\", \"bottom\", \"left\", \"right\"]),\n text: exports_external.string(),\n symbol_name: exports_external.string().optional(),\n is_movable: exports_external.boolean().optional(),\n subcircuit_id: exports_external.string().optional()\n});\nexpectTypesMatch(true);\nvar schematic_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"schematic_error\"),\n schematic_error_id: exports_external.string(),\n error_type: exports_external.literal(\"schematic_port_not_found\").default(\"schematic_port_not_found\"),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a schematic error on the schematic\");\nexpectTypesMatch(true);\nvar schematic_layout_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"schematic_layout_error\"),\n schematic_layout_error_id: getZodPrefixedIdWithDefault(\"schematic_layout_error\"),\n error_type: exports_external.literal(\"schematic_layout_error\").default(\"schematic_layout_error\"),\n source_group_id: exports_external.string(),\n schematic_group_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when schematic layout fails for a group\");\nexpectTypesMatch(true);\nvar schematic_debug_object_base = exports_external.object({\n type: exports_external.literal(\"schematic_debug_object\"),\n label: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n});\nvar schematic_debug_rect = schematic_debug_object_base.extend({\n shape: exports_external.literal(\"rect\"),\n center: point,\n size\n});\nvar schematic_debug_line = schematic_debug_object_base.extend({\n shape: exports_external.literal(\"line\"),\n start: point,\n end: point\n});\nvar schematic_debug_point = schematic_debug_object_base.extend({\n shape: exports_external.literal(\"point\"),\n center: point\n});\nvar schematic_debug_object = exports_external.discriminatedUnion(\"shape\", [\n schematic_debug_rect,\n schematic_debug_line,\n schematic_debug_point\n]);\nexpectTypesMatch(true);\nvar schematic_voltage_probe = exports_external.object({\n type: exports_external.literal(\"schematic_voltage_probe\"),\n schematic_voltage_probe_id: exports_external.string(),\n schematic_sheet_id: exports_external.string().optional(),\n source_component_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n position: point,\n schematic_trace_id: exports_external.string(),\n voltage: voltage.optional(),\n subcircuit_id: exports_external.string().optional(),\n color: exports_external.string().optional(),\n label_alignment: ninePointAnchor.optional()\n}).describe(\"Defines a voltage probe measurement point on a schematic trace\");\nexpectTypesMatch(true);\nvar schematic_manual_edit_conflict_warning = exports_external.object({\n type: exports_external.literal(\"schematic_manual_edit_conflict_warning\"),\n schematic_manual_edit_conflict_warning_id: getZodPrefixedIdWithDefault(\"schematic_manual_edit_conflict_warning\"),\n warning_type: exports_external.literal(\"schematic_manual_edit_conflict_warning\").default(\"schematic_manual_edit_conflict_warning\"),\n message: exports_external.string(),\n schematic_component_id: exports_external.string(),\n schematic_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n source_component_id: exports_external.string()\n}).describe(\"Warning emitted when a component has both manual placement and explicit schX/schY coordinates\");\nexpectTypesMatch(true);\nvar schematic_group = exports_external.object({\n type: exports_external.literal(\"schematic_group\"),\n schematic_group_id: getZodPrefixedIdWithDefault(\"schematic_group\"),\n schematic_sheet_id: exports_external.string().optional(),\n source_group_id: exports_external.string(),\n is_subcircuit: exports_external.boolean().optional(),\n subcircuit_id: exports_external.string().optional(),\n width: length,\n height: length,\n center: point,\n schematic_component_ids: exports_external.array(exports_external.string()),\n show_as_schematic_box: exports_external.boolean().optional(),\n name: exports_external.string().optional(),\n description: exports_external.string().optional()\n}).describe(\"Defines a group of components on the schematic\");\nexpectTypesMatch(true);\nvar schematic_table = exports_external.object({\n type: exports_external.literal(\"schematic_table\"),\n schematic_table_id: getZodPrefixedIdWithDefault(\"schematic_table\"),\n schematic_sheet_id: exports_external.string().optional(),\n anchor_position: point,\n column_widths: exports_external.array(distance4),\n row_heights: exports_external.array(distance4),\n cell_padding: distance4.optional(),\n border_width: distance4.optional(),\n subcircuit_id: exports_external.string().optional(),\n schematic_component_id: exports_external.string().optional(),\n anchor: ninePointAnchor.optional()\n}).describe(\"Defines a table on the schematic\");\nexpectTypesMatch(true);\nvar schematic_table_cell = exports_external.object({\n type: exports_external.literal(\"schematic_table_cell\"),\n schematic_table_cell_id: getZodPrefixedIdWithDefault(\"schematic_table_cell\"),\n schematic_sheet_id: exports_external.string().optional(),\n schematic_table_id: exports_external.string(),\n start_row_index: exports_external.number(),\n end_row_index: exports_external.number(),\n start_column_index: exports_external.number(),\n end_column_index: exports_external.number(),\n text: exports_external.string().optional(),\n center: point,\n width: distance4,\n height: distance4,\n horizontal_align: exports_external.enum([\"left\", \"center\", \"right\"]).optional(),\n vertical_align: exports_external.enum([\"top\", \"middle\", \"bottom\"]).optional(),\n font_size: distance4.optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a cell within a schematic_table\");\nexpectTypesMatch(true);\nvar schematic_sheet = exports_external.object({\n type: exports_external.literal(\"schematic_sheet\"),\n schematic_sheet_id: getZodPrefixedIdWithDefault(\"schematic_sheet\"),\n name: exports_external.string().optional(),\n sheet_index: exports_external.number().optional(),\n subcircuit_id: exports_external.string().optional(),\n outline_color: exports_external.string().optional()\n}).describe(\"Defines a schematic sheet or page that components can be placed on\");\nexpectTypesMatch(true);\nvar point_with_bulge = exports_external.object({\n x: distance4,\n y: distance4,\n bulge: exports_external.number().optional()\n});\nexpectTypesMatch(true);\nvar ring = exports_external.object({\n vertices: exports_external.array(point_with_bulge)\n});\nexpectTypesMatch(true);\nvar brep_shape = exports_external.object({\n outer_ring: ring,\n inner_rings: exports_external.array(ring).default([])\n});\nexpectTypesMatch(true);\nvar pcb_route_hint = exports_external.object({\n x: distance4,\n y: distance4,\n via: exports_external.boolean().optional(),\n via_to_layer: layer_ref.optional()\n});\nvar pcb_route_hints = exports_external.array(pcb_route_hint);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar route_hint_point = exports_external.object({\n x: distance4,\n y: distance4,\n via: exports_external.boolean().optional(),\n to_layer: layer_ref.optional(),\n trace_width: distance4.optional()\n});\nexpectTypesMatch(true);\nvar manufacturing_drc_properties = exports_external.object({\n min_trace_width: length.optional(),\n min_board_edge_clearance: length.optional(),\n min_via_hole_edge_to_via_hole_edge_clearance: length.optional(),\n min_plated_hole_drill_edge_to_drill_edge_clearance: length.optional(),\n min_trace_to_pad_edge_clearance: length.optional(),\n min_pad_edge_to_pad_edge_clearance: length.optional(),\n min_same_net_trace_edge_to_trace_edge_clearance: length.optional(),\n min_different_net_trace_edge_to_trace_edge_clearance: length.optional(),\n min_via_edge_to_pad_edge_clearance: length.optional(),\n min_via_hole_diameter: length.optional(),\n min_via_pad_diameter: length.optional()\n});\nvar pcb_component = exports_external.object({\n type: exports_external.literal(\"pcb_component\"),\n pcb_component_id: getZodPrefixedIdWithDefault(\"pcb_component\"),\n source_component_id: exports_external.string(),\n center: point,\n layer: layer_ref,\n rotation,\n display_offset_x: exports_external.string().optional().describe(\"How to display the x offset for this part, usually corresponding with how the user specified it\"),\n display_offset_y: exports_external.string().optional().describe(\"How to display the y offset for this part, usually corresponding with how the user specified it\"),\n width: length,\n height: length,\n do_not_place: exports_external.boolean().optional(),\n is_allowed_to_be_off_board: exports_external.boolean().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n position_mode: exports_external.enum([\n \"packed\",\n \"relative_to_group_anchor\",\n \"relative_to_another_component\",\n \"none\"\n ]).optional(),\n anchor_position: point.optional(),\n anchor_alignment: ninePointAnchor.optional(),\n positioned_relative_to_pcb_group_id: exports_external.string().optional(),\n positioned_relative_to_pcb_board_id: exports_external.string().optional(),\n cable_insertion_center: point.optional(),\n insertion_direction: exports_external.enum([\n \"from_above\",\n \"from_left\",\n \"from_right\",\n \"from_front\",\n \"from_back\"\n ]).optional(),\n metadata: exports_external.object({\n kicad_footprint: kicadFootprintMetadata.optional()\n }).optional(),\n obstructs_within_bounds: exports_external.boolean().default(true).describe(\"Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath\")\n}).describe(\"Defines a component on the PCB\");\nexpectTypesMatch(true);\nvar pcb_hole_circle = exports_external.object({\n type: exports_external.literal(\"pcb_hole\"),\n pcb_hole_id: getZodPrefixedIdWithDefault(\"pcb_hole\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"circle\"),\n hole_diameter: exports_external.number(),\n x: distance4,\n y: distance4,\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_circle_shape = pcb_hole_circle.describe(\"Defines a circular hole on the PCB\");\nexpectTypesMatch(true);\nvar pcb_hole_rect = exports_external.object({\n type: exports_external.literal(\"pcb_hole\"),\n pcb_hole_id: getZodPrefixedIdWithDefault(\"pcb_hole\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"rect\"),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n x: distance4,\n y: distance4,\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_rect_shape = pcb_hole_rect.describe(\"Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square.\");\nexpectTypesMatch(true);\nvar pcb_hole_circle_or_square = exports_external.object({\n type: exports_external.literal(\"pcb_hole\"),\n pcb_hole_id: getZodPrefixedIdWithDefault(\"pcb_hole\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n hole_shape: exports_external.enum([\"circle\", \"square\"]),\n hole_diameter: exports_external.number(),\n x: distance4,\n y: distance4,\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_circle_or_square_shape = pcb_hole_circle_or_square.describe(\"Defines a circular or square hole on the PCB\");\nexpectTypesMatch(true);\nvar pcb_hole_oval = exports_external.object({\n type: exports_external.literal(\"pcb_hole\"),\n pcb_hole_id: getZodPrefixedIdWithDefault(\"pcb_hole\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"oval\"),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n x: distance4,\n y: distance4,\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_oval_shape = pcb_hole_oval.describe(\"Defines an oval hole on the PCB\");\nexpectTypesMatch(true);\nvar pcb_hole_pill = exports_external.object({\n type: exports_external.literal(\"pcb_hole\"),\n pcb_hole_id: getZodPrefixedIdWithDefault(\"pcb_hole\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"pill\"),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n x: distance4,\n y: distance4,\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_pill_shape = pcb_hole_pill.describe(\"Defines a pill-shaped hole on the PCB\");\nexpectTypesMatch(true);\nvar pcb_hole_rotated_pill = exports_external.object({\n type: exports_external.literal(\"pcb_hole\"),\n pcb_hole_id: getZodPrefixedIdWithDefault(\"pcb_hole\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"rotated_pill\"),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n x: distance4,\n y: distance4,\n ccw_rotation: rotation,\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_rotated_pill_shape = pcb_hole_rotated_pill.describe(\"Defines a rotated pill-shaped hole on the PCB\");\nexpectTypesMatch(true);\nvar pcb_hole = pcb_hole_circle_or_square.or(pcb_hole_oval).or(pcb_hole_pill).or(pcb_hole_rotated_pill).or(pcb_hole_circle).or(pcb_hole_rect);\nvar pcb_plated_hole_circle = exports_external.object({\n type: exports_external.literal(\"pcb_plated_hole\"),\n shape: exports_external.literal(\"circle\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n outer_diameter: exports_external.number(),\n hole_diameter: exports_external.number(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n x: distance4,\n y: distance4,\n layers: exports_external.array(layer_ref),\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n pcb_plated_hole_id: getZodPrefixedIdWithDefault(\"pcb_plated_hole\"),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_plated_hole_oval = exports_external.object({\n type: exports_external.literal(\"pcb_plated_hole\"),\n shape: exports_external.enum([\"oval\", \"pill\"]),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n outer_width: exports_external.number(),\n outer_height: exports_external.number(),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n x: distance4,\n y: distance4,\n ccw_rotation: rotation,\n layers: exports_external.array(layer_ref),\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n pcb_plated_hole_id: getZodPrefixedIdWithDefault(\"pcb_plated_hole\"),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_circular_hole_with_rect_pad = exports_external.object({\n type: exports_external.literal(\"pcb_plated_hole\"),\n shape: exports_external.literal(\"circular_hole_with_rect_pad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"circle\"),\n pad_shape: exports_external.literal(\"rect\"),\n hole_diameter: exports_external.number(),\n rect_pad_width: exports_external.number(),\n rect_pad_height: exports_external.number(),\n rect_border_radius: exports_external.number().optional(),\n hole_offset_x: distance4.default(0),\n hole_offset_y: distance4.default(0),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n x: distance4,\n y: distance4,\n layers: exports_external.array(layer_ref),\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n pcb_plated_hole_id: getZodPrefixedIdWithDefault(\"pcb_plated_hole\"),\n soldermask_margin: exports_external.number().optional(),\n rect_ccw_rotation: rotation.optional()\n});\nvar pcb_pill_hole_with_rect_pad = exports_external.object({\n type: exports_external.literal(\"pcb_plated_hole\"),\n shape: exports_external.literal(\"pill_hole_with_rect_pad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"pill\"),\n pad_shape: exports_external.literal(\"rect\"),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n rect_pad_width: exports_external.number(),\n rect_pad_height: exports_external.number(),\n rect_border_radius: exports_external.number().optional(),\n hole_offset_x: distance4.default(0),\n hole_offset_y: distance4.default(0),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n x: distance4,\n y: distance4,\n layers: exports_external.array(layer_ref),\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n pcb_plated_hole_id: getZodPrefixedIdWithDefault(\"pcb_plated_hole\"),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_rotated_pill_hole_with_rect_pad = exports_external.object({\n type: exports_external.literal(\"pcb_plated_hole\"),\n shape: exports_external.literal(\"rotated_pill_hole_with_rect_pad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n hole_shape: exports_external.literal(\"rotated_pill\"),\n pad_shape: exports_external.literal(\"rect\"),\n hole_width: exports_external.number(),\n hole_height: exports_external.number(),\n hole_ccw_rotation: rotation,\n rect_pad_width: exports_external.number(),\n rect_pad_height: exports_external.number(),\n rect_border_radius: exports_external.number().optional(),\n rect_ccw_rotation: rotation,\n hole_offset_x: distance4.default(0),\n hole_offset_y: distance4.default(0),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n x: distance4,\n y: distance4,\n layers: exports_external.array(layer_ref),\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n pcb_plated_hole_id: getZodPrefixedIdWithDefault(\"pcb_plated_hole\"),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_hole_with_polygon_pad = exports_external.object({\n type: exports_external.literal(\"pcb_plated_hole\"),\n shape: exports_external.literal(\"hole_with_polygon_pad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n hole_shape: exports_external.enum([\"circle\", \"oval\", \"pill\", \"rotated_pill\"]),\n hole_diameter: exports_external.number().optional(),\n hole_width: exports_external.number().optional(),\n hole_height: exports_external.number().optional(),\n pad_outline: exports_external.array(exports_external.object({\n x: distance4,\n y: distance4\n })).min(3),\n hole_offset_x: distance4.default(0),\n hole_offset_y: distance4.default(0),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n x: distance4,\n y: distance4,\n layers: exports_external.array(layer_ref),\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n pcb_plated_hole_id: getZodPrefixedIdWithDefault(\"pcb_plated_hole\"),\n soldermask_margin: exports_external.number().optional(),\n ccw_rotation: rotation.optional()\n});\nvar pcb_plated_hole = exports_external.union([\n pcb_plated_hole_circle,\n pcb_plated_hole_oval,\n pcb_circular_hole_with_rect_pad,\n pcb_pill_hole_with_rect_pad,\n pcb_rotated_pill_hole_with_rect_pad,\n pcb_hole_with_polygon_pad\n]);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar pcb_port = exports_external.object({\n type: exports_external.literal(\"pcb_port\"),\n pcb_port_id: getZodPrefixedIdWithDefault(\"pcb_port\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n source_port_id: exports_external.string(),\n pcb_component_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n layers: exports_external.array(layer_ref),\n is_board_pinout: exports_external.boolean().optional()\n}).describe(\"Defines a port on the PCB\");\nexpectTypesMatch(true);\nvar pcb_smtpad_circle = exports_external.object({\n type: exports_external.literal(\"pcb_smtpad\"),\n shape: exports_external.literal(\"circle\"),\n pcb_smtpad_id: getZodPrefixedIdWithDefault(\"pcb_smtpad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n radius: exports_external.number(),\n layer: layer_ref,\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_smtpad_rect = exports_external.object({\n type: exports_external.literal(\"pcb_smtpad\"),\n shape: exports_external.literal(\"rect\"),\n pcb_smtpad_id: getZodPrefixedIdWithDefault(\"pcb_smtpad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n rect_border_radius: exports_external.number().optional(),\n corner_radius: exports_external.number().optional(),\n layer: layer_ref,\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional(),\n soldermask_margin_left: exports_external.number().optional(),\n soldermask_margin_top: exports_external.number().optional(),\n soldermask_margin_right: exports_external.number().optional(),\n soldermask_margin_bottom: exports_external.number().optional()\n});\nvar pcb_smtpad_rotated_rect = exports_external.object({\n type: exports_external.literal(\"pcb_smtpad\"),\n shape: exports_external.literal(\"rotated_rect\"),\n pcb_smtpad_id: getZodPrefixedIdWithDefault(\"pcb_smtpad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n rect_border_radius: exports_external.number().optional(),\n corner_radius: exports_external.number().optional(),\n ccw_rotation: rotation,\n layer: layer_ref,\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional(),\n soldermask_margin_left: exports_external.number().optional(),\n soldermask_margin_top: exports_external.number().optional(),\n soldermask_margin_right: exports_external.number().optional(),\n soldermask_margin_bottom: exports_external.number().optional()\n});\nvar pcb_smtpad_pill = exports_external.object({\n type: exports_external.literal(\"pcb_smtpad\"),\n shape: exports_external.literal(\"pill\"),\n pcb_smtpad_id: getZodPrefixedIdWithDefault(\"pcb_smtpad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n radius: exports_external.number(),\n layer: layer_ref,\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_smtpad_rotated_pill = exports_external.object({\n type: exports_external.literal(\"pcb_smtpad\"),\n shape: exports_external.literal(\"rotated_pill\"),\n pcb_smtpad_id: getZodPrefixedIdWithDefault(\"pcb_smtpad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n radius: exports_external.number(),\n ccw_rotation: rotation,\n layer: layer_ref,\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_smtpad_polygon = exports_external.object({\n type: exports_external.literal(\"pcb_smtpad\"),\n shape: exports_external.literal(\"polygon\"),\n pcb_smtpad_id: getZodPrefixedIdWithDefault(\"pcb_smtpad\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n points: exports_external.array(point),\n layer: layer_ref,\n port_hints: exports_external.array(exports_external.string()).optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_port_id: exports_external.string().optional(),\n is_covered_with_solder_mask: exports_external.boolean().optional(),\n soldermask_margin: exports_external.number().optional()\n});\nvar pcb_smtpad = exports_external.discriminatedUnion(\"shape\", [\n pcb_smtpad_circle,\n pcb_smtpad_rect,\n pcb_smtpad_rotated_rect,\n pcb_smtpad_rotated_pill,\n pcb_smtpad_pill,\n pcb_smtpad_polygon\n]).describe(\"Defines an SMT pad on the PCB\");\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar pcb_solder_paste_circle = exports_external.object({\n type: exports_external.literal(\"pcb_solder_paste\"),\n shape: exports_external.literal(\"circle\"),\n pcb_solder_paste_id: getZodPrefixedIdWithDefault(\"pcb_solder_paste\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n radius: exports_external.number(),\n layer: layer_ref,\n pcb_component_id: exports_external.string().optional(),\n pcb_smtpad_id: exports_external.string().optional()\n});\nvar pcb_solder_paste_rect = exports_external.object({\n type: exports_external.literal(\"pcb_solder_paste\"),\n shape: exports_external.literal(\"rect\"),\n pcb_solder_paste_id: getZodPrefixedIdWithDefault(\"pcb_solder_paste\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n layer: layer_ref,\n pcb_component_id: exports_external.string().optional(),\n pcb_smtpad_id: exports_external.string().optional()\n});\nvar pcb_solder_paste_pill = exports_external.object({\n type: exports_external.literal(\"pcb_solder_paste\"),\n shape: exports_external.literal(\"pill\"),\n pcb_solder_paste_id: getZodPrefixedIdWithDefault(\"pcb_solder_paste\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n radius: exports_external.number(),\n layer: layer_ref,\n pcb_component_id: exports_external.string().optional(),\n pcb_smtpad_id: exports_external.string().optional()\n});\nvar pcb_solder_paste_rotated_rect = exports_external.object({\n type: exports_external.literal(\"pcb_solder_paste\"),\n shape: exports_external.literal(\"rotated_rect\"),\n pcb_solder_paste_id: getZodPrefixedIdWithDefault(\"pcb_solder_paste\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n ccw_rotation: distance4,\n layer: layer_ref,\n pcb_component_id: exports_external.string().optional(),\n pcb_smtpad_id: exports_external.string().optional()\n});\nvar pcb_solder_paste_oval = exports_external.object({\n type: exports_external.literal(\"pcb_solder_paste\"),\n shape: exports_external.literal(\"oval\"),\n pcb_solder_paste_id: getZodPrefixedIdWithDefault(\"pcb_solder_paste\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n width: exports_external.number(),\n height: exports_external.number(),\n layer: layer_ref,\n pcb_component_id: exports_external.string().optional(),\n pcb_smtpad_id: exports_external.string().optional()\n});\nvar pcb_solder_paste = exports_external.union([\n pcb_solder_paste_circle,\n pcb_solder_paste_rect,\n pcb_solder_paste_pill,\n pcb_solder_paste_rotated_rect,\n pcb_solder_paste_oval\n]).describe(\"Defines solderpaste on the PCB\");\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar pcb_text = exports_external.object({\n type: exports_external.literal(\"pcb_text\"),\n pcb_text_id: getZodPrefixedIdWithDefault(\"pcb_text\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n text: exports_external.string(),\n center: point,\n layer: layer_ref,\n width: length,\n height: length,\n lines: exports_external.number(),\n align: exports_external.enum([\"bottom-left\"])\n}).describe(\"Defines text on the PCB\");\nexpectTypesMatch(true);\nvar pcb_trace_route_point_wire = exports_external.object({\n route_type: exports_external.literal(\"wire\"),\n x: distance4,\n y: distance4,\n width: distance4,\n copper_pour_id: exports_external.string().optional(),\n is_inside_copper_pour: exports_external.boolean().optional(),\n start_pcb_port_id: exports_external.string().optional(),\n end_pcb_port_id: exports_external.string().optional(),\n layer: layer_ref\n});\nvar pcb_trace_route_point_via = exports_external.object({\n route_type: exports_external.literal(\"via\"),\n x: distance4,\n y: distance4,\n copper_pour_id: exports_external.string().optional(),\n is_inside_copper_pour: exports_external.boolean().optional(),\n hole_diameter: distance4.optional(),\n outer_diameter: distance4.optional(),\n from_layer: layer_ref,\n to_layer: layer_ref\n});\nvar pcb_trace_route_point_through_pad = exports_external.object({\n route_type: exports_external.literal(\"through_pad\"),\n start: point,\n end: point,\n width: distance4,\n start_layer: layer_ref,\n end_layer: layer_ref,\n pcb_smtpad_id: exports_external.string().optional(),\n pcb_plated_hole_id: exports_external.string().optional()\n});\nvar pcb_trace_route_point = exports_external.union([\n pcb_trace_route_point_wire,\n pcb_trace_route_point_via,\n pcb_trace_route_point_through_pad\n]);\nvar pcb_trace = exports_external.object({\n type: exports_external.literal(\"pcb_trace\"),\n source_trace_id: exports_external.string().optional(),\n pcb_component_id: exports_external.string().optional(),\n pcb_trace_id: getZodPrefixedIdWithDefault(\"pcb_trace\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n route_thickness_mode: exports_external.enum([\"constant\", \"interpolated\"]).default(\"constant\").optional(),\n route_order_index: exports_external.number().optional(),\n should_round_corners: exports_external.boolean().optional(),\n trace_length: exports_external.number().optional(),\n highlight_color: exports_external.string().optional(),\n route: exports_external.array(pcb_trace_route_point)\n}).describe(\"Defines a trace on the PCB\");\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar pcb_trace_warning = exports_external.object({\n type: exports_external.literal(\"pcb_trace_warning\"),\n pcb_trace_warning_id: getZodPrefixedIdWithDefault(\"pcb_trace_warning\"),\n warning_type: exports_external.literal(\"pcb_trace_warning\").default(\"pcb_trace_warning\"),\n message: exports_external.string(),\n center: point.optional(),\n pcb_trace_id: exports_external.string(),\n source_trace_id: exports_external.string(),\n pcb_component_ids: exports_external.array(exports_external.string()),\n pcb_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a trace warning on the PCB\");\nexpectTypesMatch(true);\nvar pcb_trace_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_trace_error\"),\n pcb_trace_error_id: getZodPrefixedIdWithDefault(\"pcb_trace_error\"),\n error_type: exports_external.literal(\"pcb_trace_error\").default(\"pcb_trace_error\"),\n center: point.optional(),\n pcb_trace_id: exports_external.string(),\n source_trace_id: exports_external.string(),\n pcb_component_ids: exports_external.array(exports_external.string()),\n pcb_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a trace error on the PCB\");\nexpectTypesMatch(true);\nvar pcb_trace_missing_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_trace_missing_error\"),\n pcb_trace_missing_error_id: getZodPrefixedIdWithDefault(\"pcb_trace_missing_error\"),\n error_type: exports_external.literal(\"pcb_trace_missing_error\").default(\"pcb_trace_missing_error\"),\n center: point.optional(),\n source_trace_id: exports_external.string(),\n pcb_component_ids: exports_external.array(exports_external.string()),\n pcb_port_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines an error when a source trace has no corresponding PCB trace\");\nexpectTypesMatch(true);\nvar pcb_port_not_matched_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_port_not_matched_error\"),\n pcb_error_id: getZodPrefixedIdWithDefault(\"pcb_error\"),\n error_type: exports_external.literal(\"pcb_port_not_matched_error\").default(\"pcb_port_not_matched_error\"),\n pcb_component_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a trace error on the PCB where a port is not matched\");\nexpectTypesMatch(true);\nvar pcb_port_not_connected_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_port_not_connected_error\"),\n pcb_port_not_connected_error_id: getZodPrefixedIdWithDefault(\"pcb_port_not_connected_error\"),\n error_type: exports_external.literal(\"pcb_port_not_connected_error\").default(\"pcb_port_not_connected_error\"),\n pcb_port_ids: exports_external.array(exports_external.string()),\n pcb_component_ids: exports_external.array(exports_external.string()),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines an error when a pcb port is not connected to any trace\");\nexpectTypesMatch(true);\nvar pcb_net = exports_external.object({\n type: exports_external.literal(\"pcb_net\"),\n pcb_net_id: getZodPrefixedIdWithDefault(\"pcb_net\"),\n source_net_id: exports_external.string().optional(),\n highlight_color: exports_external.string().optional()\n}).describe(\"Defines a net on the PCB\");\nexpectTypesMatch(true);\nvar pcb_via = exports_external.object({\n type: exports_external.literal(\"pcb_via\"),\n pcb_via_id: getZodPrefixedIdWithDefault(\"pcb_via\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional(),\n x: distance4,\n y: distance4,\n outer_diameter: distance4.default(\"0.6mm\"),\n hole_diameter: distance4.default(\"0.25mm\"),\n from_layer: layer_ref.optional(),\n to_layer: layer_ref.optional(),\n layers: exports_external.array(layer_ref),\n pcb_trace_id: exports_external.string().optional(),\n net_is_assignable: exports_external.boolean().optional(),\n net_assigned: exports_external.boolean().optional(),\n is_tented: exports_external.boolean().optional()\n}).describe(\"Defines a via on the PCB\");\nexpectTypesMatch(true);\nvar pcb_board = exports_external.object({\n type: exports_external.literal(\"pcb_board\"),\n pcb_board_id: getZodPrefixedIdWithDefault(\"pcb_board\"),\n pcb_panel_id: exports_external.string().optional(),\n carrier_pcb_board_id: exports_external.string().optional(),\n is_subcircuit: exports_external.boolean().optional(),\n subcircuit_id: exports_external.string().optional(),\n is_mounted_to_carrier_board: exports_external.boolean().optional(),\n width: length.optional(),\n height: length.optional(),\n center: point,\n display_offset_x: exports_external.string().optional().describe(\"How to display the x offset for this board, usually corresponding with how the user specified it\"),\n display_offset_y: exports_external.string().optional().describe(\"How to display the y offset for this board, usually corresponding with how the user specified it\"),\n thickness: length.optional().default(1.4),\n num_layers: exports_external.number().optional().default(4),\n outline: exports_external.array(point).optional(),\n shape: exports_external.enum([\"rect\", \"polygon\"]).optional(),\n material: exports_external.enum([\"fr4\", \"fr1\"]).default(\"fr4\"),\n solder_mask_color: exports_external.string().optional(),\n silkscreen_color: exports_external.string().optional(),\n anchor_position: point.optional(),\n anchor_alignment: ninePointAnchor.optional(),\n position_mode: exports_external.enum([\"relative_to_panel_anchor\", \"none\"]).optional()\n}).merge(manufacturing_drc_properties).describe(\"Defines the board outline of the PCB\");\nexpectTypesMatch(true);\nvar pcb_panel = exports_external.object({\n type: exports_external.literal(\"pcb_panel\"),\n pcb_panel_id: getZodPrefixedIdWithDefault(\"pcb_panel\"),\n width: length,\n height: length,\n center: point,\n thickness: length.optional().default(1.4),\n covered_with_solder_mask: exports_external.boolean().optional().default(true)\n}).describe(\"Defines a PCB panel that can contain multiple boards\");\nexpectTypesMatch(true);\nvar pcb_placement_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_placement_error\"),\n pcb_placement_error_id: getZodPrefixedIdWithDefault(\"pcb_placement_error\"),\n error_type: exports_external.literal(\"pcb_placement_error\").default(\"pcb_placement_error\"),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a placement error on the PCB\");\nexpectTypesMatch(true);\nvar pcb_panelization_placement_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_panelization_placement_error\"),\n pcb_panelization_placement_error_id: getZodPrefixedIdWithDefault(\"pcb_panelization_placement_error\"),\n error_type: exports_external.literal(\"pcb_panelization_placement_error\").default(\"pcb_panelization_placement_error\"),\n pcb_panel_id: exports_external.string().optional(),\n pcb_board_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a panelization placement error on the PCB\");\nexpectTypesMatch(true);\nvar pcb_trace_hint = exports_external.object({\n type: exports_external.literal(\"pcb_trace_hint\"),\n pcb_trace_hint_id: getZodPrefixedIdWithDefault(\"pcb_trace_hint\"),\n pcb_port_id: exports_external.string(),\n pcb_component_id: exports_external.string(),\n route: exports_external.array(route_hint_point),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"A hint that can be used during generation of a PCB trace\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_line = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_line\"),\n pcb_silkscreen_line_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_line\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n stroke_width: distance4.default(\"0.1mm\"),\n x1: distance4,\n y1: distance4,\n x2: distance4,\n y2: distance4,\n layer: visible_layer\n}).describe(\"Defines a silkscreen line on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_path = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_path\"),\n pcb_silkscreen_path_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_path\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: visible_layer,\n route: exports_external.array(point),\n stroke_width: length\n}).describe(\"Defines a silkscreen path on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_text = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_text\"),\n pcb_silkscreen_text_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_text\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n font: exports_external.literal(\"tscircuit2024\").default(\"tscircuit2024\"),\n font_size: distance4.default(\"0.2mm\"),\n pcb_component_id: exports_external.string(),\n text: exports_external.string(),\n is_knockout: exports_external.boolean().default(false).optional(),\n knockout_padding: exports_external.object({\n left: length,\n top: length,\n bottom: length,\n right: length\n }).default({\n left: \"0.2mm\",\n top: \"0.2mm\",\n bottom: \"0.2mm\",\n right: \"0.2mm\"\n }).optional(),\n ccw_rotation: exports_external.number().optional(),\n layer: layer_ref,\n is_mirrored: exports_external.boolean().default(false).optional(),\n anchor_position: point.default({ x: 0, y: 0 }),\n anchor_alignment: ninePointAnchor.default(\"center\")\n}).describe(\"Defines silkscreen text on the PCB\");\nexpectTypesMatch(true);\nvar pcb_copper_text = exports_external.object({\n type: exports_external.literal(\"pcb_copper_text\"),\n pcb_copper_text_id: getZodPrefixedIdWithDefault(\"pcb_copper_text\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n font: exports_external.literal(\"tscircuit2024\").default(\"tscircuit2024\"),\n font_size: distance4.default(\"0.2mm\"),\n pcb_component_id: exports_external.string(),\n text: exports_external.string(),\n is_knockout: exports_external.boolean().default(false).optional(),\n knockout_padding: exports_external.object({\n left: length,\n top: length,\n bottom: length,\n right: length\n }).default({\n left: \"0.2mm\",\n top: \"0.2mm\",\n bottom: \"0.2mm\",\n right: \"0.2mm\"\n }).optional(),\n ccw_rotation: exports_external.number().optional(),\n layer: layer_ref,\n is_mirrored: exports_external.boolean().default(false).optional(),\n anchor_position: point.default({ x: 0, y: 0 }),\n anchor_alignment: ninePointAnchor.default(\"center\")\n}).describe(\"Defines copper text on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_rect = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_rect\"),\n pcb_silkscreen_rect_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_rect\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n width: length,\n height: length,\n layer: layer_ref,\n stroke_width: length.default(\"1mm\"),\n corner_radius: length.optional(),\n is_filled: exports_external.boolean().default(true).optional(),\n has_stroke: exports_external.boolean().optional(),\n is_stroke_dashed: exports_external.boolean().optional(),\n ccw_rotation: exports_external.number().optional()\n}).describe(\"Defines a silkscreen rect on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_circle = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_circle\"),\n pcb_silkscreen_circle_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_circle\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n radius: length,\n layer: visible_layer,\n stroke_width: length.default(\"1mm\"),\n is_filled: exports_external.boolean().optional()\n}).describe(\"Defines a silkscreen circle on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_oval = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_oval\"),\n pcb_silkscreen_oval_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_oval\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n radius_x: distance4,\n radius_y: distance4,\n layer: visible_layer,\n ccw_rotation: rotation.optional()\n}).describe(\"Defines a silkscreen oval on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_graphic_base = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_graphic\"),\n pcb_silkscreen_graphic_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_graphic\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: visible_layer,\n image_asset: asset.optional()\n});\nvar pcb_silkscreen_graphic_brep = pcb_silkscreen_graphic_base.extend({\n shape: exports_external.literal(\"brep\"),\n brep_shape\n}).describe(\"Defines a BRep silkscreen graphic on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_graphic = exports_external.discriminatedUnion(\"shape\", [pcb_silkscreen_graphic_brep]).describe(\"Defines a silkscreen graphic on the PCB\");\nexpectTypesMatch(true);\nvar pcb_silkscreen_pill = exports_external.object({\n type: exports_external.literal(\"pcb_silkscreen_pill\"),\n pcb_silkscreen_pill_id: getZodPrefixedIdWithDefault(\"pcb_silkscreen_pill\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n width: length,\n height: length,\n layer: layer_ref,\n ccw_rotation: exports_external.number().optional()\n}).describe(\"Defines a silkscreen pill on the PCB\");\nexpectTypesMatch(true);\nvar pcb_fabrication_note_text = exports_external.object({\n type: exports_external.literal(\"pcb_fabrication_note_text\"),\n pcb_fabrication_note_text_id: getZodPrefixedIdWithDefault(\"pcb_fabrication_note_text\"),\n subcircuit_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n font: exports_external.literal(\"tscircuit2024\").default(\"tscircuit2024\"),\n font_size: distance4.default(\"1mm\"),\n pcb_component_id: exports_external.string(),\n text: exports_external.string(),\n ccw_rotation: exports_external.number().optional(),\n layer: visible_layer,\n anchor_position: point.default({ x: 0, y: 0 }),\n anchor_alignment: exports_external.enum([\"center\", \"top_left\", \"top_right\", \"bottom_left\", \"bottom_right\"]).default(\"center\"),\n color: exports_external.string().optional()\n}).describe(\"Defines a fabrication note in text on the PCB, useful for leaving notes for assemblers or fabricators\");\nexpectTypesMatch(true);\nvar pcb_fabrication_note_path = exports_external.object({\n type: exports_external.literal(\"pcb_fabrication_note_path\"),\n pcb_fabrication_note_path_id: getZodPrefixedIdWithDefault(\"pcb_fabrication_note_path\"),\n pcb_component_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional(),\n layer: layer_ref,\n route: exports_external.array(point),\n stroke_width: length,\n color: exports_external.string().optional()\n}).describe(\"Defines a fabrication path on the PCB for fabricators or assemblers\");\nexpectTypesMatch(true);\nvar pcb_fabrication_note_rect = exports_external.object({\n type: exports_external.literal(\"pcb_fabrication_note_rect\"),\n pcb_fabrication_note_rect_id: getZodPrefixedIdWithDefault(\"pcb_fabrication_note_rect\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n width: length,\n height: length,\n layer: visible_layer,\n stroke_width: length.default(\"0.1mm\"),\n corner_radius: length.optional(),\n is_filled: exports_external.boolean().optional(),\n has_stroke: exports_external.boolean().optional(),\n is_stroke_dashed: exports_external.boolean().optional(),\n color: exports_external.string().optional()\n}).describe(\"Defines a fabrication note rectangle on the PCB\");\nexpectTypesMatch(true);\nvar pcb_fabrication_note_dimension = exports_external.object({\n type: exports_external.literal(\"pcb_fabrication_note_dimension\"),\n pcb_fabrication_note_dimension_id: getZodPrefixedIdWithDefault(\"pcb_fabrication_note_dimension\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: visible_layer,\n from: point,\n to: point,\n text: exports_external.string().optional(),\n text_ccw_rotation: exports_external.number().optional(),\n offset: length.optional(),\n offset_distance: length.optional(),\n offset_direction: exports_external.object({\n x: exports_external.number(),\n y: exports_external.number()\n }).optional(),\n font: exports_external.literal(\"tscircuit2024\").default(\"tscircuit2024\"),\n font_size: length.default(\"1mm\"),\n color: exports_external.string().optional(),\n arrow_size: length.default(\"1mm\")\n}).describe(\"Defines a measurement annotation within PCB fabrication notes\");\nexpectTypesMatch(true);\nvar pcb_note_text = exports_external.object({\n type: exports_external.literal(\"pcb_note_text\"),\n pcb_note_text_id: getZodPrefixedIdWithDefault(\"pcb_note_text\"),\n pcb_component_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n font: exports_external.literal(\"tscircuit2024\").default(\"tscircuit2024\"),\n font_size: distance4.default(\"1mm\"),\n text: exports_external.string().optional(),\n anchor_position: point.default({ x: 0, y: 0 }),\n anchor_alignment: exports_external.enum([\"center\", \"top_left\", \"top_right\", \"bottom_left\", \"bottom_right\"]).default(\"center\"),\n layer: visible_layer.default(\"top\"),\n is_mirrored_from_top_view: exports_external.boolean().optional(),\n color: exports_external.string().optional()\n}).describe(\"Defines a documentation note in text on the PCB\");\nexpectTypesMatch(true);\nvar pcb_note_rect = exports_external.object({\n type: exports_external.literal(\"pcb_note_rect\"),\n pcb_note_rect_id: getZodPrefixedIdWithDefault(\"pcb_note_rect\"),\n pcb_component_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n text: exports_external.string().optional(),\n center: point,\n width: length,\n height: length,\n layer: visible_layer.default(\"top\"),\n stroke_width: length.default(\"0.1mm\"),\n corner_radius: length.optional(),\n is_filled: exports_external.boolean().optional(),\n has_stroke: exports_external.boolean().optional(),\n is_stroke_dashed: exports_external.boolean().optional(),\n color: exports_external.string().optional()\n}).describe(\"Defines a rectangular documentation note on the PCB\");\nexpectTypesMatch(true);\nvar pcb_note_path = exports_external.object({\n type: exports_external.literal(\"pcb_note_path\"),\n pcb_note_path_id: getZodPrefixedIdWithDefault(\"pcb_note_path\"),\n pcb_component_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n text: exports_external.string().optional(),\n route: exports_external.array(point),\n layer: visible_layer.default(\"top\"),\n stroke_width: length.default(\"0.1mm\"),\n color: exports_external.string().optional()\n}).describe(\"Defines a polyline documentation note on the PCB\");\nexpectTypesMatch(true);\nvar pcb_note_line = exports_external.object({\n type: exports_external.literal(\"pcb_note_line\"),\n pcb_note_line_id: getZodPrefixedIdWithDefault(\"pcb_note_line\"),\n pcb_component_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n text: exports_external.string().optional(),\n x1: distance4,\n y1: distance4,\n x2: distance4,\n y2: distance4,\n layer: visible_layer.default(\"top\"),\n stroke_width: distance4.default(\"0.1mm\"),\n color: exports_external.string().optional(),\n is_dashed: exports_external.boolean().optional()\n}).describe(\"Defines a straight documentation note line on the PCB\");\nexpectTypesMatch(true);\nvar pcb_note_dimension = exports_external.object({\n type: exports_external.literal(\"pcb_note_dimension\"),\n pcb_note_dimension_id: getZodPrefixedIdWithDefault(\"pcb_note_dimension\"),\n pcb_component_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n from: point,\n to: point,\n text: exports_external.string().optional(),\n text_ccw_rotation: exports_external.number().optional(),\n offset_distance: length.optional(),\n offset_direction: exports_external.object({\n x: exports_external.number(),\n y: exports_external.number()\n }).optional(),\n font: exports_external.literal(\"tscircuit2024\").default(\"tscircuit2024\"),\n font_size: length.default(\"1mm\"),\n layer: visible_layer.default(\"top\"),\n color: exports_external.string().optional(),\n arrow_size: length.default(\"1mm\")\n}).describe(\"Defines a measurement annotation within PCB documentation notes\");\nexpectTypesMatch(true);\nvar pcb_footprint_overlap_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_footprint_overlap_error\"),\n pcb_error_id: getZodPrefixedIdWithDefault(\"pcb_error\"),\n error_type: exports_external.literal(\"pcb_footprint_overlap_error\").default(\"pcb_footprint_overlap_error\"),\n pcb_smtpad_ids: exports_external.array(exports_external.string()).optional(),\n pcb_plated_hole_ids: exports_external.array(exports_external.string()).optional(),\n pcb_hole_ids: exports_external.array(exports_external.string()).optional(),\n pcb_keepout_ids: exports_external.array(exports_external.string()).optional()\n}).describe(\"Error emitted when a pcb footprint overlaps with another element\");\nexpectTypesMatch(true);\nvar pcb_courtyard_overlap_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_courtyard_overlap_error\"),\n pcb_error_id: getZodPrefixedIdWithDefault(\"pcb_error\"),\n error_type: exports_external.literal(\"pcb_courtyard_overlap_error\").default(\"pcb_courtyard_overlap_error\"),\n pcb_component_ids: exports_external.tuple([exports_external.string(), exports_external.string()])\n}).describe(\"Error emitted when the courtyard (CrtYd) of one PCB component overlaps with the courtyard of another\");\nexpectTypesMatch(true);\nvar pcb_keepout = exports_external.object({\n type: exports_external.literal(\"pcb_keepout\"),\n shape: exports_external.literal(\"rect\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n width: distance4,\n height: distance4,\n pcb_keepout_id: exports_external.string(),\n layers: exports_external.array(exports_external.string()),\n description: exports_external.string().optional()\n}).or(exports_external.object({\n type: exports_external.literal(\"pcb_keepout\"),\n shape: exports_external.literal(\"circle\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n radius: distance4,\n pcb_keepout_id: exports_external.string(),\n layers: exports_external.array(exports_external.string()),\n description: exports_external.string().optional()\n}));\nexpectTypesMatch(true);\nvar pcb_cutout_base = exports_external.object({\n type: exports_external.literal(\"pcb_cutout\"),\n pcb_cutout_id: getZodPrefixedIdWithDefault(\"pcb_cutout\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n pcb_board_id: exports_external.string().optional(),\n pcb_panel_id: exports_external.string().optional()\n});\nvar pcb_cutout_rect = pcb_cutout_base.extend({\n shape: exports_external.literal(\"rect\"),\n center: point,\n width: length,\n height: length,\n rotation: rotation.optional(),\n corner_radius: length.optional()\n});\nexpectTypesMatch(true);\nvar pcb_cutout_circle = pcb_cutout_base.extend({\n shape: exports_external.literal(\"circle\"),\n center: point,\n radius: length\n});\nexpectTypesMatch(true);\nvar pcb_cutout_polygon = pcb_cutout_base.extend({\n shape: exports_external.literal(\"polygon\"),\n points: exports_external.array(point)\n});\nexpectTypesMatch(true);\nvar pcb_cutout_path = pcb_cutout_base.extend({\n shape: exports_external.literal(\"path\"),\n route: exports_external.array(point),\n slot_width: length,\n slot_length: length.optional(),\n space_between_slots: length.optional(),\n slot_corner_radius: length.optional()\n});\nexpectTypesMatch(true);\nvar pcb_cutout = exports_external.discriminatedUnion(\"shape\", [\n pcb_cutout_rect,\n pcb_cutout_circle,\n pcb_cutout_polygon,\n pcb_cutout_path\n]).describe(\"Defines a cutout on the PCB, removing board material.\");\nexpectTypesMatch(true);\nvar pcb_missing_footprint_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_missing_footprint_error\"),\n pcb_missing_footprint_error_id: getZodPrefixedIdWithDefault(\"pcb_missing_footprint_error\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n error_type: exports_external.literal(\"pcb_missing_footprint_error\").default(\"pcb_missing_footprint_error\"),\n source_component_id: exports_external.string()\n}).describe(\"Defines a missing footprint error on the PCB\");\nexpectTypesMatch(true);\nvar external_footprint_load_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"external_footprint_load_error\"),\n external_footprint_load_error_id: getZodPrefixedIdWithDefault(\"external_footprint_load_error\"),\n pcb_component_id: exports_external.string(),\n source_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n footprinter_string: exports_external.string().optional(),\n error_type: exports_external.literal(\"external_footprint_load_error\").default(\"external_footprint_load_error\")\n}).describe(\"Defines an error when an external footprint fails to load\");\nexpectTypesMatch(true);\nvar circuit_json_footprint_load_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"circuit_json_footprint_load_error\"),\n circuit_json_footprint_load_error_id: getZodPrefixedIdWithDefault(\"circuit_json_footprint_load_error\"),\n pcb_component_id: exports_external.string(),\n source_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n error_type: exports_external.literal(\"circuit_json_footprint_load_error\").default(\"circuit_json_footprint_load_error\"),\n circuit_json: exports_external.array(exports_external.any()).optional()\n}).describe(\"Defines an error when a circuit JSON footprint fails to load\");\nexpectTypesMatch(true);\nvar pcb_group = exports_external.object({\n type: exports_external.literal(\"pcb_group\"),\n pcb_group_id: getZodPrefixedIdWithDefault(\"pcb_group\"),\n source_group_id: exports_external.string(),\n is_subcircuit: exports_external.boolean().optional(),\n subcircuit_id: exports_external.string().optional(),\n width: length.optional(),\n height: length.optional(),\n center: point,\n display_offset_x: exports_external.string().optional().describe(\"How to display the x offset for this group, usually corresponding with how the user specified it\"),\n display_offset_y: exports_external.string().optional().describe(\"How to display the y offset for this group, usually corresponding with how the user specified it\"),\n outline: exports_external.array(point).optional(),\n anchor_position: point.optional(),\n anchor_alignment: ninePointAnchor.default(\"center\"),\n position_mode: exports_external.enum([\"packed\", \"relative_to_group_anchor\", \"none\"]).optional(),\n positioned_relative_to_pcb_group_id: exports_external.string().optional(),\n positioned_relative_to_pcb_board_id: exports_external.string().optional(),\n pcb_component_ids: exports_external.array(exports_external.string()),\n child_layout_mode: exports_external.enum([\"packed\", \"none\"]).optional(),\n name: exports_external.string().optional(),\n description: exports_external.string().optional(),\n layout_mode: exports_external.string().optional(),\n autorouter_configuration: exports_external.object({\n trace_clearance: length\n }).optional(),\n autorouter_used_string: exports_external.string().optional()\n}).describe(\"Defines a group of components on the PCB\");\nexpectTypesMatch(true);\nvar pcb_autorouting_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_autorouting_error\"),\n pcb_error_id: getZodPrefixedIdWithDefault(\"pcb_autorouting_error\"),\n error_type: exports_external.literal(\"pcb_autorouting_error\").default(\"pcb_autorouting_error\"),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"The autorouting has failed to route a portion of the board\");\nexpectTypesMatch(true);\nvar pcb_manual_edit_conflict_warning = exports_external.object({\n type: exports_external.literal(\"pcb_manual_edit_conflict_warning\"),\n pcb_manual_edit_conflict_warning_id: getZodPrefixedIdWithDefault(\"pcb_manual_edit_conflict_warning\"),\n warning_type: exports_external.literal(\"pcb_manual_edit_conflict_warning\").default(\"pcb_manual_edit_conflict_warning\"),\n message: exports_external.string(),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n source_component_id: exports_external.string()\n}).describe(\"Warning emitted when a component has both manual placement and explicit pcbX/pcbY coordinates\");\nexpectTypesMatch(true);\nvar connectorOrientationDirection = exports_external.enum([\"x-\", \"x+\", \"y+\", \"y-\"]);\nvar pcb_connector_not_in_accessible_orientation_warning = exports_external.object({\n type: exports_external.literal(\"pcb_connector_not_in_accessible_orientation_warning\"),\n pcb_connector_not_in_accessible_orientation_warning_id: getZodPrefixedIdWithDefault(\"pcb_connector_not_in_accessible_orientation_warning\"),\n warning_type: exports_external.literal(\"pcb_connector_not_in_accessible_orientation_warning\").default(\"pcb_connector_not_in_accessible_orientation_warning\"),\n message: exports_external.string(),\n pcb_component_id: exports_external.string(),\n source_component_id: exports_external.string().optional(),\n pcb_board_id: exports_external.string().optional(),\n facing_direction: connectorOrientationDirection,\n recommended_facing_direction: connectorOrientationDirection,\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Warning emitted when a connector PCB component is facing inward toward the board and should be reoriented to an outward-facing direction\");\nexpectTypesMatch(true);\nvar supplier_footprint_mismatch_warning = exports_external.object({\n type: exports_external.literal(\"supplier_footprint_mismatch_warning\"),\n supplier_footprint_mismatch_warning_id: getZodPrefixedIdWithDefault(\"supplier_footprint_mismatch_warning\"),\n warning_type: exports_external.literal(\"supplier_footprint_mismatch_warning\").default(\"supplier_footprint_mismatch_warning\"),\n message: exports_external.string(),\n source_component_id: exports_external.string(),\n pcb_component_id: exports_external.string().optional(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n supplier_name: supplier_name.optional(),\n supplier_part_number: exports_external.string().optional(),\n supplier_footprint_url: exports_external.string().optional(),\n footprint_copper_intersection_over_union: exports_external.number()\n}).describe(\"Warning emitted when a supplier part footprint does not match the expected footprint\");\nexpectTypesMatch(true);\nvar pcb_breakout_point = exports_external.object({\n type: exports_external.literal(\"pcb_breakout_point\"),\n pcb_breakout_point_id: getZodPrefixedIdWithDefault(\"pcb_breakout_point\"),\n pcb_group_id: exports_external.string(),\n subcircuit_id: exports_external.string().optional(),\n source_trace_id: exports_external.string().optional(),\n source_port_id: exports_external.string().optional(),\n source_net_id: exports_external.string().optional(),\n x: distance4,\n y: distance4\n}).describe(\"Defines a routing target within a pcb_group for a source_trace or source_net\");\nexpectTypesMatch(true);\nvar pcb_ground_plane = exports_external.object({\n type: exports_external.literal(\"pcb_ground_plane\"),\n pcb_ground_plane_id: getZodPrefixedIdWithDefault(\"pcb_ground_plane\"),\n source_pcb_ground_plane_id: exports_external.string(),\n source_net_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Defines a ground plane on the PCB\");\nexpectTypesMatch(true);\nvar pcb_ground_plane_region = exports_external.object({\n type: exports_external.literal(\"pcb_ground_plane_region\"),\n pcb_ground_plane_region_id: getZodPrefixedIdWithDefault(\"pcb_ground_plane_region\"),\n pcb_ground_plane_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: layer_ref,\n points: exports_external.array(point)\n}).describe(\"Defines a polygon region of a ground plane\");\nexpectTypesMatch(true);\nvar pcb_thermal_spoke = exports_external.object({\n type: exports_external.literal(\"pcb_thermal_spoke\"),\n pcb_thermal_spoke_id: getZodPrefixedIdWithDefault(\"pcb_thermal_spoke\"),\n pcb_ground_plane_id: exports_external.string(),\n shape: exports_external.string(),\n spoke_count: exports_external.number(),\n spoke_thickness: distance4,\n spoke_inner_diameter: distance4,\n spoke_outer_diameter: distance4,\n pcb_plated_hole_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Pattern for connecting a ground plane to a plated hole\");\nexpectTypesMatch(true);\nvar pcb_copper_pour_base = exports_external.object({\n type: exports_external.literal(\"pcb_copper_pour\"),\n pcb_copper_pour_id: getZodPrefixedIdWithDefault(\"pcb_copper_pour\"),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: layer_ref,\n source_net_id: exports_external.string().optional(),\n covered_with_solder_mask: exports_external.boolean().optional().default(true)\n});\nvar pcb_copper_pour_rect = pcb_copper_pour_base.extend({\n shape: exports_external.literal(\"rect\"),\n center: point,\n width: length,\n height: length,\n rotation: rotation.optional()\n});\nexpectTypesMatch(true);\nvar pcb_copper_pour_brep = pcb_copper_pour_base.extend({\n shape: exports_external.literal(\"brep\"),\n brep_shape\n});\nexpectTypesMatch(true);\nvar pcb_copper_pour_polygon = pcb_copper_pour_base.extend({\n shape: exports_external.literal(\"polygon\"),\n points: exports_external.array(point)\n});\nexpectTypesMatch(true);\nvar pcb_copper_pour = exports_external.discriminatedUnion(\"shape\", [\n pcb_copper_pour_rect,\n pcb_copper_pour_brep,\n pcb_copper_pour_polygon\n]).describe(\"Defines a copper pour on the PCB.\");\nexpectTypesMatch(true);\nvar pcb_component_outside_board_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_component_outside_board_error\"),\n pcb_component_outside_board_error_id: getZodPrefixedIdWithDefault(\"pcb_component_outside_board_error\"),\n error_type: exports_external.literal(\"pcb_component_outside_board_error\").default(\"pcb_component_outside_board_error\"),\n pcb_component_id: exports_external.string(),\n pcb_board_id: exports_external.string(),\n component_center: point,\n component_bounds: exports_external.object({\n min_x: exports_external.number(),\n max_x: exports_external.number(),\n min_y: exports_external.number(),\n max_y: exports_external.number()\n }),\n subcircuit_id: exports_external.string().optional(),\n source_component_id: exports_external.string().optional()\n}).describe(\"Error emitted when a PCB component is placed outside the board boundaries\");\nexpectTypesMatch(true);\nvar pcb_component_not_on_board_edge_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_component_not_on_board_edge_error\"),\n pcb_component_not_on_board_edge_error_id: getZodPrefixedIdWithDefault(\"pcb_component_not_on_board_edge_error\"),\n error_type: exports_external.literal(\"pcb_component_not_on_board_edge_error\").default(\"pcb_component_not_on_board_edge_error\"),\n pcb_component_id: exports_external.string(),\n pcb_board_id: exports_external.string(),\n component_center: point,\n pad_to_nearest_board_edge_distance: exports_external.number(),\n source_component_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when a component that must be placed on the board edge is centered away from the edge\");\nexpectTypesMatch(true);\nvar pcb_component_invalid_layer_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_component_invalid_layer_error\"),\n pcb_component_invalid_layer_error_id: getZodPrefixedIdWithDefault(\"pcb_component_invalid_layer_error\"),\n error_type: exports_external.literal(\"pcb_component_invalid_layer_error\").default(\"pcb_component_invalid_layer_error\"),\n pcb_component_id: exports_external.string().optional(),\n source_component_id: exports_external.string(),\n layer: layer_ref,\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when a component is placed on an invalid layer (components can only be on 'top' or 'bottom' layers)\");\nexpectTypesMatch(true);\nvar pcb_via_clearance_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_via_clearance_error\"),\n pcb_error_id: getZodPrefixedIdWithDefault(\"pcb_error\"),\n error_type: exports_external.literal(\"pcb_via_clearance_error\").default(\"pcb_via_clearance_error\"),\n pcb_via_ids: exports_external.array(exports_external.string()).min(2),\n minimum_clearance: distance4.optional(),\n actual_clearance: distance4.optional(),\n pcb_center: exports_external.object({\n x: exports_external.number().optional(),\n y: exports_external.number().optional()\n }).optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when vias are closer than the allowed clearance\");\nexpectTypesMatch(true);\nvar pcb_via_trace_clearance_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_via_trace_clearance_error\"),\n pcb_via_trace_clearance_error_id: getZodPrefixedIdWithDefault(\"pcb_via_trace_clearance_error\"),\n error_type: exports_external.literal(\"pcb_via_trace_clearance_error\").default(\"pcb_via_trace_clearance_error\"),\n pcb_via_id: exports_external.string(),\n pcb_trace_id: exports_external.string(),\n minimum_clearance: distance4.optional(),\n actual_clearance: distance4.optional(),\n center: exports_external.object({\n x: exports_external.number().optional(),\n y: exports_external.number().optional()\n }).optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when a via and trace are closer than the allowed clearance\");\nexpectTypesMatch(true);\nvar pcb_pad_pad_clearance_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_pad_pad_clearance_error\"),\n pcb_pad_pad_clearance_error_id: getZodPrefixedIdWithDefault(\"pcb_pad_pad_clearance_error\"),\n error_type: exports_external.literal(\"pcb_pad_pad_clearance_error\").default(\"pcb_pad_pad_clearance_error\"),\n pcb_pad_ids: exports_external.array(exports_external.string()).min(2),\n minimum_clearance: distance4.optional(),\n actual_clearance: distance4.optional(),\n center: exports_external.object({\n x: exports_external.number().optional(),\n y: exports_external.number().optional()\n }).optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when pads are closer than the allowed clearance\");\nexpectTypesMatch(true);\nvar pcb_pad_trace_clearance_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"pcb_pad_trace_clearance_error\"),\n pcb_pad_trace_clearance_error_id: getZodPrefixedIdWithDefault(\"pcb_pad_trace_clearance_error\"),\n error_type: exports_external.literal(\"pcb_pad_trace_clearance_error\").default(\"pcb_pad_trace_clearance_error\"),\n pcb_pad_id: exports_external.string(),\n pcb_trace_id: exports_external.string(),\n minimum_clearance: distance4.optional(),\n actual_clearance: distance4.optional(),\n center: exports_external.object({\n x: exports_external.number().optional(),\n y: exports_external.number().optional()\n }).optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"Error emitted when a pad and trace are closer than allowed clearance\");\nexpectTypesMatch(true);\nvar pcb_courtyard_rect = exports_external.object({\n type: exports_external.literal(\"pcb_courtyard_rect\"),\n pcb_courtyard_rect_id: getZodPrefixedIdWithDefault(\"pcb_courtyard_rect\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n width: length,\n height: length,\n layer: visible_layer,\n ccw_rotation: rotation.optional(),\n color: exports_external.string().optional()\n}).describe(\"Defines a courtyard rectangle on the PCB\");\nexpectTypesMatch(true);\nvar pcb_courtyard_outline = exports_external.object({\n type: exports_external.literal(\"pcb_courtyard_outline\"),\n pcb_courtyard_outline_id: getZodPrefixedIdWithDefault(\"pcb_courtyard_outline\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: visible_layer,\n outline: exports_external.array(point).min(2)\n}).describe(\"Defines a courtyard outline on the PCB\");\nexpectTypesMatch(true);\nvar pcb_courtyard_polygon = exports_external.object({\n type: exports_external.literal(\"pcb_courtyard_polygon\"),\n pcb_courtyard_polygon_id: getZodPrefixedIdWithDefault(\"pcb_courtyard_polygon\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n layer: visible_layer,\n points: exports_external.array(point).min(3),\n color: exports_external.string().optional()\n}).describe(\"Defines a courtyard polygon on the PCB\");\nexpectTypesMatch(true);\nvar pcb_courtyard_circle = exports_external.object({\n type: exports_external.literal(\"pcb_courtyard_circle\"),\n pcb_courtyard_circle_id: getZodPrefixedIdWithDefault(\"pcb_courtyard_circle\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n radius: length,\n layer: visible_layer,\n color: exports_external.string().optional()\n}).describe(\"Defines a courtyard circle on the PCB\");\nexpectTypesMatch(true);\nvar pcb_courtyard_pill = exports_external.object({\n type: exports_external.literal(\"pcb_courtyard_pill\"),\n pcb_courtyard_pill_id: getZodPrefixedIdWithDefault(\"pcb_courtyard_pill\"),\n pcb_component_id: exports_external.string(),\n pcb_group_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n center: point,\n width: length,\n height: length,\n radius: length,\n layer: visible_layer,\n color: exports_external.string().optional()\n}).describe(\"Defines a courtyard pill on the PCB\");\nexpectTypesMatch(true);\nvar cad_model_formats = [\n \"obj\",\n \"stl\",\n \"3mf\",\n \"gltf\",\n \"glb\",\n \"step\",\n \"wrl\"\n];\nvar cad_model_axis_directions = [\n \"x+\",\n \"x-\",\n \"y+\",\n \"y-\",\n \"z+\",\n \"z-\"\n];\nvar cadModelDefaultDirectionMap = {\n obj: \"z+\",\n stl: \"z+\",\n \"3mf\": \"z+\",\n gltf: \"y+\",\n glb: \"y+\",\n step: \"z+\",\n wrl: \"y+\"\n};\nvar cad_component = exports_external.object({\n type: exports_external.literal(\"cad_component\"),\n cad_component_id: exports_external.string(),\n pcb_component_id: exports_external.string(),\n source_component_id: exports_external.string(),\n position: point3,\n rotation: point3.optional(),\n size: point3.optional(),\n layer: layer_ref.optional(),\n subcircuit_id: exports_external.string().optional(),\n footprinter_string: exports_external.string().optional(),\n model_obj_url: exports_external.string().optional(),\n model_stl_url: exports_external.string().optional(),\n model_3mf_url: exports_external.string().optional(),\n model_gltf_url: exports_external.string().optional(),\n model_glb_url: exports_external.string().optional(),\n model_step_url: exports_external.string().optional(),\n model_wrl_url: exports_external.string().optional(),\n model_asset: asset.optional(),\n model_unit_to_mm_scale_factor: exports_external.number().optional(),\n model_board_normal_direction: exports_external.enum(cad_model_axis_directions).optional().describe(`The direction in the model's coordinate space that is considered \"up\" or \"coming out of the board surface\"`),\n model_origin_position: point3.optional(),\n model_origin_alignment: exports_external.enum([\n \"unknown\",\n \"center\",\n \"center_of_component_on_board_surface\",\n \"bottom_center_of_component\"\n ]).optional(),\n model_object_fit: exports_external.enum([\"contain_within_bounds\", \"fill_bounds\"]).optional().default(\"contain_within_bounds\"),\n model_jscad: exports_external.any().optional(),\n show_as_translucent_model: exports_external.boolean().optional(),\n show_as_bounding_box: exports_external.boolean().optional(),\n anchor_alignment: exports_external.enum([\"center\", \"center_of_component_on_board_surface\"]).optional().default(\"center\")\n}).describe(\"Defines a component on the PCB\");\nexpectTypesMatch(true);\nvar wave_shape = exports_external.enum([\"sinewave\", \"square\", \"triangle\", \"sawtooth\"]);\nvar percentage = exports_external.union([exports_external.string(), exports_external.number()]).transform((val) =\u003e {\n if (typeof val === \"string\") {\n if (val.endsWith(\"%\")) {\n return parseFloat(val.slice(0, -1)) / 100;\n }\n return parseFloat(val);\n }\n return val;\n}).pipe(exports_external.number().min(0, \"Duty cycle must be non-negative\").max(1, \"Duty cycle cannot be greater than 100%\"));\nvar simulation_dc_voltage_source = exports_external.object({\n type: exports_external.literal(\"simulation_voltage_source\"),\n simulation_voltage_source_id: getZodPrefixedIdWithDefault(\"simulation_voltage_source\"),\n is_dc_source: exports_external.literal(true).optional().default(true),\n positive_source_port_id: exports_external.string().optional(),\n negative_source_port_id: exports_external.string().optional(),\n positive_source_net_id: exports_external.string().optional(),\n negative_source_net_id: exports_external.string().optional(),\n voltage\n}).describe(\"Defines a DC voltage source for simulation\");\nvar simulation_ac_voltage_source = exports_external.object({\n type: exports_external.literal(\"simulation_voltage_source\"),\n simulation_voltage_source_id: getZodPrefixedIdWithDefault(\"simulation_voltage_source\"),\n is_dc_source: exports_external.literal(false),\n terminal1_source_port_id: exports_external.string().optional(),\n terminal2_source_port_id: exports_external.string().optional(),\n terminal1_source_net_id: exports_external.string().optional(),\n terminal2_source_net_id: exports_external.string().optional(),\n voltage: voltage.optional(),\n frequency: frequency.optional(),\n peak_to_peak_voltage: voltage.optional(),\n wave_shape: wave_shape.optional(),\n phase: rotation.optional(),\n duty_cycle: percentage.optional(),\n pulse_delay: ms.optional(),\n rise_time: ms.optional(),\n fall_time: ms.optional(),\n pulse_width: ms.optional(),\n period: ms.optional()\n}).describe(\"Defines an AC voltage source for simulation\");\nvar simulation_voltage_source = exports_external.union([simulation_dc_voltage_source, simulation_ac_voltage_source]).describe(\"Defines a voltage source for simulation\");\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar percentage2 = exports_external.union([exports_external.string(), exports_external.number()]).transform((val) =\u003e {\n if (typeof val === \"string\") {\n if (val.endsWith(\"%\")) {\n return parseFloat(val.slice(0, -1)) / 100;\n }\n return parseFloat(val);\n }\n return val;\n}).pipe(exports_external.number().min(0, \"Duty cycle must be non-negative\").max(1, \"Duty cycle cannot be greater than 100%\"));\nvar simulation_dc_current_source = exports_external.object({\n type: exports_external.literal(\"simulation_current_source\"),\n simulation_current_source_id: getZodPrefixedIdWithDefault(\"simulation_current_source\"),\n is_dc_source: exports_external.literal(true).optional().default(true),\n positive_source_port_id: exports_external.string().optional(),\n negative_source_port_id: exports_external.string().optional(),\n positive_source_net_id: exports_external.string().optional(),\n negative_source_net_id: exports_external.string().optional(),\n current\n}).describe(\"Defines a DC current source for simulation\");\nvar simulation_ac_current_source = exports_external.object({\n type: exports_external.literal(\"simulation_current_source\"),\n simulation_current_source_id: getZodPrefixedIdWithDefault(\"simulation_current_source\"),\n is_dc_source: exports_external.literal(false),\n terminal1_source_port_id: exports_external.string().optional(),\n terminal2_source_port_id: exports_external.string().optional(),\n terminal1_source_net_id: exports_external.string().optional(),\n terminal2_source_net_id: exports_external.string().optional(),\n current: current.optional(),\n frequency: frequency.optional(),\n peak_to_peak_current: current.optional(),\n wave_shape: wave_shape.optional(),\n phase: rotation.optional(),\n duty_cycle: percentage2.optional()\n}).describe(\"Defines an AC current source for simulation\");\nvar simulation_current_source = exports_external.union([simulation_dc_current_source, simulation_ac_current_source]).describe(\"Defines a current source for simulation\");\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nexpectTypesMatch(true);\nvar experiment_type = exports_external.union([\n exports_external.literal(\"spice_dc_sweep\"),\n exports_external.literal(\"spice_dc_operating_point\"),\n exports_external.literal(\"spice_transient_analysis\"),\n exports_external.literal(\"spice_ac_analysis\")\n]);\nvar spice_simulation_options = exports_external.object({\n method: exports_external.enum([\"trap\", \"gear\"]).optional(),\n reltol: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n abstol: exports_external.union([exports_external.number(), exports_external.string()]).optional(),\n vntol: exports_external.union([exports_external.number(), exports_external.string()]).optional()\n}).describe(\"SPICE solver options for a simulation experiment\");\nvar simulation_experiment = exports_external.object({\n type: exports_external.literal(\"simulation_experiment\"),\n simulation_experiment_id: getZodPrefixedIdWithDefault(\"simulation_experiment\"),\n name: exports_external.string(),\n experiment_type,\n time_per_step: duration_ms.optional(),\n start_time_ms: ms.optional(),\n end_time_ms: ms.optional(),\n spice_options: spice_simulation_options.optional()\n}).describe(\"Defines a simulation experiment configuration\");\nexpectTypesMatch(true);\nvar simulation_transient_voltage_graph = exports_external.object({\n type: exports_external.literal(\"simulation_transient_voltage_graph\"),\n simulation_transient_voltage_graph_id: getZodPrefixedIdWithDefault(\"simulation_transient_voltage_graph\"),\n simulation_experiment_id: exports_external.string(),\n timestamps_ms: exports_external.array(exports_external.number()).optional(),\n voltage_levels: exports_external.array(exports_external.number()),\n source_component_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional(),\n time_per_step: duration_ms,\n start_time_ms: ms,\n end_time_ms: ms,\n name: exports_external.string().optional(),\n color: exports_external.string().optional()\n}).describe(\"Stores voltage measurements over time for a simulation\");\nexpectTypesMatch(true);\nvar simulation_transient_current_graph = exports_external.object({\n type: exports_external.literal(\"simulation_transient_current_graph\"),\n simulation_transient_current_graph_id: getZodPrefixedIdWithDefault(\"simulation_transient_current_graph\"),\n simulation_experiment_id: exports_external.string(),\n timestamps_ms: exports_external.array(exports_external.number()).optional(),\n current_levels: exports_external.array(exports_external.number()),\n source_component_id: exports_external.string().optional(),\n subcircuit_connectivity_map_key: exports_external.string().optional(),\n time_per_step: duration_ms,\n start_time_ms: ms,\n end_time_ms: ms,\n name: exports_external.string().optional(),\n color: exports_external.string().optional()\n}).describe(\"Stores current measurements over time for a simulation\");\nexpectTypesMatch(true);\nvar simulation_switch = exports_external.object({\n type: exports_external.literal(\"simulation_switch\"),\n simulation_switch_id: getZodPrefixedIdWithDefault(\"simulation_switch\"),\n source_component_id: exports_external.string().optional(),\n closes_at: ms.optional(),\n opens_at: ms.optional(),\n starts_closed: exports_external.boolean().optional(),\n switching_frequency: frequency.optional()\n}).describe(\"Defines a switch for simulation timing control\");\nexpectTypesMatch(true);\nvar simulation_voltage_probe = exports_external.object({\n type: exports_external.literal(\"simulation_voltage_probe\"),\n simulation_voltage_probe_id: getZodPrefixedIdWithDefault(\"simulation_voltage_probe\"),\n source_component_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n signal_input_source_port_id: exports_external.string().optional(),\n signal_input_source_net_id: exports_external.string().optional(),\n reference_input_source_port_id: exports_external.string().optional(),\n reference_input_source_net_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n color: exports_external.string().optional()\n}).describe(\"Defines a voltage probe for simulation. If a reference input is not provided, it measures against ground. If a reference input is provided, it measures the differential voltage between two points.\").superRefine((data, ctx) =\u003e {\n const is_differential = data.reference_input_source_port_id || data.reference_input_source_net_id;\n if (is_differential) {\n const has_ports = !!data.signal_input_source_port_id || !!data.reference_input_source_port_id;\n const has_nets = !!data.signal_input_source_net_id || !!data.reference_input_source_net_id;\n if (has_ports \u0026\u0026 has_nets) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Cannot mix port and net connections in a differential probe.\"\n });\n } else if (has_ports) {\n if (!data.signal_input_source_port_id || !data.reference_input_source_port_id) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Differential port probe requires both signal_input_source_port_id and reference_input_source_port_id.\"\n });\n }\n } else if (has_nets) {\n if (!data.signal_input_source_net_id || !data.reference_input_source_net_id) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Differential net probe requires both signal_input_source_net_id and reference_input_source_net_id.\"\n });\n }\n }\n } else {\n if (!!data.signal_input_source_port_id === !!data.signal_input_source_net_id) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"A voltage probe must have exactly one of signal_input_source_port_id or signal_input_source_net_id.\"\n });\n }\n }\n});\nexpectTypesMatch(true);\nvar simulation_current_probe = exports_external.object({\n type: exports_external.literal(\"simulation_current_probe\"),\n simulation_current_probe_id: getZodPrefixedIdWithDefault(\"simulation_current_probe\"),\n source_component_id: exports_external.string().optional(),\n name: exports_external.string().optional(),\n positive_source_port_id: exports_external.string().optional(),\n negative_source_port_id: exports_external.string().optional(),\n positive_source_net_id: exports_external.string().optional(),\n negative_source_net_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional(),\n color: exports_external.string().optional()\n}).describe(\"Defines a current probe for simulation. It measures current flowing from the positive endpoint to the negative endpoint.\").superRefine((data, ctx) =\u003e {\n const hasPositivePort = !!data.positive_source_port_id;\n const hasNegativePort = !!data.negative_source_port_id;\n const hasPositiveNet = !!data.positive_source_net_id;\n const hasNegativeNet = !!data.negative_source_net_id;\n const hasPorts = hasPositivePort || hasNegativePort;\n const hasNets = hasPositiveNet || hasNegativeNet;\n if (hasPorts \u0026\u0026 hasNets) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Cannot mix port and net connections in a current probe.\"\n });\n return;\n }\n if (hasPorts) {\n if (!hasPositivePort || !hasNegativePort) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Current probe using source ports requires both positive_source_port_id and negative_source_port_id.\"\n });\n }\n return;\n }\n if (hasNets) {\n if (!hasPositiveNet || !hasNegativeNet) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Current probe using source nets requires both positive_source_net_id and negative_source_net_id.\"\n });\n }\n return;\n }\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"A current probe must have either positive/negative source port ids or positive/negative source net ids.\"\n });\n});\nexpectTypesMatch(true);\nvar simulation_unknown_experiment_error = base_circuit_json_error.extend({\n type: exports_external.literal(\"simulation_unknown_experiment_error\"),\n simulation_unknown_experiment_error_id: getZodPrefixedIdWithDefault(\"simulation_unknown_experiment_error\"),\n error_type: exports_external.literal(\"simulation_unknown_experiment_error\").default(\"simulation_unknown_experiment_error\"),\n simulation_experiment_id: exports_external.string().optional(),\n subcircuit_id: exports_external.string().optional()\n}).describe(\"An unknown error occurred during the simulation experiment.\");\nexpectTypesMatch(true);\nvar simulation_op_amp = exports_external.object({\n type: exports_external.literal(\"simulation_op_amp\"),\n simulation_op_amp_id: getZodPrefixedIdWithDefault(\"simulation_op_amp\"),\n source_component_id: exports_external.string().optional(),\n inverting_input_source_port_id: exports_external.string(),\n non_inverting_input_source_port_id: exports_external.string(),\n output_source_port_id: exports_external.string(),\n positive_supply_source_port_id: exports_external.string(),\n negative_supply_source_port_id: exports_external.string()\n}).describe(\"Defines a simple ideal operational amplifier for simulation\");\nexpectTypesMatch(true);\nvar simulation_spice_subcircuit = exports_external.object({\n type: exports_external.literal(\"simulation_spice_subcircuit\"),\n simulation_spice_subcircuit_id: getZodPrefixedIdWithDefault(\"simulation_spice_subcircuit\"),\n source_component_id: exports_external.string(),\n spice_pin_to_source_port_map: exports_external.record(exports_external.string(), exports_external.string()),\n subcircuit_source: exports_external.string()\n}).describe(\"Defines a custom SPICE subcircuit model for simulation\");\nexpectTypesMatch(true);\nvar hasValue = (value) =\u003e value !== undefined;\nvar simulation_oscilloscope_trace = exports_external.object({\n type: exports_external.literal(\"simulation_oscilloscope_trace\"),\n simulation_oscilloscope_trace_id: getZodPrefixedIdWithDefault(\"simulation_oscilloscope_trace\"),\n simulation_transient_voltage_graph_id: exports_external.string().optional(),\n simulation_transient_current_graph_id: exports_external.string().optional(),\n simulation_voltage_probe_id: exports_external.string().optional(),\n simulation_current_probe_id: exports_external.string().optional(),\n display_name: exports_external.string().optional(),\n color: exports_external.string().optional(),\n display_center_value: exports_external.number().optional(),\n display_center_offset_divs: exports_external.number().optional(),\n volts_per_div: exports_external.number().positive().optional(),\n amps_per_div: exports_external.number().positive().optional()\n}).describe(\"Defines how a simulation measurement is rendered as an oscilloscope-style trace.\").superRefine((data, ctx) =\u003e {\n const voltageReferences = [\n data.simulation_transient_voltage_graph_id,\n data.simulation_voltage_probe_id\n ].filter(hasValue).length;\n const currentReferences = [\n data.simulation_transient_current_graph_id,\n data.simulation_current_probe_id\n ].filter(hasValue).length;\n if (voltageReferences + currentReferences !== 1) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"An oscilloscope trace must reference exactly one voltage graph, current graph, voltage probe, or current probe.\"\n });\n }\n if (voltageReferences \u003e 0 \u0026\u0026 data.amps_per_div !== undefined) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Voltage oscilloscope traces must use volts_per_div, not amps_per_div.\"\n });\n }\n if (currentReferences \u003e 0 \u0026\u0026 data.volts_per_div !== undefined) {\n ctx.addIssue({\n code: exports_external.ZodIssueCode.custom,\n message: \"Current oscilloscope traces must use amps_per_div, not volts_per_div.\"\n });\n }\n});\nexpectTypesMatch(true);\nvar any_circuit_element = exports_external.union([\n source_trace,\n source_port,\n source_component_internal_connection,\n any_source_component,\n source_net,\n source_group,\n source_simple_chip,\n source_simple_capacitor,\n source_simple_diode,\n source_simple_led,\n source_simple_resistor,\n source_simple_power_source,\n source_simple_battery,\n source_simple_inductor,\n source_simple_pin_header,\n source_simple_pinout,\n source_simple_resonator,\n source_simple_switch,\n source_simple_transistor,\n source_simple_test_point,\n source_simple_mosfet,\n source_simple_op_amp,\n source_simple_potentiometer,\n source_simple_push_button,\n source_pcb_ground_plane,\n source_manually_placed_via,\n source_board,\n source_project_metadata,\n source_invalid_component_property_error,\n source_trace_not_connected_error,\n source_pin_missing_trace_warning,\n source_unnamed_trace_warning,\n source_missing_manufacturer_part_number_warning,\n source_no_power_pin_defined_warning,\n source_no_ground_pin_defined_warning,\n source_component_pins_underspecified_warning,\n source_pin_must_be_connected_error,\n unknown_error_finding_part,\n source_i2c_misconfigured_error,\n source_component_misconfigured_error,\n source_ambiguous_port_reference,\n pcb_component,\n pcb_hole,\n pcb_missing_footprint_error,\n external_footprint_load_error,\n circuit_json_footprint_load_error,\n pcb_manual_edit_conflict_warning,\n pcb_connector_not_in_accessible_orientation_warning,\n supplier_footprint_mismatch_warning,\n pcb_plated_hole,\n pcb_keepout,\n pcb_port,\n pcb_net,\n pcb_text,\n pcb_trace,\n pcb_trace_warning,\n pcb_via,\n pcb_smtpad,\n pcb_solder_paste,\n pcb_board,\n pcb_panel,\n pcb_group,\n pcb_trace_hint,\n pcb_silkscreen_line,\n pcb_silkscreen_path,\n pcb_silkscreen_text,\n pcb_silkscreen_pill,\n pcb_copper_text,\n pcb_silkscreen_rect,\n pcb_silkscreen_circle,\n pcb_silkscreen_oval,\n pcb_silkscreen_graphic,\n pcb_trace_error,\n pcb_trace_missing_error,\n pcb_placement_error,\n pcb_panelization_placement_error,\n pcb_port_not_matched_error,\n pcb_port_not_connected_error,\n pcb_via_clearance_error,\n pcb_via_trace_clearance_error,\n pcb_pad_pad_clearance_error,\n pcb_pad_trace_clearance_error,\n pcb_fabrication_note_path,\n pcb_fabrication_note_text,\n pcb_fabrication_note_rect,\n pcb_fabrication_note_dimension,\n pcb_note_text,\n pcb_note_rect,\n pcb_note_path,\n pcb_note_line,\n pcb_note_dimension,\n pcb_autorouting_error,\n pcb_footprint_overlap_error,\n pcb_courtyard_overlap_error,\n pcb_breakout_point,\n pcb_cutout,\n pcb_ground_plane,\n pcb_ground_plane_region,\n pcb_thermal_spoke,\n pcb_copper_pour,\n pcb_component_outside_board_error,\n pcb_component_not_on_board_edge_error,\n pcb_component_invalid_layer_error,\n pcb_courtyard_rect,\n pcb_courtyard_outline,\n pcb_courtyard_polygon,\n pcb_courtyard_circle,\n pcb_courtyard_pill,\n schematic_box,\n schematic_text,\n schematic_line,\n schematic_rect,\n schematic_circle,\n schematic_arc,\n schematic_component,\n schematic_symbol,\n schematic_port,\n schematic_trace,\n schematic_path,\n schematic_error,\n schematic_layout_error,\n schematic_net_label,\n schematic_debug_object,\n schematic_voltage_probe,\n schematic_manual_edit_conflict_warning,\n schematic_group,\n schematic_sheet,\n schematic_table,\n schematic_table_cell,\n cad_component,\n simulation_voltage_source,\n simulation_current_source,\n simulation_experiment,\n simulation_transient_voltage_graph,\n simulation_transient_current_graph,\n simulation_switch,\n simulation_voltage_probe,\n simulation_current_probe,\n simulation_oscilloscope_trace,\n simulation_unknown_experiment_error,\n simulation_op_amp,\n simulation_spice_subcircuit\n]);\nvar any_soup_element = any_circuit_element;\nexpectTypesMatch(true);\nexpectStringUnionsMatch(true);\n// ../../work/placement-analysis/node_modules/transformation-matrix/src/fromTransformAttribute.autogenerated.js\nfunction peg$subclass(child, parent) {\n function C() {\n this.constructor = child;\n }\n C.prototype = parent.prototype;\n child.prototype = new C;\n}\nfunction peg$SyntaxError(message, expected, found, location) {\n var self2 = Error.call(this, message);\n if (Object.setPrototypeOf) {\n Object.setPrototypeOf(self2, peg$SyntaxError.prototype);\n }\n self2.expected = expected;\n self2.found = found;\n self2.location = location;\n self2.name = \"SyntaxError\";\n return self2;\n}\npeg$subclass(peg$SyntaxError, Error);\nfunction peg$padEnd(str, targetLength, padString) {\n padString = padString || \" \";\n if (str.length \u003e targetLength) {\n return str;\n }\n targetLength -= str.length;\n padString += padString.repeat(targetLength);\n return str + padString.slice(0, targetLength);\n}\npeg$SyntaxError.prototype.format = function(sources) {\n var str = \"Error: \" + this.message;\n if (this.location) {\n var src = null;\n var k;\n for (k = 0;k \u003c sources.length; k++) {\n if (sources[k].source === this.location.source) {\n src = sources[k].text.split(/\\r\\n|\\n|\\r/g);\n break;\n }\n }\n var s = this.location.start;\n var offset_s = this.location.source \u0026\u0026 typeof this.location.source.offset === \"function\" ? this.location.source.offset(s) : s;\n var loc = this.location.source + \":\" + offset_s.line + \":\" + offset_s.column;\n if (src) {\n var e = this.location.end;\n var filler = peg$padEnd(\"\", offset_s.line.toString().length, \" \");\n var line = src[s.line - 1];\n var last = s.line === e.line ? e.column : line.length + 1;\n var hatLen = last - s.column || 1;\n str += `\n --\u003e ` + loc + `\n` + filler + ` |\n` + offset_s.line + \" | \" + line + `\n` + filler + \" | \" + peg$padEnd(\"\", s.column - 1, \" \") + peg$padEnd(\"\", hatLen, \"^\");\n } else {\n str += `\n at ` + loc;\n }\n }\n return str;\n};\npeg$SyntaxError.buildMessage = function(expected, found) {\n var DESCRIBE_EXPECTATION_FNS = {\n literal: function(expectation) {\n return '\"' + literalEscape(expectation.text) + '\"';\n },\n class: function(expectation) {\n var escapedParts = expectation.parts.map(function(part) {\n return Array.isArray(part) ? classEscape(part[0]) + \"-\" + classEscape(part[1]) : classEscape(part);\n });\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts.join(\"\") + \"]\";\n },\n any: function() {\n return \"any character\";\n },\n end: function() {\n return \"end of input\";\n },\n other: function(expectation) {\n return expectation.description;\n }\n };\n function hex(ch) {\n return ch.charCodeAt(0).toString(16).toUpperCase();\n }\n function literalEscape(s) {\n return s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, \"\\\\\\\"\").replace(/\\0/g, \"\\\\0\").replace(/\\t/g, \"\\\\t\").replace(/\\n/g, \"\\\\n\").replace(/\\r/g, \"\\\\r\").replace(/[\\x00-\\x0F]/g, function(ch) {\n return \"\\\\x0\" + hex(ch);\n }).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) {\n return \"\\\\x\" + hex(ch);\n });\n }\n function classEscape(s) {\n return s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\]/g, \"\\\\]\").replace(/\\^/g, \"\\\\^\").replace(/-/g, \"\\\\-\").replace(/\\0/g, \"\\\\0\").replace(/\\t/g, \"\\\\t\").replace(/\\n/g, \"\\\\n\").replace(/\\r/g, \"\\\\r\").replace(/[\\x00-\\x0F]/g, function(ch) {\n return \"\\\\x0\" + hex(ch);\n }).replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) {\n return \"\\\\x\" + hex(ch);\n });\n }\n function describeExpectation(expectation) {\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\n }\n function describeExpected(expected2) {\n var descriptions = expected2.map(describeExpectation);\n var i, j;\n descriptions.sort();\n if (descriptions.length \u003e 0) {\n for (i = 1, j = 1;i \u003c descriptions.length; i++) {\n if (descriptions[i - 1] !== descriptions[i]) {\n descriptions[j] = descriptions[i];\n j++;\n }\n }\n descriptions.length = j;\n }\n switch (descriptions.length) {\n case 1:\n return descriptions[0];\n case 2:\n return descriptions[0] + \" or \" + descriptions[1];\n default:\n return descriptions.slice(0, -1).join(\", \") + \", or \" + descriptions[descriptions.length - 1];\n }\n }\n function describeFound(found2) {\n return found2 ? '\"' + literalEscape(found2) + '\"' : \"end of input\";\n }\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\n};\n// ../../work/placement-analysis/node_modules/parsel-js/dist/parsel.js\nvar TRIM_TOKENS = new Set([\"combinator\", \"comma\"]);\nvar RECURSIVE_PSEUDO_CLASSES = new Set([\n \"not\",\n \"is\",\n \"where\",\n \"has\",\n \"matches\",\n \"-moz-any\",\n \"-webkit-any\",\n \"nth-child\",\n \"nth-last-child\"\n]);\n\n// ../../work/placement-analysis/node_modules/@tscircuit/circuit-json-util/dist/index.js\nfunction connect(map, a, b) {\n if (!a || !b)\n return;\n let setA = map.get(a);\n if (!setA) {\n setA = /* @__PURE__ */ new Set;\n map.set(a, setA);\n }\n setA.add(b);\n let setB = map.get(b);\n if (!setB) {\n setB = /* @__PURE__ */ new Set;\n map.set(b, setB);\n }\n setB.add(a);\n}\nfunction buildSubtree(soup, opts) {\n if (!opts.subcircuit_id \u0026\u0026 !opts.source_group_id)\n return [...soup];\n let effectiveOpts = opts;\n if (opts.subcircuit_id) {\n const subcircuitIds = /* @__PURE__ */ new Set([opts.subcircuit_id]);\n const groupChildren = /* @__PURE__ */ new Map;\n const groupSubcircuit = /* @__PURE__ */ new Map;\n for (const elm of soup) {\n if (elm.type === \"source_group\") {\n const groupId = elm.source_group_id;\n const subcircuitId = elm.subcircuit_id;\n if (subcircuitId) {\n groupSubcircuit.set(groupId, subcircuitId);\n }\n const parentId = elm.parent_source_group_id;\n if (parentId) {\n if (!groupChildren.has(parentId)) {\n groupChildren.set(parentId, []);\n }\n groupChildren.get(parentId).push(groupId);\n }\n }\n }\n let rootGroupId;\n for (const [groupId, subcircuitId] of groupSubcircuit) {\n if (subcircuitId === opts.subcircuit_id) {\n rootGroupId = groupId;\n break;\n }\n }\n if (rootGroupId) {\n const collectChildSubcircuits = (groupId) =\u003e {\n const children = groupChildren.get(groupId) || [];\n for (const childId of children) {\n const childSubcircuit = groupSubcircuit.get(childId);\n if (childSubcircuit) {\n subcircuitIds.add(childSubcircuit);\n }\n collectChildSubcircuits(childId);\n }\n };\n collectChildSubcircuits(rootGroupId);\n effectiveOpts = { ...opts, subcircuit_ids: Array.from(subcircuitIds) };\n }\n }\n const idMap = /* @__PURE__ */ new Map;\n for (const elm of soup) {\n const idKey = `${elm.type}_id`;\n const idVal = elm[idKey];\n if (typeof idVal === \"string\") {\n idMap.set(idVal, elm);\n }\n }\n const adj = /* @__PURE__ */ new Map;\n for (const elm of soup) {\n const entries = Object.entries(elm);\n for (const [key, val] of entries) {\n if (key === \"parent_source_group_id\")\n continue;\n if (key.endsWith(\"_id\") \u0026\u0026 typeof val === \"string\") {\n const other = idMap.get(val);\n connect(adj, elm, other);\n } else if (key.endsWith(\"_ids\") \u0026\u0026 Array.isArray(val)) {\n for (const v of val) {\n if (typeof v === \"string\") {\n const other = idMap.get(v);\n connect(adj, elm, other);\n }\n }\n }\n }\n }\n const queue = [];\n const included = /* @__PURE__ */ new Set;\n for (const elm of soup) {\n let shouldInclude = false;\n if (effectiveOpts.subcircuit_id \u0026\u0026 \"subcircuit_id\" in elm \u0026\u0026 elm.subcircuit_id === effectiveOpts.subcircuit_id) {\n shouldInclude = true;\n } else if (effectiveOpts.subcircuit_ids \u0026\u0026 \"subcircuit_id\" in elm \u0026\u0026 elm.subcircuit_id \u0026\u0026 effectiveOpts.subcircuit_ids.includes(elm.subcircuit_id)) {\n shouldInclude = true;\n } else if (effectiveOpts.source_group_id \u0026\u0026 \"source_group_id\" in elm \u0026\u0026 elm.source_group_id === effectiveOpts.source_group_id) {\n shouldInclude = true;\n } else if (effectiveOpts.source_group_id \u0026\u0026 \"member_source_group_ids\" in elm \u0026\u0026 Array.isArray(elm.member_source_group_ids) \u0026\u0026 elm.member_source_group_ids.includes(effectiveOpts.source_group_id)) {\n shouldInclude = true;\n }\n if (shouldInclude) {\n queue.push(elm);\n included.add(elm);\n }\n }\n while (queue.length \u003e 0) {\n const elm = queue.shift();\n const neighbors = adj.get(elm);\n if (!neighbors)\n continue;\n for (const n of neighbors) {\n if (!included.has(n)) {\n included.add(n);\n queue.push(n);\n }\n }\n }\n return soup.filter((e) =\u003e included.has(e));\n}\nvar cju = (circuitJsonInput, options = {}) =\u003e {\n const circuitJson = circuitJsonInput;\n let internalStore = circuitJson._internal_store;\n if (!internalStore) {\n internalStore = {\n counts: {},\n editCount: 0\n };\n circuitJson._internal_store = internalStore;\n for (const elm of circuitJson) {\n const type = elm.type;\n const idVal = elm[`${type}_id`];\n if (!idVal)\n continue;\n const idNum = Number.parseInt(idVal.split(\"_\").pop());\n if (!Number.isNaN(idNum)) {\n internalStore.counts[type] = Math.max(internalStore.counts[type] ?? 0, idNum);\n }\n }\n }\n const su2 = new Proxy({}, {\n get: (proxy_target, prop) =\u003e {\n if (prop === \"toArray\") {\n return () =\u003e {\n circuitJson.editCount = internalStore.editCount;\n return circuitJson;\n };\n }\n if (prop === \"editCount\") {\n return internalStore.editCount;\n }\n if (prop === \"subtree\") {\n return (opts) =\u003e cju(buildSubtree(circuitJson, opts), options);\n }\n if (prop === \"insert\") {\n return (elm) =\u003e {\n const component_type2 = elm.type;\n if (!component_type2) {\n throw new Error(\"insert requires an element with a type\");\n }\n internalStore.counts[component_type2] ??= -1;\n internalStore.counts[component_type2]++;\n const index = internalStore.counts[component_type2];\n const newElm = {\n ...elm,\n type: component_type2,\n [`${component_type2}_id`]: `${component_type2}_${index}`\n };\n if (options.validateInserts) {\n const parser = exports_dist[component_type2] ?? any_soup_element;\n parser.parse(newElm);\n }\n circuitJson.push(newElm);\n internalStore.editCount++;\n return newElm;\n };\n }\n if (prop === \"insertAll\") {\n return (elms) =\u003e {\n return elms.map((elm) =\u003e su2.insert(elm));\n };\n }\n const component_type = prop;\n return {\n get: (id) =\u003e circuitJson.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === id),\n getUsing: (using) =\u003e {\n const keys = Object.keys(using);\n if (keys.length !== 1) {\n throw new Error(\"getUsing requires exactly one key, e.g. { pcb_component_id }\");\n }\n const join_key = keys[0];\n const join_type = join_key.replace(\"_id\", \"\");\n const joiner = circuitJson.find((e) =\u003e e.type === join_type \u0026\u0026 e[join_key] === using[join_key]);\n if (!joiner)\n return null;\n return circuitJson.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === joiner[`${component_type}_id`]);\n },\n getWhere: (where) =\u003e {\n const keys = Object.keys(where);\n return circuitJson.find((e) =\u003e e.type === component_type \u0026\u0026 keys.every((key) =\u003e e[key] === where[key]));\n },\n list: (where) =\u003e {\n const keys = !where ? [] : Object.keys(where);\n return circuitJson.filter((e) =\u003e e.type === component_type \u0026\u0026 keys.every((key) =\u003e e[key] === where[key]));\n },\n insert: (elm) =\u003e {\n internalStore.counts[component_type] ??= -1;\n internalStore.counts[component_type]++;\n const index = internalStore.counts[component_type];\n const newElm = {\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n ...elm\n };\n if (options.validateInserts) {\n const parser = exports_dist[component_type] ?? any_soup_element;\n parser.parse(newElm);\n }\n circuitJson.push(newElm);\n internalStore.editCount++;\n return newElm;\n },\n delete: (id) =\u003e {\n const elm = circuitJson.find((e) =\u003e e[`${component_type}_id`] === id);\n if (!elm)\n return;\n circuitJson.splice(circuitJson.indexOf(elm), 1);\n internalStore.editCount++;\n },\n update: (id, newProps) =\u003e {\n const elm = circuitJson.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === id);\n if (!elm)\n return null;\n Object.assign(elm, newProps);\n internalStore.editCount++;\n return elm;\n },\n select: (selector) =\u003e {\n if (component_type === \"source_component\") {\n return circuitJson.find((e) =\u003e e.type === \"source_component\" \u0026\u0026 e.name === selector.replace(/\\./g, \"\"));\n } else if (component_type === \"pcb_port\" || component_type === \"source_port\" || component_type === \"schematic_port\") {\n const [component_name, port_selector] = selector.replace(/\\./g, \"\").split(/[\\s\\\u003e]+/);\n const source_component = circuitJson.find((e) =\u003e e.type === \"source_component\" \u0026\u0026 e.name === component_name);\n if (!source_component)\n return null;\n const source_port2 = circuitJson.find((e) =\u003e e.type === \"source_port\" \u0026\u0026 e.source_component_id === source_component.source_component_id \u0026\u0026 (e.name === port_selector || (e.port_hints ?? []).includes(port_selector)));\n if (!source_port2)\n return null;\n if (component_type === \"source_port\")\n return source_port2;\n if (component_type === \"pcb_port\") {\n return circuitJson.find((e) =\u003e e.type === \"pcb_port\" \u0026\u0026 e.source_port_id === source_port2.source_port_id);\n } else if (component_type === \"schematic_port\") {\n return circuitJson.find((e) =\u003e e.type === \"schematic_port\" \u0026\u0026 e.source_port_id === source_port2.source_port_id);\n }\n }\n }\n };\n }\n });\n return su2;\n};\ncju.unparsed = cju;\nvar cju_default = cju;\nfunction createIdKey(element) {\n const type = element.type;\n return `${type}:${element[`${type}_id`]}`;\n}\nvar cjuIndexed = (soup, options = {}) =\u003e {\n let internalStore = soup._internal_store_indexed;\n if (!internalStore) {\n internalStore = {\n counts: {},\n editCount: 0,\n indexes: {}\n };\n for (const elm of soup) {\n const type = elm.type;\n const idVal = elm[`${type}_id`];\n if (!idVal)\n continue;\n const idNum = Number.parseInt(idVal.split(\"_\").pop() || \"\");\n if (!Number.isNaN(idNum)) {\n internalStore.counts[type] = Math.max(internalStore.counts[type] ?? 0, idNum);\n }\n }\n const indexConfig = options.indexConfig || {};\n const indexes = internalStore.indexes;\n if (indexConfig.byId) {\n indexes.byId = /* @__PURE__ */ new Map;\n }\n if (indexConfig.byType) {\n indexes.byType = /* @__PURE__ */ new Map;\n }\n if (indexConfig.byRelation) {\n indexes.byRelation = /* @__PURE__ */ new Map;\n }\n if (indexConfig.bySubcircuit) {\n indexes.bySubcircuit = /* @__PURE__ */ new Map;\n }\n if (indexConfig.byCustomField \u0026\u0026 indexConfig.byCustomField.length \u003e 0) {\n indexes.byCustomField = /* @__PURE__ */ new Map;\n for (const field of indexConfig.byCustomField) {\n indexes.byCustomField.set(field, /* @__PURE__ */ new Map);\n }\n }\n for (const element of soup) {\n if (indexConfig.byId) {\n const idKey = createIdKey(element);\n indexes.byId.set(idKey, element);\n }\n if (indexConfig.byType) {\n const elementsOfType = indexes.byType.get(element.type) || [];\n elementsOfType.push(element);\n indexes.byType.set(element.type, elementsOfType);\n }\n if (indexConfig.byRelation) {\n const elementEntries = Object.entries(element);\n for (const [key, value] of elementEntries) {\n if (key.endsWith(\"_id\") \u0026\u0026 key !== `${element.type}_id` \u0026\u0026 typeof value === \"string\") {\n const relationTypeMap = indexes.byRelation.get(key) || /* @__PURE__ */ new Map;\n const relatedElements = relationTypeMap.get(value) || [];\n relatedElements.push(element);\n relationTypeMap.set(value, relatedElements);\n indexes.byRelation.set(key, relationTypeMap);\n }\n }\n }\n if (indexConfig.bySubcircuit \u0026\u0026 \"subcircuit_id\" in element) {\n const subcircuitId = element.subcircuit_id;\n if (subcircuitId \u0026\u0026 typeof subcircuitId === \"string\") {\n const subcircuitElements = indexes.bySubcircuit.get(subcircuitId) || [];\n subcircuitElements.push(element);\n indexes.bySubcircuit.set(subcircuitId, subcircuitElements);\n }\n }\n if (indexConfig.byCustomField \u0026\u0026 indexes.byCustomField) {\n for (const field of indexConfig.byCustomField) {\n if (field in element) {\n const fieldValue = element[field];\n if (fieldValue !== undefined \u0026\u0026 (typeof fieldValue === \"string\" || typeof fieldValue === \"number\")) {\n const fieldValueStr = String(fieldValue);\n const fieldMap = indexes.byCustomField.get(field);\n const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];\n elementsWithFieldValue.push(element);\n fieldMap.set(fieldValueStr, elementsWithFieldValue);\n }\n }\n }\n }\n }\n soup._internal_store_indexed = internalStore;\n }\n const suIndexed = new Proxy({}, {\n get: (proxy_target, prop) =\u003e {\n if (prop === \"toArray\") {\n return () =\u003e {\n soup.editCount = internalStore.editCount;\n return soup;\n };\n }\n if (prop === \"editCount\") {\n return internalStore.editCount;\n }\n const component_type = prop;\n return {\n get: (id) =\u003e {\n const indexConfig = options.indexConfig || {};\n if (indexConfig.byId \u0026\u0026 internalStore.indexes.byId) {\n return internalStore.indexes.byId.get(`${component_type}:${id}`) || null;\n }\n if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n return elementsOfType.find((e) =\u003e e[`${component_type}_id`] === id) || null;\n }\n return soup.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === id) || null;\n },\n getUsing: (using) =\u003e {\n const indexConfig = options.indexConfig || {};\n const keys = Object.keys(using);\n if (keys.length !== 1) {\n throw new Error(\"getUsing requires exactly one key, e.g. { pcb_component_id }\");\n }\n const join_key = keys[0];\n const join_type = join_key.replace(\"_id\", \"\");\n if (indexConfig.byRelation \u0026\u0026 internalStore.indexes.byRelation) {\n const relationMap = internalStore.indexes.byRelation.get(join_key);\n if (relationMap) {\n const relatedElements = relationMap.get(using[join_key]) || [];\n const joiner2 = relatedElements.find((e) =\u003e e.type === join_type);\n if (!joiner2)\n return null;\n const joinerId = joiner2[`${component_type}_id`];\n if (indexConfig.byId \u0026\u0026 internalStore.indexes.byId) {\n return internalStore.indexes.byId.get(`${component_type}:${joinerId}`) || null;\n }\n if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n return elementsOfType.find((e) =\u003e e[`${component_type}_id`] === joinerId) || null;\n }\n return soup.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === joinerId) || null;\n }\n }\n const joiner = soup.find((e) =\u003e e.type === join_type \u0026\u0026 e[join_key] === using[join_key]);\n if (!joiner)\n return null;\n return soup.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === joiner[`${component_type}_id`]) || null;\n },\n getWhere: (where) =\u003e {\n const indexConfig = options.indexConfig || {};\n const keys = Object.keys(where);\n if (keys.length === 1 \u0026\u0026 indexConfig.byCustomField \u0026\u0026 internalStore.indexes.byCustomField) {\n const field = keys[0];\n const fieldMap = internalStore.indexes.byCustomField.get(field);\n if (fieldMap) {\n const fieldValue = String(where[field]);\n const elementsWithFieldValue = fieldMap.get(fieldValue) || [];\n return elementsWithFieldValue.find((e) =\u003e e.type === component_type) || null;\n }\n }\n if (\"subcircuit_id\" in where \u0026\u0026 indexConfig.bySubcircuit \u0026\u0026 internalStore.indexes.bySubcircuit) {\n const subcircuitId = where.subcircuit_id;\n const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];\n return subcircuitElements.find((e) =\u003e e.type === component_type \u0026\u0026 keys.every((key) =\u003e e[key] === where[key])) || null;\n }\n if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n return elementsOfType.find((e) =\u003e keys.every((key) =\u003e e[key] === where[key])) || null;\n }\n return soup.find((e) =\u003e e.type === component_type \u0026\u0026 keys.every((key) =\u003e e[key] === where[key])) || null;\n },\n list: (where) =\u003e {\n const indexConfig = options.indexConfig || {};\n const keys = !where ? [] : Object.keys(where);\n if (keys.length === 0 \u0026\u0026 indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n return internalStore.indexes.byType.get(component_type) || [];\n }\n if (keys.length === 1 \u0026\u0026 keys[0] === \"subcircuit_id\" \u0026\u0026 indexConfig.bySubcircuit \u0026\u0026 internalStore.indexes.bySubcircuit) {\n const subcircuitId = where.subcircuit_id;\n const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];\n return subcircuitElements.filter((e) =\u003e e.type === component_type);\n }\n let elementsToFilter;\n if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n elementsToFilter = internalStore.indexes.byType.get(component_type) || [];\n } else {\n elementsToFilter = soup.filter((e) =\u003e e.type === component_type);\n }\n if (keys.length \u003e 0) {\n return elementsToFilter.filter((e) =\u003e keys.every((key) =\u003e e[key] === where[key]));\n }\n return elementsToFilter;\n },\n insert: (elm) =\u003e {\n internalStore.counts[component_type] ??= -1;\n internalStore.counts[component_type]++;\n const index = internalStore.counts[component_type];\n const newElm = {\n type: component_type,\n [`${component_type}_id`]: `${component_type}_${index}`,\n ...elm\n };\n if (options.validateInserts) {\n const parser = exports_dist[component_type] ?? any_soup_element;\n parser.parse(newElm);\n }\n soup.push(newElm);\n internalStore.editCount++;\n const indexConfig = options.indexConfig || {};\n if (indexConfig.byId \u0026\u0026 internalStore.indexes.byId) {\n const idKey = createIdKey(newElm);\n internalStore.indexes.byId.set(idKey, newElm);\n }\n if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n elementsOfType.push(newElm);\n internalStore.indexes.byType.set(component_type, elementsOfType);\n }\n if (indexConfig.byRelation \u0026\u0026 internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(newElm);\n for (const [key, value] of elementEntries) {\n if (key.endsWith(\"_id\") \u0026\u0026 key !== `${newElm.type}_id` \u0026\u0026 typeof value === \"string\") {\n const relationTypeMap = internalStore.indexes.byRelation.get(key) || /* @__PURE__ */ new Map;\n const relatedElements = relationTypeMap.get(value) || [];\n relatedElements.push(newElm);\n relationTypeMap.set(value, relatedElements);\n internalStore.indexes.byRelation.set(key, relationTypeMap);\n }\n }\n }\n if (indexConfig.bySubcircuit \u0026\u0026 internalStore.indexes.bySubcircuit \u0026\u0026 \"subcircuit_id\" in newElm) {\n const subcircuitId = newElm.subcircuit_id;\n if (subcircuitId \u0026\u0026 typeof subcircuitId === \"string\") {\n const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];\n subcircuitElements.push(newElm);\n internalStore.indexes.bySubcircuit.set(subcircuitId, subcircuitElements);\n }\n }\n if (indexConfig.byCustomField \u0026\u0026 internalStore.indexes.byCustomField) {\n for (const field of indexConfig.byCustomField) {\n if (field in newElm) {\n const fieldValue = newElm[field];\n if (fieldValue !== undefined \u0026\u0026 (typeof fieldValue === \"string\" || typeof fieldValue === \"number\")) {\n const fieldValueStr = String(fieldValue);\n const fieldMap = internalStore.indexes.byCustomField.get(field);\n const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];\n elementsWithFieldValue.push(newElm);\n fieldMap.set(fieldValueStr, elementsWithFieldValue);\n }\n }\n }\n }\n return newElm;\n },\n delete: (id) =\u003e {\n const indexConfig = options.indexConfig || {};\n let elm;\n if (indexConfig.byId \u0026\u0026 internalStore.indexes.byId) {\n elm = internalStore.indexes.byId.get(`${component_type}:${id}`);\n } else if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n elm = elementsOfType.find((e) =\u003e e[`${component_type}_id`] === id);\n } else {\n elm = soup.find((e) =\u003e e[`${component_type}_id`] === id);\n }\n if (!elm)\n return;\n const elmIndex = soup.indexOf(elm);\n if (elmIndex \u003e= 0) {\n soup.splice(elmIndex, 1);\n internalStore.editCount++;\n }\n if (indexConfig.byId \u0026\u0026 internalStore.indexes.byId) {\n const idKey = createIdKey(elm);\n internalStore.indexes.byId.delete(idKey);\n }\n if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n const filteredElements = elementsOfType.filter((e) =\u003e e[`${component_type}_id`] !== id);\n internalStore.indexes.byType.set(component_type, filteredElements);\n }\n if (indexConfig.byRelation \u0026\u0026 internalStore.indexes.byRelation) {\n for (const [\n relationKey,\n relationMap\n ] of internalStore.indexes.byRelation.entries()) {\n for (const [relationValue, elements] of relationMap.entries()) {\n const updatedElements = elements.filter((e) =\u003e e !== elm);\n if (updatedElements.length === 0) {\n relationMap.delete(relationValue);\n } else {\n relationMap.set(relationValue, updatedElements);\n }\n }\n }\n }\n if (indexConfig.bySubcircuit \u0026\u0026 internalStore.indexes.bySubcircuit \u0026\u0026 \"subcircuit_id\" in elm) {\n const subcircuitId = elm.subcircuit_id;\n if (subcircuitId) {\n const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];\n const updatedElements = subcircuitElements.filter((e) =\u003e e !== elm);\n if (updatedElements.length === 0) {\n internalStore.indexes.bySubcircuit.delete(subcircuitId);\n } else {\n internalStore.indexes.bySubcircuit.set(subcircuitId, updatedElements);\n }\n }\n }\n if (indexConfig.byCustomField \u0026\u0026 internalStore.indexes.byCustomField) {\n for (const fieldMap of internalStore.indexes.byCustomField.values()) {\n for (const [fieldValue, elements] of fieldMap.entries()) {\n const updatedElements = elements.filter((e) =\u003e e !== elm);\n if (updatedElements.length === 0) {\n fieldMap.delete(fieldValue);\n } else {\n fieldMap.set(fieldValue, updatedElements);\n }\n }\n }\n }\n },\n update: (id, newProps) =\u003e {\n const indexConfig = options.indexConfig || {};\n let elm;\n if (indexConfig.byId \u0026\u0026 internalStore.indexes.byId) {\n elm = internalStore.indexes.byId.get(`${component_type}:${id}`);\n } else if (indexConfig.byType \u0026\u0026 internalStore.indexes.byType) {\n const elementsOfType = internalStore.indexes.byType.get(component_type) || [];\n elm = elementsOfType.find((e) =\u003e e[`${component_type}_id`] === id);\n } else {\n elm = soup.find((e) =\u003e e.type === component_type \u0026\u0026 e[`${component_type}_id`] === id);\n }\n if (!elm)\n return null;\n if (indexConfig.byRelation \u0026\u0026 internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(elm);\n for (const [key, value] of elementEntries) {\n if (key.endsWith(\"_id\") \u0026\u0026 key !== `${elm.type}_id` \u0026\u0026 typeof value === \"string\") {\n if (key in newProps \u0026\u0026 newProps[key] !== value) {\n const relationTypeMap = internalStore.indexes.byRelation.get(key);\n if (relationTypeMap) {\n const relatedElements = relationTypeMap.get(value) || [];\n const updatedElements = relatedElements.filter((e) =\u003e e !== elm);\n if (updatedElements.length === 0) {\n relationTypeMap.delete(value);\n } else {\n relationTypeMap.set(value, updatedElements);\n }\n }\n }\n }\n }\n }\n if (indexConfig.bySubcircuit \u0026\u0026 internalStore.indexes.bySubcircuit \u0026\u0026 \"subcircuit_id\" in elm \u0026\u0026 \"subcircuit_id\" in newProps) {\n const oldSubcircuitId = elm.subcircuit_id;\n const newSubcircuitId = newProps.subcircuit_id;\n if (oldSubcircuitId !== newSubcircuitId) {\n const subcircuitElements = internalStore.indexes.bySubcircuit.get(oldSubcircuitId) || [];\n const updatedElements = subcircuitElements.filter((e) =\u003e e !== elm);\n if (updatedElements.length === 0) {\n internalStore.indexes.bySubcircuit.delete(oldSubcircuitId);\n } else {\n internalStore.indexes.bySubcircuit.set(oldSubcircuitId, updatedElements);\n }\n }\n }\n if (indexConfig.byCustomField \u0026\u0026 internalStore.indexes.byCustomField) {\n for (const field of indexConfig.byCustomField) {\n if (field in elm \u0026\u0026 field in newProps \u0026\u0026 elm[field] !== newProps[field]) {\n const fieldMap = internalStore.indexes.byCustomField.get(field);\n if (fieldMap) {\n const oldValue = String(elm[field]);\n const elements = fieldMap.get(oldValue) || [];\n const updatedElements = elements.filter((e) =\u003e e !== elm);\n if (updatedElements.length === 0) {\n fieldMap.delete(oldValue);\n } else {\n fieldMap.set(oldValue, updatedElements);\n }\n }\n }\n }\n }\n Object.assign(elm, newProps);\n internalStore.editCount++;\n if (indexConfig.byRelation \u0026\u0026 internalStore.indexes.byRelation) {\n const elementEntries = Object.entries(elm);\n for (const [key, value] of elementEntries) {\n if (key.endsWith(\"_id\") \u0026\u0026 key !== `${elm.type}_id` \u0026\u0026 typeof value === \"string\") {\n if (key in newProps) {\n const relationTypeMap = internalStore.indexes.byRelation.get(key) || /* @__PURE__ */ new Map;\n const relatedElements = relationTypeMap.get(value) || [];\n if (!relatedElements.includes(elm)) {\n relatedElements.push(elm);\n relationTypeMap.set(value, relatedElements);\n internalStore.indexes.byRelation.set(key, relationTypeMap);\n }\n }\n }\n }\n }\n if (indexConfig.bySubcircuit \u0026\u0026 internalStore.indexes.bySubcircuit \u0026\u0026 \"subcircuit_id\" in elm \u0026\u0026 \"subcircuit_id\" in newProps) {\n const subcircuitId = elm.subcircuit_id;\n if (subcircuitId \u0026\u0026 typeof subcircuitId === \"string\") {\n const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];\n if (!subcircuitElements.includes(elm)) {\n subcircuitElements.push(elm);\n internalStore.indexes.bySubcircuit.set(subcircuitId, subcircuitElements);\n }\n }\n }\n if (indexConfig.byCustomField \u0026\u0026 internalStore.indexes.byCustomField) {\n for (const field of indexConfig.byCustomField) {\n if (field in elm \u0026\u0026 field in newProps) {\n const fieldValue = elm[field];\n if (fieldValue !== undefined \u0026\u0026 (typeof fieldValue === \"string\" || typeof fieldValue === \"number\")) {\n const fieldValueStr = String(fieldValue);\n const fieldMap = internalStore.indexes.byCustomField.get(field);\n const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];\n if (!elementsWithFieldValue.includes(elm)) {\n elementsWithFieldValue.push(elm);\n fieldMap.set(fieldValueStr, elementsWithFieldValue);\n }\n }\n }\n }\n }\n return elm;\n },\n select: (selector) =\u003e {\n if (component_type === \"source_component\") {\n return soup.find((e) =\u003e e.type === \"source_component\" \u0026\u0026 e.name === selector.replace(/\\./g, \"\")) || null;\n } else if (component_type === \"pcb_port\" || component_type === \"source_port\" || component_type === \"schematic_port\") {\n const [component_name, port_selector] = selector.replace(/\\./g, \"\").split(/[\\s\\\u003e]+/);\n const source_component = soup.find((e) =\u003e e.type === \"source_component\" \u0026\u0026 e.name === component_name);\n if (!source_component)\n return null;\n const source_port2 = soup.find((e) =\u003e e.type === \"source_port\" \u0026\u0026 e.source_component_id === source_component.source_component_id \u0026\u0026 (e.name === port_selector || (e.port_hints ?? []).includes(port_selector)));\n if (!source_port2)\n return null;\n if (component_type === \"source_port\")\n return source_port2;\n if (component_type === \"pcb_port\") {\n return soup.find((e) =\u003e e.type === \"pcb_port\" \u0026\u0026 e.source_port_id === source_port2.source_port_id) || null;\n } else if (component_type === \"schematic_port\") {\n return soup.find((e) =\u003e e.type === \"schematic_port\" \u0026\u0026 e.source_port_id === source_port2.source_port_id) || null;\n }\n }\n return null;\n }\n };\n }\n });\n return suIndexed;\n};\ncjuIndexed.unparsed = cjuIndexed;\n\n// ../../work/placement-analysis/lib/utils/schematic-sheets.ts\nvar getSchematicSheetNamesById = (circuitJson) =\u003e {\n const map = new Map;\n for (const element of circuitJson) {\n if (element.type === \"schematic_sheet\" \u0026\u0026 element.name) {\n map.set(element.schematic_sheet_id, element.name);\n }\n }\n return map;\n};\n\n// ../../work/placement-analysis/lib/utils/placements.ts\nvar isSchematicBox = (el) =\u003e el.type === \"schematic_box\";\nvar isSchematicComponent = (el) =\u003e el.type === \"schematic_component\";\nvar getSchematicSheetId = (el) =\u003e el.schematic_sheet_id;\nvar getSourceComponentName = (circuitJson, sourceComponentId) =\u003e {\n if (!sourceComponentId)\n return;\n return cju_default(circuitJson).source_component.get(sourceComponentId)?.name;\n};\nvar getSourceComponentMetadata = (schematicBox, circuitJson) =\u003e {\n if (!schematicBox.schematic_component_id)\n return {};\n const util3 = cju_default(circuitJson);\n const sc = util3.schematic_component.get(schematicBox.schematic_component_id);\n if (!sc?.source_component_id)\n return {};\n const sourceComponent = util3.source_component.get(sc.source_component_id);\n return {\n sourceComponentId: sc.source_component_id,\n sourceComponentName: sourceComponent?.name\n };\n};\nvar schematicComponentToPlacement = (schematicComponent, circuitJson, schematicSheetNameById, schematicBox) =\u003e {\n let schematicSheetId = getSchematicSheetId(schematicComponent);\n if (schematicSheetId === undefined \u0026\u0026 schematicBox) {\n schematicSheetId = getSchematicSheetId(schematicBox);\n }\n let schematicSheetName;\n if (schematicSheetId) {\n schematicSheetName = schematicSheetNameById.get(schematicSheetId);\n }\n const placement = {\n lineItemType: \"SchematicBoxPlacement\",\n positionAnchor: \"center\",\n schX: schematicComponent.center.x,\n schY: schematicComponent.center.y,\n width: schematicBox?.width ?? schematicComponent.size.width,\n height: schematicBox?.height ?? schematicComponent.size.height,\n sourceComponentId: schematicComponent.source_component_id,\n sourceComponentName: getSourceComponentName(circuitJson, schematicComponent.source_component_id),\n schematicComponentId: schematicComponent.schematic_component_id,\n schematicSymbolId: schematicBox?.schematic_symbol_id ?? schematicComponent.schematic_symbol_id,\n subcircuitId: schematicComponent.subcircuit_id ?? schematicBox?.subcircuit_id\n };\n if (schematicSheetId) {\n placement.schematicSheetId = schematicSheetId;\n }\n if (schematicSheetName) {\n placement.schematicSheetName = schematicSheetName;\n }\n return placement;\n};\nvar schematicBoxToPlacement = (schematicBox, circuitJson, schematicSheetNameById) =\u003e {\n const schematicSheetId = getSchematicSheetId(schematicBox);\n let schematicSheetName;\n if (schematicSheetId) {\n schematicSheetName = schematicSheetNameById.get(schematicSheetId);\n }\n const placement = {\n lineItemType: \"SchematicBoxPlacement\",\n positionAnchor: \"center\",\n schX: schematicBox.x,\n schY: schematicBox.y,\n width: schematicBox.width,\n height: schematicBox.height,\n ...getSourceComponentMetadata(schematicBox, circuitJson),\n schematicComponentId: schematicBox.schematic_component_id,\n schematicSymbolId: schematicBox.schematic_symbol_id,\n subcircuitId: schematicBox.subcircuit_id\n };\n if (schematicSheetId) {\n placement.schematicSheetId = schematicSheetId;\n }\n if (schematicSheetName) {\n placement.schematicSheetName = schematicSheetName;\n }\n return placement;\n};\nvar buildSolverContext = (circuitJson) =\u003e {\n const schematicBoxes = circuitJson.filter(isSchematicBox);\n const schematicSheetNameById = getSchematicSheetNamesById(circuitJson);\n const schematicComponentIds = new Set(circuitJson.filter(isSchematicComponent).map((sc) =\u003e sc.schematic_component_id));\n const componentPlacements = [\n ...circuitJson.filter(isSchematicComponent).map((sc) =\u003e schematicComponentToPlacement(sc, circuitJson, schematicSheetNameById, schematicBoxes.find((sb) =\u003e sb.schematic_component_id === sc.schematic_component_id))),\n ...schematicBoxes.filter((sb) =\u003e !sb.schematic_component_id || !schematicComponentIds.has(sb.schematic_component_id)).map((sb) =\u003e schematicBoxToPlacement(sb, circuitJson, schematicSheetNameById))\n ];\n return { circuitJson, componentPlacements };\n};\n\n// ../../work/placement-analysis/lib/solvers/SwitchPullResistorPlacementSolver/SwitchPullResistorPlacementSolver.ts\nclass SwitchPullResistorPlacementSolver extends BaseSolver {\n params;\n constructor(params) {\n super();\n this.params = params;\n }\n _step() {\n const index = new PlacementNetworkIndex(this.params.ctx);\n for (const pair of getSwitchPullResistorPairs(index)) {\n const { resistor, switchBox, signalPort, signalSchY, pullDirection } = pair;\n if (pair.horizontalPushbutton)\n continue;\n const signal = index.connected(signalPort.source_port_id);\n if (index.portsByNet.get(signal)?.length !== 2)\n continue;\n if (signalPort.needs_external_pullup || signalPort.needs_external_pulldown)\n continue;\n const wrongSideGap = pullDirection === \"up\" ? signalSchY - (resistor.schY + resistor.height / 2) : resistor.schY - resistor.height / 2 - signalSchY;\n if (wrongSideGap \u003c= 1.5)\n continue;\n const preferredSide = pullDirection === \"up\" ? \"above\" : \"below\";\n this.params.issues.push({\n lineItemType: \"PullResistorOnWrongSide\",\n resistorSchematicBox: resistor,\n hostSchematicBox: switchBox,\n signalSourcePortId: signalPort.source_port_id,\n signalPinName: signalPort.name,\n signalSchY,\n pullDirection,\n preferredSide,\n wrongSideGap,\n maxRecommendedWrongSideGap: 1.5,\n message: `place ${resistor.sourceComponentName} ${preferredSide} ${switchBox.sourceComponentName} so the pull-${pullDirection} branch reads toward ${pullDirection === \"up\" ? \"power\" : \"ground\"}`\n });\n }\n this.solved = true;\n }\n}\n\n// ../../work/placement-analysis/lib/utils/trace-name.ts\nfunction getTraceName(circuitJson, trace) {\n const sourceTrace = circuitJson.find((e) =\u003e e.type === \"source_trace\" \u0026\u0026 e.source_trace_id === trace.source_trace_id);\n if (sourceTrace?.type === \"source_trace\" \u0026\u0026 sourceTrace.name)\n return sourceTrace.name;\n const first = trace.edges[0];\n const last = trace.edges.at(-1);\n const endpointName = (point2, id) =\u003e {\n const ports = circuitJson.filter((e) =\u003e e.type === \"schematic_port\" \u0026\u0026 e.schematic_sheet_id === trace.schematic_sheet_id \u0026\u0026 (id ? e.schematic_port_id === id : Math.hypot(e.center.x - point2.x, e.center.y - point2.y) \u003c= 0.01));\n if (ports.length !== 1 || ports[0]?.type !== \"schematic_port\")\n return;\n const port = ports[0];\n const sourcePort = circuitJson.find((e) =\u003e e.type === \"source_port\" \u0026\u0026 e.source_port_id === port.source_port_id);\n const component = circuitJson.find((e) =\u003e e.type === \"schematic_component\" \u0026\u0026 e.schematic_component_id === port.schematic_component_id);\n const sourceComponentId = sourcePort?.type === \"source_port\" ? sourcePort.source_component_id : component?.type === \"schematic_component\" ? component.source_component_id : undefined;\n const sourceComponent = circuitJson.find((e) =\u003e e.type === \"source_component\" \u0026\u0026 e.source_component_id === sourceComponentId);\n if (sourceComponent?.type !== \"source_component\" || !sourceComponent.name)\n return;\n const pin = sourcePort?.type === \"source_port\" \u0026\u0026 sourcePort.name ? sourcePort.name : port.pin_number !== undefined ? `pin${port.pin_number}` : port.display_pin_label;\n return pin ? `${sourceComponent.name}.${pin}` : sourceComponent.name;\n };\n const from = first \u0026\u0026 endpointName(first.from, first.from_schematic_port_id);\n const to = last \u0026\u0026 endpointName(last.to, last.to_schematic_port_id);\n if (from \u0026\u0026 to)\n return `${from} to ${to}`;\n return sourceTrace?.type === \"source_trace\" \u0026\u0026 sourceTrace.display_name || from || to || \"trace\";\n}\n\n// ../../work/placement-analysis/node_modules/calculate-elbow/lib/calculateElbowBends.ts\nvar calculateElbowBends = (p1, p2, overshootAmount) =\u003e {\n const result = [{ x: p1.x, y: p1.y }];\n const midX = (p1.x + p2.x) / 2;\n const midY = (p1.y + p2.y) / 2;\n const p2Target = { x: p2.x, y: p2.y };\n switch (p2.facingDirection) {\n case \"x+\":\n p2Target.x += overshootAmount;\n break;\n case \"x-\":\n p2Target.x -= overshootAmount;\n break;\n case \"y+\":\n p2Target.y += overshootAmount;\n break;\n case \"y-\":\n p2Target.y -= overshootAmount;\n break;\n }\n const startDir = p1.facingDirection ?? \"none\";\n const endDir = p2.facingDirection ?? \"none\";\n const push = (pt) =\u003e {\n const last = result[result.length - 1];\n if (last.x !== pt.x || last.y !== pt.y)\n result.push(pt);\n };\n const yAligned = Math.abs(p1.y - p2.y) \u003c= Math.max(0.000001, overshootAmount * 0.1);\n const xAligned = Math.abs(p1.x - p2.x) \u003c= Math.max(0.000001, overshootAmount * 0.1);\n if (startDir === \"none\" \u0026\u0026 endDir === \"none\") {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 1;\n push({ x: midX, y: p1.y });\n push({ x: midX, y: p2.y });\n } else if (startDir === \"x+\" \u0026\u0026 endDir === \"y+\") {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2;\n if (p1.x \u003e p2.x \u0026\u0026 p1.y \u003c p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.1;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p2.y + overshootAmount });\n push({ x: p2.x, y: p2.y + overshootAmount });\n } else if (!xAligned \u0026\u0026 !yAligned \u0026\u0026 p1.x \u003c p2.x \u0026\u0026 p1.y \u003e p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.2;\n push({ x: p2.x, y: p1.y });\n } else if (xAligned) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.3;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p2.y + overshootAmount });\n push({ x: p2.x, y: p2.y + overshootAmount });\n } else {\n if (p1.x \u003c p2.x) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.4;\n push({ x: midX, y: p1.y });\n push({ x: midX, y: p2Target.y });\n push({ x: p2.x, y: p2Target.y });\n } else if (p1.y \u003c= p2.y + overshootAmount) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.5;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p1.y + overshootAmount });\n push({ x: p2.x, y: p1.y + overshootAmount });\n push({ x: p2.x, y: p2.y });\n } else {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.6;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: (p1.y + p2.y) / 2 });\n push({ x: p2.x, y: (p1.y + p2.y) / 2 });\n }\n }\n } else if (startDir === \"x+\" \u0026\u0026 endDir === \"x+\" \u0026\u0026 !yAligned) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 3;\n const commonX = Math.max(p1.x + overshootAmount, p2Target.x);\n push({ x: commonX, y: p1.y });\n push({ x: commonX, y: p2.y });\n } else if (startDir === \"x+\" \u0026\u0026 endDir === \"x+\" \u0026\u0026 yAligned) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 3.1;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p1.y + overshootAmount });\n push({ x: p2.x + overshootAmount, y: p1.y + overshootAmount });\n push({ x: p2.x + overshootAmount, y: p2.y });\n } else if (startDir === \"x+\" \u0026\u0026 endDir === \"y-\") {\n if (xAligned \u0026\u0026 p1.y \u003c= p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.11;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: midY });\n push({ x: p2.x, y: midY });\n } else if (xAligned \u0026\u0026 p1.y \u003e p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.12;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p2.y - overshootAmount });\n push({ x: p2.x, y: p2.y - overshootAmount });\n } else if (p1.x \u003c p2.x \u0026\u0026 p1.y \u003c p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.2;\n push({ x: p2.x, y: p1.y });\n } else {\n if (p1.x \u003e p2.x \u0026\u0026 p1.y \u003c p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.3;\n const p1OvershootX = p1.x + overshootAmount;\n push({ x: p1OvershootX, y: p1.y });\n push({ x: p1OvershootX, y: midY });\n push({ x: p2.x, y: midY });\n } else if (p1.x \u003e p2.x \u0026\u0026 p1.y \u003e p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.4;\n const p1OvershootX = p1.x + overshootAmount;\n push({ x: p1OvershootX, y: p1.y });\n push({ x: p1OvershootX, y: p2Target.y });\n push({ x: p2.x, y: p2Target.y });\n } else if (p1.y === p2.y) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.5;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p1.y - overshootAmount });\n push({ x: p2.x, y: p1.y - overshootAmount });\n } else {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.6;\n push({ x: midX, y: p1.y });\n push({ x: midX, y: p2Target.y });\n push({ x: p2.x, y: p2Target.y });\n }\n }\n } else if (startDir === \"x+\" \u0026\u0026 endDir === \"x-\" \u0026\u0026 p1.x + overshootAmount \u003e= p2.x - overshootAmount \u0026\u0026 !yAligned) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 5;\n const p1OvershootX = p1.x + overshootAmount;\n push({ x: p1OvershootX, y: p1.y });\n push({ x: p1OvershootX, y: midY });\n push({ x: p2Target.x, y: midY });\n push({ x: p2Target.x, y: p2Target.y });\n } else if (startDir === \"x+\" \u0026\u0026 endDir === \"x-\" \u0026\u0026 yAligned \u0026\u0026 p2.x \u003e p1.x) {} else if (startDir === \"x+\" \u0026\u0026 endDir === \"x-\" \u0026\u0026 yAligned) {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 7;\n push({ x: p1.x + overshootAmount, y: p1.y });\n push({ x: p1.x + overshootAmount, y: p1.y + overshootAmount });\n push({ x: p2.x - overshootAmount, y: p1.y + overshootAmount });\n push({ x: p2.x - overshootAmount, y: p1.y });\n } else {\n globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 8;\n if (startDir === \"x+\") {\n push({ x: p1.x + overshootAmount, y: p1.y });\n }\n push({ x: midX, y: result[result.length - 1].y });\n push({ x: midX, y: p2Target.y });\n push({ x: p2Target.x, y: p2Target.y });\n }\n push({ x: p2.x, y: p2.y });\n return result;\n};\n\n// ../../work/placement-analysis/node_modules/calculate-elbow/lib/index.ts\nvar calculateElbow = (point1, point2, options = {}) =\u003e {\n let p1 = point1;\n let p2 = point2;\n let orderFlipped = false;\n if (p1.x \u003e p2.x || p1.x === p2.x \u0026\u0026 p1.y \u003e p2.y) {\n orderFlipped = true;\n [p1, p2] = [p2, p1];\n }\n const mirrorX = p1.facingDirection === \"x-\";\n const mirrorY = p1.facingDirection === \"y-\";\n const mirrorPoint = (pt) =\u003e {\n const x = mirrorX ? p1.x - (pt.x - p1.x) : pt.x;\n const y = mirrorY ? p1.y - (pt.y - p1.y) : pt.y;\n let facing = pt.facingDirection;\n if (mirrorX) {\n if (facing === \"x+\")\n facing = \"x-\";\n else if (facing === \"x-\")\n facing = \"x+\";\n }\n if (mirrorY) {\n if (facing === \"y+\")\n facing = \"y-\";\n else if (facing === \"y-\")\n facing = \"y+\";\n }\n return { x, y, facingDirection: facing };\n };\n const rotateCW = (pt, centre) =\u003e {\n const dx = pt.x - centre.x;\n const dy = pt.y - centre.y;\n const x = centre.x + dy;\n const y = centre.y - dx;\n let facing = pt.facingDirection;\n switch (facing) {\n case \"x+\":\n facing = \"y-\";\n break;\n case \"y-\":\n facing = \"x-\";\n break;\n case \"x-\":\n facing = \"y+\";\n break;\n case \"y+\":\n facing = \"x+\";\n break;\n }\n return { x, y, facingDirection: facing };\n };\n const rotateCCW = (pt, centre) =\u003e {\n const dx = pt.x - centre.x;\n const dy = pt.y - centre.y;\n return { x: centre.x - dy, y: centre.y + dx };\n };\n const mp1 = mirrorX || mirrorY ? mirrorPoint(p1) : p1;\n const mp2 = mirrorX || mirrorY ? mirrorPoint(p2) : p2;\n let rp1 = mp1;\n let rp2 = mp2;\n let rotated = false;\n if (mp1.facingDirection === \"y+\") {\n rotated = true;\n rp1 = { ...mp1, facingDirection: \"x+\" };\n rp2 = rotateCW(mp2, mp1);\n }\n const overshootAmount = options?.overshoot ?? 0.1 * Math.max(Math.abs(rp1.x - rp2.x), Math.abs(rp1.y - rp2.y));\n let result = calculateElbowBends(rp1, rp2, overshootAmount);\n if (rotated) {\n result = result.map((pt) =\u003e rotateCCW(pt, rp1));\n }\n if (mirrorX || mirrorY) {\n result = result.map(({ x, y }) =\u003e ({\n x: mirrorX ? p1.x - (x - p1.x) : x,\n y: mirrorY ? p1.y - (y - p1.y) : y\n }));\n }\n return orderFlipped ? result.reverse() : result;\n};\n\n// ../../work/placement-analysis/lib/utils/schematic-text-geometry.ts\nvar rectPolygon = (bounds) =\u003e [\n { x: bounds.left, y: bounds.bottom },\n { x: bounds.right, y: bounds.bottom },\n { x: bounds.right, y: bounds.top },\n { x: bounds.left, y: bounds.top }\n];\nvar advance = (character) =\u003e {\n if (/\\s/.test(character))\n return 0.28;\n if (/[ilI.,:;!'|]/.test(character))\n return 0.25;\n if (/[MW@%]/.test(character))\n return 0.9;\n if (/[mw]/.test(character))\n return 0.8;\n if (/[A-Z]/.test(character))\n return 0.67;\n return 0.56;\n};\nvar widthInEm = (text) =\u003e Array.from(text).reduce((width, character) =\u003e width + advance(character), 0);\nfunction getSchematicTextPolygons(text) {\n const size2 = text.font_size;\n if (!Number.isFinite(size2) || size2 \u003c= 0 || !Number.isFinite(text.rotation) || !Number.isFinite(text.position.x) || !Number.isFinite(text.position.y))\n return [];\n const anchor = text.anchor;\n const horizontal = anchor.includes(\"left\") ? 0 : anchor.includes(\"right\") ? 1 : 0.5;\n const top = anchor.includes(\"top\") ? 0 : anchor.includes(\"bottom\") ? size2 : size2 / 2;\n const radians = -text.rotation * Math.PI / 180;\n const cos = Math.cos(radians);\n const sin = Math.sin(radians);\n return text.text.split(`\n`).flatMap((line, index) =\u003e {\n const visible = line.trim();\n if (!visible)\n return [];\n const leading = line.length - line.trimStart().length;\n const left = (widthInEm(line.slice(0, leading)) - widthInEm(line) * horizontal) * size2;\n const polygon = rectPolygon({\n left,\n right: left + widthInEm(visible) * size2,\n top: top - index * size2 - size2 * 0.05,\n bottom: top - (index + 1) * size2 + size2 * 0.05\n });\n return [\n polygon.map(({ x, y }) =\u003e ({\n x: text.position.x + x * cos - y * sin,\n y: text.position.y + x * sin + y * cos\n }))\n ];\n });\n}\nfunction polygonsOverlap(a, b) {\n for (const polygon of [a, b]) {\n for (let i = 0;i \u003c polygon.length; i++) {\n const p = polygon[i];\n const q = polygon[(i + 1) % polygon.length];\n const length2 = Math.hypot(q.x - p.x, q.y - p.y);\n if (length2 \u003c 0.000000001)\n continue;\n const nx = -(q.y - p.y) / length2;\n const ny = (q.x - p.x) / length2;\n const project = (points) =\u003e points.map(({ x, y }) =\u003e x * nx + y * ny);\n const pa = project(a);\n const pb = project(b);\n if (Math.min(Math.max(...pa), Math.max(...pb)) - Math.max(Math.min(...pa), Math.min(...pb)) \u003c= 0.000001)\n return false;\n }\n }\n return true;\n}\nfunction traceSegmentPolygon(from, to) {\n const length2 = Math.hypot(to.x - from.x, to.y - from.y);\n if (length2 \u003c 0.000000001)\n return;\n const dx = -(to.y - from.y) / length2 * 0.01;\n const dy = (to.x - from.x) / length2 * 0.01;\n return [\n { x: from.x + dx, y: from.y + dy },\n { x: to.x + dx, y: to.y + dy },\n { x: to.x - dx, y: to.y - dy },\n { x: from.x - dx, y: from.y - dy }\n ];\n}\nfunction segmentCrossesPolygon(from, to, polygon) {\n if (Math.hypot(to.x - from.x, to.y - from.y) \u003c 0.000000001)\n return false;\n let low = 0;\n let high = 1;\n for (let i = 0;i \u003c polygon.length; i++) {\n const p = polygon[i];\n const q = polygon[(i + 1) % polygon.length];\n const length2 = Math.hypot(q.x - p.x, q.y - p.y);\n if (length2 \u003c 0.000000001)\n continue;\n const nx = -(q.y - p.y) / length2;\n const ny = (q.x - p.x) / length2;\n const start = (from.x - p.x) * nx + (from.y - p.y) * ny - 0.000001;\n const end = (to.x - p.x) * nx + (to.y - p.y) * ny - 0.000001;\n if (start \u003c= 0 \u0026\u0026 end \u003c= 0)\n return false;\n if (start \u003c= 0)\n low = Math.max(low, -start / (end - start));\n if (end \u003c= 0)\n high = Math.min(high, -start / (end - start));\n if (high \u003c= low)\n return false;\n }\n return high \u003e low;\n}\nvar polygonBounds = (polygons) =\u003e {\n const points = polygons.flat();\n return {\n left: Math.min(...points.map((p) =\u003e p.x)),\n right: Math.max(...points.map((p) =\u003e p.x)),\n top: Math.max(...points.map((p) =\u003e p.y)),\n bottom: Math.min(...points.map((p) =\u003e p.y))\n };\n};\n\n// ../../work/placement-analysis/lib/solvers/TraceSimplificationSolver/TraceSimplificationSolver.ts\nclass TraceSimplificationSolver extends BaseSolver {\n static EPSILON = 0.01;\n ctx;\n out;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.ctx = ctx;\n this.out = issues;\n }\n _step() {\n const ports = this.ctx.circuitJson.filter((element) =\u003e element.type === \"schematic_port\");\n const portsById = new Map(ports.map((port) =\u003e [port.schematic_port_id, port]));\n const placementsByComponentId = new Map(this.ctx.componentPlacements.flatMap((placement) =\u003e placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));\n const emittedMoves = new Set;\n for (const trace of this.ctx.circuitJson.filter((element) =\u003e element.type === \"schematic_trace\")) {\n const points = this.getTracePoints(trace);\n const currentTurnCount = this.countTurns(points);\n if (currentTurnCount !== 3)\n continue;\n const candidates = [\n this.getCandidate({\n trace,\n points,\n atStart: true,\n currentTurnCount,\n ports,\n portsById,\n placementsByComponentId\n }),\n this.getCandidate({\n trace,\n points,\n atStart: false,\n currentTurnCount,\n ports,\n portsById,\n placementsByComponentId\n })\n ].filter((candidate) =\u003e Boolean(candidate));\n for (const candidate of [...candidates]) {\n if (!candidate.target.sourceComponentName?.startsWith(\"U\"))\n continue;\n for (const point2 of [points[0], points.at(-1)]) {\n const port = this.findPortAtPoint(ports, point2, trace.schematic_sheet_id);\n const target = port?.schematic_component_id ? placementsByComponentId.get(port.schematic_component_id) : undefined;\n if (!target || !/^[CR]/.test(target.sourceComponentName ?? \"\"))\n continue;\n candidates.push({\n target,\n deltaSchX: -candidate.deltaSchX,\n deltaSchY: -candidate.deltaSchY,\n currentTurnCount,\n suggestedTurnCount: candidate.suggestedTurnCount\n });\n }\n }\n const priority = (candidate) =\u003e /^[CR]/.test(candidate.target.sourceComponentName ?? \"\") ? 0 : candidate.target.sourceComponentName?.startsWith(\"U\") ? 2 : 1;\n candidates.sort((a, b) =\u003e priority(a) - priority(b));\n for (const candidate of candidates) {\n if (this.wouldOverlapAnotherComponent(candidate))\n continue;\n if (!this.validateMove(trace, candidate, ports))\n continue;\n const moveKey = [\n candidate.target.schematicComponentId,\n candidate.deltaSchX.toFixed(3),\n candidate.deltaSchY.toFixed(3)\n ].join(\"\\x00\");\n if (emittedMoves.has(moveKey))\n break;\n emittedMoves.add(moveKey);\n this.out.push(this.makeIssue(trace, candidate));\n break;\n }\n }\n this.solved = true;\n }\n getCandidate({\n trace,\n points,\n atStart,\n currentTurnCount,\n ports,\n portsById,\n placementsByComponentId\n }) {\n if (points.length \u003c 4)\n return;\n const terminalIndex = atStart ? 0 : points.length - 1;\n const leadIndex = atStart ? 1 : points.length - 2;\n const acrossIndex = atStart ? 2 : points.length - 3;\n const retainedIndex = atStart ? 3 : points.length - 4;\n const terminalPoint = points[terminalIndex];\n const leadPoint = points[leadIndex];\n const acrossPoint = points[acrossIndex];\n const retainedPoint = points[retainedIndex];\n const terminalEdge = atStart ? trace.edges[0] : trace.edges.at(-1);\n if (!terminalEdge)\n return;\n const portId = atStart ? terminalEdge.from_schematic_port_id : terminalEdge.to_schematic_port_id;\n const port = portId ? portsById.get(portId) : this.findPortAtPoint(ports, terminalPoint, trace.schematic_sheet_id);\n if (!port?.schematic_component_id || !port.facing_direction)\n return;\n const leadAxis = this.getAxis(terminalPoint, leadPoint);\n const shiftAxis = this.getAxis(leadPoint, acrossPoint);\n const retainedAxis = this.getAxis(acrossPoint, retainedPoint);\n const portAxis = port.facing_direction === \"left\" || port.facing_direction === \"right\" ? \"horizontal\" : \"vertical\";\n if (!leadAxis || !shiftAxis || !retainedAxis)\n return;\n if (leadAxis !== portAxis || shiftAxis === portAxis || retainedAxis !== portAxis) {\n return;\n }\n if (!this.isPointInFacingDirection(terminalPoint, leadPoint, port.facing_direction) || !this.isPointInFacingDirection(acrossPoint, retainedPoint, port.facing_direction)) {\n return;\n }\n const target = placementsByComponentId.get(port.schematic_component_id);\n if (!target)\n return;\n const deltaSchX = acrossPoint.x - leadPoint.x;\n const deltaSchY = acrossPoint.y - leadPoint.y;\n if (Math.abs(deltaSchX) \u003c= TraceSimplificationSolver.EPSILON \u0026\u0026 Math.abs(deltaSchY) \u003c= TraceSimplificationSolver.EPSILON) {\n return;\n }\n const movedTerminalPoint = {\n x: terminalPoint.x + deltaSchX,\n y: terminalPoint.y + deltaSchY\n };\n const suggestedPoints = atStart ? [movedTerminalPoint, ...points.slice(2)] : [...points.slice(0, -2), movedTerminalPoint];\n const suggestedTurnCount = this.countTurns(suggestedPoints);\n if (suggestedTurnCount === undefined || suggestedTurnCount !== 1 || suggestedTurnCount \u003e= currentTurnCount) {\n return;\n }\n return {\n target,\n deltaSchX,\n deltaSchY,\n currentTurnCount,\n suggestedTurnCount\n };\n }\n validateMove(targetTrace, candidate, ports) {\n const componentId = candidate.target.schematicComponentId;\n const sheetId = candidate.target.schematicSheetId;\n const sheetPorts = ports.filter((p) =\u003e p.schematic_sheet_id === sheetId);\n const movingPorts = sheetPorts.filter((p) =\u003e p.schematic_component_id === componentId);\n const traces = this.ctx.circuitJson.filter((e) =\u003e e.type === \"schematic_trace\" \u0026\u0026 e.schematic_sheet_id === sheetId);\n const touchesPort = (trace, port) =\u003e trace.edges.some((edge) =\u003e edge.from_schematic_port_id === port.schematic_port_id || edge.to_schematic_port_id === port.schematic_port_id || this.pointsEqual(edge.from, port.center) || this.pointsEqual(edge.to, port.center));\n const affected = traces.filter((trace) =\u003e movingPorts.some((port) =\u003e touchesPort(trace, port)));\n if (!affected.includes(targetTrace))\n return false;\n if (this.ctx.circuitJson.some((e) =\u003e e.type === \"schematic_net_label\" \u0026\u0026 e.schematic_sheet_id === sheetId \u0026\u0026 movingPorts.some((p) =\u003e this.pointsEqual(e.anchor_position ?? e.center, p.center))))\n return false;\n const shift = (point2) =\u003e ({\n x: point2.x + candidate.deltaSchX,\n y: point2.y + candidate.deltaSchY\n });\n const directions2 = {\n left: \"x-\",\n right: \"x+\",\n up: \"y+\",\n down: \"y-\"\n };\n const endpoint = (port, moved) =\u003e ({\n ...moved \u0026\u0026 port.schematic_component_id === componentId ? shift(port.center) : port.center,\n facingDirection: directions2[port.facing_direction]\n });\n const length2 = (points) =\u003e points.slice(1).reduce((sum, p, i) =\u003e sum + Math.abs(p.x - points[i].x) + Math.abs(p.y - points[i].y), 0);\n const segments = (points) =\u003e points.slice(1).map((to, i) =\u003e ({ from: points[i], to }));\n const movedBounds = centeredRect(candidate.target.schX + candidate.deltaSchX, candidate.target.schY + candidate.deltaSchY, candidate.target.width, candidate.target.height);\n const unaffected = traces.filter((trace) =\u003e !affected.includes(trace));\n if (unaffected.some((trace) =\u003e trace.edges.some((edge) =\u003e segmentCrossesPolygon(edge.from, edge.to, rectPolygon(movedBounds)))))\n return false;\n const textPolygons = this.ctx.circuitJson.flatMap((e) =\u003e {\n if (e.type === \"schematic_net_label\" \u0026\u0026 e.schematic_sheet_id === sheetId)\n return [rectPolygon(getNetLabelBounds(e))];\n if (e.type !== \"schematic_text\" || e.schematic_sheet_id !== sheetId)\n return [];\n return getSchematicTextPolygons(e.schematic_component_id === componentId ? { ...e, position: shift(e.position) } : e);\n });\n if (textPolygons.some((polygon) =\u003e polygonsOverlap(polygon, rectPolygon(movedBounds))))\n return false;\n const proposed = [];\n for (const trace of affected) {\n const oldPoints = this.getTracePoints(trace);\n if (oldPoints.length \u003c 2 || trace.junctions?.length)\n return false;\n const resolve = (point2, id) =\u003e {\n const matches = sheetPorts.filter((p) =\u003e id ? p.schematic_port_id === id : this.pointsEqual(p.center, point2));\n return matches.length === 1 \u0026\u0026 this.pointsEqual(matches[0].center, point2) ? matches[0] : undefined;\n };\n const start = resolve(oldPoints[0], trace.edges[0].from_schematic_port_id);\n const end = resolve(oldPoints.at(-1), trace.edges.at(-1).to_schematic_port_id);\n if (!start?.facing_direction || !end?.facing_direction)\n return false;\n if (movingPorts.some((p) =\u003e touchesPort(trace, p) \u0026\u0026 p !== start \u0026\u0026 p !== end))\n return false;\n const isInteriorConnection = (point2) =\u003e !this.pointsEqual(point2, start.center) \u0026\u0026 !this.pointsEqual(point2, end.center) \u0026\u0026 segments(oldPoints).some(({ from, to }) =\u003e Math.abs(Math.hypot(point2.x - from.x, point2.y - from.y) + Math.hypot(point2.x - to.x, point2.y - to.y) - Math.hypot(to.x - from.x, to.y - from.y)) \u003c 0.000001);\n if (traces.some((other) =\u003e other !== trace \u0026\u0026 other.edges.some((edge) =\u003e isInteriorConnection(edge.from) || isInteriorConnection(edge.to))))\n return false;\n if (this.ctx.circuitJson.some((e) =\u003e e.type === \"schematic_net_label\" \u0026\u0026 e.schematic_sheet_id === sheetId \u0026\u0026 isInteriorConnection(e.anchor_position ?? e.center)))\n return false;\n const points = calculateElbow(endpoint(start, true), endpoint(end, true)).filter((point2, i, all) =\u003e i === 0 || !this.pointsEqual(point2, all[i - 1]));\n const turns = this.countTurns(points);\n const oldTurns = this.countTurns(oldPoints);\n if (points.length \u003c 2 || turns === undefined || oldTurns === undefined || turns \u003e oldTurns || length2(points) \u003e length2(oldPoints) + 0.000001)\n return false;\n if (!this.isPointInFacingDirection(points[0], points[1], start.facing_direction) || !this.isPointInFacingDirection(points.at(-1), points.at(-2), end.facing_direction))\n return false;\n if (trace === targetTrace) {\n const baselineTurns = this.countTurns(calculateElbow(endpoint(start, false), endpoint(end, false)));\n if (turns \u003e= oldTurns || baselineTurns === undefined || turns \u003e= baselineTurns)\n return false;\n candidate.suggestedTurnCount = turns;\n }\n for (const segment of segments(points)) {\n if (textPolygons.some((polygon2) =\u003e segmentCrossesPolygon(segment.from, segment.to, polygon2)))\n return false;\n if (this.ctx.componentPlacements.some((p) =\u003e {\n if (p.schematicSheetId !== sheetId)\n return false;\n const bounds = p.schematicComponentId === componentId ? movedBounds : centeredRect(p.schX, p.schY, p.width, p.height);\n return segmentCrossesPolygon(segment.from, segment.to, rectPolygon(bounds));\n }))\n return false;\n const polygon = traceSegmentPolygon(segment.from, segment.to);\n if (!polygon)\n continue;\n const otherSegments = [\n ...unaffected.flatMap((t) =\u003e t.edges),\n ...proposed.flatMap((t) =\u003e segments(t.points))\n ];\n if (otherSegments.some((edge) =\u003e {\n if ([start, end].some((port) =\u003e port.schematic_component_id !== componentId \u0026\u0026 [segment.from, segment.to].some((p) =\u003e this.pointsEqual(p, port.center)) \u0026\u0026 [edge.from, edge.to].some((p) =\u003e this.pointsEqual(p, port.center))) \u0026\u0026 this.getAxis(segment.from, segment.to) !== this.getAxis(edge.from, edge.to))\n return false;\n const other = traceSegmentPolygon(edge.from, edge.to);\n return other \u0026\u0026 polygonsOverlap(polygon, other);\n }))\n return false;\n }\n proposed.push({ schematicTraceId: trace.schematic_trace_id, points });\n }\n candidate.suggestedTraces = proposed;\n return true;\n }\n getTracePoints(trace) {\n const firstEdge = trace.edges[0];\n if (!firstEdge)\n return [];\n const points = [firstEdge.from];\n for (const edge of trace.edges) {\n const previousPoint = points.at(-1);\n if (!this.pointsEqual(previousPoint, edge.from))\n return [];\n points.push(edge.to);\n }\n return points;\n }\n countTurns(points) {\n const axes = [];\n for (const [index, point2] of points.slice(1).entries()) {\n const previousPoint = points[index];\n if (this.pointsEqual(previousPoint, point2))\n continue;\n const axis = this.getAxis(previousPoint, point2);\n if (!axis)\n return;\n axes.push(axis);\n }\n return axes.slice(1).filter((axis, index) =\u003e axis !== axes[index]).length;\n }\n pointsEqual(a, b) {\n const { EPSILON: EPSILON3 } = TraceSimplificationSolver;\n return Math.abs(a.x - b.x) \u003c= EPSILON3 \u0026\u0026 Math.abs(a.y - b.y) \u003c= EPSILON3;\n }\n getAxis(a, b) {\n const dx = Math.abs(b.x - a.x);\n const dy = Math.abs(b.y - a.y);\n const { EPSILON: EPSILON3 } = TraceSimplificationSolver;\n if (dx \u003c= EPSILON3 \u0026\u0026 dy \u003e EPSILON3)\n return \"vertical\";\n if (dy \u003c= EPSILON3 \u0026\u0026 dx \u003e EPSILON3)\n return \"horizontal\";\n return;\n }\n isPointInFacingDirection(origin, point2, facingDirection) {\n const { EPSILON: EPSILON3 } = TraceSimplificationSolver;\n switch (facingDirection) {\n case \"left\":\n return point2.x \u003c origin.x - EPSILON3;\n case \"right\":\n return point2.x \u003e origin.x + EPSILON3;\n case \"up\":\n return point2.y \u003e origin.y + EPSILON3;\n case \"down\":\n return point2.y \u003c origin.y - EPSILON3;\n }\n }\n findPortAtPoint(ports, point2, schematicSheetId) {\n const { EPSILON: EPSILON3 } = TraceSimplificationSolver;\n return ports.find((port) =\u003e port.schematic_sheet_id === schematicSheetId \u0026\u0026 Math.abs(port.center.x - point2.x) \u003c= EPSILON3 \u0026\u0026 Math.abs(port.center.y - point2.y) \u003c= EPSILON3);\n }\n wouldOverlapAnotherComponent(candidate) {\n const movedBounds = centeredRect(candidate.target.schX + candidate.deltaSchX, candidate.target.schY + candidate.deltaSchY, candidate.target.width, candidate.target.height);\n return this.ctx.componentPlacements.some((placement) =\u003e {\n if (placement === candidate.target)\n return false;\n if (placement.schematicSheetId !== candidate.target.schematicSheetId) {\n return false;\n }\n return Boolean(rectOverlap(movedBounds, centeredRect(placement.schX, placement.schY, placement.width, placement.height)));\n });\n }\n makeIssue(trace, candidate) {\n const targetName = candidate.target.sourceComponentName ?? candidate.target.schematicComponentId ?? \"component\";\n const direction = this.getMoveDirection(candidate.deltaSchX, candidate.deltaSchY);\n const distance5 = Math.abs(candidate.deltaSchX || candidate.deltaSchY);\n const newSchX = candidate.target.schX + candidate.deltaSchX;\n const newSchY = candidate.target.schY + candidate.deltaSchY;\n return {\n lineItemType: \"TraceCanBeSimplifiedByMovingComponent\",\n schematicTraceId: trace.schematic_trace_id,\n traceName: getTraceName(this.ctx.circuitJson, trace),\n targetComponent: candidate.target,\n deltaSchX: candidate.deltaSchX,\n deltaSchY: candidate.deltaSchY,\n newSchX,\n newSchY,\n currentTurnCount: candidate.currentTurnCount,\n suggestedTurnCount: candidate.suggestedTurnCount,\n suggestedTraces: candidate.suggestedTraces,\n message: `move ${targetName} ${direction} by ${fmtNumber(distance5)} (to schX=${fmtNumber(newSchX)}, schY=${fmtNumber(newSchY)}) to reduce this trace from ${candidate.currentTurnCount} turns to ${candidate.suggestedTurnCount}`\n };\n }\n getMoveDirection(deltaSchX, deltaSchY) {\n if (Math.abs(deltaSchX) \u003e TraceSimplificationSolver.EPSILON) {\n return deltaSchX \u003e 0 ? \"right\" : \"left\";\n }\n return deltaSchY \u003e 0 ? \"up\" : \"down\";\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"traceName\", issue.traceName);\n addAttr(attrs, \"targetComponentName\", issue.targetComponent.sourceComponentName);\n addAttr(attrs, \"deltaSchX\", issue.deltaSchX, { formatDelta: true });\n addAttr(attrs, \"deltaSchY\", issue.deltaSchY, { formatDelta: true });\n addAttr(attrs, \"newSchX\", issue.newSchX);\n addAttr(attrs, \"newSchY\", issue.newSchY);\n addAttr(attrs, \"currentTurnCount\", issue.currentTurnCount);\n addAttr(attrs, \"suggestedTurnCount\", issue.suggestedTurnCount);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cTraceCanBeSimplifiedByMovingComponent ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/getPowerOrGroundConnectionIds.ts\nfunction getPowerOrGroundConnectionIds(circuitJson) {\n const powerOrGroundIds = new Set;\n const idsByConnectivityKey = new Map;\n for (const element of circuitJson) {\n if (element.type !== \"source_net\" \u0026\u0026 element.type !== \"source_port\")\n continue;\n const id = element.type === \"source_net\" ? element.source_net_id : element.source_port_id;\n const isPowerOrGround = element.type === \"source_net\" ? element.is_power || element.is_ground || element.is_positive_voltage_source : element.provides_power || element.requires_power || element.provides_ground || element.requires_ground;\n if (isPowerOrGround)\n powerOrGroundIds.add(id);\n const key = element.subcircuit_connectivity_map_key;\n if (key !== undefined) {\n const ids = idsByConnectivityKey.get(key) ?? [];\n ids.push(id);\n idsByConnectivityKey.set(key, ids);\n }\n }\n const sourceConnectivity = getSourcePortConnectivityMapFromCircuitJson(circuitJson);\n const networks = findConnectedNetworks([\n ...Object.values(sourceConnectivity.netMap),\n ...idsByConnectivityKey.values()\n ]);\n for (const ids of Object.values(networks)) {\n if (ids.some((id) =\u003e powerOrGroundIds.has(id))) {\n for (const id of ids)\n powerOrGroundIds.add(id);\n }\n }\n return powerOrGroundIds;\n}\n\n// ../../work/placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/TwoPinComponentOrientationSolver.ts\nclass TwoPinComponentOrientationSolver extends BaseSolver {\n static EPSILON = 0.01;\n ctx;\n out;\n powerOrGroundConnectionIds;\n constructor({\n ctx,\n issues\n }) {\n super();\n this.ctx = ctx;\n this.out = issues;\n this.powerOrGroundConnectionIds = getPowerOrGroundConnectionIds(ctx.circuitJson);\n }\n _step() {\n const ports = this.ctx.circuitJson.filter((element) =\u003e element.type === \"schematic_port\");\n const portsById = new Map(ports.map((port) =\u003e [port.schematic_port_id, port]));\n const portsByComponentId = new Map;\n for (const port of ports) {\n if (!port.schematic_component_id)\n continue;\n const componentPorts = portsByComponentId.get(port.schematic_component_id) ?? [];\n componentPorts.push(port);\n portsByComponentId.set(port.schematic_component_id, componentPorts);\n }\n const placementsByComponentId = new Map(this.ctx.componentPlacements.flatMap((placement) =\u003e placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));\n const bestCandidateByComponentId = new Map;\n for (const trace of this.ctx.circuitJson.filter((element) =\u003e element.type === \"schematic_trace\")) {\n const points = this.getTracePoints(trace);\n const currentTurnCount = this.countTurns(points);\n if (currentTurnCount === undefined || currentTurnCount \u003c 2)\n continue;\n const endpoints = this.getTraceEndpoints(trace, points, ports, portsById);\n if (!endpoints)\n continue;\n for (const [targetEndpoint, connectedEndpoint] of [\n endpoints,\n [endpoints[1], endpoints[0]]\n ]) {\n const candidate = this.getFlipCandidate({\n trace,\n targetEndpoint,\n connectedEndpoint,\n currentTurnCount,\n portsByComponentId,\n placementsByComponentId\n });\n if (!candidate)\n continue;\n const componentId = candidate.targetPort.schematic_component_id;\n const existing = bestCandidateByComponentId.get(componentId);\n if (!existing || this.isBetterCandidate(candidate, existing)) {\n bestCandidateByComponentId.set(componentId, candidate);\n }\n }\n }\n for (const candidate of bestCandidateByComponentId.values()) {\n this.out.push(this.makeIssue(candidate));\n }\n this.solved = true;\n }\n getFlipCandidate({\n trace,\n targetEndpoint,\n connectedEndpoint,\n currentTurnCount,\n portsByComponentId,\n placementsByComponentId\n }) {\n const targetPort = targetEndpoint.port;\n const connectedPort = connectedEndpoint.port;\n const targetComponentId = targetPort.schematic_component_id;\n const connectedComponentId = connectedPort.schematic_component_id;\n if (!targetComponentId || !connectedComponentId || targetComponentId === connectedComponentId || targetPort.schematic_sheet_id !== connectedPort.schematic_sheet_id) {\n return;\n }\n const componentPorts = portsByComponentId.get(targetComponentId);\n if (componentPorts?.length !== 2)\n return;\n if (componentPorts.some((port) =\u003e port.source_port_id \u0026\u0026 this.powerOrGroundConnectionIds.has(port.source_port_id))) {\n return;\n }\n const connectedComponentPorts = portsByComponentId.get(connectedComponentId) ?? [];\n if (connectedComponentPorts.length \u003c= 2)\n return;\n const otherPort = componentPorts.find((port) =\u003e port.schematic_port_id !== targetPort.schematic_port_id);\n if (!otherPort || !this.areOppositePorts(targetPort, otherPort))\n return;\n const currentFacingDirection = targetPort.facing_direction;\n const suggestedFacingDirection = otherPort.facing_direction;\n if (!currentFacingDirection || !suggestedFacingDirection)\n return;\n if (!this.traceLeavesPortInFacingDirection(targetEndpoint))\n return;\n const connectedPoint = connectedPort.center;\n if (this.isPointInFacingDirection(targetPort.center, connectedPoint, currentFacingDirection) || !this.isPointInFacingDirection(otherPort.center, connectedPoint, suggestedFacingDirection) || !connectedPort.facing_direction || !this.isPointInFacingDirection(connectedPoint, otherPort.center, connectedPort.facing_direction)) {\n return;\n }\n const suggestedTurnCount = this.getMinimumTurnCount(otherPort.center, connectedPoint, suggestedFacingDirection);\n if (suggestedTurnCount \u003e= currentTurnCount)\n return;\n const targetPlacement = placementsByComponentId.get(targetComponentId);\n const connectedPlacement = placementsByComponentId.get(connectedComponentId);\n if (!targetPlacement || !connectedPlacement)\n return;\n return {\n trace,\n targetPort,\n targetPlacement,\n connectedPlacement,\n suggestedFacingDirection,\n currentTurnCount,\n suggestedTurnCount,\n traceLength: this.getTraceLength(targetEndpoint.pointsFromEndpoint)\n };\n }\n getTraceEndpoints(trace, points, ports, portsById) {\n const firstEdge = trace.edges[0];\n const lastEdge = trace.edges.at(-1);\n if (!firstEdge || !lastEdge || points.length \u003c 2)\n return;\n const startPort = firstEdge.from_schematic_port_id ? portsById.get(firstEdge.from_schematic_port_id) : this.findPortAtPoint(ports, points[0], trace.schematic_sheet_id);\n const endPort = lastEdge.to_schematic_port_id ? portsById.get(lastEdge.to_schematic_port_id) : this.findPortAtPoint(ports, points.at(-1), trace.schematic_sheet_id);\n if (!startPort || !endPort)\n return;\n return [\n { port: startPort, pointsFromEndpoint: points },\n { port: endPort, pointsFromEndpoint: [...points].reverse() }\n ];\n }\n getTracePoints(trace) {\n const firstEdge = trace.edges[0];\n if (!firstEdge)\n return [];\n const points = [firstEdge.from];\n for (const edge of trace.edges) {\n if (!this.pointsEqual(points.at(-1), edge.from))\n return [];\n points.push(edge.to);\n }\n return points;\n }\n countTurns(points) {\n const axes = [];\n for (const [index, point2] of points.slice(1).entries()) {\n const previousPoint = points[index];\n if (this.pointsEqual(previousPoint, point2))\n continue;\n const axis = this.getAxis(previousPoint, point2);\n if (!axis)\n return;\n if (axes.at(-1) !== axis)\n axes.push(axis);\n }\n return Math.max(0, axes.length - 1);\n }\n traceLeavesPortInFacingDirection(endpoint) {\n const nextPoint = endpoint.pointsFromEndpoint.find((point2) =\u003e !this.pointsEqual(point2, endpoint.port.center));\n return Boolean(nextPoint \u0026\u0026 endpoint.port.facing_direction \u0026\u0026 this.isPointInFacingDirection(endpoint.port.center, nextPoint, endpoint.port.facing_direction));\n }\n areOppositePorts(a, b) {\n const horizontal = (a.facing_direction === \"left\" \u0026\u0026 b.facing_direction === \"right\" || a.facing_direction === \"right\" \u0026\u0026 b.facing_direction === \"left\") \u0026\u0026 Math.abs(a.center.y - b.center.y) \u003c= TwoPinComponentOrientationSolver.EPSILON;\n const vertical = (a.facing_direction === \"up\" \u0026\u0026 b.facing_direction === \"down\" || a.facing_direction === \"down\" \u0026\u0026 b.facing_direction === \"up\") \u0026\u0026 Math.abs(a.center.x - b.center.x) \u003c= TwoPinComponentOrientationSolver.EPSILON;\n return horizontal || vertical;\n }\n getMinimumTurnCount(from, to, facingDirection) {\n const alignedWithFacingAxis = facingDirection === \"left\" || facingDirection === \"right\" ? Math.abs(from.y - to.y) \u003c= TwoPinComponentOrientationSolver.EPSILON : Math.abs(from.x - to.x) \u003c= TwoPinComponentOrientationSolver.EPSILON;\n return alignedWithFacingAxis ? 0 : 1;\n }\n isPointInFacingDirection(origin, point2, facingDirection) {\n const { EPSILON: EPSILON3 } = TwoPinComponentOrientationSolver;\n switch (facingDirection) {\n case \"left\":\n return point2.x \u003c origin.x - EPSILON3;\n case \"right\":\n return point2.x \u003e origin.x + EPSILON3;\n case \"up\":\n return point2.y \u003e origin.y + EPSILON3;\n case \"down\":\n return point2.y \u003c origin.y - EPSILON3;\n }\n }\n getAxis(a, b) {\n const dx = Math.abs(a.x - b.x);\n const dy = Math.abs(a.y - b.y);\n const { EPSILON: EPSILON3 } = TwoPinComponentOrientationSolver;\n if (dx \u003c= EPSILON3 \u0026\u0026 dy \u003e EPSILON3)\n return \"vertical\";\n if (dy \u003c= EPSILON3 \u0026\u0026 dx \u003e EPSILON3)\n return \"horizontal\";\n return;\n }\n pointsEqual(a, b) {\n const { EPSILON: EPSILON3 } = TwoPinComponentOrientationSolver;\n return Math.abs(a.x - b.x) \u003c= EPSILON3 \u0026\u0026 Math.abs(a.y - b.y) \u003c= EPSILON3;\n }\n findPortAtPoint(ports, point2, schematicSheetId) {\n return ports.find((port) =\u003e port.schematic_sheet_id === schematicSheetId \u0026\u0026 this.pointsEqual(port.center, point2));\n }\n getTraceLength(points) {\n return points.slice(1).reduce((length2, point2, index) =\u003e {\n const previousPoint = points[index];\n return length2 + Math.abs(point2.x - previousPoint.x) + Math.abs(point2.y - previousPoint.y);\n }, 0);\n }\n isBetterCandidate(candidate, existing) {\n const improvement = candidate.currentTurnCount - candidate.suggestedTurnCount;\n const existingImprovement = existing.currentTurnCount - existing.suggestedTurnCount;\n return improvement \u003e existingImprovement || improvement === existingImprovement \u0026\u0026 candidate.traceLength \u003e existing.traceLength;\n }\n makeIssue(candidate) {\n const targetName = candidate.targetPlacement.sourceComponentName ?? candidate.targetPlacement.schematicComponentId ?? \"component\";\n const connectedName = candidate.connectedPlacement.sourceComponentName ?? candidate.connectedPlacement.schematicComponentId ?? \"connected component\";\n const targetPin = candidate.targetPort.pin_number ? `pin${candidate.targetPort.pin_number}` : candidate.targetPort.display_pin_label;\n return {\n lineItemType: \"TwoPinComponentCouldBeFlipped\",\n schematicTraceId: candidate.trace.schematic_trace_id,\n traceName: getTraceName(this.ctx.circuitJson, candidate.trace),\n targetComponent: candidate.targetPlacement,\n connectedComponent: candidate.connectedPlacement,\n targetPin,\n currentFacingDirection: candidate.targetPort.facing_direction,\n suggestedFacingDirection: candidate.suggestedFacingDirection,\n deltaSchRotation: 180,\n currentTurnCount: candidate.currentTurnCount,\n suggestedTurnCount: candidate.suggestedTurnCount,\n message: `rotate ${targetName} by 180° so ${targetPin ?? \"its connected pin\"} faces ${connectedName} and reduce this trace from ${candidate.currentTurnCount} turns to ${candidate.suggestedTurnCount}`\n };\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"traceName\", issue.traceName);\n addAttr(attrs, \"targetComponentName\", issue.targetComponent.sourceComponentName);\n addAttr(attrs, \"connectedComponentName\", issue.connectedComponent.sourceComponentName);\n addAttr(attrs, \"targetPin\", issue.targetPin);\n addAttr(attrs, \"currentFacingDirection\", issue.currentFacingDirection);\n addAttr(attrs, \"suggestedFacingDirection\", issue.suggestedFacingDirection);\n addAttr(attrs, \"deltaSchRotation\", issue.deltaSchRotation);\n addAttr(attrs, \"currentTurnCount\", issue.currentTurnCount);\n addAttr(attrs, \"suggestedTurnCount\", issue.suggestedTurnCount);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cTwoPinComponentCouldBeFlipped ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/VerboseNetLabelSolver/VerboseNetLabelSolver.ts\nclass VerboseNetLabelSolver extends BaseSolver {\n params;\n VERBOSE_NET_LABEL_MESSAGE = \"Create trace with schDisplayLabel\";\n netLabels;\n tokenToInvolvedPin;\n schematicSheetNameById;\n currentIndex = 0;\n seen = new Set;\n constructor(params) {\n super();\n this.params = params;\n const { circuitJson } = params.ctx;\n this.netLabels = circuitJson.filter((el) =\u003e this.isSchematicNetLabel(el));\n this.tokenToInvolvedPin = this.buildTokenToInvolvedPinMap(circuitJson);\n this.schematicSheetNameById = getSchematicSheetNamesById(circuitJson);\n this.solved = this.netLabels.length === 0;\n }\n _step() {\n const label = this.netLabels[this.currentIndex++];\n if (!label) {\n this.solved = true;\n return;\n }\n this.solved = this.currentIndex \u003e= this.netLabels.length;\n const seenKey = `${label.schematic_sheet_id ?? \"\"}:${label.text}`;\n if (!label.text.includes(\"/\") || this.seen.has(seenKey))\n return;\n this.seen.add(seenKey);\n let schematicSheetName;\n if (label.schematic_sheet_id) {\n schematicSheetName = this.schematicSheetNameById.get(label.schematic_sheet_id);\n }\n const issue = {\n lineItemType: \"VerboseSchematicNetLabel\",\n schematicNetLabelId: label.schematic_net_label_id,\n sourceNetId: label.source_net_id,\n schematicSheetId: label.schematic_sheet_id,\n schematicSheetName,\n text: label.text,\n involvedPins: this.getInvolvedPins(label.text, this.tokenToInvolvedPin),\n schX: label.center.x,\n schY: label.center.y,\n message: this.VERBOSE_NET_LABEL_MESSAGE\n };\n this.params.issues.push(issue);\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"message\", issue.message);\n addAttr(attrs, \"text\", issue.text);\n addAttr(attrs, \"involvedPins\", issue.involvedPins.join(\",\"));\n addAttr(attrs, \"schSheetName\", issue.schematicSheetName);\n addAttr(attrs, \"schX\", issue.schX);\n addAttr(attrs, \"schY\", issue.schY);\n return `\u003cVerboseSchematicNetLabel ${attrs.join(\" \")} /\u003e`;\n }\n isSchematicNetLabel(el) {\n return el.type === \"schematic_net_label\";\n }\n isSourcePort(el) {\n return el.type === \"source_port\";\n }\n getSourceComponentWithName(el) {\n if (el.type !== \"source_component\" || !(\"source_component_id\" in el) || !(\"name\" in el) || typeof el.source_component_id !== \"string\" || typeof el.name !== \"string\")\n return null;\n return { source_component_id: el.source_component_id, name: el.name };\n }\n getSourcePortNameCandidates(port) {\n return [\n port.most_frequently_referenced_by_name,\n port.name,\n ...port.port_hints ?? [],\n port.pin_number === undefined ? undefined : String(port.pin_number)\n ].filter((n) =\u003e Boolean(n));\n }\n getBestSourcePortName(port) {\n return port.most_frequently_referenced_by_name ?? port.name ?? (port.pin_number === undefined ? \"\" : `pin${port.pin_number}`);\n }\n buildTokenToInvolvedPinMap(circuitJson) {\n const sourceComponentById = new Map(circuitJson.flatMap((el) =\u003e {\n const sc = this.getSourceComponentWithName(el);\n return sc ? [sc] : [];\n }).map((sc) =\u003e [sc.source_component_id, sc]));\n const map = new Map;\n for (const port of circuitJson.filter((el) =\u003e this.isSourcePort(el))) {\n if (!port.source_component_id)\n continue;\n const sc = sourceComponentById.get(port.source_component_id);\n if (!sc?.name)\n continue;\n const involvedPin = `${sc.name}.${this.getBestSourcePortName(port)}`;\n for (const name of this.getSourcePortNameCandidates(port)) {\n map.set(`${sc.name}_${name}`, involvedPin);\n }\n }\n return map;\n }\n getInvolvedPins(text, tokenToInvolvedPin) {\n const pins = new Set;\n for (const token of text.split(\"/\")) {\n const pin = tokenToInvolvedPin.get(token);\n if (pin)\n pins.add(pin);\n }\n return Array.from(pins);\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/SchematicTextClearanceSolver/SchematicTextClearanceSolver.ts\nclass SchematicTextClearanceSolver extends BaseSolver {\n params;\n texts;\n obstacles;\n sheetNames;\n index = 0;\n constructor(params) {\n super();\n this.params = params;\n const { ctx } = params;\n this.sheetNames = getSchematicSheetNamesById(ctx.circuitJson);\n const customSymbolIds = new Set(ctx.circuitJson.flatMap((element) =\u003e element.type === \"schematic_component\" \u0026\u0026 element.is_box_with_pins === false \u0026\u0026 !element.symbol_name ? [element.schematic_component_id] : []));\n const seenText = new Set;\n this.texts = ctx.circuitJson.flatMap((element) =\u003e {\n if (element.type !== \"schematic_text\")\n return [];\n if (element.schematic_component_id || element.schematic_symbol_id || \"source_trace_id\" in element \u0026\u0026 element.source_trace_id)\n return [];\n const polygons = getSchematicTextPolygons(element);\n if (!polygons.length)\n return [];\n const sheetId = element.schematic_sheet_id;\n const fingerprint = JSON.stringify([\n sheetId,\n element.text,\n element.position.x,\n element.position.y,\n element.font_size,\n element.anchor,\n element.rotation,\n element.color\n ]);\n if (seenText.has(fingerprint))\n return [];\n seenText.add(fingerprint);\n return [\n {\n text: element,\n polygons,\n sheetId,\n object: {\n type: \"text\",\n id: element.schematic_text_id,\n text: element.text\n }\n }\n ];\n });\n this.obstacles = [\n ...ctx.componentPlacements.flatMap((p) =\u003e p.schematicComponentId \u0026\u0026 !customSymbolIds.has(p.schematicComponentId) ? [\n {\n object: {\n type: \"component\",\n id: p.schematicComponentId,\n componentName: p.sourceComponentName,\n schematicComponentId: p.schematicComponentId\n },\n polygons: [\n rectPolygon(centeredRect(p.schX, p.schY, p.width, p.height))\n ],\n sheetId: p.schematicSheetId\n }\n ] : []),\n ...ctx.circuitJson.flatMap((element) =\u003e element.type === \"schematic_trace\" ? [\n {\n object: {\n type: \"trace\",\n id: element.schematic_trace_id\n },\n sheetId: element.schematic_sheet_id,\n segments: element.edges,\n polygons: element.edges.flatMap((edge) =\u003e {\n const polygon = traceSegmentPolygon(edge.from, edge.to);\n return polygon ? [polygon] : [];\n })\n }\n ] : [])\n ];\n this.solved = this.texts.length === 0;\n }\n _step() {\n const text = this.texts[this.index];\n const targets = [...this.obstacles, ...this.texts.slice(this.index + 1)];\n const collisions = targets.filter((target) =\u003e this.collides(text, target));\n if (collisions.length) {\n const suggestedMove = this.findClearPosition(text);\n for (const target of collisions) {\n this.params.issues.push({\n lineItemType: \"SchematicTextCollision\",\n schematicSheetId: text.sheetId,\n schematicSheetName: text.sheetId ? this.sheetNames.get(text.sheetId) : undefined,\n schematicTextId: text.text.schematic_text_id,\n text: text.text.text,\n collidingObject: target.object,\n textBounds: polygonBounds(text.polygons),\n collidingObjectBounds: polygonBounds(target.polygons),\n suggestedMove,\n message: `Text \"${text.text.text}\" overlaps ${target.object.type} ${target.object.componentName ?? target.object.id}; reposition the text to leave its visible area clear.`\n });\n }\n }\n this.index++;\n this.solved = this.index \u003e= this.texts.length;\n }\n collides(text, obstacle) {\n if (text.sheetId !== obstacle.sheetId)\n return false;\n return text.polygons.some((a) =\u003e obstacle.segments ? obstacle.segments.some((edge) =\u003e segmentCrossesPolygon(edge.from, edge.to, a)) : obstacle.polygons.some((b) =\u003e polygonsOverlap(a, b)));\n }\n findClearPosition(text) {\n const obstacles = [\n ...this.obstacles,\n ...this.texts.filter((t) =\u003e t !== text)\n ];\n const step = Math.max(0.1, text.text.font_size / 2);\n for (let distance5 = step;distance5 \u003c= Math.max(4, text.text.font_size * 8); distance5 += step) {\n for (const [dx, dy] of [\n [0, distance5],\n [0, -distance5],\n [-distance5, 0],\n [distance5, 0]\n ]) {\n const newSchX = Math.round((text.text.position.x + dx) * 1000) / 1000;\n const newSchY = Math.round((text.text.position.y + dy) * 1000) / 1000;\n const moved = {\n ...text,\n polygons: getSchematicTextPolygons({\n ...text.text,\n position: { x: newSchX, y: newSchY }\n })\n };\n if (obstacles.every((obstacle) =\u003e !this.collides(moved, obstacle)))\n return { newSchX, newSchY };\n }\n }\n return;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"schematicTextId\", issue.schematicTextId);\n addAttr(attrs, \"text\", issue.text);\n addAttr(attrs, \"collidingObjectType\", issue.collidingObject.type);\n addAttr(attrs, \"collidingObjectId\", issue.collidingObject.id);\n addAttr(attrs, \"newSchX\", issue.suggestedMove?.newSchX);\n addAttr(attrs, \"newSchY\", issue.suggestedMove?.newSchY);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cSchematicTextCollision ${attrs.join(\" \")} /\u003e`;\n }\n}\n\n// ../../work/placement-analysis/lib/solvers/ResetNetworkGroupingSolver/ResetNetworkGroupingSolver.ts\nclass ResetNetworkGroupingSolver extends BaseSolver {\n params;\n static MIN_DISTANCE = 6;\n networks;\n index = 0;\n constructor(params) {\n super();\n this.params = params;\n this.networks = this.findNetworks(params.ctx);\n this.solved = this.networks.length === 0;\n }\n _step() {\n const network = this.networks[this.index];\n const rcMembers = network.members.slice(0, 2);\n const threshold = Math.max(ResetNetworkGroupingSolver.MIN_DISTANCE, ...rcMembers.map((p) =\u003e 3 * Math.max(p.width, p.height)));\n const distances = rcMembers.map((p) =\u003e Math.hypot(Math.max(0, Math.abs(p.schX - network.pinPosition.x) - p.width / 2), Math.max(0, Math.abs(p.schY - network.pinPosition.y) - p.height / 2)));\n if (distances.some((distance5) =\u003e distance5 \u003e threshold)) {\n const hostName = network.host.sourceComponentName ?? network.host.schematicComponentId;\n const resetPin = resetPinName(network.pin);\n const memberNames = rcMembers.map((p) =\u003e p.sourceComponentName ?? p.schematicComponentId).join(\", \");\n this.params.issues.push({\n lineItemType: \"ResetNetworkNotGrouped\",\n hostSchematicBox: network.host,\n resetSourcePortId: network.pin.source_port_id,\n resetPinName: resetPin,\n supportNetworkComponents: network.members,\n maxDistanceFromResetPin: Math.round(Math.max(...distances) * 100) / 100,\n maxRecommendedDistance: threshold,\n message: `Group ${memberNames} near ${hostName}.${resetPin} so the reset pull-up and capacitor can be read together. Preserve all net connections; associated test points may remain in a debug area.`\n });\n }\n this.index++;\n this.solved = this.index \u003e= this.networks.length;\n }\n findNetworks(ctx) {\n const root = getSourceConnectivity(ctx.circuitJson);\n const sources = ctx.circuitJson.filter((e) =\u003e e.type === \"source_component\");\n const sourceById = new Map(sources.map((e) =\u003e [e.source_component_id, e]));\n const ports = ctx.circuitJson.filter((e) =\u003e e.type === \"source_port\");\n const portsByComponent = new Map;\n const portsByNet = new Map;\n const power = new Set;\n const ground = new Set;\n for (const port of ports) {\n if (!port.source_component_id)\n continue;\n const componentPorts = portsByComponent.get(port.source_component_id) ?? [];\n componentPorts.push(port);\n portsByComponent.set(port.source_component_id, componentPorts);\n const net = root(port.source_port_id);\n const netPorts = portsByNet.get(net) ?? [];\n netPorts.push(port);\n portsByNet.set(net, netPorts);\n if (port.provides_power || port.requires_power)\n power.add(net);\n if (port.provides_ground || port.requires_ground)\n ground.add(net);\n }\n for (const element of ctx.circuitJson) {\n if (element.type !== \"source_net\")\n continue;\n if (element.is_power || element.is_positive_voltage_source)\n power.add(root(element.source_net_id));\n if (element.is_ground)\n ground.add(root(element.source_net_id));\n }\n const placementBySource = new Map(ctx.componentPlacements.flatMap((p) =\u003e p.sourceComponentId ? [[p.sourceComponentId, p]] : []));\n const schematicPorts = ctx.circuitJson.filter((e) =\u003e e.type === \"schematic_port\");\n const schematicComponents = new Map(ctx.circuitJson.filter((e) =\u003e e.type === \"schematic_component\").map((e) =\u003e [e.schematic_component_id, e]));\n const networks = [];\n const seen = new Set;\n for (const pin of ports) {\n if (!pin.source_component_id || !resetPinName(pin) || pin.do_not_connect)\n continue;\n if (sourceById.get(pin.source_component_id)?.ftype !== \"simple_chip\")\n continue;\n const net = root(pin.source_port_id);\n if (seen.has(net) || power.has(net) || ground.has(net))\n continue;\n seen.add(net);\n const peers = portsByNet.get(net) ?? [];\n const chips = new Set(peers.filter((p) =\u003e p.source_component_id \u0026\u0026 sourceById.get(p.source_component_id)?.ftype === \"simple_chip\").map((p) =\u003e p.source_component_id));\n if (chips.size !== 1)\n continue;\n const host = placementBySource.get(pin.source_component_id);\n const schematicPin = schematicPorts.find((p) =\u003e p.source_port_id === pin.source_port_id \u0026\u0026 p.schematic_component_id === host?.schematicComponentId);\n if (!host || !schematicPin || schematicPin.schematic_sheet_id !== host.schematicSheetId)\n continue;\n const pullups = [];\n const capacitors = [];\n const testpoints = [];\n let unsupported = false;\n for (const id of new Set(peers.map((p) =\u003e p.source_component_id))) {\n if (!id || id === pin.source_component_id)\n continue;\n const type = sourceById.get(id)?.ftype;\n const componentPorts = portsByComponent.get(id) ?? [];\n const placement = placementBySource.get(id);\n if (type === \"simple_connector\" || type === \"simple_pin_header\")\n continue;\n if (!placement) {\n unsupported = true;\n break;\n }\n if (type === \"simple_test_point\" \u0026\u0026 componentPorts.length === 1) {\n testpoints.push(placement);\n continue;\n }\n if (componentPorts.length !== 2) {\n unsupported = true;\n break;\n }\n const other = componentPorts.find((p) =\u003e root(p.source_port_id) !== net);\n if (!other) {\n unsupported = true;\n break;\n }\n const otherNet = root(other.source_port_id);\n if (type === \"simple_resistor\" \u0026\u0026 power.has(otherNet) \u0026\u0026 !ground.has(otherNet))\n pullups.push(placement);\n else if (type === \"simple_capacitor\" \u0026\u0026 ground.has(otherNet) \u0026\u0026 !power.has(otherNet))\n capacitors.push(placement);\n else {\n unsupported = true;\n break;\n }\n }\n if (unsupported || pullups.length !== 1 || capacitors.length !== 1)\n continue;\n const members = [...pullups, ...capacitors, ...testpoints];\n const hostGroup = host.schematicComponentId ? schematicComponents.get(host.schematicComponentId)?.schematic_group_id : undefined;\n if (members.some((member) =\u003e {\n const group = member.schematicComponentId ? schematicComponents.get(member.schematicComponentId)?.schematic_group_id : undefined;\n return member.schematicSheetId !== host.schematicSheetId || member.subcircuitId !== host.subcircuitId || group !== hostGroup;\n }))\n continue;\n networks.push({ host, pin, pinPosition: schematicPin.center, members });\n }\n return networks;\n }\n static issueToString(issue) {\n const attrs = [];\n addAttr(attrs, \"hostComponentName\", issue.hostSchematicBox.sourceComponentName);\n addAttr(attrs, \"resetPin\", issue.resetPinName);\n addAttr(attrs, \"supportNetworkComponents\", issue.supportNetworkComponents.map((p) =\u003e p.sourceComponentName ?? p.schematicComponentId).join(\",\"));\n addAttr(attrs, \"maxDistanceFromResetPin\", issue.maxDistanceFromResetPin);\n addAttr(attrs, \"maxRecommendedDistance\", issue.maxRecommendedDistance);\n addAttr(attrs, \"message\", issue.message);\n return `\u003cResetNetworkNotGrouped ${attrs.join(\" \")} /\u003e`;\n }\n}\nvar resetPinName = (port) =\u003e [port.name, ...port.port_hints ?? []].find((name) =\u003e /^N?(RESET|RST)(N|B)?$/.test(name.toUpperCase().replace(/[_\\-!~#/]/g, \"\")));\n\n// ../../work/placement-analysis/lib/solvers/SchematicPlacementPipeline/SchematicPlacementPipeline.ts\nvar solversByIssueType = {\n CapacitorSeparatedFromChipPins: [ChipPinPairCapacitorPlacementSolver],\n PiFilterComponentsNotGrouped: [PiFilterPlacementSolver],\n MosfetGateNetworkNotGrouped: [MosfetGateNetworkPlacementSolver],\n FlybackDiodeSeparatedFromRelayCoil: [RelayFlybackDiodePlacementSolver],\n ComponentOverlap: [SchematicBoxOverlapSolver],\n SchematicBoxHasALotOfSurroundingWhitespace: [],\n CapacitorSymbolHorizontal: [\n CapacitorOrientationSolver,\n TwoPinComponentRailOrientationSolver\n ],\n VerboseSchematicNetLabel: [VerboseNetLabelSolver],\n PinHeaderSchematicBoxTooWide: [SchematicBoxTooWideSolver],\n GenericSchematicBoxTooWide: [SchematicBoxTooWideSolver],\n SchematicBoxInnerLabelCollision: [SchematicBoxInnerLabelCollisionSolver],\n SchematicPinPaddingToEdgeTooLarge: [SchematicPinPaddingToEdgeSolver],\n DiodeResistorNotAligned: [DiodeResistorAlignmentSolver],\n ComponentPinsWouldAlignWithVerticalShift: [ComponentPinAlignmentSolver],\n TraceCanBeSimplifiedByMovingComponent: [TraceSimplificationSolver],\n FourPinCrystalPatternMismatch: [FourPinCrystalPatternSolver],\n CrystalNotCenteredOverLoadCapacitors: [CrystalLoadCapacitorPlacementSolver],\n ComponentNetLabelCollision: [ComponentNetLabelCollisionSolver],\n ComponentBoxNetLabelCollision: [ComponentNetLabelCollisionSolver],\n NetLabelCollision: [ComponentNetLabelCollisionSolver],\n FeedbackNetworkNotCompact: [FeedbackNetworkPlacementSolver],\n PullResistorOnWrongSide: [\n PullResistorPlacementSolver,\n SwitchPullResistorPlacementSolver\n ],\n SchematicTextCollision: [SchematicTextClearanceSolver],\n ResetNetworkNotGrouped: [ResetNetworkGroupingSolver],\n TwoPinComponentCouldBeFlipped: [TwoPinComponentOrientationSolver],\n TwoPinComponentShouldBeVertical: [TwoPinComponentRailOrientationSolver],\n TwoPinComponentHasInvertedRails: [TwoPinComponentRailOrientationSolver],\n DecouplingCapacitorsNotCloseTogether: [DecouplingCapacitorGroupingSolver],\n ConnectorPositionCausesTraceDetours: [ConnectorPlacementSolver],\n LowSideTransistorNotAlignedWithLoad: [LowSideTransistorPlacementSolver],\n UsbSeriesResistorsNotAligned: [UsbSeriesResistorPlacementSolver],\n CurrentSenseShuntSeparatedFromInputs: [CurrentSenseShuntPlacementSolver],\n VoltageDividerSupplyResistorBelowGroundResistor: [\n VoltageDividerPlacementSolver\n ],\n RegulatorCapacitorsOnWrongSides: [\n RegulatorInputOutputCapacitorPlacementSolver\n ]\n};\n\nclass SchematicPlacementPipeline extends BasePipelineSolver {\n ctx;\n issues = [];\n pipelineDef = [\n definePipelineStep(\"SchematicTextClearanceSolver\", SchematicTextClearanceSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"ResetNetworkGroupingSolver\", ResetNetworkGroupingSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"SchematicBoxOverlapSolver\", SchematicBoxOverlapSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"CapacitorOrientationSolver\", CapacitorOrientationSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"VerboseNetLabelSolver\", VerboseNetLabelSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"SchematicBoxTooWideSolver\", SchematicBoxTooWideSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"SchematicPinPaddingToEdgeSolver\", SchematicPinPaddingToEdgeSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"SchematicBoxInnerLabelCollisionSolver\", SchematicBoxInnerLabelCollisionSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"DiodeResistorAlignmentSolver\", DiodeResistorAlignmentSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"ComponentPinAlignmentSolver\", ComponentPinAlignmentSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"TraceSimplificationSolver\", TraceSimplificationSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"FourPinCrystalPatternSolver\", FourPinCrystalPatternSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"CrystalLoadCapacitorPlacementSolver\", CrystalLoadCapacitorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"TwoPinComponentOrientationSolver\", TwoPinComponentOrientationSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"FeedbackNetworkPlacementSolver\", FeedbackNetworkPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"TwoPinComponentRailOrientationSolver\", TwoPinComponentRailOrientationSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"PullResistorPlacementSolver\", PullResistorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"SwitchPullResistorPlacementSolver\", SwitchPullResistorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"ComponentNetLabelCollisionSolver\", ComponentNetLabelCollisionSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"DecouplingCapacitorGroupingSolver\", DecouplingCapacitorGroupingSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"ConnectorPlacementSolver\", ConnectorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"LowSideTransistorPlacementSolver\", LowSideTransistorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"UsbSeriesResistorPlacementSolver\", UsbSeriesResistorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"RegulatorInputOutputCapacitorPlacementSolver\", RegulatorInputOutputCapacitorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"VoltageDividerPlacementSolver\", VoltageDividerPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"CurrentSenseShuntPlacementSolver\", CurrentSenseShuntPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"RelayFlybackDiodePlacementSolver\", RelayFlybackDiodePlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"PiFilterPlacementSolver\", PiFilterPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"MosfetGateNetworkPlacementSolver\", MosfetGateNetworkPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ]),\n definePipelineStep(\"ChipPinPairCapacitorPlacementSolver\", ChipPinPairCapacitorPlacementSolver, (p) =\u003e [\n { ctx: p.ctx, issues: p.issues }\n ])\n ];\n selectedIssueTypes;\n constructor(circuitJson, options = {}) {\n super(circuitJson);\n if (options.issueTypes !== undefined) {\n this.selectedIssueTypes = new Set(options.issueTypes);\n const selectedSolvers = new Set(options.issueTypes.flatMap((type) =\u003e solversByIssueType[type]));\n this.pipelineDef = this.pipelineDef.filter((step) =\u003e selectedSolvers.has(step.solverClass));\n }\n }\n _setup() {\n this.ctx = buildSolverContext(this.inputProblem);\n }\n getOutput() {\n const railOrientationComponentIds = new Set(this.issues.flatMap((issue) =\u003e issue.lineItemType === \"TwoPinComponentShouldBeVertical\" \u0026\u0026 issue.schematicBox.schematicComponentId ? [issue.schematicBox.schematicComponentId] : []));\n return {\n issues: this.issues.filter((issue) =\u003e issue.lineItemType !== \"CapacitorSymbolHorizontal\" || !railOrientationComponentIds.has(issue.schematicBox.schematicComponentId ?? \"\")).filter((issue) =\u003e this.selectedIssueTypes === undefined || this.selectedIssueTypes.has(issue.lineItemType)),\n componentPlacements: this.ctx.componentPlacements\n };\n }\n}\n\n// ../../work/placement-analysis/lib/utils/issue-context.ts\nvar POSITION_EPSILON = 0.01;\nvar getRelevantPlacementsForIssues = ({\n issues,\n componentPlacements,\n circuitJson\n}) =\u003e {\n const relevantPlacements = new Set;\n const placementByComponentId = new Map(componentPlacements.flatMap((placement) =\u003e placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));\n const placementsByName = new Map;\n for (const placement of componentPlacements) {\n if (!placement.sourceComponentName)\n continue;\n const namedPlacements = placementsByName.get(placement.sourceComponentName);\n if (namedPlacements)\n namedPlacements.push(placement);\n else\n placementsByName.set(placement.sourceComponentName, [placement]);\n }\n const addPlacement = (placement) =\u003e {\n if (!placement)\n return;\n const canonicalPlacement = placement.schematicComponentId ? placementByComponentId.get(placement.schematicComponentId) : componentPlacements.find((candidate) =\u003e candidate.sourceComponentId === placement.sourceComponentId \u0026\u0026 candidate.schX === placement.schX \u0026\u0026 candidate.schY === placement.schY);\n if (canonicalPlacement)\n relevantPlacements.add(canonicalPlacement);\n };\n const addComponentName = (componentName, schematicSheetId) =\u003e {\n if (!componentName)\n return;\n for (const placement of placementsByName.get(componentName) ?? []) {\n if (schematicSheetId === undefined || placement.schematicSheetId === schematicSheetId) {\n relevantPlacements.add(placement);\n }\n }\n };\n for (const issue of issues) {\n switch (issue.lineItemType) {\n case \"CapacitorSeparatedFromChipPins\":\n addPlacement(issue.hostSchematicBox);\n addPlacement(issue.capacitorSchematicBox);\n break;\n case \"PiFilterComponentsNotGrouped\":\n addPlacement(issue.inductorSchematicBox);\n addPlacement(issue.firstCapacitorSchematicBox);\n addPlacement(issue.secondCapacitorSchematicBox);\n break;\n case \"MosfetGateNetworkNotGrouped\":\n addPlacement(issue.mosfetSchematicBox);\n addPlacement(issue.seriesGateResistorSchematicBox);\n addPlacement(issue.gateSourceResistorSchematicBox);\n break;\n case \"FlybackDiodeSeparatedFromRelayCoil\":\n addPlacement(issue.relaySchematicBox);\n addPlacement(issue.diodeSchematicBox);\n break;\n case \"CurrentSenseShuntSeparatedFromInputs\":\n addPlacement(issue.amplifierSchematicBox);\n addPlacement(issue.shuntSchematicBox);\n break;\n case \"VoltageDividerSupplyResistorBelowGroundResistor\":\n addPlacement(issue.supplyResistorSchematicBox);\n addPlacement(issue.groundResistorSchematicBox);\n break;\n case \"RegulatorCapacitorsOnWrongSides\":\n addPlacement(issue.regulatorSchematicBox);\n addPlacement(issue.inputCapacitorSchematicBox);\n addPlacement(issue.outputCapacitorSchematicBox);\n break;\n case \"UsbSeriesResistorsNotAligned\":\n addPlacement(issue.positiveResistorSchematicBox);\n addPlacement(issue.negativeResistorSchematicBox);\n break;\n case \"LowSideTransistorNotAlignedWithLoad\":\n addPlacement(issue.transistorSchematicBox);\n addPlacement(issue.loadSchematicBox);\n addPlacement(issue.baseResistorSchematicBox);\n addPlacement(issue.clampDiodeSchematicBox);\n break;\n case \"DecouplingCapacitorsNotCloseTogether\":\n for (const placement of issue.capacitorSchematicBoxes)\n addPlacement(placement);\n break;\n case \"ConnectorPositionCausesTraceDetours\":\n addPlacement(issue.connectorSchematicBox);\n for (const placement of issue.connectedComponents)\n addPlacement(placement);\n break;\n case \"ResetNetworkNotGrouped\":\n addPlacement(issue.hostSchematicBox);\n for (const placement of issue.supportNetworkComponents)\n addPlacement(placement);\n break;\n case \"SchematicTextCollision\":\n if (issue.collidingObject.schematicComponentId)\n addPlacement(placementByComponentId.get(issue.collidingObject.schematicComponentId));\n if (issue.collidingObject.type === \"trace\") {\n for (const placement of getTraceEndpointPlacements({\n schematicTraceId: issue.collidingObject.id,\n circuitJson,\n placementByComponentId\n }))\n addPlacement(placement);\n }\n break;\n case \"ComponentOverlap\":\n addPlacement(issue.firstComponent);\n addPlacement(issue.secondComponent);\n break;\n case \"SchematicBoxHasALotOfSurroundingWhitespace\":\n case \"CapacitorSymbolHorizontal\":\n case \"PinHeaderSchematicBoxTooWide\":\n case \"GenericSchematicBoxTooWide\":\n case \"SchematicBoxInnerLabelCollision\":\n case \"SchematicPinPaddingToEdgeTooLarge\":\n addPlacement(issue.schematicBox);\n break;\n case \"VerboseSchematicNetLabel\":\n for (const pin of issue.involvedPins) {\n addComponentName(getComponentNameFromPin(pin), issue.schematicSheetId);\n }\n break;\n case \"DiodeResistorNotAligned\":\n addPlacement(issue.diodeSchematicBox);\n addPlacement(issue.resistorSchematicBox);\n break;\n case \"ComponentPinsWouldAlignWithVerticalShift\":\n addPlacement(issue.firstComponent);\n addPlacement(issue.secondComponent);\n addPlacement(issue.targetComponent);\n break;\n case \"TraceCanBeSimplifiedByMovingComponent\":\n addPlacement(issue.targetComponent);\n for (const placement of getTraceEndpointPlacements({\n schematicTraceId: issue.schematicTraceId,\n circuitJson,\n placementByComponentId\n })) {\n relevantPlacements.add(placement);\n }\n break;\n case \"FourPinCrystalPatternMismatch\":\n for (const target of issue.suggestedPlacements)\n addPlacement(target.schematicBox);\n break;\n case \"CrystalNotCenteredOverLoadCapacitors\":\n addPlacement(issue.crystalSchematicBox);\n addPlacement(issue.firstLoadCapacitorSchematicBox);\n addPlacement(issue.secondLoadCapacitorSchematicBox);\n break;\n case \"TwoPinComponentCouldBeFlipped\":\n addPlacement(issue.targetComponent);\n addPlacement(issue.connectedComponent);\n break;\n case \"FeedbackNetworkNotCompact\":\n addPlacement(issue.amplifierSchematicBox);\n for (const component of issue.feedbackComponents)\n addPlacement(component);\n break;\n case \"TwoPinComponentShouldBeVertical\":\n case \"TwoPinComponentHasInvertedRails\":\n addPlacement(issue.schematicBox);\n break;\n case \"PullResistorOnWrongSide\":\n addPlacement(issue.resistorSchematicBox);\n addPlacement(issue.hostSchematicBox);\n break;\n case \"ComponentNetLabelCollision\":\n addPlacement(issue.firstComponent);\n addPlacement(issue.secondComponent);\n break;\n case \"ComponentBoxNetLabelCollision\":\n addPlacement(issue.boxComponent);\n addPlacement(issue.labelComponent);\n break;\n case \"NetLabelCollision\":\n for (const pair of issue.pairs) {\n addComponentName(pair.comp1Name, issue.schematicSheetId);\n addComponentName(pair.comp2Name, issue.schematicSheetId);\n }\n for (const move of issue.moves) {\n addComponentName(move.componentName, issue.schematicSheetId);\n }\n break;\n }\n }\n return componentPlacements.filter((placement) =\u003e relevantPlacements.has(placement));\n};\nvar getIssueSchematicSheetContext = (issue) =\u003e {\n if (\"schematicSheetId\" in issue || \"schematicSheetName\" in issue) {\n const schematicSheetId = \"schematicSheetId\" in issue \u0026\u0026 typeof issue.schematicSheetId === \"string\" ? issue.schematicSheetId : undefined;\n const schematicSheetName = \"schematicSheetName\" in issue \u0026\u0026 typeof issue.schematicSheetName === \"string\" ? issue.schematicSheetName : undefined;\n if (schematicSheetId || schematicSheetName) {\n return { schematicSheetId, schematicSheetName };\n }\n }\n for (const value of Object.values(issue).flat()) {\n if (isSchematicBoxPlacement(value)) {\n return {\n schematicSheetId: value.schematicSheetId,\n schematicSheetName: value.schematicSheetName\n };\n }\n }\n return {};\n};\nvar getComponentNameFromPin = (pin) =\u003e {\n const separatorIndex = pin.lastIndexOf(\".\");\n return separatorIndex === -1 ? pin : pin.slice(0, separatorIndex);\n};\nvar isSchematicBoxPlacement = (value) =\u003e Boolean(value \u0026\u0026 typeof value === \"object\" \u0026\u0026 \"positionAnchor\" in value \u0026\u0026 value.positionAnchor === \"center\" \u0026\u0026 \"schX\" in value \u0026\u0026 \"schY\" in value \u0026\u0026 \"width\" in value \u0026\u0026 \"height\" in value);\nvar getTraceEndpointPlacements = ({\n schematicTraceId,\n circuitJson,\n placementByComponentId\n}) =\u003e {\n const trace = circuitJson.find((element) =\u003e element.type === \"schematic_trace\" \u0026\u0026 element.schematic_trace_id === schematicTraceId);\n const firstEdge = trace?.edges[0];\n const lastEdge = trace?.edges.at(-1);\n if (!trace || !firstEdge || !lastEdge)\n return [];\n const ports = circuitJson.filter((element) =\u003e element.type === \"schematic_port\");\n const portsById = new Map(ports.map((port) =\u003e [port.schematic_port_id, port]));\n const endpointPorts = [\n firstEdge.from_schematic_port_id ? portsById.get(firstEdge.from_schematic_port_id) : findPortAtPoint(ports, firstEdge.from, trace.schematic_sheet_id),\n lastEdge.to_schematic_port_id ? portsById.get(lastEdge.to_schematic_port_id) : findPortAtPoint(ports, lastEdge.to, trace.schematic_sheet_id)\n ];\n return endpointPorts.flatMap((port) =\u003e {\n const placement = port?.schematic_component_id ? placementByComponentId.get(port.schematic_component_id) : undefined;\n return placement ? [placement] : [];\n });\n};\nvar findPortAtPoint = (ports, point2, schematicSheetId) =\u003e ports.find((port) =\u003e port.schematic_sheet_id === schematicSheetId \u0026\u0026 Math.abs(port.center.x - point2.x) \u003c= POSITION_EPSILON \u0026\u0026 Math.abs(port.center.y - point2.y) \u003c= POSITION_EPSILON);\n\n// ../../work/placement-analysis/lib/analyze-schematic-placement.ts\nclass SchematicPlacementAnalysis {\n lineItems;\n groupBySchematicSheet;\n constructor(lineItems, groupBySchematicSheet = false) {\n this.lineItems = lineItems;\n this.groupBySchematicSheet = groupBySchematicSheet;\n }\n getLineItems() {\n return this.lineItems;\n }\n getIssues(filter = {}) {\n return this.lineItems.flatMap((item) =\u003e item.lineItemType === \"SchematicPlacementIssues\" ? item.issues : []).filter((issue) =\u003e (filter.issueTypes === undefined || filter.issueTypes.includes(issue.lineItemType)) \u0026\u0026 (filter.schematicSheetId === undefined || (getIssueSchematicSheetContext(issue).schematicSheetId ?? \"\") === filter.schematicSheetId));\n }\n getIssueCounts(filter = {}) {\n const counts = {\n FlybackDiodeSeparatedFromRelayCoil: 0,\n ComponentOverlap: 0,\n SchematicBoxHasALotOfSurroundingWhitespace: 0,\n CapacitorSymbolHorizontal: 0,\n VerboseSchematicNetLabel: 0,\n PinHeaderSchematicBoxTooWide: 0,\n GenericSchematicBoxTooWide: 0,\n SchematicBoxInnerLabelCollision: 0,\n SchematicPinPaddingToEdgeTooLarge: 0,\n DiodeResistorNotAligned: 0,\n ComponentPinsWouldAlignWithVerticalShift: 0,\n TraceCanBeSimplifiedByMovingComponent: 0,\n FourPinCrystalPatternMismatch: 0,\n CrystalNotCenteredOverLoadCapacitors: 0,\n ComponentNetLabelCollision: 0,\n ComponentBoxNetLabelCollision: 0,\n NetLabelCollision: 0,\n FeedbackNetworkNotCompact: 0,\n PullResistorOnWrongSide: 0,\n SchematicTextCollision: 0,\n ResetNetworkNotGrouped: 0,\n TwoPinComponentCouldBeFlipped: 0,\n TwoPinComponentShouldBeVertical: 0,\n TwoPinComponentHasInvertedRails: 0,\n DecouplingCapacitorsNotCloseTogether: 0,\n ConnectorPositionCausesTraceDetours: 0,\n LowSideTransistorNotAlignedWithLoad: 0,\n UsbSeriesResistorsNotAligned: 0,\n RegulatorCapacitorsOnWrongSides: 0,\n VoltageDividerSupplyResistorBelowGroundResistor: 0,\n CurrentSenseShuntSeparatedFromInputs: 0,\n PiFilterComponentsNotGrouped: 0,\n MosfetGateNetworkNotGrouped: 0,\n CapacitorSeparatedFromChipPins: 0\n };\n for (const issue of this.getIssues(filter))\n counts[issue.lineItemType]++;\n return counts;\n }\n getString() {\n return this.toString();\n }\n schematicBoxPlacementsToString(lineItem) {\n const attrs = [];\n addAttr(attrs, \"componentName\", lineItem.sourceComponentName);\n addAttr(attrs, \"positionAnchor\", lineItem.positionAnchor);\n addAttr(attrs, \"schX\", lineItem.schX);\n addAttr(attrs, \"schY\", lineItem.schY);\n addAttr(attrs, \"width\", lineItem.width);\n addAttr(attrs, \"height\", lineItem.height);\n return `\u003cSchematicBoxPlacement ${attrs.join(\" \")} /\u003e`;\n }\n schematicIssuesToString(issue) {\n switch (issue.lineItemType) {\n case \"CapacitorSeparatedFromChipPins\":\n return ChipPinPairCapacitorPlacementSolver.issueToString(issue);\n case \"PiFilterComponentsNotGrouped\":\n return PiFilterPlacementSolver.issueToString(issue);\n case \"MosfetGateNetworkNotGrouped\":\n return MosfetGateNetworkPlacementSolver.issueToString(issue);\n case \"CurrentSenseShuntSeparatedFromInputs\":\n return CurrentSenseShuntPlacementSolver.issueToString(issue);\n case \"ComponentOverlap\":\n return SchematicBoxOverlapSolver.issueToString(issue);\n case \"CapacitorSymbolHorizontal\":\n return CapacitorOrientationSolver.issueToString(issue);\n case \"DecouplingCapacitorsNotCloseTogether\":\n return DecouplingCapacitorGroupingSolver.issueToString(issue);\n case \"VerboseSchematicNetLabel\":\n return VerboseNetLabelSolver.issueToString(issue);\n case \"PinHeaderSchematicBoxTooWide\":\n case \"GenericSchematicBoxTooWide\":\n return SchematicBoxTooWideSolver.issueToString(issue);\n case \"SchematicBoxInnerLabelCollision\":\n return SchematicBoxInnerLabelCollisionSolver.issueToString(issue);\n case \"SchematicPinPaddingToEdgeTooLarge\":\n return SchematicPinPaddingToEdgeSolver.issueToString(issue);\n case \"DiodeResistorNotAligned\":\n return DiodeResistorAlignmentSolver.issueToString(issue);\n case \"ComponentPinsWouldAlignWithVerticalShift\":\n return ComponentPinAlignmentSolver.issueToString(issue);\n case \"TraceCanBeSimplifiedByMovingComponent\":\n return TraceSimplificationSolver.issueToString(issue);\n case \"FourPinCrystalPatternMismatch\":\n return FourPinCrystalPatternSolver.issueToString(issue);\n case \"CrystalNotCenteredOverLoadCapacitors\":\n return CrystalLoadCapacitorPlacementSolver.issueToString(issue);\n case \"TwoPinComponentCouldBeFlipped\":\n return TwoPinComponentOrientationSolver.issueToString(issue);\n case \"FeedbackNetworkNotCompact\":\n return FeedbackNetworkPlacementSolver.issueToString(issue);\n case \"TwoPinComponentShouldBeVertical\":\n case \"TwoPinComponentHasInvertedRails\":\n return TwoPinComponentRailOrientationSolver.issueToString(issue);\n case \"PullResistorOnWrongSide\":\n return PullResistorPlacementSolver.issueToString(issue);\n case \"NetLabelCollision\":\n return ComponentNetLabelCollisionSolver.netLabelCollisionToString(issue);\n case \"SchematicTextCollision\":\n return SchematicTextClearanceSolver.issueToString(issue);\n case \"ResetNetworkNotGrouped\":\n return ResetNetworkGroupingSolver.issueToString(issue);\n case \"ConnectorPositionCausesTraceDetours\":\n return ConnectorPlacementSolver.issueToString(issue);\n case \"LowSideTransistorNotAlignedWithLoad\":\n return LowSideTransistorPlacementSolver.issueToString(issue);\n case \"FlybackDiodeSeparatedFromRelayCoil\":\n return RelayFlybackDiodePlacementSolver.issueToString(issue);\n case \"VoltageDividerSupplyResistorBelowGroundResistor\":\n return VoltageDividerPlacementSolver.issueToString(issue);\n case \"RegulatorCapacitorsOnWrongSides\":\n return RegulatorInputOutputCapacitorPlacementSolver.issueToString(issue);\n case \"UsbSeriesResistorsNotAligned\":\n return UsbSeriesResistorPlacementSolver.issueToString(issue);\n default:\n return \"\";\n }\n }\n toString() {\n const schematicBoxPlacements = this.lineItems.filter((lineItem) =\u003e lineItem.lineItemType === \"SchematicBoxPlacement\");\n const issues = this.lineItems.flatMap((lineItem) =\u003e lineItem.lineItemType === \"SchematicPlacementIssues\" ? lineItem.issues : []);\n if (issues.length === 0)\n return \"\";\n if (!this.groupBySchematicSheet) {\n return this.issueContextToLines(schematicBoxPlacements, issues).join(`\n`);\n }\n const groups = new Map;\n const getOrCreateGroup = (context) =\u003e {\n const key = context.schematicSheetId ?? context.schematicSheetName ?? \"__default__\";\n const existingGroup = groups.get(key);\n if (existingGroup)\n return existingGroup;\n const group = { ...context, placements: [], issues: [] };\n groups.set(key, group);\n return group;\n };\n for (const issue of issues) {\n getOrCreateGroup(getIssueSchematicSheetContext(issue)).issues.push(issue);\n }\n for (const placement of schematicBoxPlacements) {\n getOrCreateGroup({\n schematicSheetId: placement.schematicSheetId,\n schematicSheetName: placement.schematicSheetName\n }).placements.push(placement);\n }\n return [...groups.values()].flatMap((group) =\u003e {\n const sheetAttrs = [];\n addAttr(sheetAttrs, \"name\", group.schematicSheetName);\n addAttr(sheetAttrs, \"id\", group.schematicSheetId);\n return [\n `\u003cSchematicSheet${sheetAttrs.length \u003e 0 ? ` ${sheetAttrs.join(\" \")}` : \"\"}\u003e`,\n ...this.issueContextToLines(group.placements, group.issues),\n \"\u003c/SchematicSheet\u003e\"\n ];\n }).join(`\n`);\n }\n issueContextToLines(placements, issues) {\n return [\n ...placements.length \u003e 0 ? [\n \"\u003cSchematicBoxPositions\u003e\",\n ...placements.map(this.schematicBoxPlacementsToString),\n \"\u003c/SchematicBoxPositions\u003e\"\n ] : [],\n \"\u003cSchematicPlacementIssues\u003e\",\n ...issues.map(this.schematicIssuesToString),\n \"\u003c/SchematicPlacementIssues\u003e\"\n ];\n }\n}\nvar analyzeSchematicPlacement = (circuitJson, options = {}) =\u003e {\n const pipeline = new SchematicPlacementPipeline(circuitJson, options);\n pipeline.solve();\n const { issues, componentPlacements } = pipeline.getOutput();\n const relevantPlacements = getRelevantPlacementsForIssues({\n issues,\n componentPlacements,\n circuitJson\n });\n const lineItems = [\n ...relevantPlacements,\n ...issues.length \u003e 0 ? [{ lineItemType: \"SchematicPlacementIssues\", issues }] : []\n ];\n const schematicSheetIds = new Set(circuitJson.flatMap((element) =\u003e (\"schematic_sheet_id\" in element) \u0026\u0026 typeof element.schematic_sheet_id === \"string\" ? [element.schematic_sheet_id] : []));\n return new SchematicPlacementAnalysis(lineItems, schematicSheetIds.size \u003e 1);\n};\nexport {\n analyzeSchematicPlacement,\n SchematicPlacementAnalysis\n};\n","content_mimetype":"text/javascript","created_at":"2026-10-02T13:22:24.798Z"}; window.SSR_PACKAGE_RELEASES = [{"package_release_id":"e8d285f7-c3d8-46f5-9a54-344fdde0124e","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.42","github_commit_sha":null,"is_locked":false,"is_latest":true,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-02T13:22:22.003Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-ccffada3c1cc24d393e7b2485cb701f3","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=e8d285f7-c3d8-46f5-9a54-344fdde0124e\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=e8d285f7-c3d8-46f5-9a54-344fdde0124e\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=e8d285f7-c3d8-46f5-9a54-344fdde0124e\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"e71955f1-3143-4a6a-a8da-ab60e8de3107","user_code_job_started_at":"2026-10-02T13:23:20.198Z","user_code_job_completed_at":"2026-10-02T13:30:59.469Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=e837906ae4d11af3aec6e2470d91183f7f9e3288e735c8792e7b583751ac8755","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"7f0777f4-dc21-4437-9e6f-ebde4b669fb3","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.41","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T22:07:09.291Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-88fa85c314bf8931d33a675d0af77ef4","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=7f0777f4-dc21-4437-9e6f-ebde4b669fb3\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=7f0777f4-dc21-4437-9e6f-ebde4b669fb3\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=7f0777f4-dc21-4437-9e6f-ebde4b669fb3\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"03de9193-07eb-4ca8-bf98-665a4a8e2d9f","user_code_job_started_at":"2026-10-01T22:09:52.447Z","user_code_job_completed_at":"2026-10-01T22:14:10.566Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=9688fdc8b36514ec318adff8626d4d001a659b415ac7cc813f2982588866649c","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"cb88c834-87f2-42f1-8839-a2893dd7b77e","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.40","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T20:07:21.988Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-85f9fc0bda57dda31ee240f31e8f0e21","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cb88c834-87f2-42f1-8839-a2893dd7b77e\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cb88c834-87f2-42f1-8839-a2893dd7b77e\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cb88c834-87f2-42f1-8839-a2893dd7b77e\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"da634aa4-6ef3-4426-9540-c989b1b24149","user_code_job_started_at":"2026-10-01T20:08:24.586Z","user_code_job_completed_at":"2026-10-01T20:15:26.238Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=edfecaea839bb02a10a71fa145382119dfbdf8644e8a60a62f7cf7ae0758ff8a","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"eff8e44f-df88-45ae-8a73-08d51421cc9a","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.39","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T12:59:57.213Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-7c69f1d3cc1940077b94069473c34143","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=eff8e44f-df88-45ae-8a73-08d51421cc9a\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=eff8e44f-df88-45ae-8a73-08d51421cc9a\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=eff8e44f-df88-45ae-8a73-08d51421cc9a\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"1ad489c1-8dbf-4464-91b9-3a33337f50be","user_code_job_started_at":"2026-10-01T13:02:19.193Z","user_code_job_completed_at":"2026-10-01T13:07:13.503Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=815db28c942f86dbd756957fee8234fcc27e7a24b5c2ecb1d8cda669ce8b28ac","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"cf2755d5-b1b4-4613-ada6-5c83dfd1f1b2","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.38","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-29T21:47:51.307Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-666f5e3ac28c60407e94fd174b34bc96","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cf2755d5-b1b4-4613-ada6-5c83dfd1f1b2\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cf2755d5-b1b4-4613-ada6-5c83dfd1f1b2\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cf2755d5-b1b4-4613-ada6-5c83dfd1f1b2\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"0d3f64cf-0209-4ff5-a679-3139f205741b","user_code_job_started_at":"2026-09-30T09:27:58.098Z","user_code_job_completed_at":"2026-09-30T09:33:47.909Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=5a2a22c44380fb5f630e9bb5b2a13c8104bc1a28f7de65fc7a0b8d093627a64d","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"72713054-ab49-4de2-86c6-dd75de86c72a","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.37","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-29T21:19:35.655Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-5ba886cc821b3e1ed29cd83fd1087e84","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=72713054-ab49-4de2-86c6-dd75de86c72a\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=72713054-ab49-4de2-86c6-dd75de86c72a\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=72713054-ab49-4de2-86c6-dd75de86c72a\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"a97d6661-142b-4955-b514-c23869497488","user_code_job_started_at":"2026-09-29T21:20:41.790Z","user_code_job_completed_at":"2026-09-29T21:26:43.014Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=8b29c87fa7a9755935d093054b32b26c31c1474bf1e02d627314a62093c2aaa0","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"42dc2f35-a358-4a70-91d6-ece51c8e3b0c","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.36","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-29T20:22:46.527Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-bf88206ef41d8320b5900aa9be90c400","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=42dc2f35-a358-4a70-91d6-ece51c8e3b0c\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=42dc2f35-a358-4a70-91d6-ece51c8e3b0c\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=42dc2f35-a358-4a70-91d6-ece51c8e3b0c\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"6a74adb8-2792-4e06-bffe-a77e06bc5a1a","user_code_job_started_at":"2026-09-29T21:11:19.002Z","user_code_job_completed_at":"2026-09-29T21:17:24.459Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=fc58d8044fbb2bbb2fe06294c06f92d9802ed1c36566a8e9de46ec2d868dd248","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"7921fca5-1f01-4780-a2fa-2dd577a676d4","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.35","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-29T08:21:44.910Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-8da6b1f9875e14de66c90bebfcf71569","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=7921fca5-1f01-4780-a2fa-2dd577a676d4\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=7921fca5-1f01-4780-a2fa-2dd577a676d4\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=7921fca5-1f01-4780-a2fa-2dd577a676d4\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"80d55c61-3242-4715-9e69-b7e0071b8c5c","user_code_job_started_at":"2026-09-29T08:24:12.484Z","user_code_job_completed_at":"2026-09-29T08:29:28.630Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=b945040405f9026c98fe39f9a0d45687f4ad06687b111292e21b9e1536d467ea","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"f5a61295-5678-4a3c-9bd5-c5856c6292c3","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.31","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-28T15:55:43.368Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-480a00f19984466ac54b70a7f56e2c22","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=f5a61295-5678-4a3c-9bd5-c5856c6292c3\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=f5a61295-5678-4a3c-9bd5-c5856c6292c3\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=f5a61295-5678-4a3c-9bd5-c5856c6292c3\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"1bcccfa2-7d79-4e2c-9e2f-b78977b3bdbd","user_code_job_started_at":"2026-09-28T15:59:14.254Z","user_code_job_completed_at":"2026-09-28T16:04:38.940Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=46a55a24f98f31d91e675d3bbbd10a804bbe28a00d5c1d92257d425b5e6f2606","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"95596b22-6452-4859-8279-da5cd4dce137","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.29","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-28T13:06:10.225Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-d091e2dbeb1c29802525a3f94bdd7ebb","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=95596b22-6452-4859-8279-da5cd4dce137\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=95596b22-6452-4859-8279-da5cd4dce137\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=95596b22-6452-4859-8279-da5cd4dce137\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"7c54c658-4750-455c-a2d4-8e82181b9a83","user_code_job_started_at":"2026-09-28T13:07:26.877Z","user_code_job_completed_at":"2026-09-28T13:12:50.028Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=1162f1387251a6a53174f03303c79ce7a167d3f97f664f26880e11bc617e2518","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"cbf86c3a-c1ea-4f02-97d9-8c247c50d863","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.28","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-26T18:06:06.002Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-2b5733ad557ac4fd7eac22f85c2b58b2","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cbf86c3a-c1ea-4f02-97d9-8c247c50d863\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cbf86c3a-c1ea-4f02-97d9-8c247c50d863\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=cbf86c3a-c1ea-4f02-97d9-8c247c50d863\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"b0fc9656-832a-4616-b98a-d39e5880cc8f","user_code_job_started_at":"2026-09-26T18:07:16.024Z","user_code_job_completed_at":"2026-09-26T18:12:21.503Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=fc5b1bb4a754d31ece2b423dceed5910b58cda7cf605eda001e571046c8891a3","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"99ad9d8e-02ed-4a62-ac9c-8956df5726b1","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.27","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-26T17:31:31.455Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-0960a20090bcda5514fc96cf6fbf5aff","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=99ad9d8e-02ed-4a62-ac9c-8956df5726b1\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=99ad9d8e-02ed-4a62-ac9c-8956df5726b1\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=99ad9d8e-02ed-4a62-ac9c-8956df5726b1\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"262836c9-b294-4832-8b88-b22c24f351a5","user_code_job_started_at":"2026-09-26T17:32:17.306Z","user_code_job_completed_at":"2026-09-26T17:37:52.188Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=f7802abf451fc193056963ebb584009f375a65edf98a508fa7cbc751b48723ff","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"07ea852e-6b36-47ae-a16b-0059e75b5ec8","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.26","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-26T16:08:41.627Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-a60d936fc7d372e69a9959af5e7a08d4","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=07ea852e-6b36-47ae-a16b-0059e75b5ec8\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=07ea852e-6b36-47ae-a16b-0059e75b5ec8\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=07ea852e-6b36-47ae-a16b-0059e75b5ec8\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"2641a5b9-936d-4367-bf1f-5bcf20182638","user_code_job_started_at":"2026-09-26T16:09:36.200Z","user_code_job_completed_at":"2026-09-26T16:13:21.040Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=219f20c7188ef5c53f94ee9da6b42380072a052bbb625e3b38886df1ab514dfb","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"ce250c35-efe6-4bb6-9846-e1ccb66cd2d5","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.25","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-26T16:08:01.567Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-3c87a91ce7ae945989808a42fa2e4006","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=ce250c35-efe6-4bb6-9846-e1ccb66cd2d5\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=ce250c35-efe6-4bb6-9846-e1ccb66cd2d5\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=ce250c35-efe6-4bb6-9846-e1ccb66cd2d5\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"83c73f02-7dcc-4f2f-a0cf-1249c15e25f0","user_code_job_started_at":"2026-09-26T16:08:42.833Z","user_code_job_completed_at":"2026-09-26T16:12:08.309Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=3d50b69f05812c94eaa111867b00c1292fb11ac3e17b232791c7b84091642182","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"190d64af-16e5-4219-b78b-51669ed598b5","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.24","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-26T16:06:12.341Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-a745f1e69b37ff514696ed90070a488a","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=190d64af-16e5-4219-b78b-51669ed598b5\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=190d64af-16e5-4219-b78b-51669ed598b5\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=190d64af-16e5-4219-b78b-51669ed598b5\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"d17e493a-2b17-41ee-83cb-67ddff8a9af2","user_code_job_started_at":"2026-09-26T16:07:11.391Z","user_code_job_completed_at":"2026-09-26T16:12:08.324Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=7f12f425736e368b291e7237a5cdb2acf3e391ffc93ca8b8ac05d59ef834a1db","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"b37da591-1051-4120-a7b1-cd3eede5562f","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.23","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-25T13:29:43.172Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-507fba0a537e78a23baa74801ad10acf","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=b37da591-1051-4120-a7b1-cd3eede5562f\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=b37da591-1051-4120-a7b1-cd3eede5562f\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=b37da591-1051-4120-a7b1-cd3eede5562f\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"9f431582-e384-48a3-9a8f-be14dffd8d65","user_code_job_started_at":"2026-09-25T13:30:37.049Z","user_code_job_completed_at":"2026-09-25T13:35:22.633Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=fec2e1bcd2d105e2df3e7ab3d1ee9a3dad09ebabcc7010c1e7949cdb483ba730","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"8ee71242-0d6c-4ee4-8f69-02901ac7bbf8","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.22","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-25T12:26:19.147Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-4d376fc19dfef475550c6a9b677c59b5","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8ee71242-0d6c-4ee4-8f69-02901ac7bbf8\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8ee71242-0d6c-4ee4-8f69-02901ac7bbf8\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8ee71242-0d6c-4ee4-8f69-02901ac7bbf8\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"210913de-fe92-4d95-bf98-af0b1498823f","user_code_job_started_at":"2026-09-25T12:26:54.286Z","user_code_job_completed_at":"2026-09-25T12:30:37.652Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=7b21056958d4a2b76f35133cef555be7cfbbe18729d750394dcef7dceec08467","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"d147f457-53fb-444e-9fa7-85ee390784e8","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.21","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-22T14:58:59.484Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-932759638241f10c5e8c33eb109ac734","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d147f457-53fb-444e-9fa7-85ee390784e8\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d147f457-53fb-444e-9fa7-85ee390784e8\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d147f457-53fb-444e-9fa7-85ee390784e8\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"3b012c7b-9957-4824-ba87-2435e1e9ee14","user_code_job_started_at":"2026-09-22T14:59:40.309Z","user_code_job_completed_at":"2026-09-22T15:04:35.417Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=eeff93e2c355e360ec97684690fb53cf77e6c9ef0bf3a4e35531c597835292e6","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"da9bbc70-169b-4ffb-b165-2f84e23da65c","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.20","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-21T13:34:25.986Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-d2ea1ec889d8f60ab2f5bdbc293a838b","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=da9bbc70-169b-4ffb-b165-2f84e23da65c\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=da9bbc70-169b-4ffb-b165-2f84e23da65c\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=da9bbc70-169b-4ffb-b165-2f84e23da65c\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"bb7640d4-957c-478c-8efa-6f2dbb82c7a0","user_code_job_started_at":"2026-09-21T13:35:02.601Z","user_code_job_completed_at":"2026-09-21T13:39:07.874Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=03d2bf1bb046c99064f52f147a9a7ede51a66a2edad91b8e749a38ac653c2e7a","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"575c3059-0e95-4601-9a67-4db9ffb7d032","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.19","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-14T15:48:46.601Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-965b877ca179b8ef590128beee376fcd","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=575c3059-0e95-4601-9a67-4db9ffb7d032\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=575c3059-0e95-4601-9a67-4db9ffb7d032\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=575c3059-0e95-4601-9a67-4db9ffb7d032\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"7cf2e588-f306-407a-866b-4ca83618f8be","user_code_job_started_at":"2026-09-14T15:50:12.754Z","user_code_job_completed_at":"2026-09-14T15:52:46.023Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=c47045ea86427a548194f00a546bdf915ed33f250e5014d68d2f2b07735fdf01","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"608c3e4c-60be-42ff-beec-a38c15d5c8f8","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.18","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-14T14:18:37.700Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-52231ac5a3d2038c83fd31dae0b726c1","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=608c3e4c-60be-42ff-beec-a38c15d5c8f8\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=608c3e4c-60be-42ff-beec-a38c15d5c8f8\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=608c3e4c-60be-42ff-beec-a38c15d5c8f8\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"c1809d68-3a39-4e4d-a566-033b8a872335","user_code_job_started_at":"2026-09-14T14:20:06.825Z","user_code_job_completed_at":"2026-09-14T14:22:28.650Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=a4a4c6bce840527a0b0a073f7c64805fdf23f5a012d652c00ca1e0bd6b54515c","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"a783da99-4595-49c5-a3ce-198b77760fc9","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.17","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-14T13:57:56.309Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-c1009dfcaa8d91896c25d92d3b1b579b","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=a783da99-4595-49c5-a3ce-198b77760fc9\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=a783da99-4595-49c5-a3ce-198b77760fc9\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=a783da99-4595-49c5-a3ce-198b77760fc9\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"1a488ac9-8455-4a44-ae7e-eea969db673a","user_code_job_started_at":"2026-09-14T14:02:10.051Z","user_code_job_completed_at":"2026-09-14T14:04:41.631Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=54adc9a401d8db7535007c2d79027a1f77cd946d26d95833fbc9cca766c73291","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"08713481-ca94-4dad-8f44-a6e8f2e92ab6","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.16","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-11T21:21:13.195Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-caa73f063ac80b16533570968545ea1f","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=08713481-ca94-4dad-8f44-a6e8f2e92ab6\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=08713481-ca94-4dad-8f44-a6e8f2e92ab6\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=08713481-ca94-4dad-8f44-a6e8f2e92ab6\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"7c5e1c7f-7b4c-45c1-8a09-bc65c86b4711","user_code_job_started_at":"2026-09-11T21:21:30.474Z","user_code_job_completed_at":"2026-09-11T21:23:41.421Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=06f6ab05c99b8a42cb6c9ae0370554edd095f8f32f8a4d802507334a5484c4cf","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"34e703c2-b4a6-45cb-ac02-edd0b4bf8c34","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.16-nema17.1","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":false,"is_pr_preview":false,"created_at":"2026-09-11T21:20:10.267Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-112f86d4941b0c904c6629c119cce047","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":null,"user_code_job_started_at":null,"user_code_job_completed_at":null,"user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"36aefa5d-e57c-4c72-9b98-f37f33eb7826","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.14","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-05T14:14:23.095Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-0a5f07b1336865830f90976bdf24a4cb","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=36aefa5d-e57c-4c72-9b98-f37f33eb7826\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=36aefa5d-e57c-4c72-9b98-f37f33eb7826\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=36aefa5d-e57c-4c72-9b98-f37f33eb7826\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"88e99428-1434-4b18-928c-9c6e87b1081f","user_code_job_started_at":"2026-09-05T14:14:50.307Z","user_code_job_completed_at":"2026-09-05T14:23:07.727Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=e4a4bdaf23fefd20af3a67d13e68cada98e85a54ac67ca7db00e4d03e0f4835b","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"a83b8d4b-86c7-4e57-a399-e3c1a03f2374","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.13","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-26T13:48:17.417Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-de162876523e6e1deb6b55166e525bfc","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=a83b8d4b-86c7-4e57-a399-e3c1a03f2374\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=a83b8d4b-86c7-4e57-a399-e3c1a03f2374\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=a83b8d4b-86c7-4e57-a399-e3c1a03f2374\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"91352f48-acea-4a88-91a9-b118782aa842","user_code_job_started_at":"2026-08-26T13:48:33.167Z","user_code_job_completed_at":"2026-08-26T13:59:02.540Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=b1622ef4bb876434ec5525f375d261fadfd8a829733baaf549e9d26701e67da9","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"c68f478b-d2f7-4e1e-a54c-c65c42ab100a","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.12","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-25T12:31:00.013Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-b9860ac23b22c2e6d9bcc085df617852","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=c68f478b-d2f7-4e1e-a54c-c65c42ab100a\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=c68f478b-d2f7-4e1e-a54c-c65c42ab100a\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=c68f478b-d2f7-4e1e-a54c-c65c42ab100a\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"af331ee8-f7cc-4d2d-8dd0-a3c4aebccc10","user_code_job_started_at":"2026-08-25T12:31:18.200Z","user_code_job_completed_at":"2026-08-25T12:35:23.670Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=3db943c2a7480a83363f6345d8887bd927e26156fbdb8b24f9889cf294b0ed5d","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"475116de-d065-4f1e-b68e-9b8fa84addf7","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.11","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-25T09:54:33.116Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-17b11ce44fac39b9d4d3408d52b57e74","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=475116de-d065-4f1e-b68e-9b8fa84addf7\u0026file_path=dist%2Findex.circuit%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=475116de-d065-4f1e-b68e-9b8fa84addf7\u0026file_path=dist%2Findex.circuit%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=475116de-d065-4f1e-b68e-9b8fa84addf7\u0026file_path=dist%2Findex.circuit%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"a6c89c3d-edd2-4f09-a478-94089612c33f","user_code_job_started_at":"2026-08-25T09:55:24.229Z","user_code_job_completed_at":"2026-08-25T09:59:07.664Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=2724b1f994dca50efe154bdc622dec674091cf45697f21ebbba60d0bc22e6ef2","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"d09aa437-8b63-40e4-97df-54796132df64","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.10","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-21T14:25:35.310Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-4679841238dbc76e315b449eb96994f0","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d09aa437-8b63-40e4-97df-54796132df64\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d09aa437-8b63-40e4-97df-54796132df64\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d09aa437-8b63-40e4-97df-54796132df64\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"ba32b833-b009-4371-a63c-78f754e7121a","user_code_job_started_at":"2026-08-21T14:26:24.122Z","user_code_job_completed_at":"2026-08-21T14:30:27.156Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=8c81115f3a44e77def1ef65fc3bae7a83b9a7cdc3a1cb20a1896421993727f4f","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"d212a3a1-e4e1-4e7d-b2a9-4776edc79834","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.9","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-21T13:31:00.200Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-ae6fec442bd8f029d929c1b7c738f85b","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d212a3a1-e4e1-4e7d-b2a9-4776edc79834\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d212a3a1-e4e1-4e7d-b2a9-4776edc79834\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d212a3a1-e4e1-4e7d-b2a9-4776edc79834\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"08896090-3fc1-4cef-ab61-69ce096e392d","user_code_job_started_at":"2026-08-21T13:31:28.036Z","user_code_job_completed_at":"2026-08-21T13:35:12.517Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=b3e044234f864b2254831b616859fcd95720833ada2a4d6367e3e67b3391233b","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"40aaa93b-fd56-4dd5-bd37-81728a3fda64","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.8","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-21T13:23:11.463Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-30fb73149b2f890637471e9ebf3ad1df","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=40aaa93b-fd56-4dd5-bd37-81728a3fda64\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=40aaa93b-fd56-4dd5-bd37-81728a3fda64\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=40aaa93b-fd56-4dd5-bd37-81728a3fda64\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"619d6ce3-7d32-4828-920e-a7b9c893cf3c","user_code_job_started_at":"2026-08-21T13:23:42.302Z","user_code_job_completed_at":"2026-08-21T13:27:14.952Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=4fb7efafc99e8560391b08369e83045ba7f43a22de1b47081ab863e0d74e483c","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"835cc8cf-dfd3-41de-b4a8-8b99c146b071","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.7","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-21T12:57:38.254Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-63eb631ca4945adbb89e7bd5ab95f819","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=835cc8cf-dfd3-41de-b4a8-8b99c146b071\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=835cc8cf-dfd3-41de-b4a8-8b99c146b071\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=835cc8cf-dfd3-41de-b4a8-8b99c146b071\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"08e2f730-36e3-4fb2-a441-78099d47cf1f","user_code_job_started_at":"2026-08-21T12:58:02.580Z","user_code_job_completed_at":"2026-08-21T13:01:34.207Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=1af85ac5206c79370d3b8fafa85cdb22d1ffff1d1ab6fe80583e351a0cf7639b","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"e1f376f9-50f2-4437-9c89-96a2a2536713","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.6","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-19T17:08:50.918Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-65a6b00f7d0e063d3e10efbfbc12dc8d","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=e1f376f9-50f2-4437-9c89-96a2a2536713\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=e1f376f9-50f2-4437-9c89-96a2a2536713\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=e1f376f9-50f2-4437-9c89-96a2a2536713\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"a60e4cbe-2e95-4cfc-bb4b-adb53b316c05","user_code_job_started_at":"2026-08-19T17:09:23.753Z","user_code_job_completed_at":"2026-08-19T17:12:36.171Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=e6ee62aad6ac1dd8d7ebb4a66d006688e7f83a3a3c381ee2093eaf270964c954","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"a10f104e-b67e-42de-b200-b344d7b70b64","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.5","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-19T10:42:29.176Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-cb4fdba932a6700359384c63c2e18f52","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"e956cb86-cc55-430e-9300-22ec0a5156d5","user_code_job_started_at":"2026-08-19T10:43:01.324Z","user_code_job_completed_at":"2026-08-19T10:49:46.579Z","user_code_job_error":{"message":"There was an error running the job on our infrastructure, this is probably not your code, see build logs","error_code":"user_code_job_infrastructure_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=34c8fb28216e5e4ce2bd14052d1b891407faa44a45171ef0aa10376dad4ce7cd","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"2c48ca3c-6a03-4e11-89ae-31397ee4e2dc","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.4","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-08T01:51:39.287Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-34f5b427580c8397b3e33fac7e80917a","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=2c48ca3c-6a03-4e11-89ae-31397ee4e2dc\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=2c48ca3c-6a03-4e11-89ae-31397ee4e2dc\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=2c48ca3c-6a03-4e11-89ae-31397ee4e2dc\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"435e946d-4668-470a-8663-beb72875721e","user_code_job_started_at":"2026-08-08T08:49:21.050Z","user_code_job_completed_at":"2026-08-08T08:51:05.525Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=4b922ad9c40320a1e1998c67d5817cfe4d41bf4c2ca5c5e395800efea6e937a9","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"e0a3934a-5e4e-4a7a-94c3-5c0bfdfe5bce","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.3","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":false,"is_pr_preview":false,"created_at":"2026-08-08T00:47:52.933Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-7808892ea143d7ce9c9a00b0189f228c","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":null,"user_code_job_started_at":null,"user_code_job_completed_at":null,"user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"4e0554f1-5a1c-4695-9fd1-eade4aa72160","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.2","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-08T00:40:25.595Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-98dbc3cc6dbd29f9c6d8446af251aeeb","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=4e0554f1-5a1c-4695-9fd1-eade4aa72160\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=4e0554f1-5a1c-4695-9fd1-eade4aa72160\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=4e0554f1-5a1c-4695-9fd1-eade4aa72160\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"f918c826-be4a-4185-bd75-a483511c6c0a","user_code_job_started_at":"2026-08-08T00:40:58.785Z","user_code_job_completed_at":"2026-08-08T00:43:51.328Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=7a5c7bea4377ca345103afc8775dd7b58247afe4fc72cf932637b03ea427d0f2","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"86a5ae2f-7ee0-4c43-a016-fbfcf145c0e8","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.1","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-08T00:25:17.319Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-3214604e2dd40ea42e0a6dbfae60ec51","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=86a5ae2f-7ee0-4c43-a016-fbfcf145c0e8\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=86a5ae2f-7ee0-4c43-a016-fbfcf145c0e8\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=86a5ae2f-7ee0-4c43-a016-fbfcf145c0e8\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"7e12b65a-fbb4-4a73-8f74-8f0be658ce48","user_code_job_started_at":"2026-08-08T00:25:44.383Z","user_code_job_completed_at":"2026-08-08T00:28:48.368Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=57c71d4580757a59cc95daf6626a67d4836d98bbb0b77cdb7efbb1087efd788f","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"ec3b714f-63e8-42f5-8a2f-580234f6f912","package_id":"f064ebaf-e000-4825-a7fb-2871976fb32b","version":"1.0.0","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-08-07T23:10:26.763Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-29be2dca7ac1b3760ea4c807dddeda16","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"c3e5eaa4-4003-4c5a-bef5-aabc293e7c76","user_code_job_started_at":"2026-08-07T23:11:00.381Z","user_code_job_completed_at":"2026-08-07T23:16:29.555Z","user_code_job_error":{"message":"Your code failed to build (exit code 1), see build logs for the error details","error_code":"user_code_build_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=c94e164d69cd676707e253a989ba5eabfd1429092965afe214b978683897af48","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null}]; window.SSR_PACKAGE_BUILDS = []; window.SSR_RELATED_PACKAGES = [{"package_id":"06a07953-7d64-492c-803d-e5e9badffdd9","creator_account_id":"96f144ef-7dfe-4068-aac0-8753c8ab5f62","latest_package_release_id":"ae9d054a-2cdb-4e61-acbc-af70cabaedf8","last_built_release_id":"ae9d054a-2cdb-4e61-acbc-af70cabaedf8","latest_package_release_fs_sha":"md5-e3df978b4a23e2ca5335cb2b159789c2","latest_pcb_preview_image_url":"https://registry-api.tscircuit.com/package_files/view?package_release_id=ae9d054a-2cdb-4e61-acbc-af70cabaedf8\u0026file_path=dist%2Fpcb.svg","latest_sch_preview_image_url":"https://registry-api.tscircuit.com/package_files/view?package_release_id=ae9d054a-2cdb-4e61-acbc-af70cabaedf8\u0026file_path=dist%2Fschematic.svg","latest_cad_preview_image_url":"https://registry-api.tscircuit.com/package_files/view?package_release_id=ae9d054a-2cdb-4e61-acbc-af70cabaedf8\u0026file_path=dist%2F3d.png","latest_version":"0.0.1","license":"unset","owner_org_id":"719473db-1754-470b-a747-20148ebb82aa","org_owner_tscircuit_handle":"imrishabh18","owner_github_username":"imrishabh18","github_repo_full_name":null,"is_source_from_github":false,"description":null,"name":"imrishabh18/3d-model-test","unscoped_name":"3d-model-test","star_count":0,"created_at":"2026-02-05T10:25:33.249Z","updated_at":"2026-02-09T10:48:53.557Z","ai_description":"It loads a 3D model of an electronic component onto a circuit board with specified positioning.","ai_usage_instructions":null,"is_private":false,"is_unlisted":false,"is_public":true,"public_dist_enabled":false,"has_public_dist":true,"starred_at":null,"default_view":"3d","website":null,"github_installation_id":null,"allow_pr_previews":false,"related_type":"same_author","thumbnail_url":"https://registry-api.tscircuit.com/package_files/view?package_release_id=ae9d054a-2cdb-4e61-acbc-af70cabaedf8\u0026file_path=dist%2F3d.png"},{"package_id":"d2ea0487-143c-447f-a62e-ab971c2524cd","creator_account_id":"9f398687-69d0-4ef4-a48c-bb6dc990e7df","latest_package_release_id":"bde55b83-e437-4d8f-b5c0-1e0b68a70ec3","last_built_release_id":"bde55b83-e437-4d8f-b5c0-1e0b68a70ec3","latest_package_release_fs_sha":"md5-4095a4495925ad2deb356dc9c3cccaaf","latest_pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=bde55b83-e437-4d8f-b5c0-1e0b68a70ec3\u0026file_path=dist%2Findex%2Fpcb.svg","latest_sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=bde55b83-e437-4d8f-b5c0-1e0b68a70ec3\u0026file_path=dist%2Findex%2Fschematic.svg","latest_cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=bde55b83-e437-4d8f-b5c0-1e0b68a70ec3\u0026file_path=dist%2Findex%2F3d.png","latest_version":"1.4.0","license":"unset","owner_org_id":"7ca3101d-0ece-4182-a775-d3aee7d7f0a0","org_owner_tscircuit_handle":"astra","owner_github_username":null,"github_repo_full_name":null,"is_source_from_github":false,"description":null,"name":"astra/nema17-stepper-motor-controller-spring-clamp-rp2040","unscoped_name":"nema17-stepper-motor-controller-spring-clamp-rp2040","star_count":0,"created_at":"2026-09-26T19:14:57.511Z","updated_at":"2026-09-28T19:52:44.691Z","ai_description":"A 4-layer RP2040 controller board that negotiates USB‑C PD motor power and drives a NEMA17 stepper via a DRV8825, with current sensing, thermal shutdown, RGB status LED, buzzer alarm, optional AS5600 encoder, protection/filtering, and test points.","ai_usage_instructions":null,"is_private":false,"is_unlisted":false,"is_public":true,"public_dist_enabled":false,"has_public_dist":true,"starred_at":null,"default_view":"files","website":null,"github_installation_id":null,"allow_pr_previews":false,"related_type":"similar_ai_description","thumbnail_url":"https://api.tscircuit.com/package_files/view?package_release_id=bde55b83-e437-4d8f-b5c0-1e0b68a70ec3\u0026file_path=dist%2Findex%2Fpcb.svg"},{"package_id":"b956dcd0-e37b-4022-a655-c93ee2f70790","creator_account_id":"9f398687-69d0-4ef4-a48c-bb6dc990e7df","latest_package_release_id":"05cd794e-886e-4afb-bce4-2057190a6e7b","last_built_release_id":"05cd794e-886e-4afb-bce4-2057190a6e7b","latest_package_release_fs_sha":"md5-02368e63f555bf5f853432c70765cb04","latest_pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=05cd794e-886e-4afb-bce4-2057190a6e7b\u0026file_path=dist%2Findex%2Fpcb.svg","latest_sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=05cd794e-886e-4afb-bce4-2057190a6e7b\u0026file_path=dist%2Findex%2Fschematic.svg","latest_cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=05cd794e-886e-4afb-bce4-2057190a6e7b\u0026file_path=dist%2Findex%2F3d.png","latest_version":"0.1.5","license":"unset","owner_org_id":"f154d4e0-ac63-47a3-948e-a13da34df910","org_owner_tscircuit_handle":"seveibar","owner_github_username":"seveibar","github_repo_full_name":null,"is_source_from_github":false,"description":null,"name":"seveibar/am3352-dev-board-4layer-dogbone","unscoped_name":"am3352-dev-board-4layer-dogbone","star_count":0,"created_at":"2026-09-19T20:54:27.568Z","updated_at":"2026-09-21T23:56:14.470Z","ai_description":"Defines PCB footprints and pin mappings for a TI AM3352ZCZ100 processor, JST GH connectors, and assembly-part lookup helpers for capacitors, resistors, and headers.","ai_usage_instructions":null,"is_private":false,"is_unlisted":false,"is_public":true,"public_dist_enabled":false,"has_public_dist":true,"starred_at":null,"default_view":"files","website":null,"github_installation_id":null,"allow_pr_previews":false,"related_type":"random","thumbnail_url":"https://api.tscircuit.com/package_files/view?package_release_id=05cd794e-886e-4afb-bce4-2057190a6e7b\u0026file_path=dist%2Findex%2Fpcb.svg"}]; window.SSR_PACKAGE_ROUTE = {"author":"imrishabh18","packageName":"rp2040-motor-controller","packageNameWithScope":"imrishabh18/rp2040-motor-controller","version":null,"isLegacyRoute":false,"kind":"file","filePath":"vendor/schematic-style-analysis.js"};

imrishabh18/rp2040-motor-controller

An RP2040-based NEMA17 stepper-motor controller with USB-C programming and PD motor-power negotiation, DRV8825 dual H-bridge drive, current/temperature telemetry, protected power filtering, status RGB LED, buzzer alarm, and optional magnetic encoder.

Version
1.0.42
License
unset
Stars
3

vendor/schematic-style-analysis.js

// Browser bundle of tscircuit/circuit-json-schematic-placement-analysis
// Commit fc054b4b47def6c22247f21c112345bc1a6ddf66 (PR #168); MIT licensed.
// Built with: bun build lib/analyze-schematic-placement.ts --target browser
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
function __accessProp(key) {
  return this[key];
}
var __toESMCache_node;
var __toESMCache_esm;
var __toESM = (mod, isNodeMode, target) => {
  var canCache = mod != null && typeof mod === "object";
  if (canCache) {
    var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
    var cached = cache.get(mod);
    if (cached)
      return cached;
  }
  target = mod != null ? __create(__getProtoOf(mod)) : {};
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
  for (let key of __getOwnPropNames(mod))
    if (!__hasOwnProp.call(to, key))
      __defProp(to, key, {
        get: __accessProp.bind(mod, key),
        enumerable: true
      });
  if (canCache)
    cache.set(mod, to);
  return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __returnValue = (v) => v;
function __exportSetter(name, newValue) {
  this[name] = __returnValue.bind(null, newValue);
}
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: __exportSetter.bind(all, name)
    });
};

// ../../work/placement-analysis/node_modules/svgson/dist/svgson.umd.js
var require_svgson_umd = __commonJS((exports, module) => {
  (function(global, factory) {
    typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, global.svgson = factory());
  })(exports, function() {
    /*!
       * Determine if an object is a Buffer
       *
       * @author   Feross Aboukhadijeh <https://feross.org>
       * @license  MIT
       */
    var isBuffer_1 = function(obj) {
      return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer);
    };
    function isBuffer(obj) {
      return !!obj.constructor && typeof obj.constructor.isBuffer === "function" && obj.constructor.isBuffer(obj);
    }
    function isSlowBuffer(obj) {
      return typeof obj.readFloatLE === "function" && typeof obj.slice === "function" && isBuffer(obj.slice(0, 0));
    }
    var toString2 = Object.prototype.toString;
    var kindOf = function kindOf2(val) {
      if (typeof val === "undefined") {
        return "undefined";
      }
      if (val === null) {
        return "null";
      }
      if (val === true || val === false || val instanceof Boolean) {
        return "boolean";
      }
      if (typeof val === "string" || val instanceof String) {
        return "string";
      }
      if (typeof val === "number" || val instanceof Number) {
        return "number";
      }
      if (typeof val === "function" || val instanceof Function) {
        return "function";
      }
      if (typeof Array.isArray !== "undefined" && Array.isArray(val)) {
        return "array";
      }
      if (val instanceof RegExp) {
        return "regexp";
      }
      if (val instanceof Date) {
        return "date";
      }
      var type = toString2.call(val);
      if (type === "[object RegExp]") {
        return "regexp";
      }
      if (type === "[object Date]") {
        return "date";
      }
      if (type === "[object Arguments]") {
        return "arguments";
      }
      if (type === "[object Error]") {
        return "error";
      }
      if (isBuffer_1(val)) {
        return "buffer";
      }
      if (type === "[object Set]") {
        return "set";
      }
      if (type === "[object WeakSet]") {
        return "weakset";
      }
      if (type === "[object Map]") {
        return "map";
      }
      if (type === "[object WeakMap]") {
        return "weakmap";
      }
      if (type === "[object Symbol]") {
        return "symbol";
      }
      if (type === "[object Int8Array]") {
        return "int8array";
      }
      if (type === "[object Uint8Array]") {
        return "uint8array";
      }
      if (type === "[object Uint8ClampedArray]") {
        return "uint8clampedarray";
      }
      if (type === "[object Int16Array]") {
        return "int16array";
      }
      if (type === "[object Uint16Array]") {
        return "uint16array";
      }
      if (type === "[object Int32Array]") {
        return "int32array";
      }
      if (type === "[object Uint32Array]") {
        return "uint32array";
      }
      if (type === "[object Float32Array]") {
        return "float32array";
      }
      if (type === "[object Float64Array]") {
        return "float64array";
      }
      return "object";
    };
    function createCommonjsModule(fn, module2) {
      return module2 = { exports: {} }, fn(module2, module2.exports), module2.exports;
    }
    var renameKeys = createCommonjsModule(function(module2) {
      (function() {
        function rename(obj, fn) {
          if (typeof fn !== "function") {
            return obj;
          }
          var res = {};
          for (var key in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, key)) {
              res[fn(key, obj[key]) || key] = obj[key];
            }
          }
          return res;
        }
        if (module2.exports) {
          module2.exports = rename;
        } else {
          {
            window.rename = rename;
          }
        }
      })();
    });
    var deepRenameKeys = function renameDeep(obj, cb) {
      var type = kindOf(obj);
      if (type !== "object" && type !== "array") {
        throw new Error("expected an object");
      }
      var res = [];
      if (type === "object") {
        obj = renameKeys(obj, cb);
        res = {};
      }
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          var val = obj[key];
          if (kindOf(val) === "object" || kindOf(val) === "array") {
            res[key] = renameDeep(val, cb);
          } else {
            res[key] = val;
          }
        }
      }
      return res;
    };
    var eventemitter3 = createCommonjsModule(function(module2) {
      var has = Object.prototype.hasOwnProperty, prefix = "~";
      function Events() {}
      if (Object.create) {
        Events.prototype = Object.create(null);
        if (!new Events().__proto__)
          prefix = false;
      }
      function EE(fn, context, once) {
        this.fn = fn;
        this.context = context;
        this.once = once || false;
      }
      function EventEmitter() {
        this._events = new Events;
        this._eventsCount = 0;
      }
      EventEmitter.prototype.eventNames = function eventNames() {
        var names = [], events, name;
        if (this._eventsCount === 0)
          return names;
        for (name in events = this._events) {
          if (has.call(events, name))
            names.push(prefix ? name.slice(1) : name);
        }
        if (Object.getOwnPropertySymbols) {
          return names.concat(Object.getOwnPropertySymbols(events));
        }
        return names;
      };
      EventEmitter.prototype.listeners = function listeners(event, exists) {
        var evt = prefix ? prefix + event : event, available = this._events[evt];
        if (exists)
          return !!available;
        if (!available)
          return [];
        if (available.fn)
          return [available.fn];
        for (var i = 0, l = available.length, ee = new Array(l);i < l; i++) {
          ee[i] = available[i].fn;
        }
        return ee;
      };
      EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
        var evt = prefix ? prefix + event : event;
        if (!this._events[evt])
          return false;
        var listeners = this._events[evt], len = arguments.length, args, i;
        if (listeners.fn) {
          if (listeners.once)
            this.removeListener(event, listeners.fn, undefined, true);
          switch (len) {
            case 1:
              return listeners.fn.call(listeners.context), true;
            case 2:
              return listeners.fn.call(listeners.context, a1), true;
            case 3:
              return listeners.fn.call(listeners.context, a1, a2), true;
            case 4:
              return listeners.fn.call(listeners.context, a1, a2, a3), true;
            case 5:
              return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
            case 6:
              return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
          }
          for (i = 1, args = new Array(len - 1);i < len; i++) {
            args[i - 1] = arguments[i];
          }
          listeners.fn.apply(listeners.context, args);
        } else {
          var length = listeners.length, j;
          for (i = 0;i < length; i++) {
            if (listeners[i].once)
              this.removeListener(event, listeners[i].fn, undefined, true);
            switch (len) {
              case 1:
                listeners[i].fn.call(listeners[i].context);
                break;
              case 2:
                listeners[i].fn.call(listeners[i].context, a1);
                break;
              case 3:
                listeners[i].fn.call(listeners[i].context, a1, a2);
                break;
              case 4:
                listeners[i].fn.call(listeners[i].context, a1, a2, a3);
                break;
              default:
                if (!args)
                  for (j = 1, args = new Array(len - 1);j < len; j++) {
                    args[j - 1] = arguments[j];
                  }
                listeners[i].fn.apply(listeners[i].context, args);
            }
          }
        }
        return true;
      };
      EventEmitter.prototype.on = function on(event, fn, context) {
        var listener = new EE(fn, context || this), evt = prefix ? prefix + event : event;
        if (!this._events[evt])
          this._events[evt] = listener, this._eventsCount++;
        else if (!this._events[evt].fn)
          this._events[evt].push(listener);
        else
          this._events[evt] = [this._events[evt], listener];
        return this;
      };
      EventEmitter.prototype.once = function once(event, fn, context) {
        var listener = new EE(fn, context || this, true), evt = prefix ? prefix + event : event;
        if (!this._events[evt])
          this._events[evt] = listener, this._eventsCount++;
        else if (!this._events[evt].fn)
          this._events[evt].push(listener);
        else
          this._events[evt] = [this._events[evt], listener];
        return this;
      };
      EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
        var evt = prefix ? prefix + event : event;
        if (!this._events[evt])
          return this;
        if (!fn) {
          if (--this._eventsCount === 0)
            this._events = new Events;
          else
            delete this._events[evt];
          return this;
        }
        var listeners = this._events[evt];
        if (listeners.fn) {
          if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) {
            if (--this._eventsCount === 0)
              this._events = new Events;
            else
              delete this._events[evt];
          }
        } else {
          for (var i = 0, events = [], length = listeners.length;i < length; i++) {
            if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) {
              events.push(listeners[i]);
            }
          }
          if (events.length)
            this._events[evt] = events.length === 1 ? events[0] : events;
          else if (--this._eventsCount === 0)
            this._events = new Events;
          else
            delete this._events[evt];
        }
        return this;
      };
      EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
        var evt;
        if (event) {
          evt = prefix ? prefix + event : event;
          if (this._events[evt]) {
            if (--this._eventsCount === 0)
              this._events = new Events;
            else
              delete this._events[evt];
          }
        } else {
          this._events = new Events;
          this._eventsCount = 0;
        }
        return this;
      };
      EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
      EventEmitter.prototype.addListener = EventEmitter.prototype.on;
      EventEmitter.prototype.setMaxListeners = function setMaxListeners() {
        return this;
      };
      EventEmitter.prefixed = prefix;
      EventEmitter.EventEmitter = EventEmitter;
      {
        module2.exports = EventEmitter;
      }
    });
    function _defineProperty(obj, key, value) {
      if (key in obj) {
        Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
      } else {
        obj[key] = value;
      }
      return obj;
    }
    var noop = function noop2() {};
    var State = {
      data: "state-data",
      cdata: "state-cdata",
      tagBegin: "state-tag-begin",
      tagName: "state-tag-name",
      tagEnd: "state-tag-end",
      attributeNameStart: "state-attribute-name-start",
      attributeName: "state-attribute-name",
      attributeNameEnd: "state-attribute-name-end",
      attributeValueBegin: "state-attribute-value-begin",
      attributeValue: "state-attribute-value"
    };
    var Action = {
      lt: "action-lt",
      gt: "action-gt",
      space: "action-space",
      equal: "action-equal",
      quote: "action-quote",
      slash: "action-slash",
      char: "action-char",
      error: "action-error"
    };
    var Type$1 = {
      text: "text",
      openTag: "open-tag",
      closeTag: "close-tag",
      attributeName: "attribute-name",
      attributeValue: "attribute-value"
    };
    var charToAction = {
      " ": Action.space,
      "\t": Action.space,
      "\n": Action.space,
      "\r": Action.space,
      "<": Action.lt,
      ">": Action.gt,
      '"': Action.quote,
      "'": Action.quote,
      "=": Action.equal,
      "/": Action.slash
    };
    var getAction = function getAction2(char) {
      return charToAction[char] || Action.char;
    };
    var create$1 = function create2(options) {
      var _State$data, _State$tagBegin, _State$tagName, _State$tagEnd, _State$attributeNameS, _State$attributeName, _State$attributeNameE, _State$attributeValue, _State$attributeValue2, _lexer$stateMachine;
      options = Object.assign({ debug: false }, options);
      var lexer2 = new eventemitter3;
      var state = State.data;
      var data = "";
      var tagName = "";
      var attrName = "";
      var attrValue = "";
      var isClosing = "";
      var openingQuote = "";
      var emit = function emit2(type, value) {
        if (tagName[0] === "?" || tagName[0] === "!") {
          return;
        }
        var event = { type, value };
        if (options.debug) {
          console.log("emit:", event);
        }
        lexer2.emit("data", event);
      };
      lexer2.stateMachine = (_lexer$stateMachine = {}, _defineProperty(_lexer$stateMachine, State.data, (_State$data = {}, _defineProperty(_State$data, Action.lt, function() {
        if (data.trim()) {
          emit(Type$1.text, data);
        }
        tagName = "";
        isClosing = false;
        state = State.tagBegin;
      }), _defineProperty(_State$data, Action.char, function(char) {
        data += char;
      }), _State$data)), _defineProperty(_lexer$stateMachine, State.cdata, _defineProperty({}, Action.char, function(char) {
        data += char;
        if (data.substr(-3) === "]]>") {
          emit(Type$1.text, data.slice(0, -3));
          data = "";
          state = State.data;
        }
      })), _defineProperty(_lexer$stateMachine, State.tagBegin, (_State$tagBegin = {}, _defineProperty(_State$tagBegin, Action.space, noop), _defineProperty(_State$tagBegin, Action.char, function(char) {
        tagName = char;
        state = State.tagName;
      }), _defineProperty(_State$tagBegin, Action.slash, function() {
        tagName = "";
        isClosing = true;
      }), _State$tagBegin)), _defineProperty(_lexer$stateMachine, State.tagName, (_State$tagName = {}, _defineProperty(_State$tagName, Action.space, function() {
        if (isClosing) {
          state = State.tagEnd;
        } else {
          state = State.attributeNameStart;
          emit(Type$1.openTag, tagName);
        }
      }), _defineProperty(_State$tagName, Action.gt, function() {
        if (isClosing) {
          emit(Type$1.closeTag, tagName);
        } else {
          emit(Type$1.openTag, tagName);
        }
        data = "";
        state = State.data;
      }), _defineProperty(_State$tagName, Action.slash, function() {
        state = State.tagEnd;
        emit(Type$1.openTag, tagName);
      }), _defineProperty(_State$tagName, Action.char, function(char) {
        tagName += char;
        if (tagName === "![CDATA[") {
          state = State.cdata;
          data = "";
          tagName = "";
        }
      }), _State$tagName)), _defineProperty(_lexer$stateMachine, State.tagEnd, (_State$tagEnd = {}, _defineProperty(_State$tagEnd, Action.gt, function() {
        emit(Type$1.closeTag, tagName);
        data = "";
        state = State.data;
      }), _defineProperty(_State$tagEnd, Action.char, noop), _State$tagEnd)), _defineProperty(_lexer$stateMachine, State.attributeNameStart, (_State$attributeNameS = {}, _defineProperty(_State$attributeNameS, Action.char, function(char) {
        attrName = char;
        state = State.attributeName;
      }), _defineProperty(_State$attributeNameS, Action.gt, function() {
        data = "";
        state = State.data;
      }), _defineProperty(_State$attributeNameS, Action.space, noop), _defineProperty(_State$attributeNameS, Action.slash, function() {
        isClosing = true;
        state = State.tagEnd;
      }), _State$attributeNameS)), _defineProperty(_lexer$stateMachine, State.attributeName, (_State$attributeName = {}, _defineProperty(_State$attributeName, Action.space, function() {
        state = State.attributeNameEnd;
      }), _defineProperty(_State$attributeName, Action.equal, function() {
        emit(Type$1.attributeName, attrName);
        state = State.attributeValueBegin;
      }), _defineProperty(_State$attributeName, Action.gt, function() {
        attrValue = "";
        emit(Type$1.attributeName, attrName);
        emit(Type$1.attributeValue, attrValue);
        data = "";
        state = State.data;
      }), _defineProperty(_State$attributeName, Action.slash, function() {
        isClosing = true;
        attrValue = "";
        emit(Type$1.attributeName, attrName);
        emit(Type$1.attributeValue, attrValue);
        state = State.tagEnd;
      }), _defineProperty(_State$attributeName, Action.char, function(char) {
        attrName += char;
      }), _State$attributeName)), _defineProperty(_lexer$stateMachine, State.attributeNameEnd, (_State$attributeNameE = {}, _defineProperty(_State$attributeNameE, Action.space, noop), _defineProperty(_State$attributeNameE, Action.equal, function() {
        emit(Type$1.attributeName, attrName);
        state = State.attributeValueBegin;
      }), _defineProperty(_State$attributeNameE, Action.gt, function() {
        attrValue = "";
        emit(Type$1.attributeName, attrName);
        emit(Type$1.attributeValue, attrValue);
        data = "";
        state = State.data;
      }), _defineProperty(_State$attributeNameE, Action.char, function(char) {
        attrValue = "";
        emit(Type$1.attributeName, attrName);
        emit(Type$1.attributeValue, attrValue);
        attrName = char;
        state = State.attributeName;
      }), _State$attributeNameE)), _defineProperty(_lexer$stateMachine, State.attributeValueBegin, (_State$attributeValue = {}, _defineProperty(_State$attributeValue, Action.space, noop), _defineProperty(_State$attributeValue, Action.quote, function(char) {
        openingQuote = char;
        attrValue = "";
        state = State.attributeValue;
      }), _defineProperty(_State$attributeValue, Action.gt, function() {
        attrValue = "";
        emit(Type$1.attributeValue, attrValue);
        data = "";
        state = State.data;
      }), _defineProperty(_State$attributeValue, Action.char, function(char) {
        openingQuote = "";
        attrValue = char;
        state = State.attributeValue;
      }), _State$attributeValue)), _defineProperty(_lexer$stateMachine, State.attributeValue, (_State$attributeValue2 = {}, _defineProperty(_State$attributeValue2, Action.space, function(char) {
        if (openingQuote) {
          attrValue += char;
        } else {
          emit(Type$1.attributeValue, attrValue);
          state = State.attributeNameStart;
        }
      }), _defineProperty(_State$attributeValue2, Action.quote, function(char) {
        if (openingQuote === char) {
          emit(Type$1.attributeValue, attrValue);
          state = State.attributeNameStart;
        } else {
          attrValue += char;
        }
      }), _defineProperty(_State$attributeValue2, Action.gt, function(char) {
        if (openingQuote) {
          attrValue += char;
        } else {
          emit(Type$1.attributeValue, attrValue);
          data = "";
          state = State.data;
        }
      }), _defineProperty(_State$attributeValue2, Action.slash, function(char) {
        if (openingQuote) {
          attrValue += char;
        } else {
          emit(Type$1.attributeValue, attrValue);
          isClosing = true;
          state = State.tagEnd;
        }
      }), _defineProperty(_State$attributeValue2, Action.char, function(char) {
        attrValue += char;
      }), _State$attributeValue2)), _lexer$stateMachine);
      var step = function step2(char) {
        if (options.debug) {
          console.log(state, char);
        }
        var actions = lexer2.stateMachine[state];
        var action = actions[getAction(char)] || actions[Action.error] || actions[Action.char];
        action(char);
      };
      lexer2.write = function(str) {
        var len = str.length;
        for (var i = 0;i < len; i++) {
          step(str[i]);
        }
      };
      return lexer2;
    };
    var lexer = {
      State,
      Action,
      Type: Type$1,
      create: create$1
    };
    var Type = lexer.Type;
    var NodeType = {
      element: "element",
      text: "text"
    };
    var createNode = function createNode2(params) {
      return Object.assign({
        name: "",
        type: NodeType.element,
        value: "",
        parent: null,
        attributes: {},
        children: []
      }, params);
    };
    var create = function create2(options) {
      options = Object.assign({
        stream: false,
        parentNodes: true,
        doneEvent: "done",
        tagPrefix: "tag:",
        emitTopLevelOnly: false,
        debug: false
      }, options);
      var lexer$1 = undefined, rootNode = undefined, current = undefined, attrName = undefined;
      var reader2 = new eventemitter3;
      var handleLexerData = function handleLexerData2(data) {
        switch (data.type) {
          case Type.openTag:
            if (current === null) {
              current = rootNode;
              current.name = data.value;
            } else {
              var node = createNode({
                name: data.value,
                parent: current
              });
              current.children.push(node);
              current = node;
            }
            break;
          case Type.closeTag:
            var parent = current.parent;
            if (!options.parentNodes) {
              current.parent = null;
            }
            if (current.name !== data.value) {
              break;
            }
            if (options.stream && parent === rootNode) {
              rootNode.children = [];
              current.parent = null;
            }
            if (!options.emitTopLevelOnly || parent === rootNode) {
              reader2.emit(options.tagPrefix + current.name, current);
              reader2.emit("tag", current.name, current);
            }
            if (current === rootNode) {
              lexer$1.removeAllListeners("data");
              reader2.emit(options.doneEvent, current);
              rootNode = null;
            }
            current = parent;
            break;
          case Type.text:
            if (current) {
              current.children.push(createNode({
                type: NodeType.text,
                value: data.value,
                parent: options.parentNodes ? current : null
              }));
            }
            break;
          case Type.attributeName:
            attrName = data.value;
            current.attributes[attrName] = "";
            break;
          case Type.attributeValue:
            current.attributes[attrName] = data.value;
            break;
        }
      };
      reader2.reset = function() {
        lexer$1 = lexer.create({ debug: options.debug });
        lexer$1.on("data", handleLexerData);
        rootNode = createNode();
        current = null;
        attrName = "";
        reader2.parse = lexer$1.write;
      };
      reader2.reset();
      return reader2;
    };
    var parseSync = function parseSync2(xml, options) {
      options = Object.assign({}, options, { stream: false, tagPrefix: ":" });
      var reader2 = create(options);
      var res = undefined;
      reader2.on("done", function(ast) {
        res = ast;
      });
      reader2.parse(xml);
      return res;
    };
    var reader = {
      parseSync,
      create,
      NodeType
    };
    var reader_1 = reader.parseSync;
    var parseInput = function parseInput2(input) {
      var parsed = reader_1("<root>".concat(input, "</root>"), {
        parentNodes: false
      });
      var isValid = parsed.children && parsed.children.length > 0 && parsed.children.every(function(node) {
        return node.name === "svg";
      });
      if (isValid) {
        return parsed.children.length === 1 ? parsed.children[0] : parsed.children;
      } else {
        throw Error("nothing to parse");
      }
    };
    var camelize = function camelize2(node) {
      return deepRenameKeys(node, function(key) {
        if (!notCamelcase(key)) {
          return toCamelCase(key);
        }
        return key;
      });
    };
    var toCamelCase = function toCamelCase2(prop) {
      return prop.replace(/[-|:]([a-z])/gi, function(all, letter) {
        return letter.toUpperCase();
      });
    };
    var notCamelcase = function notCamelcase2(prop) {
      return /^(data|aria)(-\w+)/.test(prop);
    };
    var escapeText = function escapeText2(text) {
      if (text) {
        var str = String(text);
        return /[&<>]/.test(str) ? "<![CDATA[".concat(str.replace(/]]>/, "]]]]><![CDATA[>"), "]]>") : str;
      }
      return "";
    };
    var escapeAttr = function escapeAttr2(attr) {
      return String(attr).replace(/&/g, "&amp;").replace(/'/g, "&apos;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    };
    var svgsonSync = function svgsonSync2(input) {
      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$transformNode = _ref.transformNode, transformNode = _ref$transformNode === undefined ? function(node) {
        return node;
      } : _ref$transformNode, _ref$camelcase = _ref.camelcase, camelcase = _ref$camelcase === undefined ? false : _ref$camelcase;
      var applyFilters = function applyFilters2(input2) {
        var n;
        n = transformNode(input2);
        if (camelcase) {
          n = camelize(n);
        }
        return n;
      };
      return applyFilters(parseInput(input));
    };
    function svgson() {
      for (var _len = arguments.length, args = new Array(_len), _key = 0;_key < _len; _key++) {
        args[_key] = arguments[_key];
      }
      return new Promise(function(resolve, reject) {
        try {
          var res = svgsonSync.apply(undefined, args);
          resolve(res);
        } catch (e) {
          reject(e);
        }
      });
    }
    var stringify = function stringify2(_ast) {
      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$transformAttr = _ref.transformAttr, transformAttr = _ref$transformAttr === undefined ? function(key, value, escape) {
        return "".concat(key, '="').concat(escape(value), '"');
      } : _ref$transformAttr, _ref$transformNode = _ref.transformNode, transformNode = _ref$transformNode === undefined ? function(node) {
        return node;
      } : _ref$transformNode, _ref$selfClose = _ref.selfClose, selfClose = _ref$selfClose === undefined ? true : _ref$selfClose;
      if (Array.isArray(_ast)) {
        return _ast.map(function(ast2) {
          return stringify2(ast2, {
            transformAttr,
            selfClose,
            transformNode
          });
        }).join("");
      }
      var ast = transformNode(_ast);
      if (ast.type === "text") {
        return escapeText(ast.value);
      }
      var attributes = "";
      for (var attr in ast.attributes) {
        var attrStr = transformAttr(attr, ast.attributes[attr], escapeAttr, ast.name);
        attributes += attrStr ? " ".concat(attrStr) : "";
      }
      return ast.children && ast.children.length > 0 || !selfClose ? "<".concat(ast.name).concat(attributes, ">").concat(stringify2(ast.children, {
        transformAttr,
        transformNode,
        selfClose
      }), "</").concat(ast.name, ">") : "<".concat(ast.name).concat(attributes, "/>");
    };
    var indexUmd = Object.assign({}, {
      parse: svgson,
      parseSync: svgsonSync,
      stringify
    });
    return indexUmd;
  });
});

// ../../work/placement-analysis/node_modules/@tscircuit/alphabet/dist/index.js
var svgAlphabet = {
  "0": "M0.301025 0.257813 L0.206593 0.283385 L0.122042 0.361307 L0.075923 0.474441 L0.064942 0.642221 L0.091296 0.78289 L0.159376 0.899463 L0.257104 0.961214 L0.344948 0.961214 L0.442678 0.899463 L0.510757 0.78289 L0.537111 0.642221 L0.526131 0.474441 L0.480012 0.361307 L0.39546 0.283385 L0.301025 0.257813",
  "1": "M0.220426 0.40845 L0.381626 0.270996 L0.381626 0.948966",
  "2": "M0.110409 0.39212 L0.125621 0.342293 L0.170571 0.295823 L0.244237 0.26431 L0.291518 0.257813 L0.373319 0.263799 L0.434683 0.290705 L0.468239 0.331966 L0.480292 0.379913 L0.479492 0.411806 L0.465088 0.465192 L0.402571 0.568988 L0.245134 0.766438 L0.07959 0.948045 L0.522462 0.948045",
  "3": "M0.081606 0.345073 L0.119154 0.315633 L0.178996 0.284091 L0.255265 0.257813 L0.349133 0.263062 L0.43127 0.289348 L0.48994 0.336662 L0.525141 0.394491 L0.513407 0.457577 L0.466472 0.504892 L0.384334 0.541692 L0.290464 0.56272 L0.20833 0.573235 L0.290464 0.583749 L0.384334 0.610035 L0.466472 0.652092 L0.519274 0.709922 L0.531007 0.773007 L0.50754 0.841351 L0.454738 0.899179 L0.3726 0.946494 L0.310412 0.961214 L0.209503 0.959111 L0.127367 0.946494 L0.071046 0.929671",
  "4": "M0.418494 0.270996 L0.048828 0.724199 L0.553224 0.724199 M0.414181 0.578167 L0.414181 0.94897",
  "5": "M0.074951 0.270996 L0.074951 0.614701 L0.267655 0.5695 L0.405247 0.586502 L0.460002 0.617189 L0.498028 0.660731 L0.527101 0.779401 L0.513352 0.841049 L0.477274 0.889568 L0.406378 0.93463 L0.324445 0.958337 L0.247399 0.962139 L0.182516 0.949767 L0.130068 0.925508 L0.074951 0.875607 M0.074951 0.270996 L0.527101 0.270996",
  "6": "M0.428549 0.257813 L0.341433 0.285053 L0.26073 0.312099 L0.192188 0.360182 L0.138902 0.410969 L0.098219 0.500422 L0.070249 0.584267 L0.067264 0.670716 L0.065164 0.756863 L0.087163 0.820973 L0.108168 0.861042 L0.157916 0.913131 L0.210981 0.948192 L0.29279 0.961214 L0.384548 0.956206 L0.456409 0.924151 L0.507262 0.881077 L0.5349 0.821975 L0.537111 0.771889 L0.521634 0.718798 L0.498418 0.67372 L0.463042 0.636657 L0.414398 0.613617 L0.34696 0.598591 L0.28284 0.595587 L0.215403 0.605604 L0.145756 0.641665 L0.109274 0.678729 L0.064942 0.724006",
  "7": "M0.071534 0.270996 L0.530519 0.270996 L0.495935 0.291702 L0.477752 0.305407 L0.435186 0.346112 L0.412067 0.374136 L0.388565 0.40796 L0.365315 0.448098 L0.342943 0.495062 L0.322081 0.549366 L0.303364 0.611524 L0.287416 0.68205 L0.270077 0.80465 L0.26253 0.94897",
  "8": "M0.286761 0.257813 L0.210684 0.27162 L0.1414 0.305622 L0.092494 0.382125 L0.111513 0.450128 L0.16857 0.502193 L0.228345 0.539382 L0.377781 0.594635 L0.470161 0.645637 L0.52586 0.706203 L0.538087 0.792269 L0.506841 0.87621 L0.438915 0.927212 L0.339743 0.961214 L0.263666 0.959089 L0.174004 0.929337 L0.102003 0.881523 L0.063965 0.811395 L0.066682 0.741266 L0.102003 0.671139 L0.180797 0.608448 L0.259591 0.580822 L0.358762 0.548945 L0.456576 0.49688 L0.486463 0.446941 L0.487822 0.362999 L0.453859 0.302434 L0.384574 0.265245 L0.286761 0.257813",
  "9": "M0.511026 0.437812 L0.491026 0.347812 L0.451026 0.297812 L0.391026 0.267812 L0.311026 0.257813 L0.231026 0.267812 L0.161026 0.297812 L0.111026 0.347812 L0.091026 0.417812 L0.111026 0.487812 L0.161026 0.537812 L0.231026 0.567812 L0.311026 0.577812 L0.391026 0.557812 L0.451026 0.517812 L0.491026 0.477812 L0.511026 0.437812 M0.510026 0.438812 L0.434026 0.636812 L0.381026 0.777812 L0.337026 0.879812 L0.301026 0.957812",
  "!": "M0.301026 0.270996 L0.301026 0.749566 M0.251466 0.94897 L0.350587 0.94897",
  '"': "M0.16504 0.270996 L0.16504 0.523022 M0.437013 0.270996 L0.437013 0.523022",
  "#": "M0.20958 0.282227 L0.146515 0.949754 M0.461844 0.282227 L0.398779 0.949754 M0.032999 0.526969 L0.600587 0.452796 M0.001465 0.82366 L0.569055 0.749486",
  $: "M0.307121 0.240234 L0.307121 1.083502 M0.490031 0.415915 L0.404676 0.328075 L0.23396 0.310507 L0.136407 0.398347 L0.099828 0.521324 L0.124213 0.591596 L0.197379 0.644299 L0.429061 0.697003 L0.502224 0.749708 L0.526613 0.837547 L0.477836 0.960526 L0.355897 1.013228 L0.197379 0.99566 L0.112021 0.942957 L0.07544 0.837547",
  "'": "M0.301026 0.270996 L0.301026 0.523022",
  "(": "M0.413087 0.241211 L0.372337 0.28347 L0.331589 0.334184 L0.290838 0.393349 L0.25009 0.460965 L0.219528 0.528584 L0.199153 0.5962 L0.188966 0.655364 L0.199153 0.714529 L0.219528 0.782146 L0.25009 0.849764 L0.290838 0.91738 L0.331589 0.976544 L0.372337 1.027258 L0.413087 1.069491",
  ")": "M0.188966 0.241211 L0.229716 0.28347 L0.270466 0.334184 L0.311213 0.393349 L0.351964 0.460965 L0.382526 0.528584 L0.4029 0.5962 L0.413087 0.655364 L0.4029 0.714529 L0.382526 0.782146 L0.351964 0.849764 L0.311213 0.91738 L0.270466 0.976544 L0.229716 1.027258 L0.188966 1.069491",
  "*": "M0.301026 0.458702 L0.301026 0.681942 M0.301026 0.458702 L0.520997 0.536834 M0.301026 0.458702 L0.439954 0.257813 M0.301026 0.458702 L0.162098 0.257813 M0.301026 0.458702 L0.081055 0.536834",
  "+": "M0.042969 0.66845 L0.559083 0.66845 M0.301023 0.428223 L0.301023 0.908661",
  ",": "M0.38672 0.852051 L0.215333 1.030661 L0.301025 1.119971",
  "-": "M0.173829 0.686035 L0.428224 0.686035",
  ".": "M0.362549 0.851074 L0.239503 0.851074",
  "/": "M0.062501 1.035249 L0.539551 0.270996",
  "<": "M0.559083 0.441895 L0.042969 0.66939 L0.042969 0.66939 L0.559083 0.896902",
  "=": "M0.042969 0.545898 L0.559083 0.545898 M0.042969 0.80837 L0.559083 0.80837",
  ">": "M0.042969 0.441895 L0.559083 0.66939 L0.559083 0.66939 L0.042969 0.896902",
  A: "M0.018067 0.94897 L0.290179 0.270996 L0.583986 0.94897 M0.155303 0.684521 L0.433548 0.684521",
  B: "M0.063965 0.94897 L0.063965 0.278953 L0.209356 0.270996 L0.342486 0.294394 L0.432179 0.37292 L0.418224 0.48773 L0.312686 0.549166 L0.084728 0.575531 L0.306377 0.589434 L0.468877 0.647456 L0.538087 0.736658 L0.5324 0.85202 L0.501247 0.902983 L0.42355 0.944398 L0.063965 0.94897",
  C: "M0.529054 0.419847 L0.498425 0.345196 L0.442238 0.292341 L0.33583 0.257813 L0.257199 0.268357 L0.187906 0.303748 L0.120243 0.385432 L0.072998 0.599844 L0.110073 0.815385 L0.165381 0.902183 L0.222883 0.942801 L0.334904 0.961214 L0.43253 0.937679 L0.504816 0.868999 L0.529054 0.772065",
  D: "M0.064454 0.94897 L0.071838 0.285078 L0.171217 0.270996 L0.247348 0.272633 L0.37101 0.306078 L0.462461 0.378304 L0.514748 0.475555 L0.535591 0.576392 L0.537599 0.652313 L0.528065 0.717381 L0.508562 0.772419 L0.445948 0.855695 L0.362356 0.90871 L0.225203 0.945862 L0.064454 0.94897",
  E: "M0.080078 0.270996 L0.080078 0.94897 M0.080078 0.270996 L0.521974 0.270996 M0.080078 0.609981 L0.389405 0.609981 M0.080078 0.94897 L0.521974 0.94897",
  F: "M0.086426 0.270996 L0.086426 0.94897 M0.091304 0.275607 L0.515626 0.275607 M0.091304 0.607677 L0.447344 0.607677",
  G: "M0.498034 0.284943 L0.374621 0.257813 L0.244219 0.268648 L0.160577 0.311997 L0.094556 0.398116 L0.056397 0.58404 L0.076752 0.785532 L0.120865 0.858197 L0.188947 0.916734 L0.271008 0.953591 L0.357069 0.961214 L0.43715 0.932047 L0.501262 0.858539 L0.545656 0.648611 L0.329595 0.648131",
  H: "M0.066895 0.270996 L0.066895 0.94897 M0.066895 0.595658 L0.530009 0.595658 M0.535157 0.270996 L0.535157 0.94897",
  I: "M0.301026 0.270996 L0.301026 0.94897",
  J: "M0.506839 0.270996 L0.507814 0.782193 L0.498468 0.846168 L0.480733 0.880789 L0.455864 0.90832 L0.426095 0.929408 L0.360746 0.954812 L0.302508 0.962139 L0.223573 0.953638 L0.16538 0.930312 L0.137072 0.907715 L0.116428 0.880312 L0.102822 0.848819 L0.095633 0.813947 L0.094239 0.776413",
  K: "M0.035401 0.270996 L0.035401 0.94897 M0.502258 0.316194 L0.035401 0.687823 M0.212484 0.582361 L0.566652 0.933903",
  L: "M0.07544 0.270996 L0.07544 0.94897 L0.526613 0.94897",
  M: "M0.042481 0.94897 L0.042481 0.270996 L0.301027 0.712492 L0.559571 0.270996 L0.559571 0.94897",
  N: "M0.067871 0.94897 L0.067871 0.270996 L0.534181 0.94897 L0.525031 0.270996",
  O: "M0.287293 0.961214 L0.19843 0.933567 L0.1172 0.849451 L0.057129 0.563945 L0.114348 0.350255 L0.18455 0.289392 L0.306101 0.257813 L0.42054 0.29572 L0.487543 0.365003 L0.544923 0.625294 L0.516366 0.789624 L0.465476 0.884596 L0.375084 0.949287 L0.287293 0.961214",
  P: "M0.070557 0.94897 L0.070557 0.28379 L0.20704 0.270996 L0.329134 0.278993 L0.408525 0.300514 L0.444022 0.317908 L0.500637 0.368929 L0.525796 0.423728 L0.531496 0.50384 L0.508934 0.554205 L0.473724 0.582043 L0.417577 0.604365 L0.336375 0.620372 L0.226014 0.629268 L0.082368 0.630258",
  Q: "M0.282435 1.050813 L0.195447 1.019646 L0.115933 0.924817 L0.057129 0.602943 L0.113139 0.362034 L0.18186 0.293418 L0.300844 0.257813 L0.412868 0.300553 L0.478457 0.37866 L0.534625 0.672103 L0.506671 0.857367 L0.456855 0.964437 L0.368371 1.037368 L0.282435 1.050813 M0.341225 0.815559 L0.544923 1.070653",
  R: "M0.034912 0.944112 L0.034912 0.288556 L0.227127 0.270996 L0.362038 0.276867 L0.443423 0.294907 L0.477644 0.309614 L0.505809 0.328757 L0.526616 0.352817 L0.544963 0.418061 L0.543241 0.475921 L0.524463 0.517817 L0.49076 0.546518 L0.444265 0.564799 L0.355195 0.578739 L0.047653 0.589627 M0.303054 0.617306 L0.56714 0.94897",
  S: "M0.483037 0.364333 L0.407613 0.267477 L0.22883 0.257813 L0.128623 0.327565 L0.087712 0.455539 L0.104656 0.518727 L0.168054 0.573307 L0.41928 0.617318 L0.503796 0.669342 L0.535157 0.759324 L0.493846 0.900055 L0.367668 0.961214 L0.205436 0.956661 L0.116711 0.907038 L0.066895 0.790334",
  T: "M0.022949 0.270996 L0.579103 0.270996 M0.309284 0.270996 L0.309284 0.94897",
  U: "M0.072022 0.270996 L0.07308 0.648875 L0.080372 0.75167 L0.099024 0.827813 L0.134786 0.885729 L0.181571 0.924023 L0.251464 0.95168 L0.339655 0.962139 L0.401553 0.951668 L0.45232 0.924086 L0.482701 0.891771 L0.495745 0.870529 L0.515699 0.81637 L0.525014 0.744626 L0.530031 0.272017",
  V: "M0.027832 0.270996 L0.320083 0.94897 L0.57422 0.270996",
  W: "M0 0.270996 L0.079799 0.940377 L0.285198 0.472884 L0.505255 0.94897 L0.602052 0.270996",
  X: "M0.009034 0.270996 L0.586805 0.94897 M0.593019 0.270996 L0.015246 0.94897",
  Y: "M0.018067 0.270996 L0.293132 0.574135 M0.583986 0.271959 L0.294954 0.57606 L0.305277 0.94897",
  Z: "M0.053711 0.270996 L0.548341 0.270996 L0.053711 0.94897 L0.548341 0.94897",
  "[": "M0.404542 0.240234 L0.197511 0.240234 L0.197511 1.069424 L0.404542 1.069424",
  "\\": "M0.062501 0.270996 L0.539551 1.035249",
  "]": "M0.19751 0.240234 L0.404542 0.240234 L0.404542 1.069424 L0.19751 1.069424",
  "^": "M0.035156 0.523931 L0.301024 0.270996 L0.566896 0.523931",
  _: "M0 1.160601 L0.602052 1.160601",
  a: "M0.527101 0.439941 L0.527101 0.973965 M0.527101 0.553824 L0.451366 0.477535 L0.376759 0.439941 L0.263722 0.439941 L0.187989 0.477535 L0.112255 0.553824 L0.074951 0.66881 L0.074951 0.745099 L0.112255 0.85898 L0.187989 0.93527 L0.263722 0.973965 L0.376759 0.973965 L0.451366 0.93527 L0.527101 0.85898",
  b: "M0.07666 0.240234 L0.07666 0.959985 M0.07666 0.582737 L0.151822 0.514237 L0.225865 0.480483 L0.338045 0.480483 L0.413211 0.514237 L0.488374 0.582737 L0.525392 0.685983 L0.525392 0.754485 L0.488374 0.856739 L0.413211 0.92524 L0.338045 0.959985 L0.225865 0.959985 L0.151822 0.92524 L0.07666 0.856739",
  c: "M0.512452 0.553823 L0.441624 0.477535 L0.371854 0.439941 L0.26614 0.439941 L0.195312 0.477535 L0.124486 0.553823 L0.0896 0.668808 L0.0896 0.745099 L0.124486 0.858979 L0.195312 0.93527 L0.26614 0.973965 L0.371854 0.973965 L0.441624 0.93527 L0.512452 0.858979",
  d: "M0.525392 0.240234 L0.525392 0.959985 M0.525392 0.582737 L0.450232 0.514237 L0.376189 0.480483 L0.264006 0.480483 L0.188844 0.514237 L0.11368 0.582737 L0.076661 0.685983 L0.076661 0.754485 L0.11368 0.856739 L0.188844 0.92524 L0.264006 0.959985 L0.376189 0.959985 L0.450232 0.92524 L0.525392 0.856739",
  e: "M0.059571 0.668808 L0.542482 0.668808 M0.542482 0.592521 L0.502641 0.516231 L0.461594 0.477535 L0.381914 0.439941 L0.261186 0.439941 L0.180299 0.477535 L0.099412 0.553823 L0.059571 0.668808 L0.059571 0.745099 L0.099412 0.858979 L0.180299 0.93527 L0.261186 0.973965 L0.381914 0.973965 L0.461594 0.93527 L0.542482 0.858979",
  f: "M0.512941 0.240234 L0.406984 0.240234 L0.301026 0.274346 L0.248047 0.374731 L0.248047 0.946817 M0.089112 0.476088 L0.459965 0.476088",
  g: "M0.525392 0.439941 L0.525392 0.989395 L0.488373 1.091918 L0.45023 1.126757 L0.376189 1.160601 L0.264004 1.160601 L0.188844 1.126757 L0.113681 1.058075 L0.076661 0.954555 M0.525392 0.542467 L0.45023 0.473786 L0.376189 0.439941 L0.264004 0.439941 L0.188844 0.473786 L0.113681 0.542467 L0.076661 0.645988 L0.076661 0.714669 L0.113681 0.817193 L0.188844 0.885875 L0.264004 0.920713 L0.376189 0.920713 L0.45023 0.885875 L0.525392 0.817193",
  h: "M0.092041 0.240234 L0.092041 0.946817 M0.092041 0.61058 L0.205937 0.509225 L0.282214 0.476086 L0.396109 0.476086 L0.47187 0.509225 L0.510011 0.61058 L0.510011 0.946817",
  i: "M0.261026 0.240234 L0.341026 0.240234 M0.300978 0.476089 L0.300978 0.946817",
  j: "M0.3853 0.240234 L0.447023 0.240234 M0.416159 0.465708 L0.416159 1.011689 L0.383887 1.108586 L0.252832 1.140264 L0.15503 1.108586",
  k: "M0.065186 0.240234 L0.065186 0.946817 M0.493824 0.476086 L0.065186 0.812323 M0.236758 0.677829 L0.536867 0.946817",
  l: "M0.301026 0.234863 L0.301026 0.946441",
  m: "M0.050538 0.439941 L0.050538 0.960796 M0.050538 0.588758 L0.114405 0.476607 L0.157178 0.439941 L0.236864 0.439941 L0.279637 0.476607 L0.32241 0.588758 L0.32241 0.960796 M0.32241 0.588758 L0.386281 0.476607 L0.428467 0.439941 L0.50874 0.439941 L0.551515 0.476607 L0.551515 0.960796",
  n: "M0.092041 0.439941 L0.092041 0.960796 M0.092041 0.588758 L0.205936 0.476607 L0.282216 0.439941 L0.396113 0.439941 L0.471871 0.476607 L0.510011 0.588758 L0.510011 0.960796",
  o: "M0.247175 0.439941 L0.175178 0.477535 L0.103186 0.553823 L0.066895 0.668808 L0.066895 0.745099 L0.103186 0.858979 L0.175178 0.93527 L0.247175 0.973965 L0.354874 0.973965 L0.426872 0.93527 L0.498866 0.858979 L0.535157 0.745099 L0.535157 0.668808 L0.498866 0.553823 L0.426872 0.477535 L0.354874 0.439941 L0.247175 0.439941",
  p: "M0.076904 0.439941 L0.076904 1.154244 M0.076904 0.541563 L0.151986 0.473487 L0.225944 0.439941 L0.338005 0.439941 L0.413087 0.473487 L0.488166 0.541563 L0.525148 0.644169 L0.525148 0.712246 L0.488166 0.813866 L0.413087 0.881942 L0.338005 0.916471 L0.225944 0.916471 L0.151986 0.881942 L0.076904 0.813866",
  q: "M0.525148 0.441895 L0.525148 1.156195 M0.525148 0.5435 L0.450067 0.47544 L0.376106 0.441895 L0.264042 0.441895 L0.188966 0.47544 L0.113885 0.5435 L0.076905 0.646108 L0.076905 0.714187 L0.113885 0.815809 L0.188966 0.883886 L0.264042 0.918418 L0.376106 0.918418 L0.450067 0.883886 L0.525148 0.815809",
  r: "M0.107422 0.439941 L0.107422 0.960796 M0.107422 0.663164 L0.155824 0.551014 L0.252626 0.476607 L0.349428 0.439941 L0.49463 0.439941",
  s: "M0.475556 0.477535 L0.400757 0.439941 L0.276092 0.439941 L0.176361 0.477535 L0.101563 0.553823 L0.101563 0.630112 L0.176361 0.668808 L0.301024 0.668808 L0.425688 0.745099 L0.50049 0.821387 L0.50049 0.897677 L0.425688 0.93527 L0.325956 0.973965 L0.201295 0.973965 L0.126496 0.93527 L0.101563 0.858979",
  t: "M0.246032 0.297852 L0.246032 0.826549 L0.301023 0.919323 L0.411011 0.950848 L0.520997 0.950848 M0.081055 0.515799 L0.466004 0.515799",
  u: "M0.092041 0.454102 L0.092041 0.826134 L0.13018 0.937211 L0.205936 0.974954 L0.319832 0.974954 L0.396113 0.937211 L0.510011 0.826134 M0.510011 0.454102 L0.510011 0.974954",
  v: "M0.048828 0.453125 L0.301026 0.961719 M0.553224 0.453125 L0.301026 0.961719",
  w: "M0 0.453125 L0.150512 0.961719 M0.301024 0.453125 L0.150512 0.961719 M0.301024 0.453125 L0.451539 0.961719 M0.602052 0.453125 L0.451539 0.961719",
  x: "M0.03711 0.453125 L0.564943 0.961719 M0.564943 0.453125 L0.03711 0.961719",
  y: "M0.084618 0.453125 L0.320232 0.921476 M0.55713 0.453125 L0.320232 0.921476 L0.242119 1.055289 L0.163369 1.122196 L0.084618 1.155166 L0.044922 1.155166",
  z: "M0.505373 0.452148 L0.09668 0.961651 M0.09668 0.452148 L0.505373 0.452148 M0.09668 0.961651 L0.505373 0.961651"
};
var lineAlphabet = {};
for (const letter in svgAlphabet) {
  lineAlphabet[letter] = [];
  const segs = svgAlphabet[letter].split("M").slice(1).map((seg) => seg.split("L").map((pr) => pr.trim().split(" ").map(parseFloat)));
  for (const seg of segs) {
    for (let i = 0;i < seg.length - 1; i++) {
      lineAlphabet[letter].push({
        x1: seg[i][0],
        y1: 1 - seg[i][1],
        x2: seg[i + 1][0],
        y2: 1 - seg[i + 1][1]
      });
    }
  }
}

// ../../work/placement-analysis/node_modules/iobuffer/lib/text.js
var encoder = new TextEncoder;

// ../../work/placement-analysis/node_modules/iobuffer/lib/iobuffer.js
var defaultByteLength = 1024 * 8;
var hostBigEndian = (() => {
  const array = new Uint8Array(4);
  const view = new Uint32Array(array.buffer);
  return !((view[0] = 1) & array[0]);
})();
var typedArrays = {
  int8: globalThis.Int8Array,
  uint8: globalThis.Uint8Array,
  int16: globalThis.Int16Array,
  uint16: globalThis.Uint16Array,
  int32: globalThis.Int32Array,
  uint32: globalThis.Uint32Array,
  uint64: globalThis.BigUint64Array,
  int64: globalThis.BigInt64Array,
  float32: globalThis.Float32Array,
  float64: globalThis.Float64Array
};

// ../../work/placement-analysis/node_modules/fast-png/lib/helpers/crc.js
var crcTable = [];
for (let n = 0;n < 256; n++) {
  let c = n;
  for (let k = 0;k < 8; k++) {
    if (c & 1) {
      c = 3988292384 ^ c >>> 1;
    } else {
      c = c >>> 1;
    }
  }
  crcTable[n] = c;
}

// ../../work/placement-analysis/node_modules/fast-png/lib/helpers/decode_interlace_adam7.js
var uint16 = new Uint16Array([255]);
var uint8 = new Uint8Array(uint16.buffer);
var osIsLittleEndian = uint8[0] === 255;

// ../../work/placement-analysis/node_modules/fast-png/lib/helpers/decode_interlace_null.js
var uint162 = new Uint16Array([255]);
var uint82 = new Uint8Array(uint162.buffer);
var osIsLittleEndian2 = uint82[0] === 255;
var empty = new Uint8Array(0);

// ../../work/placement-analysis/node_modules/fast-png/lib/helpers/signature.js
var pngSignature = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10);

// ../../work/placement-analysis/node_modules/fast-png/lib/helpers/text.js
var latin1Decoder = new TextDecoder("latin1");
// ../../work/placement-analysis/node_modules/graphics-debug/dist/chunk-WDTSQY35.js
var import_svgson = __toESM(require_svgson_umd(), 1);

// ../../work/placement-analysis/node_modules/graphics-debug/dist/chunk-K37Y2KHE.js
var mergeGraphics = (graphics1, graphics2) => {
  return {
    ...graphics1,
    rects: [...graphics1.rects ?? [], ...graphics2.rects ?? []],
    points: [...graphics1.points ?? [], ...graphics2.points ?? []],
    lines: [...graphics1.lines ?? [], ...graphics2.lines ?? []],
    infiniteLines: [
      ...graphics1.infiniteLines ?? [],
      ...graphics2.infiniteLines ?? []
    ],
    polygons: [...graphics1.polygons ?? [], ...graphics2.polygons ?? []],
    circles: [...graphics1.circles ?? [], ...graphics2.circles ?? []],
    arrows: [...graphics1.arrows ?? [], ...graphics2.arrows ?? []],
    texts: [...graphics1.texts ?? [], ...graphics2.texts ?? []]
  };
};

// ../../work/placement-analysis/node_modules/graphics-debug/dist/chunk-OB4CGOL3.js
function setStepOfAllObjects(graphics, step) {
  if (graphics.points) {
    for (const p of graphics.points) {
      p.step = step;
    }
  }
  if (graphics.lines) {
    for (const line of graphics.lines) {
      line.step = step;
    }
  }
  if (graphics.infiniteLines) {
    for (const infiniteLine of graphics.infiniteLines) {
      infiniteLine.step = step;
    }
  }
  if (graphics.polygons) {
    for (const polygon of graphics.polygons) {
      polygon.step = step;
    }
  }
  if (graphics.rects) {
    for (const rect of graphics.rects) {
      rect.step = step;
    }
  }
  if (graphics.circles) {
    for (const circle of graphics.circles) {
      circle.step = step;
    }
  }
  if (graphics.texts) {
    for (const text of graphics.texts) {
      text.step = step;
    }
  }
  return graphics;
}

// ../../work/placement-analysis/node_modules/@tscircuit/solver-utils/dist/index.js
var BaseSolver = class {
  MAX_ITERATIONS = 1e5;
  solved = false;
  failed = false;
  iterations = 0;
  progress = 0;
  error = null;
  activeSubSolver;
  failedSubSolvers;
  timeToSolve;
  stats = {};
  _setupDone = false;
  getSolverName() {
    return this.constructor.name;
  }
  setup() {
    if (this._setupDone)
      return;
    this._setup();
    this._setupDone = true;
  }
  _setup() {}
  step() {
    if (!this._setupDone) {
      this.setup();
    }
    if (this.solved)
      return;
    if (this.failed)
      return;
    this.iterations++;
    try {
      this._step();
    } catch (e) {
      this.error = `${this.getSolverName()} error: ${e}`;
      this.failed = true;
      throw e;
    }
    if (!this.solved && this.iterations >= this.MAX_ITERATIONS) {
      this.tryFinalAcceptance();
    }
    if (!this.solved && this.iterations >= this.MAX_ITERATIONS) {
      this.error = `${this.getSolverName()} ran out of iterations`;
      this.failed = true;
    }
    if ("computeProgress" in this) {
      this.progress = this.computeProgress();
    }
  }
  _step() {}
  getConstructorParams() {
    throw new Error("getConstructorParams not implemented");
  }
  getOutput() {
    return null;
  }
  solve() {
    const startTime = Date.now();
    while (!this.solved && !this.failed) {
      this.step();
    }
    const endTime = Date.now();
    this.timeToSolve = endTime - startTime;
  }
  visualize() {
    return {
      lines: [],
      points: [],
      rects: [],
      circles: []
    };
  }
  tryFinalAcceptance() {}
  preview() {
    return {
      lines: [],
      points: [],
      rects: [],
      circles: []
    };
  }
};
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
  return {
    solverName,
    solverClass,
    getConstructorParams,
    onSolved: opts.onSolved
  };
}
var BasePipelineSolver = class extends BaseSolver {
  startTimeOfStage = {};
  endTimeOfStage = {};
  timeSpentOnStage = {};
  firstIterationOfStage = {};
  currentPipelineStageIndex = 0;
  inputProblem;
  pipelineOutputs = {};
  constructor(inputProblem) {
    super();
    this.inputProblem = inputProblem;
    this.MAX_ITERATIONS = 1e6;
  }
  _step() {
    const pipelineStageDef = this.pipelineDef[this.currentPipelineStageIndex];
    if (!pipelineStageDef) {
      this.solved = true;
      return;
    }
    if (this.activeSubSolver) {
      this.activeSubSolver.step();
      if (this.activeSubSolver.solved) {
        this.endTimeOfStage[pipelineStageDef.solverName] = performance.now();
        this.timeSpentOnStage[pipelineStageDef.solverName] = this.endTimeOfStage[pipelineStageDef.solverName] - this.startTimeOfStage[pipelineStageDef.solverName];
        const output = this.activeSubSolver.getOutput();
        if (output !== null) {
          this.pipelineOutputs[pipelineStageDef.solverName] = output;
        }
        pipelineStageDef.onSolved?.(this);
        this.activeSubSolver = null;
        this.currentPipelineStageIndex++;
      } else if (this.activeSubSolver.failed) {
        this.error = this.activeSubSolver?.error;
        this.failed = true;
        this.activeSubSolver = null;
      }
      return;
    }
    const constructorParams = pipelineStageDef.getConstructorParams(this);
    this.activeSubSolver = new pipelineStageDef.solverClass(...constructorParams);
    this[pipelineStageDef.solverName] = this.activeSubSolver;
    this.timeSpentOnStage[pipelineStageDef.solverName] = 0;
    this.startTimeOfStage[pipelineStageDef.solverName] = performance.now();
    this.firstIterationOfStage[pipelineStageDef.solverName] = this.iterations;
  }
  solveUntilStage(stageName) {
    while (this.getCurrentStageName().toLowerCase() !== stageName.toLowerCase()) {
      this.step();
      if (this.failed || this.solved)
        break;
    }
  }
  getCurrentStageName() {
    return this.pipelineDef[this.currentPipelineStageIndex]?.solverName ?? "none";
  }
  getStageProgress() {
    const totalStages = this.pipelineDef.length;
    if (totalStages === 0)
      return 1;
    const currentStageProgress = this.activeSubSolver?.progress ?? 0;
    return (this.currentPipelineStageIndex + currentStageProgress) / totalStages;
  }
  getStageStats() {
    const stats = {};
    for (const stage of this.pipelineDef) {
      const timeSpent = this.timeSpentOnStage[stage.solverName] || 0;
      const firstIteration = this.firstIterationOfStage[stage.solverName] || 0;
      const currentIteration = this.iterations;
      const iterations = stage.solverName === this.getCurrentStageName() ? currentIteration - firstIteration : 0;
      const completed = this.currentPipelineStageIndex > this.pipelineDef.findIndex((s) => s.solverName === stage.solverName);
      stats[stage.solverName] = {
        timeSpent,
        iterations,
        completed
      };
    }
    return stats;
  }
  initialVisualize() {
    return null;
  }
  finalVisualize() {
    return null;
  }
  visualize() {
    if (!this.solved && this.activeSubSolver) {
      return this.activeSubSolver.visualize();
    }
    let stageStepOffset = 0;
    const initialVisualization = this.initialVisualize();
    if (initialVisualization) {
      setStepOfAllObjects(initialVisualization, 0);
      stageStepOffset = 1;
    }
    let finalVisualization = null;
    if (this.solved) {
      finalVisualization = this.finalVisualize();
    }
    const visualizations = [initialVisualization].filter(Boolean).concat(this.pipelineDef.map((stage, stageIndex) => {
      const solver = this[stage.solverName];
      const viz = solver?.visualize();
      if (!viz)
        return null;
      setStepOfAllObjects(viz, stageIndex + stageStepOffset);
      return viz;
    }).filter(Boolean));
    if (visualizations.length === 0) {
      return { points: [], rects: [], lines: [], circles: [], texts: [] };
    }
    if (this.solved && finalVisualization) {
      setStepOfAllObjects(finalVisualization, visualizations.length + stageStepOffset + 1);
      visualizations.push(finalVisualization);
    }
    if (visualizations.length === 1) {
      return visualizations[0];
    }
    return {
      points: visualizations.flatMap((v) => v.points || []),
      rects: visualizations.flatMap((v) => v.rects || []),
      lines: visualizations.flatMap((v) => v.lines || []),
      circles: visualizations.flatMap((v) => v.circles || []),
      texts: visualizations.flatMap((v) => v.texts || [])
    };
  }
  preview() {
    if (this.activeSubSolver) {
      return this.activeSubSolver.preview();
    }
    return super.preview();
  }
  computeProgress() {
    return this.getStageProgress();
  }
  getStageOutput(stageOutput) {
    return this.pipelineOutputs[stageOutput];
  }
  getAllOutputs() {
    return { ...this.pipelineOutputs };
  }
  hasStageOutput(stageName) {
    return stageName in this.pipelineOutputs;
  }
  getSolver(stageName) {
    return this[stageName];
  }
};

// ../../work/placement-analysis/lib/utils/source-connectivity.ts
function getSourceConnectivity(circuitJson) {
  const parent = new Map;
  const find = (id) => {
    const next = parent.get(id);
    if (next === undefined || next === id)
      return id;
    const root = find(next);
    parent.set(id, root);
    return root;
  };
  const join = (ids) => {
    const first = ids[0];
    if (!first)
      return;
    const root = find(first);
    for (const id of ids.slice(1))
      parent.set(find(id), root);
  };
  for (const element of circuitJson) {
    if (element.type === "source_port" || element.type === "source_net") {
      const id = element.type === "source_port" ? element.source_port_id : element.source_net_id;
      if (element.subcircuit_connectivity_map_key)
        join([id, `connectivity:${element.subcircuit_connectivity_map_key}`]);
    }
    if (element.type === "source_trace") {
      join([
        ...element.connected_source_port_ids,
        ...element.connected_source_net_ids,
        ...element.subcircuit_connectivity_map_key ? [`connectivity:${element.subcircuit_connectivity_map_key}`] : []
      ]);
    }
    if (element.type === "source_component_internal_connection")
      join(element.source_port_ids);
    if (element.type === "source_component") {
      for (const ids of element.internally_connected_source_port_ids ?? [])
        join(ids);
    }
  }
  return find;
}

// ../../work/placement-analysis/lib/utils/placement-network-index.ts
class PlacementNetworkIndex {
  connected;
  components = new Map;
  portsByComponent = new Map;
  portsByNet = new Map;
  powerNets = new Set;
  groundNets = new Set;
  placements = new Map;
  schematicComponents = new Map;
  schematicPorts = new Map;
  constructor(ctx) {
    this.connected = getSourceConnectivity(ctx.circuitJson);
    for (const placement of ctx.componentPlacements) {
      if (placement.sourceComponentId)
        append(this.placements, placement.sourceComponentId, placement);
    }
    for (const element of ctx.circuitJson) {
      if (element.type === "source_component")
        this.components.set(element.source_component_id, element);
      if (element.type === "source_port" && element.source_component_id) {
        append(this.portsByComponent, element.source_component_id, element);
        append(this.portsByNet, this.connected(element.source_port_id), element);
      }
      if (element.type === "source_net") {
        const net = this.connected(element.source_net_id);
        if (element.is_power || element.is_positive_voltage_source)
          this.powerNets.add(net);
        if (element.is_ground)
          this.groundNets.add(net);
      }
      if (element.type === "schematic_component")
        this.schematicComponents.set(element.schematic_component_id, element);
      if (element.type === "schematic_port" && element.source_port_id)
        append(this.schematicPorts, element.source_port_id, element);
    }
  }
  placement(componentId) {
    const placements = this.placements.get(componentId);
    return placements?.length === 1 ? placements[0] : undefined;
  }
  port(sourcePort) {
    const placement = this.placement(sourcePort.source_component_id);
    const ports = this.schematicPorts.get(sourcePort.source_port_id)?.filter((port) => port.schematic_component_id === placement?.schematicComponentId);
    return ports?.length === 1 ? ports[0] : undefined;
  }
  namedPort(componentId, name) {
    const ports = this.portsByComponent.get(componentId)?.filter((port) => port.name === name || port.port_hints?.includes(name));
    return ports?.length === 1 ? ports[0] : undefined;
  }
  twoTerminalNets(componentId) {
    const ports = this.portsByComponent.get(componentId);
    if (ports?.length !== 2)
      return;
    const first = this.connected(ports[0].source_port_id);
    const second = this.connected(ports[1].source_port_id);
    if (first !== second)
      return [first, second];
  }
  isRail(net) {
    return this.powerNets.has(net) || this.groundNets.has(net);
  }
  isDirectOpAmpFeedback(componentId) {
    const nets = this.twoTerminalNets(componentId);
    if (!nets || nets.some((net) => this.isRail(net)))
      return false;
    return nets.some((net) => (this.portsByNet.get(net) ?? []).some((port) => {
      const hostId = port.source_component_id;
      if (this.components.get(hostId)?.ftype !== "simple_op_amp")
        return false;
      const output = this.namedPort(hostId, "output");
      if (output?.source_port_id !== port.source_port_id)
        return false;
      return ["inverting_input", "non_inverting_input"].some((name) => {
        const input = this.namedPort(hostId, name);
        if (!input)
          return false;
        const inputNet = this.connected(input.source_port_id);
        return inputNet !== net && nets.includes(inputNet);
      });
    }));
  }
  sameLocalScope(first, second) {
    if (first.schematicSheetId !== second.schematicSheetId || first.subcircuitId !== second.subcircuitId)
      return false;
    const a = this.schematicComponents.get(first.schematicComponentId ?? "");
    const b = this.schematicComponents.get(second.schematicComponentId ?? "");
    if (!a || !b || a.schematic_group_id !== b.schematic_group_id)
      return false;
    const firstSource = this.components.get(first.sourceComponentId ?? "");
    const secondSource = this.components.get(second.sourceComponentId ?? "");
    return firstSource?.source_group_id === secondSource?.source_group_id && firstSource?.subcircuit_id === secondSource?.subcircuit_id;
  }
}
function append(map, key, value) {
  const values = map.get(key);
  if (values)
    values.push(value);
  else
    map.set(key, [value]);
}

// ../../work/placement-analysis/lib/utils/format.ts
var fmtNumber = (value) => {
  if (Number.isInteger(value))
    return String(value);
  return value.toFixed(3).replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1");
};
var fmtDelta = (value) => {
  const formatted = fmtNumber(value);
  return value > 0 ? `+${formatted}` : formatted;
};
var escapeAttr = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
var addAttr = (attrs, key, value, options) => {
  if (value === undefined)
    return;
  const stringValue = typeof value === "number" ? options?.formatDelta ? fmtDelta(value) : fmtNumber(value) : escapeAttr(value);
  attrs.push(`${key}="${stringValue}"`);
};

// ../../work/placement-analysis/lib/solvers/FourPinCrystalPatternSolver/FourPinCrystalPatternSolver.ts
class FourPinCrystalPatternSolver extends BaseSolver {
  input;
  constructor(input) {
    super();
    this.input = input;
  }
  _step() {
    const { ctx, issues } = this.input;
    const index = new PlacementNetworkIndex(ctx);
    for (const component of index.components.values()) {
      if (component.ftype !== "simple_crystal")
        continue;
      const id = component.source_component_id;
      const ports = index.portsByComponent.get(id) ?? [];
      if (ports.length !== 4)
        continue;
      const ground = ports.filter((p) => index.groundNets.has(index.connected(p.source_port_id)));
      const signals = ports.filter((p) => !ground.includes(p));
      if (ground.length !== 2 || signals.length !== 2)
        continue;
      const groundNet = index.connected(ground[0].source_port_id);
      if (index.connected(ground[1].source_port_id) !== groundNet)
        continue;
      const signalNets = signals.map((p) => index.connected(p.source_port_id));
      if (signalNets[0] === signalNets[1])
        continue;
      const loads = signalNets.map((net) => [...index.components.values()].filter((c) => {
        if (c.ftype !== "simple_capacitor")
          return false;
        const nets = index.twoTerminalNets(c.source_component_id);
        return nets?.includes(net) && nets.includes(groundNet);
      }));
      if (loads.some((c) => c.length !== 1) || loads[0][0] === loads[1][0])
        continue;
      const resistors = [...index.components.values()].filter((c) => {
        if (c.ftype !== "simple_resistor")
          return false;
        const nets = index.twoTerminalNets(c.source_component_id);
        return nets && nets.filter((n) => signalNets.includes(n)).length === 1 && !nets.some((n) => index.isRail(n));
      });
      if (resistors.length !== 1)
        continue;
      const resistor = resistors[0];
      const resistorNets = index.twoTerminalNets(resistor.source_component_id);
      const bottomIndex = signalNets.findIndex((n) => resistorNets.includes(n));
      const topIndex = 1 - bottomIndex;
      const crystal = index.placement(id);
      const ids = [
        id,
        loads[topIndex][0].source_component_id,
        loads[bottomIndex][0].source_component_id,
        resistor.source_component_id
      ];
      const placements = ids.map((id2) => index.placement(id2));
      if (!crystal || placements.some((p) => !p || p.schematicSheetId !== crystal.schematicSheetId))
        continue;
      if (ids.some((id2) => (index.portsByComponent.get(id2) ?? []).some((p) => !index.port(p))))
        continue;
      const { schX: x, schY: y } = crystal;
      const halfHeight = Math.max(0.6, Math.max(crystal.width, crystal.height) / 2);
      const span = halfHeight + 1;
      const left = x - Math.max(2, placements[1].width + 1, placements[2].width + 1);
      const right = x + Math.max(2, placements[3].width + 1);
      const portTarget = (p, px, py) => ({
        sourcePortId: p.source_port_id,
        pinNumber: p.pin_number,
        newSchX: round(px),
        newSchY: round(py)
      });
      const top = signals[topIndex], bottom = signals[bottomIndex];
      const a = index.port(top), b = index.port(bottom);
      const crystalRotation = angleDelta(90 - Math.atan2(a.center.y - b.center.y, a.center.x - b.center.x) * 180 / Math.PI);
      const radians = crystalRotation * Math.PI / 180;
      const rotatedPin = (p) => {
        const current = index.port(p).center;
        const dx = current.x - x, dy = current.y - y;
        return portTarget(p, x + dx * Math.cos(radians) - dy * Math.sin(radians), y + dx * Math.sin(radians) + dy * Math.cos(radians));
      };
      const targets = [
        {
          schematicBox: crystal,
          newSchX: x,
          newSchY: y,
          deltaSchRotation: crystalRotation,
          pins: [
            top,
            bottom,
            ...ground.toSorted((a2, b2) => (a2.pin_number ?? 0) - (b2.pin_number ?? 0))
          ].map(rotatedPin)
        }
      ];
      const addPassive = (componentId, cx, cy, rightNet) => {
        const pp = index.portsByComponent.get(componentId);
        const rightPort = pp.find((p) => index.connected(p.source_port_id) === rightNet);
        const leftPort = pp.find((p) => p !== rightPort);
        const rp = index.port(rightPort), lp = index.port(leftPort);
        const halfWidth = Math.hypot(rp.center.x - lp.center.x, rp.center.y - lp.center.y) / 2;
        targets.push({
          schematicBox: index.placement(componentId),
          newSchX: round(cx),
          newSchY: round(cy),
          deltaSchRotation: angleDelta(-Math.atan2(rp.center.y - lp.center.y, rp.center.x - lp.center.x) * 180 / Math.PI),
          pins: [
            portTarget(leftPort, cx - halfWidth, cy),
            portTarget(rightPort, cx + halfWidth, cy)
          ]
        });
      };
      addPassive(ids[1], left, y + span, signalNets[topIndex]);
      addPassive(ids[2], left, y - span, signalNets[bottomIndex]);
      addPassive(ids[3], right, y - span, resistorNets.find((n) => !signalNets.includes(n)));
      const matches = targets.every((t) => Math.abs(t.newSchX - t.schematicBox.schX) <= 0.1 && Math.abs(t.newSchY - t.schematicBox.schY) <= 0.1 && Math.abs(t.deltaSchRotation) <= 1 && t.pins.every((p) => {
        const actual = index.port(index.portsByComponent.get(t.schematicBox.sourceComponentId).find((s) => s.source_port_id === p.sourcePortId));
        return Math.abs(actual.center.x - p.newSchX) <= 0.1 && Math.abs(actual.center.y - p.newSchY) <= 0.1;
      }));
      if (matches)
        continue;
      const moves = targets.map((t) => `${t.schematicBox.sourceComponentName ?? t.schematicBox.sourceComponentId}: schX=${t.newSchX}, schY=${t.newSchY}, rotate by ${t.deltaSchRotation} degrees`);
      const pinInstructions = targets[0].pins.map((p) => `pin ${p.pinNumber ?? p.sourcePortId} at (${p.newSchX}, ${p.newSchY})`).join("; ");
      issues.push({
        lineItemType: "FourPinCrystalPatternMismatch",
        crystalSchematicBox: crystal,
        suggestedPlacements: targets,
        message: `Arrange the four-pin crystal vertically, both load capacitors horizontally to its left (one above and one below), and the series resistor horizontally to its lower right. ${moves.join("; ")}. Crystal ${pinInstructions}. Keep the grounded case pins on opposite sides of the crystal, each connected to GND. Connect the capacitor ground ends to a left-hand ground bus, capacitor signal ends to the corresponding top/bottom crystal signals, and the resistor from the bottom signal toward the external oscillator connection. Rotations are relative to the current symbols; positive is counterclockwise.`
      });
    }
    this.solved = true;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "crystalName", issue.crystalSchematicBox.sourceComponentName);
    addAttr(attrs, "message", issue.message);
    return `<FourPinCrystalPatternMismatch ${attrs.join(" ")} />`;
  }
}
var round = (n) => Math.round(n * 100) / 100;
var angleDelta = (n) => round(((n + 180) % 360 + 360) % 360 - 180);

// ../../work/placement-analysis/lib/solvers/ChipPinPairCapacitorPlacementSolver/ChipPinPairCapacitorPlacementSolver.ts
class ChipPinPairCapacitorPlacementSolver extends BaseSolver {
  params;
  index;
  capacitorIds;
  unpopulated = new Set;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    for (const element of params.ctx.circuitJson)
      if (element.type === "pcb_component" && element.do_not_place)
        this.unpopulated.add(element.source_component_id);
    this.capacitorIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_capacitor").map((component) => component.source_component_id);
    this.solved = this.capacitorIds.length === 0;
  }
  _step() {
    const capacitorId = this.capacitorIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.capacitorIds.length;
    if (!capacitorId || this.unpopulated.has(capacitorId))
      return;
    const index = this.index;
    const component = index.components.get(capacitorId);
    const capacitor = index.placement(capacitorId);
    const capacitorPorts = index.portsByComponent.get(capacitorId) ?? [];
    const nets = index.twoTerminalNets(capacitorId);
    if (component?.ftype !== "simple_capacitor" || !Number.isFinite(component.capacitance) || component.capacitance <= 0 || !capacitor || !nets || nets.some((net) => index.isRail(net)) || capacitorPorts.some((port) => port.do_not_connect || hasSupplyRole(port)))
      return;
    const peers = nets.map((net) => {
      const members = index.portsByNet.get(net) ?? [];
      if (members.length !== 2)
        return;
      return members.find((port) => port.source_component_id !== capacitorId);
    });
    const [first, second] = peers;
    if (!first || !second || first.source_component_id !== second.source_component_id || first.do_not_connect || second.do_not_connect || hasSupplyRole(first) || hasSupplyRole(second))
      return;
    const hostId = first.source_component_id;
    const host = index.placement(hostId);
    if (index.components.get(hostId)?.ftype !== "simple_chip" || this.unpopulated.has(hostId) || !host || !index.sameLocalScope(host, capacitor))
      return;
    const chipPorts = [first, second];
    const pins = chipPorts.map((port) => index.port(port));
    const capPins = capacitorPorts.map((port) => index.port(port));
    if ([...pins, ...capPins].some((pin) => !pin || pin.schematic_sheet_id !== host.schematicSheetId || !Number.isFinite(pin.center.x) || !Number.isFinite(pin.center.y)) || [host, capacitor].some((box) => ![box.schX, box.schY, box.width, box.height].every(Number.isFinite) || box.width <= 0 || box.height <= 0))
      return;
    const firstPin = pins[0], secondPin = pins[1];
    const side = firstPin.facing_direction;
    if (!side || side !== secondPin.facing_direction)
      return;
    const horizontal = side === "left" || side === "right";
    const sign = side === "left" || side === "down" ? -1 : 1;
    const pinSpan = Math.hypot(firstPin.center.x - secondPin.center.x, firstPin.center.y - secondPin.center.y);
    if (pinSpan < 0.01)
      return;
    const oppositeDistance = -sign * (horizontal ? capacitor.schX - host.schX : capacitor.schY - host.schY);
    const halfBodies = horizontal ? (host.width + capacitor.width) / 2 : (host.height + capacitor.height) / 2;
    if (oppositeDistance <= halfBodies + 0.2)
      return;
    const maxPinDistance = Math.max(...pins.map((pin, i) => Math.hypot(pin.center.x - capPins[i].center.x, pin.center.y - capPins[i].center.y)));
    const maxRecommendedPinDistance = Math.max(4, 3 * Math.max(capacitor.width, capacitor.height), 2 * pinSpan);
    if (maxPinDistance <= maxRecommendedPinDistance)
      return;
    this.params.issues.push({
      lineItemType: "CapacitorSeparatedFromChipPins",
      hostSchematicBox: host,
      capacitorSchematicBox: capacitor,
      chipSourcePortIds: [
        chipPorts[0].source_port_id,
        chipPorts[1].source_port_id
      ],
      maxPinDistance,
      maxRecommendedPinDistance,
      message: `Place ${capacitor.sourceComponentName ?? capacitorId} beside its two connected pins on the ${side} side of ${host.sourceComponentName ?? hostId} so their connections can be read together. Preserve pin connections, leave room for labels, and reroute affected traces; exact alignment is not required.`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "hostComponentName", issue.hostSchematicBox.sourceComponentName);
    addAttr(attrs, "capacitorName", issue.capacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "maxPinDistance", issue.maxPinDistance);
    addAttr(attrs, "maxRecommendedPinDistance", issue.maxRecommendedPinDistance);
    addAttr(attrs, "message", issue.message);
    return `<CapacitorSeparatedFromChipPins ${attrs.join(" ")} />`;
  }
}
function hasSupplyRole(port) {
  return Boolean(port.requires_power || port.provides_power || port.requires_ground || port.provides_ground || port.requires_voltage !== undefined || port.provides_voltage !== undefined);
}

// ../../work/placement-analysis/lib/solvers/PiFilterPlacementSolver/PiFilterPlacementSolver.ts
class PiFilterPlacementSolver extends BaseSolver {
  params;
  index;
  inductorIds;
  unpopulated = new Set;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    for (const e of params.ctx.circuitJson)
      if (e.type === "pcb_component" && e.do_not_place)
        this.unpopulated.add(e.source_component_id);
    for (const e of params.ctx.circuitJson)
      if (e.type === "pcb_component" && !e.do_not_place)
        this.unpopulated.delete(e.source_component_id);
    this.inductorIds = [...this.index.components.values()].filter((c) => c.ftype === "simple_inductor" && !this.unpopulated.has(c.source_component_id)).map((c) => c.source_component_id);
    this.solved = this.inductorIds.length === 0;
  }
  _step() {
    const id = this.inductorIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.inductorIds.length;
    if (!id)
      return;
    const index = this.index;
    const inductor = this.localPart(id);
    const nets = index.twoTerminalNets(id);
    if (!inductor || !nets || nets.some((net) => index.isRail(net)))
      return;
    const branches = nets.map((net) => {
      const peers = index.portsByNet.get(net) ?? [];
      if (peers.some((p) => p.source_component_id !== id && !this.unpopulated.has(p.source_component_id) && index.components.get(p.source_component_id)?.ftype === "simple_inductor"))
        return;
      const capacitors = peers.filter((p) => {
        const c = index.components.get(p.source_component_id);
        const capNets = index.twoTerminalNets(p.source_component_id);
        return c?.ftype === "simple_capacitor" && !this.unpopulated.has(p.source_component_id) && capNets?.some((n) => n !== net && index.groundNets.has(n));
      });
      if (capacitors.length !== 1)
        return;
      const capacitorPort = capacitors[0];
      const component = index.components.get(capacitorPort.source_component_id);
      if (component.ftype !== "simple_capacitor" || !Number.isFinite(component.capacitance) || component.capacitance <= 0)
        return;
      const capacitor = this.localPart(capacitorPort.source_component_id);
      if (!capacitor || !index.sameLocalScope(inductor.placement, capacitor.placement))
        return;
      const capPin = index.port(capacitorPort);
      const seriesPin = index.port(inductor.ports.find((p) => index.connected(p.source_port_id) === net));
      return {
        placement: capacitor.placement,
        ground: index.twoTerminalNets(capacitorPort.source_component_id).find((n) => n !== net),
        distance: Math.hypot(capPin.center.x - seriesPin.center.x, capPin.center.y - seriesPin.center.y)
      };
    });
    const [first, second] = branches;
    if (!first || !second || first.ground !== second.ground)
      return;
    const placements = [inductor.placement, first.placement, second.placement];
    const maxRecommendedSignalPinDistance = Math.max(4, ...placements.map((p) => 3 * Math.max(p.width, p.height)));
    const maxSignalPinDistance = Math.max(first.distance, second.distance);
    if (maxSignalPinDistance <= maxRecommendedSignalPinDistance)
      return;
    const name = (p) => p.sourceComponentName ?? p.sourceComponentId;
    this.params.issues.push({
      lineItemType: "PiFilterComponentsNotGrouped",
      inductorSchematicBox: inductor.placement,
      firstCapacitorSchematicBox: first.placement,
      secondCapacitorSchematicBox: second.placement,
      maxSignalPinDistance,
      maxRecommendedSignalPinDistance,
      message: `Group ${name(first.placement)} and ${name(second.placement)} beside the connected ends of ${name(inductor.placement)} so the series path and both grounded branches of the pi filter can be read together. Preserve pin connections, allow room for labels, and reroute affected traces.`
    });
  }
  localPart(id) {
    const placement = this.index.placement(id);
    const ports = this.index.portsByComponent.get(id);
    if (!placement || ports?.length !== 2 || ports.some((p) => {
      const pin = this.index.port(p);
      return p.do_not_connect || !pin || pin.schematic_sheet_id !== placement.schematicSheetId || !Number.isFinite(pin.center.x) || !Number.isFinite(pin.center.y);
    }))
      return;
    return { placement, ports };
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "inductorName", issue.inductorSchematicBox.sourceComponentName);
    addAttr(attrs, "firstCapacitorName", issue.firstCapacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "secondCapacitorName", issue.secondCapacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "maxSignalPinDistance", issue.maxSignalPinDistance);
    addAttr(attrs, "maxRecommendedSignalPinDistance", issue.maxRecommendedSignalPinDistance);
    addAttr(attrs, "message", issue.message);
    return `<PiFilterComponentsNotGrouped ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/MosfetGateNetworkPlacementSolver/MosfetGateNetworkPlacementSolver.ts
class MosfetGateNetworkPlacementSolver extends BaseSolver {
  params;
  index;
  mosfetIds;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    this.mosfetIds = [...this.index.components.keys()].filter((id) => this.mosfetPorts(id));
    this.solved = this.mosfetIds.length === 0;
  }
  _step() {
    const id = this.mosfetIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.mosfetIds.length;
    if (!id)
      return;
    const index = this.index;
    const mosfet = index.placement(id);
    const roles = this.mosfetPorts(id);
    if (!mosfet)
      return;
    const gateNet = index.connected(roles.gate.source_port_id);
    const sourceNet = index.connected(roles.sources[0].source_port_id);
    const drainNet = index.connected(roles.drains[0].source_port_id);
    if (new Set([gateNet, sourceNet, drainNet]).size !== 3 || index.isRail(gateNet))
      return;
    if ([roles.gate, ...roles.sources, ...roles.drains].some((p) => {
      const pin = index.port(p);
      return !pin || pin.schematic_sheet_id !== mosfet.schematicSheetId;
    }))
      return;
    const peers = (index.portsByNet.get(gateNet) ?? []).filter((p) => p.source_component_id !== id);
    if (peers.length !== 2)
      return;
    const resistors = peers.map((p) => {
      const resistorId = p.source_component_id;
      const component = index.components.get(resistorId);
      const placement = index.placement(resistorId);
      const nets = index.twoTerminalNets(resistorId);
      if (component?.ftype !== "simple_resistor" || !Number.isFinite(component.resistance) || component.resistance <= 0 || !placement || !nets || !index.sameLocalScope(mosfet, placement) || index.portsByComponent.get(resistorId).some((port) => {
        const pin = index.port(port);
        return port.do_not_connect || !pin || pin.schematic_sheet_id !== mosfet.schematicSheetId;
      }))
        return;
      return { placement, otherNet: nets.find((net) => net !== gateNet) };
    });
    if (resistors.some((r) => !r))
      return;
    const shunts = resistors.filter((r) => r.otherNet === sourceNet);
    const series = resistors.filter((r) => r.otherNet !== sourceNet);
    if (shunts.length !== 1 || series.length !== 1)
      return;
    const gateSourceResistor = shunts[0].placement;
    const seriesGateResistor = series[0].placement;
    if (series[0].otherNet === drainNet || index.isRail(series[0].otherNet))
      return;
    const maxRecommendedBodyGap = Math.max(6, 3 * Math.max(mosfet.width, mosfet.height));
    const maxBodyGap = Math.max(bodyGap(mosfet, seriesGateResistor), bodyGap(mosfet, gateSourceResistor));
    if (maxBodyGap <= maxRecommendedBodyGap)
      return;
    this.params.issues.push({
      lineItemType: "MosfetGateNetworkNotGrouped",
      mosfetSchematicBox: mosfet,
      seriesGateResistorSchematicBox: seriesGateResistor,
      gateSourceResistorSchematicBox: gateSourceResistor,
      maxBodyGap,
      maxRecommendedBodyGap,
      message: `Group ${seriesGateResistor.sourceComponentName ?? seriesGateResistor.sourceComponentId} and ${gateSourceResistor.sourceComponentName ?? gateSourceResistor.sourceComponentId} beside ${mosfet.sourceComponentName ?? id}'s gate/source pins so the gate-drive branch can be read together. Preserve all pin connections, leave room for labels, and reroute affected traces.`
    });
  }
  mosfetPorts(id) {
    const type = this.index.components.get(id)?.ftype;
    if (type !== "simple_mosfet" && type !== "simple_chip")
      return;
    const ports = this.index.portsByComponent.get(id) ?? [];
    const gate = ports.filter((p) => hasRole(p, /^(G|GATE)$/));
    const sources = ports.filter((p) => hasRole(p, /^(S|SOURCE)[0-9]*$/));
    const drains = ports.filter((p) => hasRole(p, /^(D|DRAIN)[0-9]*$/));
    if (gate.length !== 1 || !sources.length || !drains.length || gate.length + sources.length + drains.length !== ports.length || new Set([...gate, ...sources, ...drains]).size !== ports.length || ports.some((p) => p.do_not_connect))
      return;
    for (const group of [sources, drains])
      if (new Set(group.map((p) => this.index.connected(p.source_port_id))).size !== 1)
        return;
    return { gate: gate[0], sources, drains };
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "mosfetName", issue.mosfetSchematicBox.sourceComponentName);
    addAttr(attrs, "seriesGateResistorName", issue.seriesGateResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "gateSourceResistorName", issue.gateSourceResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "maxBodyGap", issue.maxBodyGap);
    addAttr(attrs, "maxRecommendedBodyGap", issue.maxRecommendedBodyGap);
    addAttr(attrs, "message", issue.message);
    return `<MosfetGateNetworkNotGrouped ${attrs.join(" ")} />`;
  }
}
function hasRole(port, pattern) {
  return [port.name, ...port.port_hints ?? []].some((hint) => pattern.test(hint.toUpperCase().replace(/[\s_]/g, "")));
}
function bodyGap(a, b) {
  return Math.hypot(Math.max(0, Math.abs(a.schX - b.schX) - (a.width + b.width) / 2), Math.max(0, Math.abs(a.schY - b.schY) - (a.height + b.height) / 2));
}

// ../../work/placement-analysis/lib/solvers/RelayFlybackDiodePlacementSolver/RelayFlybackDiodePlacementSolver.ts
class RelayFlybackDiodePlacementSolver extends BaseSolver {
  params;
  index;
  relayIds;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    this.relayIds = [...this.index.components.keys()].filter((id) => this.coilPorts(id));
    this.solved = this.relayIds.length === 0;
  }
  _step() {
    const relayId = this.relayIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.relayIds.length;
    if (!relayId)
      return;
    const index = this.index;
    const relay = index.placement(relayId);
    const coil = this.coilPorts(relayId);
    if (!relay || coil.some((p) => p.do_not_connect))
      return;
    const nets = coil.map((p) => index.connected(p.source_port_id));
    if (nets[0] === nets[1])
      return;
    if (this.relayIds.some((id) => id !== relayId && this.coilPorts(id).every((p) => nets.includes(index.connected(p.source_port_id)))))
      return;
    const diodeIds = new Set((index.portsByNet.get(nets[0]) ?? []).filter((p) => index.components.get(p.source_component_id)?.ftype === "simple_diode").map((p) => p.source_component_id).filter((id) => index.twoTerminalNets(id)?.includes(nets[1])));
    if (diodeIds.size !== 1)
      return;
    const diodeId = [...diodeIds][0];
    const diode = index.placement(diodeId);
    const anode = this.uniquePort(diodeId, /^(?:ANODE|A)$/);
    const cathode = this.uniquePort(diodeId, /^(?:CATHODE|K)$/);
    if (!diode || !index.sameLocalScope(relay, diode) || !anode || !cathode || anode === cathode || anode.do_not_connect || cathode.do_not_connect)
      return;
    const anodeNet = index.connected(anode.source_port_id);
    const cathodeNet = index.connected(cathode.source_port_id);
    if (index.isRail(anodeNet) || index.groundNets.has(cathodeNet) || !this.hasGroundedDriver(anodeNet, cathodeNet))
      return;
    const coilPins = coil.map((p) => index.port(p));
    const diodePins = [anode, cathode].map((p) => index.port(p));
    if ([...coilPins, ...diodePins].some((p) => !p || p.schematic_sheet_id !== relay.schematicSheetId))
      return;
    const [first, second] = coilPins;
    const left = Math.min(first.center.x, second.center.x);
    const right = Math.max(first.center.x, second.center.x);
    const bottom = Math.min(first.center.y, second.center.y);
    const top = Math.max(first.center.y, second.center.y);
    const gapX = Math.max(left - (diode.schX + diode.width / 2), diode.schX - diode.width / 2 - right, 0);
    const gapY = Math.max(bottom - (diode.schY + diode.height / 2), diode.schY - diode.height / 2 - top, 0);
    const distanceFromCoilPins = Math.hypot(gapX, gapY);
    const pinSpan = Math.hypot(right - left, top - bottom);
    if (distanceFromCoilPins <= Math.max(1.5, 2 * pinSpan) || distanceFromCoilPins > Math.max(8, 4 * Math.max(relay.width, relay.height)))
      return;
    if (!this.params.ctx.circuitJson.some((e) => e.type === "schematic_net_label" && e.schematic_sheet_id === relay.schematicSheetId && e.anchor_position && diodePins.some((p) => Math.hypot(p.center.x - e.anchor_position.x, p.center.y - e.anchor_position.y) < 0.01 && !this.hasWireAtPin(p))))
      return;
    this.params.issues.push({
      lineItemType: "FlybackDiodeSeparatedFromRelayCoil",
      relaySchematicBox: relay,
      diodeSchematicBox: diode,
      coilSourcePortIds: [coil[0].source_port_id, coil[1].source_port_id],
      distanceFromCoilPins,
      message: `Place ${diode.sourceComponentName ?? diodeId} beside ${relay.sourceComponentName ?? relayId}'s coil pins so the flyback protection loop can be read together. Preserve diode polarity and all pin connections; leave room for labels and reroute affected traces.`
    });
  }
  hasWireAtPin(pin) {
    return this.params.ctx.circuitJson.some((e) => e.type === "schematic_trace" && e.schematic_sheet_id === pin.schematic_sheet_id && e.edges.some(({ from, to }) => {
      const dx = to.x - from.x, dy = to.y - from.y;
      const lengthSquared = dx * dx + dy * dy;
      const t = lengthSquared ? Math.max(0, Math.min(1, ((pin.center.x - from.x) * dx + (pin.center.y - from.y) * dy) / lengthSquared)) : 0;
      return Math.hypot(pin.center.x - from.x - t * dx, pin.center.y - from.y - t * dy) < 0.01;
    }));
  }
  uniquePort(id, pattern) {
    const ports = this.index.portsByComponent.get(id)?.filter((p) => hasHint(p, pattern));
    return ports?.length === 1 ? ports[0] : undefined;
  }
  coilPorts(id) {
    if (this.index.components.get(id)?.ftype !== "simple_chip")
      return;
    const ports = this.index.portsByComponent.get(id) ?? [];
    if (!this.uniquePort(id, /^(?:COM|COMMON)$/) || !ports.some((p) => hasHint(p, /^(?:NO|NC|NORMALLYOPEN|NORMALLYCLOSED)$/)))
      return;
    const coil = ports.filter((p) => hasHint(p, /^(?:COIL[A-B12]|A[12])$/));
    if (coil.length !== 2)
      return;
    for (const [a, b] of [
      ["COILA", "COILB"],
      ["COIL1", "COIL2"],
      ["A1", "A2"]
    ]) {
      const first = this.uniquePort(id, new RegExp(`^${a}$`));
      const second = this.uniquePort(id, new RegExp(`^${b}$`));
      if (first && second && first !== second && !hasHint(first, new RegExp(`^${b}$`)) && !hasHint(second, new RegExp(`^${a}$`)))
        return [first, second];
    }
  }
  hasGroundedDriver(anodeNet, cathodeNet) {
    return (this.index.portsByNet.get(anodeNet) ?? []).some((p) => {
      const id = p.source_component_id;
      const component = this.index.components.get(id);
      if (component?.ftype !== "simple_chip" && !(component?.ftype === "simple_transistor" && component.transistor_type === "npn"))
        return false;
      if (this.index.portsByComponent.get(id)?.length !== 3)
        return false;
      const c = this.uniquePort(id, /^(?:C|COLLECTOR)$/);
      const e = this.uniquePort(id, /^(?:E|EMITTER)$/);
      const b = this.uniquePort(id, /^(?:B|BASE)$/);
      if (!c || !e || !b || new Set([c, e, b]).size !== 3 || [c, e, b].some((p2) => p2.do_not_connect) || c.source_port_id !== p.source_port_id)
        return false;
      const emitterNet = this.index.connected(e.source_port_id), baseNet = this.index.connected(b.source_port_id);
      return this.index.groundNets.has(emitterNet) && !this.index.powerNets.has(emitterNet) && new Set([anodeNet, cathodeNet, emitterNet, baseNet]).size === 4;
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "relayName", issue.relaySchematicBox.sourceComponentName);
    addAttr(attrs, "diodeName", issue.diodeSchematicBox.sourceComponentName);
    addAttr(attrs, "distanceFromCoilPins", issue.distanceFromCoilPins);
    addAttr(attrs, "message", issue.message);
    return `<FlybackDiodeSeparatedFromRelayCoil ${attrs.join(" ")} />`;
  }
}
function hasHint(port, pattern) {
  return [port.name, ...port.port_hints ?? []].some((hint) => pattern.test(hint.toUpperCase().replace(/[\s_]/g, "")));
}

// ../../work/placement-analysis/lib/solvers/CurrentSenseShuntPlacementSolver/CurrentSenseShuntPlacementSolver.ts
var EPSILON = 0.01;

class CurrentSenseShuntPlacementSolver extends BaseSolver {
  params;
  index;
  hostIds;
  traces;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    this.hostIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_chip").map((component) => component.source_component_id);
    this.traces = params.ctx.circuitJson.filter((element) => element.type === "schematic_trace");
    this.solved = this.hostIds.length === 0;
  }
  _step() {
    const hostId = this.hostIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.hostIds.length;
    if (!hostId)
      return;
    const index = this.index;
    const host = index.placement(hostId);
    const ports = index.portsByComponent.get(hostId) ?? [];
    const positive = ports.filter((port) => inputRole(port) === "positive");
    const negative = ports.filter((port) => inputRole(port) === "negative");
    const outputs = ports.filter((port) => hasHint2(port, /^(?:OUT|VOUT|OUTPUT)$/));
    if (!host || positive.length !== 1 || negative.length !== 1 || outputs.length !== 1 || !ports.some((port) => hasHint2(port, /^(?:VS|VCC|VDD)$/)) || !ports.some((port) => hasHint2(port, /^(?:GND|GROUND|VSS)$/)))
      return;
    const inputs = [positive[0], negative[0]];
    const nets = inputs.map((port) => index.connected(port.source_port_id));
    if (inputs.some((port) => port.do_not_connect) || nets[0] === nets[1] || nets.includes(index.connected(outputs[0].source_port_id)))
      return;
    const pins = inputs.map((port) => index.port(port));
    const [positivePin, negativePin] = pins;
    if (!positivePin || !negativePin || !positivePin.facing_direction || positivePin.facing_direction !== negativePin.facing_direction || pins.some((pin) => pin.schematic_sheet_id !== host.schematicSheetId))
      return;
    const resistorIds = new Set((index.portsByNet.get(nets[0]) ?? []).filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").map((port) => port.source_component_id).filter((id) => index.twoTerminalNets(id)?.includes(nets[1])));
    if (resistorIds.size !== 1)
      return;
    const shuntId = [...resistorIds][0];
    const component = index.components.get(shuntId);
    if (component?.ftype !== "simple_resistor" || !Number.isFinite(component.resistance) || component.resistance <= 0 || component.resistance > 1)
      return;
    if (nets.some((net) => (index.portsByNet.get(net) ?? []).some((port) => port.source_component_id !== hostId && inputRole(port) !== undefined && index.components.get(port.source_component_id)?.ftype === "simple_chip")))
      return;
    const shunt = index.placement(shuntId);
    if (!shunt || !index.sameLocalScope(host, shunt))
      return;
    const shuntPorts = index.portsByComponent.get(shuntId);
    if (shuntPorts.some((port) => port.do_not_connect))
      return;
    const shuntPins = nets.map((net) => index.port(shuntPorts.find((port) => index.connected(port.source_port_id) === net)));
    if (shuntPins.some((pin) => !pin || pin.schematic_sheet_id !== host.schematicSheetId))
      return;
    const horizontalInputs = positivePin.facing_direction === "left" || positivePin.facing_direction === "right";
    const across = (point) => horizontalInputs ? point.y : point.x;
    const first = across(positivePin.center), second = across(negativePin.center);
    const span = Math.abs(first - second);
    if (span < EPSILON)
      return;
    const shuntAcross = horizontalInputs ? shunt.schY : shunt.schX;
    const halfSize = (horizontalInputs ? shunt.height : shunt.width) / 2;
    const inputBandGap = Math.max(Math.min(first, second) - (shuntAcross + halfSize), shuntAcross - halfSize - Math.max(first, second));
    if (inputBandGap <= Math.max(1.5, 2 * span) || Math.hypot(shunt.schX - host.schX, shunt.schY - host.schY) > Math.max(8, 4 * Math.max(host.width, host.height)))
      return;
    const visible = pins.map((pin, i) => this.hasVisibleConnection(shuntPins[i], pin, nets[i]));
    if (visible[0] === visible[1])
      return;
    const labeledIndex = visible[0] ? 1 : 0;
    const labeledNet = nets[labeledIndex];
    if (!this.params.ctx.circuitJson.some((element) => {
      if (element.type !== "schematic_net_label" || element.schematic_sheet_id !== host.schematicSheetId)
        return false;
      if (element.source_net_id && (index.connected(element.source_net_id) === labeledNet || index.connected(`connectivity:${element.source_net_id}`) === labeledNet))
        return true;
      const pin = shuntPins[labeledIndex].center;
      if (element.anchor_position && Math.hypot(element.anchor_position.x - pin.x, element.anchor_position.y - pin.y) < EPSILON)
        return true;
      return element.source_trace_id !== undefined && this.sourceTraceTouchesNet(element.source_trace_id, labeledNet);
    }))
      return;
    this.params.issues.push({
      lineItemType: "CurrentSenseShuntSeparatedFromInputs",
      amplifierSchematicBox: host,
      shuntSchematicBox: shunt,
      positiveInputSourcePortId: inputs[0].source_port_id,
      negativeInputSourcePortId: inputs[1].source_port_id,
      inputBandGap,
      message: `Place ${shunt.sourceComponentName ?? shuntId} near ${host.sourceComponentName ?? hostId}.${inputs[0].name}/${inputs[1].name}, so both sense connections can be read together. Move or rotate the shunt as needed; preserve all pin connections and leave room for labels.`
    });
  }
  hasVisibleConnection(from, to, net) {
    const edges = this.traces.filter((trace) => {
      if (trace.schematic_sheet_id !== from.schematic_sheet_id)
        return false;
      if (trace.subcircuit_connectivity_map_key)
        return this.index.connected(`connectivity:${trace.subcircuit_connectivity_map_key}`) === net;
      if (this.sourceTraceTouchesNet(trace.source_trace_id, net))
        return true;
      const endpoints = [trace.edges[0]?.from, trace.edges.at(-1)?.to];
      const endpointNets = new Set(this.params.ctx.circuitJson.flatMap((element) => element.type === "schematic_port" && element.source_port_id && element.schematic_sheet_id === trace.schematic_sheet_id && endpoints.some((point) => point && Math.hypot(point.x - element.center.x, point.y - element.center.y) < EPSILON) ? [this.index.connected(element.source_port_id)] : []));
      return endpointNets.size === 1 && endpointNets.has(net);
    }).flatMap((trace) => trace.edges);
    const reached = edges.filter((edge) => onSegment(from.center, edge.from, edge.to));
    const visited = new Set;
    for (let i = 0;i < reached.length; i++) {
      const current = reached[i];
      if (onSegment(to.center, current.from, current.to))
        return true;
      for (const [edgeIndex, edge] of edges.entries()) {
        if (visited.has(edgeIndex) || ![current.from, current.to].some((point) => onSegment(point, edge.from, edge.to)) && ![edge.from, edge.to].some((point) => onSegment(point, current.from, current.to)))
          continue;
        visited.add(edgeIndex);
        reached.push(edge);
      }
    }
    return false;
  }
  sourceTraceTouchesNet(traceId, net) {
    if (!traceId)
      return false;
    const source = this.params.ctx.circuitJson.find((element) => element.type === "source_trace" && element.source_trace_id === traceId);
    return source?.type === "source_trace" && source.connected_source_port_ids.some((id) => this.index.connected(id) === net);
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "amplifierName", issue.amplifierSchematicBox.sourceComponentName);
    addAttr(attrs, "shuntName", issue.shuntSchematicBox.sourceComponentName);
    addAttr(attrs, "inputBandGap", issue.inputBandGap);
    addAttr(attrs, "message", issue.message);
    return `<CurrentSenseShuntSeparatedFromInputs ${attrs.join(" ")} />`;
  }
}
function hasHint2(port, pattern) {
  return [port.name, ...port.port_hints ?? []].some((hint) => pattern.test(hint.toUpperCase().replace(/[\s_]/g, "")));
}
function inputRole(port) {
  const positive = hasHint2(port, /^(?:IN\+|VIN\+|INPOS|VINPOS)$/);
  const negative = hasHint2(port, /^(?:IN-|VIN-|INNEG|VINNEG)$/);
  return positive === negative ? undefined : positive ? "positive" : "negative";
}
function onSegment(point, from, to) {
  const dx = to.x - from.x, dy = to.y - from.y;
  const length = Math.hypot(dx, dy);
  if (length < EPSILON)
    return Math.hypot(point.x - from.x, point.y - from.y) < EPSILON;
  const projection = ((point.x - from.x) * dx + (point.y - from.y) * dy) / length;
  return projection >= -EPSILON && projection <= length + EPSILON && Math.abs((point.x - from.x) * dy - (point.y - from.y) * dx) / length < EPSILON;
}

// ../../work/placement-analysis/lib/solvers/VoltageDividerPlacementSolver/VoltageDividerPlacementSolver.ts
class VoltageDividerPlacementSolver extends BaseSolver {
  params;
  index;
  positiveNets = new Set;
  resistorIds;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    this.resistorIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_resistor").map((component) => component.source_component_id);
    for (const element of params.ctx.circuitJson) {
      if (element.type === "source_net" && element.is_positive_voltage_source)
        this.positiveNets.add(this.index.connected(element.source_net_id));
    }
    this.solved = this.resistorIds.length === 0;
  }
  _step() {
    const supplyId = this.resistorIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.resistorIds.length;
    if (!supplyId || !this.isResistor(supplyId))
      return;
    const index = this.index;
    const nets = index.twoTerminalNets(supplyId);
    if (!nets)
      return;
    const rails = nets.filter((net) => index.isRail(net));
    if (rails.length !== 1)
      return;
    const supplyNet = rails[0];
    if (!this.positiveNets.has(supplyNet) || index.groundNets.has(supplyNet))
      return;
    const tap = nets.find((net) => net !== supplyNet);
    const tapPorts = index.portsByNet.get(tap) ?? [];
    const resistorIds = new Set(tapPorts.filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").map((port) => port.source_component_id));
    if (resistorIds.size !== 2)
      return;
    const groundId = [...resistorIds].find((id) => id !== supplyId);
    if (!this.isResistor(groundId))
      return;
    const groundNets = index.twoTerminalNets(groundId);
    const groundNet = groundNets?.find((net) => net !== tap);
    if (!groundNets?.includes(tap) || !groundNet || !index.groundNets.has(groundNet) || index.powerNets.has(groundNet) || !tapPorts.some((port) => !resistorIds.has(port.source_component_id)))
      return;
    const supply = index.placement(supplyId);
    const ground = index.placement(groundId);
    if (!supply || !ground || !index.sameLocalScope(supply, ground))
      return;
    const supplyTap = this.getDownwardResistorPorts(supplyId, supplyNet, tap);
    const groundTap = this.getDownwardResistorPorts(groundId, tap, groundNet);
    if (!supplyTap || !groundTap)
      return;
    const reversedBodyGap = ground.schY - ground.height / 2 - (supply.schY + supply.height / 2);
    if (reversedBodyGap <= 1.5)
      return;
    this.params.issues.push({
      lineItemType: "VoltageDividerSupplyResistorBelowGroundResistor",
      supplyResistorSchematicBox: supply,
      groundResistorSchematicBox: ground,
      supplyTapSourcePortId: supplyTap.bottom.source_port_id,
      groundTapSourcePortId: groundTap.top.source_port_id,
      reversedBodyGap,
      message: `Place ${supply.sourceComponentName ?? supplyId} above ${ground.sourceComponentName ?? groundId}, close enough to read their shared divider tap. Preserve all connections and leave room for labels; exact alignment is not required.`
    });
  }
  isResistor(id) {
    const component = this.index.components.get(id);
    return component?.ftype === "simple_resistor" && Number.isFinite(component.resistance) && component.resistance > 0;
  }
  getDownwardResistorPorts(id, topNet, bottomNet) {
    const index = this.index;
    const placement = index.placement(id);
    const ports = index.portsByComponent.get(id);
    if (ports.some((port) => port.do_not_connect))
      return;
    const top = ports.find((port) => index.connected(port.source_port_id) === topNet);
    const bottom = ports.find((port) => index.connected(port.source_port_id) === bottomNet);
    if (!top || !bottom)
      return;
    const topPin = index.port(top);
    const bottomPin = index.port(bottom);
    if (!topPin || !bottomPin || topPin.schematic_sheet_id !== placement.schematicSheetId || bottomPin.schematic_sheet_id !== placement.schematicSheetId || topPin.facing_direction !== "up" || bottomPin.facing_direction !== "down" || topPin.center.y <= bottomPin.center.y)
      return;
    return { top, bottom };
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "supplyResistorName", issue.supplyResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "groundResistorName", issue.groundResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "reversedBodyGap", issue.reversedBodyGap);
    addAttr(attrs, "message", issue.message);
    return `<VoltageDividerSupplyResistorBelowGroundResistor ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/RegulatorInputOutputCapacitorPlacementSolver/RegulatorInputOutputCapacitorPlacementSolver.ts
class RegulatorInputOutputCapacitorPlacementSolver extends BaseSolver {
  params;
  index;
  hostIds;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    this.hostIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_chip").map((component) => component.source_component_id);
    this.solved = this.hostIds.length === 0;
  }
  _step() {
    const hostId = this.hostIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.hostIds.length;
    if (!hostId)
      return;
    const index = this.index;
    const host = index.placement(hostId);
    const ports = index.portsByComponent.get(hostId) ?? [];
    if (!host || ports.some((port) => !portRole(port)))
      return;
    const inputs = ports.filter((port) => portRole(port) === "input");
    const outputs = ports.filter((port) => portRole(port) === "output");
    const grounds = ports.filter((port) => portRole(port) === "ground");
    if (inputs.length !== 1 || outputs.length !== 1 || !grounds.length)
      return;
    const input = inputs[0];
    const output = outputs[0];
    if ([input, output, ...grounds].some((port) => port.do_not_connect))
      return;
    const inputNet = index.connected(input.source_port_id);
    const outputNet = index.connected(output.source_port_id);
    const groundNets = new Set(grounds.map((port) => index.connected(port.source_port_id)));
    if (groundNets.size !== 1)
      return;
    const groundNet = [...groundNets][0];
    if (new Set([inputNet, outputNet, groundNet]).size !== 3 || !(index.groundNets.has(groundNet) || grounds.some((port) => port.requires_ground || port.provides_ground)) || !(index.powerNets.has(inputNet) || input.requires_power) || !(index.powerNets.has(outputNet) || output.provides_power))
      return;
    const inputPin = index.port(input);
    const outputPin = index.port(output);
    if (!inputPin || !outputPin || inputPin.schematic_sheet_id !== host.schematicSheetId || outputPin.schematic_sheet_id !== host.schematicSheetId)
      return;
    const horizontal = inputPin.facing_direction === "left" && outputPin.facing_direction === "right" || inputPin.facing_direction === "right" && outputPin.facing_direction === "left";
    const vertical = inputPin.facing_direction === "up" && outputPin.facing_direction === "down" || inputPin.facing_direction === "down" && outputPin.facing_direction === "up";
    if (!horizontal && !vertical)
      return;
    const sign = outputPin.facing_direction === "right" || outputPin.facing_direction === "up" ? 1 : -1;
    const pinSeparation = sign * (horizontal ? outputPin.center.x - inputPin.center.x : outputPin.center.y - inputPin.center.y);
    if (pinSeparation <= 0.01)
      return;
    const inputCap = this.localCapacitor(host, inputNet, groundNet);
    const outputCap = this.localCapacitor(host, outputNet, groundNet);
    if (!inputCap || !outputCap)
      return;
    const beyondOppositeSide = (cap, side) => {
      const distance = side * sign * (horizontal ? cap.schX - host.schX : cap.schY - host.schY);
      const halfBodies = horizontal ? (host.width + cap.width) / 2 : (host.height + cap.height) / 2;
      return distance > halfBodies + 0.2;
    };
    if (!beyondOppositeSide(inputCap, 1) || !beyondOppositeSide(outputCap, -1))
      return;
    const name = host.sourceComponentName ?? hostId;
    this.params.issues.push({
      lineItemType: "RegulatorCapacitorsOnWrongSides",
      regulatorSchematicBox: host,
      inputCapacitorSchematicBox: inputCap,
      outputCapacitorSchematicBox: outputCap,
      inputSourcePortId: input.source_port_id,
      outputSourcePortId: output.source_port_id,
      message: `Place ${inputCap.sourceComponentName} near ${name}.${input.name} on the ${inputPin.facing_direction} side and ${outputCap.sourceComponentName} near ${name}.${output.name} on the ${outputPin.facing_direction} side. Preserve all connections and leave room for labels; exact alignment is not required.`
    });
  }
  localCapacitor(host, rail, ground) {
    const index = this.index;
    const candidates = [];
    const maxDistance = Math.max(6, 4 * Math.max(host.width, host.height));
    const ids = new Set((index.portsByNet.get(rail) ?? []).map((port) => port.source_component_id));
    for (const id of ids) {
      if (index.components.get(id)?.ftype !== "simple_capacitor")
        continue;
      const nets = index.twoTerminalNets(id);
      const cap = index.placement(id);
      if (!nets?.includes(ground) || !cap || !index.sameLocalScope(host, cap))
        continue;
      if (Math.hypot(cap.schX - host.schX, cap.schY - host.schY) > maxDistance)
        continue;
      const ports = index.portsByComponent.get(id);
      if (ports.some((port) => port.do_not_connect || !index.port(port) || index.port(port).schematic_sheet_id !== host.schematicSheetId))
        continue;
      candidates.push(cap);
    }
    return candidates.length === 1 ? candidates[0] : undefined;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "regulatorName", issue.regulatorSchematicBox.sourceComponentName);
    addAttr(attrs, "inputCapacitorName", issue.inputCapacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "outputCapacitorName", issue.outputCapacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "message", issue.message);
    return `<RegulatorCapacitorsOnWrongSides ${attrs.join(" ")} />`;
  }
}
function portRole(port) {
  const roles = new Set;
  for (const hint of [port.name, ...port.port_hints ?? []]) {
    const name = hint.toUpperCase().replace(/[ _-]/g, "");
    if (/^(?:VIN|IN|INPUT)$/.test(name))
      roles.add("input");
    else if (/^(?:VOUT|OUT|OUTPUT)$/.test(name))
      roles.add("output");
    else if (/^(?:GND\d*|VSS)$/.test(name))
      roles.add("ground");
    else if (/^(?:EN|ENABLE|CE|SHDN|NC\d*|EP|PAD|ADJ|FB|BYP|BYPASS|NR|PG|PGOOD)$/.test(name))
      roles.add("control");
  }
  return roles.size === 1 ? [...roles][0] : undefined;
}

// ../../work/placement-analysis/lib/utils/geometry.ts
function centeredRect(cx, cy, w, h) {
  return {
    left: cx - w / 2,
    right: cx + w / 2,
    top: cy + h / 2,
    bottom: cy - h / 2
  };
}
function rectOverlap(a, b) {
  const ow = Math.min(a.right, b.right) - Math.max(a.left, b.left);
  const oh = Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom);
  return ow > 0 && oh > 0 ? { ow, oh } : null;
}

// ../../work/placement-analysis/lib/solvers/ConnectorPlacementSolver/ConnectorPlacementSolver.ts
var EPSILON2 = 0.01;
var directions = {
  right: { x: 1, y: 0 },
  left: { x: -1, y: 0 },
  up: { x: 0, y: 1 },
  down: { x: 0, y: -1 }
};
var dot = (a, b) => a.x * b.x + a.y * b.y;
var distance = (a, b) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
var near = (a, b) => distance(a, b) <= EPSILON2;
var round2 = (value) => Math.round(value * 100) / 100;

class ConnectorPlacementSolver extends BaseSolver {
  params;
  constructor(params) {
    super();
    this.params = params;
  }
  _step() {
    const { ctx, issues } = this.params;
    const index = new PlacementNetworkIndex(ctx);
    for (const ports of index.portsByComponent.values()) {
      for (const port of ports) {
        const net = index.connected(port.source_port_id);
        if (port.requires_ground || port.provides_ground)
          index.groundNets.add(net);
        if (port.requires_power || port.provides_power)
          index.powerNets.add(net);
      }
    }
    const allTraces = ctx.circuitJson.filter((e) => e.type === "schematic_trace");
    for (const [id, source] of index.components) {
      if (source.ftype !== "simple_pin_header" && source.ftype !== "simple_connector")
        continue;
      const connector = index.placement(id);
      const sourcePorts = index.portsByComponent.get(id) ?? [];
      if (!connector || sourcePorts.length < 2)
        continue;
      const pins = sourcePorts.map((p) => index.port(p));
      const facing = pins[0]?.facing_direction;
      if (!facing || pins.some((p) => !p || p.facing_direction !== facing))
        continue;
      const along = directions[facing];
      const across = { x: -along.y, y: along.x };
      const traces = allTraces.filter((t) => t.schematic_sheet_id === connector.schematicSheetId);
      const railLabels = ctx.circuitJson.filter((e) => e.type === "schematic_net_label" && e.schematic_sheet_id === connector.schematicSheetId);
      const connections = [];
      let ambiguous = false;
      for (const sourcePort of sourcePorts) {
        const pin = index.port(sourcePort);
        const net = index.connected(sourcePort.source_port_id);
        const peers = (index.portsByNet.get(net) ?? []).filter((p) => p.source_port_id !== sourcePort.source_port_id);
        const incidentTraces = traces.filter((t) => t.edges.some((edge) => near(edge.from, pin.center) || near(edge.to, pin.center)));
        if (index.isRail(net)) {
          if (incidentTraces.some((t) => !railLabels.some((label) => label.anchor_position && joins(t, pin.center, label.anchor_position))))
            ambiguous = true;
          continue;
        }
        if (peers.length === 0) {
          if (incidentTraces.length > 0)
            ambiguous = true;
          continue;
        }
        const peer = peers.length === 1 ? index.port(peers[0]) : undefined;
        const component = peers.length === 1 ? index.placement(peers[0].source_component_id) : undefined;
        if (!peer?.facing_direction || !component || !index.sameLocalScope(connector, component) || dot(directions[peer.facing_direction], along) !== -1) {
          ambiguous = true;
          break;
        }
        connections.push({ pin, peer, component });
      }
      if (ambiguous || connections.length < 2)
        continue;
      if (connections.some((c) => dot(c.peer.center, along) >= dot(c.pin.center, along) - 2))
        continue;
      const detouredConnections = connections.map((c) => traces.filter((t) => joins(t, c.pin.center, c.peer.center) && bendCount(t) >= 3)).filter((t) => t.length > 0);
      if (detouredConnections.length < 2)
        continue;
      const detours = detouredConnections.flat();
      const ordered = [...connections].sort((a, b) => dot(a.pin.center, across) - dot(b.pin.center, across));
      if (ordered.some((c, i) => i > 0 && dot(c.peer.center, across) <= dot(ordered[i - 1].peer.center, across) + EPSILON2))
        continue;
      const center = { x: connector.schX, y: connector.schY };
      const pinOffset = Math.max(...connections.map((c) => dot(c.pin.center, along) - dot(center, along)));
      const targetAlong = Math.min(...connections.map((c) => dot(c.peer.center, along))) - 2 - pinOffset;
      const offsets = connections.map((c) => dot(c.peer.center, across) - dot(c.pin.center, across) + dot(center, across)).sort((a, b) => a - b);
      const targetAcross = offsets[Math.floor(offsets.length / 2)];
      const target = {
        x: round2(along.x * targetAlong + across.x * targetAcross),
        y: round2(along.y * targetAlong + across.y * targetAcross)
      };
      const delta = { x: target.x - center.x, y: target.y - center.y };
      const movedPin = (pin) => ({
        x: pin.center.x + delta.x,
        y: pin.center.y + delta.y
      });
      if (connections.some((c) => distance(movedPin(c.pin), c.peer.center) > distance(c.pin.center, c.peer.center) + EPSILON2))
        continue;
      const before = connections.reduce((sum, c) => sum + distance(c.pin.center, c.peer.center), 0);
      const after = connections.reduce((sum, c) => sum + distance(movedPin(c.pin), c.peer.center), 0);
      if (before - after < 4 || after > before * 0.75)
        continue;
      const obstacles = ctx.componentPlacements.filter((p) => p.schematicSheetId === connector.schematicSheetId && p.schematicComponentId !== connector.schematicComponentId);
      const targetBounds = centeredRect(target.x, target.y, connector.width + 0.4, connector.height + 0.4);
      if (obstacles.some((p) => rectOverlap(targetBounds, centeredRect(p.schX, p.schY, p.width, p.height))))
        continue;
      if (connections.some((c) => {
        const start = movedPin(c.pin);
        const end = c.peer.center;
        const middleAlong = (dot(start, along) + dot(end, along)) / 2;
        const points = [
          start,
          {
            x: along.x * middleAlong + across.x * dot(start, across),
            y: along.y * middleAlong + across.y * dot(start, across)
          },
          {
            x: along.x * middleAlong + across.x * dot(end, across),
            y: along.y * middleAlong + across.y * dot(end, across)
          },
          end
        ];
        return obstacles.some((p) => p.schematicComponentId !== c.component.schematicComponentId && points.slice(1).some((point, i) => segmentCrossesBox(points[i], point, p)));
      }))
        continue;
      const connectedComponents = [
        ...new Map(connections.map((c) => [
          c.component.schematicComponentId,
          c.component
        ])).values()
      ];
      const name = connector.sourceComponentName ?? connector.schematicComponentId;
      issues.push({
        lineItemType: "ConnectorPositionCausesTraceDetours",
        connectorSchematicBox: connector,
        connectedComponents,
        schematicTraceIds: [
          ...new Set(detours.map((t) => t.schematic_trace_id))
        ],
        evaluatedSignalCount: connections.length,
        newSchX: target.x,
        newSchY: target.y,
        deltaSchX: round2(delta.x),
        deltaSchY: round2(delta.y),
        currentTotalSignalDistance: round2(before),
        suggestedTotalSignalDistance: round2(after),
        message: `Move ${name} to schX=${target.x}, schY=${target.y} so its signal pins face ${connectedComponents.map((p) => p.sourceComponentName ?? p.schematicComponentId).join(", ")}. Preserve rotation and pin assignments; reroute the connections and attached rail labels.`
      });
    }
    this.solved = true;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "connectorComponentName", issue.connectorSchematicBox.sourceComponentName);
    addAttr(attrs, "connectedComponents", issue.connectedComponents.map((p) => p.sourceComponentName ?? p.schematicComponentId).join(","));
    for (const key of [
      "evaluatedSignalCount",
      "newSchX",
      "newSchY",
      "deltaSchX",
      "deltaSchY",
      "currentTotalSignalDistance",
      "suggestedTotalSignalDistance"
    ])
      addAttr(attrs, key, issue[key]);
    addAttr(attrs, "message", issue.message);
    return `<ConnectorPositionCausesTraceDetours ${attrs.join(" ")} />`;
  }
}
function joins(trace, a, b) {
  const first = trace.edges[0]?.from;
  const last = trace.edges.at(-1)?.to;
  return !!first && !!last && (near(first, a) && near(last, b) || near(first, b) && near(last, a));
}
function bendCount(trace) {
  let previousAxis;
  let bends = 0;
  for (let i = 0;i < trace.edges.length; i++) {
    const edge = trace.edges[i];
    if (i > 0 && !near(trace.edges[i - 1].to, edge.from))
      return 0;
    if (near(edge.from, edge.to))
      continue;
    const axis = Math.abs(edge.from.y - edge.to.y) < EPSILON2 ? "x" : Math.abs(edge.from.x - edge.to.x) < EPSILON2 ? "y" : undefined;
    if (!axis)
      return 0;
    if (previousAxis && previousAxis !== axis)
      bends++;
    previousAxis = axis;
  }
  return bends;
}
function segmentCrossesBox(a, b, box) {
  const bounds = centeredRect(box.schX, box.schY, box.width + 0.2, box.height + 0.2);
  return Math.max(a.x, b.x) > bounds.left && Math.min(a.x, b.x) < bounds.right && Math.max(a.y, b.y) > bounds.bottom && Math.min(a.y, b.y) < bounds.top;
}

// ../../work/placement-analysis/lib/solvers/LowSideTransistorPlacementSolver/LowSideTransistorPlacementSolver.ts
class LowSideTransistorPlacementSolver extends BaseSolver {
  index;
  positiveNets = new Set;
  transistorIds;
  issues;
  currentIndex = 0;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.issues = issues;
    this.index = new PlacementNetworkIndex(ctx);
    for (const element of ctx.circuitJson) {
      if (element.type === "source_net" && element.is_positive_voltage_source)
        this.positiveNets.add(this.index.connected(element.source_net_id));
    }
    this.transistorIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_transistor" && component.transistor_type === "npn").map((component) => component.source_component_id);
    this.solved = this.transistorIds.length === 0;
  }
  _step() {
    const id = this.transistorIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.transistorIds.length;
    if (!id)
      return;
    const index = this.index;
    const transistor = index.placement(id);
    if (!transistor || index.portsByComponent.get(id)?.length !== 3)
      return;
    const base = index.namedPort(id, "base");
    const collector = index.namedPort(id, "collector");
    const emitter = index.namedPort(id, "emitter");
    if (!base || !collector || !emitter)
      return;
    const baseNet = index.connected(base.source_port_id);
    const collectorNet = index.connected(collector.source_port_id);
    const emitterNet = index.connected(emitter.source_port_id);
    if (new Set([baseNet, collectorNet, emitterNet]).size !== 3 || !index.groundNets.has(emitterNet) || index.powerNets.has(emitterNet) || index.isRail(baseNet) || index.isRail(collectorNet))
      return;
    const basePeers = (index.portsByNet.get(baseNet) ?? []).filter((port) => port.source_component_id !== id);
    if (basePeers.length !== 1)
      return;
    const resistorId = basePeers[0].source_component_id;
    const resistor = index.components.get(resistorId);
    const baseResistor = index.placement(resistorId);
    const resistorNets = index.twoTerminalNets(resistorId);
    const inputNet = resistorNets?.find((net) => net !== baseNet);
    if (resistor?.ftype !== "simple_resistor" || resistor.resistance <= 0 || !baseResistor || !index.sameLocalScope(transistor, baseResistor) || !inputNet || index.isRail(inputNet) || inputNet === collectorNet)
      return;
    const collectorPeers = (index.portsByNet.get(collectorNet) ?? []).filter((port) => port.source_component_id !== id);
    const loadPeers = collectorPeers.filter((port) => {
      const type = index.components.get(port.source_component_id)?.ftype;
      return type === "simple_chip";
    });
    if (loadPeers.length !== 1)
      return;
    const loadId = loadPeers[0].source_component_id;
    const load = index.placement(loadId);
    const loadNets = index.twoTerminalNets(loadId);
    const supplyNet = loadNets?.find((net) => net !== collectorNet);
    if (!load || !index.sameLocalScope(transistor, load) || !supplyNet || !this.positiveNets.has(supplyNet) || index.groundNets.has(supplyNet))
      return;
    const clampPeers = collectorPeers.filter((port) => port.source_component_id !== loadId);
    if (clampPeers.length !== 1)
      return;
    const clampId = clampPeers[0].source_component_id;
    const clamp = index.placement(clampId);
    const anode = index.namedPort(clampId, "anode");
    const cathode = index.namedPort(clampId, "cathode");
    if (index.components.get(clampId)?.ftype !== "simple_diode" || !index.twoTerminalNets(clampId) || !anode || !cathode || index.connected(anode.source_port_id) !== collectorNet || index.connected(cathode.source_port_id) !== supplyNet || !clamp || !index.sameLocalScope(transistor, clamp))
      return;
    const collectorPin = index.port(collector);
    const emitterPin = index.port(emitter);
    const basePin = index.port(base);
    if (!collectorPin || !emitterPin || !basePin)
      return;
    const collectorFacingDirection = collectorPin.facing_direction;
    const emitterFacingDirection = emitterPin.facing_direction;
    if (!collectorFacingDirection || !emitterFacingDirection)
      return;
    const placementProblems = [];
    if (transistor.schY >= load.schY)
      placementProblems.push("transistor_not_below_load");
    if (collectorFacingDirection !== "up")
      placementProblems.push("collector_not_up");
    if (emitterFacingDirection !== "down")
      placementProblems.push("emitter_not_down");
    if (placementProblems.length === 0)
      return;
    const name = transistor.sourceComponentName ?? id;
    const loadName = load.sourceComponentName ?? loadId;
    this.issues.push({
      lineItemType: "LowSideTransistorNotAlignedWithLoad",
      transistorSchematicBox: transistor,
      loadSchematicBox: load,
      baseResistorSchematicBox: baseResistor,
      clampDiodeSchematicBox: clamp,
      collectorSourcePortId: collector.source_port_id,
      emitterSourcePortId: emitter.source_port_id,
      collectorFacingDirection,
      emitterFacingDirection,
      placementProblems,
      message: `Arrange ${name} below ${loadName}, with its collector facing up toward the load and emitter facing down toward ground; place ${baseResistor.sourceComponentName ?? resistorId} beside the base. Preserve all pin connections and reroute affected traces.`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "transistorName", issue.transistorSchematicBox.sourceComponentName);
    addAttr(attrs, "loadName", issue.loadSchematicBox.sourceComponentName);
    addAttr(attrs, "baseResistorName", issue.baseResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "clampDiodeName", issue.clampDiodeSchematicBox.sourceComponentName);
    addAttr(attrs, "placementProblems", issue.placementProblems.join(","));
    addAttr(attrs, "collectorFacingDirection", issue.collectorFacingDirection);
    addAttr(attrs, "emitterFacingDirection", issue.emitterFacingDirection);
    addAttr(attrs, "message", issue.message);
    return `<LowSideTransistorNotAlignedWithLoad ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/UsbSeriesResistorPlacementSolver/UsbSeriesResistorPlacementSolver.ts
class UsbSeriesResistorPlacementSolver extends BaseSolver {
  params;
  index;
  hostIds;
  reportedPairs = new Set;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    this.index = new PlacementNetworkIndex(params.ctx);
    this.hostIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_chip").map((component) => component.source_component_id);
    this.solved = this.hostIds.length === 0;
  }
  _step() {
    const hostId = this.hostIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.hostIds.length;
    if (!hostId)
      return;
    const ports = this.index.portsByComponent.get(hostId) ?? [];
    const positivePorts = ports.filter((port) => usbRole(port) === "positive");
    const negativePorts = ports.filter((port) => usbRole(port) === "negative");
    if (positivePorts.length !== 1 || negativePorts.length !== 1)
      return;
    const positivePort = positivePorts[0];
    const negativePort = negativePorts[0];
    const positive = this.seriesResistor(positivePort);
    const negative = this.seriesResistor(negativePort);
    if (!positive || !negative || positive.axis !== negative.axis || !this.index.sameLocalScope(positive.placement, negative.placement) || new Set([
      positive.hostNet,
      negative.hostNet,
      positive.interfaceNet,
      negative.interfaceNet
    ]).size !== 4 || !this.shareInterface(positive, negative, hostId))
      return;
    const pairKey = [positive.id, negative.id].sort().join("\x00");
    if (this.reportedPairs.has(pairKey))
      return;
    const a = positive.placement;
    const b = negative.placement;
    const horizontal = positive.axis === "horizontal";
    const along = Math.abs(horizontal ? a.schX - b.schX : a.schY - b.schY);
    const across = Math.abs(horizontal ? a.schY - b.schY : a.schX - b.schX);
    const alongA = horizontal ? a.width : a.height;
    const alongB = horizontal ? b.width : b.height;
    const acrossA = horizontal ? a.height : a.width;
    const acrossB = horizontal ? b.height : b.width;
    const bodyGap2 = along - (alongA + alongB) / 2;
    if (bodyGap2 < Math.max(alongA, alongB) || across >= (acrossA + acrossB) / 2 - 0.01)
      return;
    this.reportedPairs.add(pairKey);
    const positiveName = a.sourceComponentName ?? positive.id;
    const negativeName = b.sourceComponentName ?? negative.id;
    this.params.issues.push({
      lineItemType: "UsbSeriesResistorsNotAligned",
      positiveResistorSchematicBox: a,
      negativeResistorSchematicBox: b,
      hostSourceComponentId: hostId,
      positiveSourcePortId: positivePort.source_port_id,
      negativeSourcePortId: negativePort.source_port_id,
      signalAxis: positive.axis,
      message: `Place ${positiveName} (D+) and ${negativeName} (D−) near each other and draw clear traces to their corresponding USB ports. Exact alignment is not required; preserve pin assignments and leave space for labels.`
    });
  }
  seriesResistor(hostPort) {
    const index = this.index;
    const hostNet = index.connected(hostPort.source_port_id);
    if (index.isRail(hostNet))
      return;
    const candidates = new Set((index.portsByNet.get(hostNet) ?? []).filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").map((port) => port.source_component_id));
    if (candidates.size !== 1)
      return;
    const id = [...candidates][0];
    const nets = index.twoTerminalNets(id);
    const interfaceNet = nets?.find((net) => net !== hostNet);
    const placement = index.placement(id);
    if (!interfaceNet || index.isRail(interfaceNet) || !placement)
      return;
    if ((index.portsByNet.get(interfaceNet) ?? []).some((port) => port.source_component_id !== id && index.components.get(port.source_component_id)?.ftype === "simple_resistor"))
      return;
    const pins = index.portsByComponent.get(id).map((port) => index.port(port));
    const [first, second] = pins;
    if (!first || !second)
      return;
    const facing = new Set([first.facing_direction, second.facing_direction]);
    let axis;
    if (facing.has("left") && facing.has("right") && Math.abs(first.center.y - second.center.y) < 0.01)
      axis = "horizontal";
    else if (facing.has("up") && facing.has("down") && Math.abs(first.center.x - second.center.x) < 0.01)
      axis = "vertical";
    else
      return;
    return { id, placement, hostNet, interfaceNet, axis };
  }
  shareInterface(positive, negative, hostId) {
    const peerIds = (net) => new Set((this.index.portsByNet.get(net) ?? []).map((port) => port.source_component_id).filter((id) => id !== hostId && id !== positive.id && id !== negative.id && (this.index.portsByComponent.get(id)?.length ?? 0) > 2));
    const positivePeers = peerIds(positive.interfaceNet);
    return [...peerIds(negative.interfaceNet)].some((id) => positivePeers.has(id));
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "positiveResistorName", issue.positiveResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "negativeResistorName", issue.negativeResistorSchematicBox.sourceComponentName);
    addAttr(attrs, "signalAxis", issue.signalAxis);
    addAttr(attrs, "message", issue.message);
    return `<UsbSeriesResistorsNotAligned ${attrs.join(" ")} />`;
  }
}
function usbRole(port) {
  const roles = new Set;
  for (const hint of [port.name, ...port.port_hints ?? []]) {
    const name = hint.toUpperCase();
    if (/^(?:USB_?)?D(?:P|\+|_POS)$/.test(name))
      roles.add("positive");
    if (/^(?:USB_?)?D(?:M|N|-|_NEG)$/.test(name))
      roles.add("negative");
  }
  return roles.size === 1 ? [...roles][0] : undefined;
}

// ../../work/placement-analysis/lib/utils/graphics.ts
function mergeGraphicsObjects(objects) {
  return objects.filter((o) => o !== undefined).reduce((acc, o) => mergeGraphics(acc, o), {});
}
function highlightPlacement(placement, color, label) {
  return {
    rects: [
      {
        center: { x: placement.schX, y: placement.schY },
        width: placement.width,
        height: placement.height,
        stroke: color,
        fill: color.replace("0.95", "0.15"),
        label
      }
    ]
  };
}
function visualizeCircuitJson(circuitJson) {
  const rects = circuitJson.filter((el) => el.type === "schematic_box").map((el) => {
    const box = el;
    return {
      center: { x: box.x, y: box.y },
      width: box.width,
      height: box.height,
      stroke: "hsl(0,0%,60%)"
    };
  });
  return { rects };
}

// ../../work/placement-analysis/lib/solvers/CapacitorOrientationSolver/CapacitorOrientationSolver.ts
class CapacitorOrientationSolver extends BaseSolver {
  static EPSILON = 0.01;
  static ORIENTATION_MESSAGE = 'Use schOrientation="vertical" on this capacitor to fix the symbol orientation';
  ctx;
  out;
  schematicComponentById;
  sourceComponentById;
  capacitorPlacements;
  feedbackCapacitorIds;
  currentPlacementIndex = 0;
  horizontalSymbolNames = new Set([
    "capacitor_left",
    "capacitor_right"
  ]);
  constructor({
    ctx,
    issues: out
  }) {
    super();
    this.ctx = ctx;
    this.out = out;
    this.schematicComponentById = this.buildSchematicComponentById(ctx.circuitJson);
    this.sourceComponentById = this.buildSourceComponentById(ctx.circuitJson);
    this.capacitorPlacements = this.getCapacitorPlacements();
    const networks = new PlacementNetworkIndex(ctx);
    this.feedbackCapacitorIds = new Set(this.capacitorPlacements.flatMap((capacitor) => capacitor.sourceComponentId && networks.isDirectOpAmpFeedback(capacitor.sourceComponentId) ? [capacitor.sourceComponentId] : []));
    this.solved = this.capacitorPlacements.length === 0;
  }
  getCapacitorPlacements() {
    return this.ctx.componentPlacements.filter((p) => p.sourceComponentId !== undefined && this.sourceComponentById.get(p.sourceComponentId)?.ftype === "simple_capacitor").map((p) => ({
      schX: p.schX,
      schY: p.schY,
      width: p.width,
      height: p.height,
      sourceComponentId: p.sourceComponentId,
      sourceComponentName: p.sourceComponentName,
      schematicComponentId: p.schematicComponentId,
      schematicSheetId: p.schematicSheetId,
      schematicSheetName: p.schematicSheetName
    }));
  }
  _step() {
    const currentPlacement = this.capacitorPlacements[this.currentPlacementIndex];
    if (!currentPlacement) {
      this.solved = true;
      return;
    }
    this.currentPlacementIndex += 1;
    this.solved = this.currentPlacementIndex >= this.capacitorPlacements.length;
    const issue = this.getIssueForPlacement(currentPlacement);
    if (issue)
      this.out.push(issue);
  }
  visualize() {
    const focusedPlacement = this.getFocusedPlacement();
    return mergeGraphicsObjects([
      visualizeCircuitJson(this.ctx.circuitJson),
      focusedPlacement ? highlightPlacement(focusedPlacement, "hsl(210, 100%, 50%, 0.95)", "capacitorOrientation") : undefined
    ]);
  }
  getFocusedPlacement() {
    if (this.capacitorPlacements.length === 0)
      return;
    const index = this.iterations === 0 ? this.currentPlacementIndex : Math.max(0, this.currentPlacementIndex - 1);
    return this.capacitorPlacements[index];
  }
  buildSchematicComponentById(circuitJson) {
    return new Map(circuitJson.filter((el) => el.type === "schematic_component").map((sc) => [sc.schematic_component_id, sc]));
  }
  buildSourceComponentById(circuitJson) {
    return new Map(circuitJson.flatMap((el) => {
      if (el.type !== "source_component" || !("source_component_id" in el) || typeof el.source_component_id !== "string")
        return [];
      return [
        {
          type: "source_component",
          source_component_id: el.source_component_id,
          ftype: "ftype" in el && typeof el.ftype === "string" ? el.ftype : undefined
        }
      ];
    }).map((sc) => [sc.source_component_id, sc]));
  }
  createIssuePlacement(placement) {
    return {
      positionAnchor: "center",
      schX: placement.schX,
      schY: placement.schY,
      width: placement.width,
      height: placement.height,
      sourceComponentId: placement.sourceComponentId,
      sourceComponentName: placement.sourceComponentName,
      schematicComponentId: placement.schematicComponentId,
      schematicSheetId: placement.schematicSheetId,
      schematicSheetName: placement.schematicSheetName
    };
  }
  getIssueForPlacement(placement) {
    if (!placement.schematicComponentId || !placement.sourceComponentId)
      return;
    const schematicComponent = this.schematicComponentById.get(placement.schematicComponentId);
    if (!schematicComponent)
      return;
    if (!this.horizontalSymbolNames.has(schematicComponent.symbol_name ?? ""))
      return;
    if (this.feedbackCapacitorIds.has(placement.sourceComponentId))
      return;
    if (this.isInlineWithHorizontalTraces(placement.schematicComponentId))
      return;
    return {
      lineItemType: "CapacitorSymbolHorizontal",
      schematicBox: this.createIssuePlacement(placement),
      message: CapacitorOrientationSolver.ORIENTATION_MESSAGE
    };
  }
  isInlineWithHorizontalTraces(schematicComponentId) {
    const ports = this.ctx.circuitJson.filter((element) => element.type === "schematic_port" && element.schematic_component_id === schematicComponentId);
    if (ports.length !== 2)
      return false;
    const traces = ports.map((port) => this.getOutwardHorizontalTrace(port));
    return traces.every((trace) => trace !== undefined) && traces.some((trace) => trace !== undefined && trace.edges.every((edge) => Math.abs(edge.from.y - edge.to.y) <= CapacitorOrientationSolver.EPSILON));
  }
  getOutwardHorizontalTrace(port) {
    if (port.facing_direction !== "left" && port.facing_direction !== "right")
      return;
    return this.ctx.circuitJson.find((element) => element.type === "schematic_trace" && element.schematic_sheet_id === port.schematic_sheet_id && element.edges.some((edge) => {
      const other = this.pointsEqual(edge.from, port.center) ? edge.to : this.pointsEqual(edge.to, port.center) ? edge.from : undefined;
      return other !== undefined && Math.abs(other.y - port.center.y) <= CapacitorOrientationSolver.EPSILON && (port.facing_direction === "left" ? other.x < port.center.x - CapacitorOrientationSolver.EPSILON : other.x > port.center.x + CapacitorOrientationSolver.EPSILON);
    }));
  }
  pointsEqual(first, second) {
    return Math.abs(first.x - second.x) <= CapacitorOrientationSolver.EPSILON && Math.abs(first.y - second.y) <= CapacitorOrientationSolver.EPSILON;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
    addAttr(attrs, "schX", issue.schematicBox.schX);
    addAttr(attrs, "schY", issue.schematicBox.schY);
    addAttr(attrs, "width", issue.schematicBox.width);
    addAttr(attrs, "height", issue.schematicBox.height);
    addAttr(attrs, "message", issue.message);
    return `<CapacitorSymbolHorizontal ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/DecouplingCapacitorGroupingSolver/DecouplingCapacitorGroupingSolver.ts
class DecouplingCapacitorGroupingSolver extends BaseSolver {
  params;
  static MIN_BODY_GAP = 4;
  banks = [];
  netNames = new Map;
  bankIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    const index = new PlacementNetworkIndex(params.ctx);
    const powerNets = new Set(index.powerNets);
    const groundNets = new Set(index.groundNets);
    for (const element of params.ctx.circuitJson) {
      if (element.type === "source_net") {
        const net = index.connected(element.source_net_id);
        if (!this.netNames.has(net))
          this.netNames.set(net, element.name);
      }
    }
    for (const ports of index.portsByComponent.values()) {
      for (const port of ports) {
        if (port.do_not_connect)
          continue;
        const net = index.connected(port.source_port_id);
        if (port.provides_power || port.requires_power)
          powerNets.add(net);
        if (port.provides_ground || port.requires_ground)
          groundNets.add(net);
        if ((powerNets.has(net) || groundNets.has(net)) && !this.netNames.has(net))
          this.netNames.set(net, port.name);
      }
    }
    for (const component of index.components.values()) {
      if (component.ftype !== "simple_capacitor")
        continue;
      const id = component.source_component_id;
      const placement = index.placement(id);
      const nets = index.twoTerminalNets(id);
      const ports = index.portsByComponent.get(id);
      if (!placement || !nets || !ports || ports.some((port) => {
        const schematicPort = index.port(port);
        return port.do_not_connect || !schematicPort || schematicPort.schematic_sheet_id !== placement.schematicSheetId;
      }))
        continue;
      const power = nets.find((net) => powerNets.has(net) && !groundNets.has(net));
      const ground = nets.find((net) => groundNets.has(net) && !powerNets.has(net));
      if (!power || !ground)
        continue;
      const bank = this.banks.find((candidate) => candidate.power === power && candidate.ground === ground && index.sameLocalScope(candidate.capacitors[0], placement));
      if (bank)
        bank.capacitors.push(placement);
      else
        this.banks.push({ power, ground, capacitors: [placement] });
    }
    this.solved = this.banks.length === 0;
  }
  _step() {
    const bank = this.banks[this.bankIndex++];
    this.solved = this.bankIndex >= this.banks.length;
    if (bank.capacitors.length < 2)
      return;
    const maxRecommendedBodyGap = Math.max(DecouplingCapacitorGroupingSolver.MIN_BODY_GAP, ...bank.capacitors.map((box) => 3 * Math.max(box.width, box.height)));
    let maxBodyGap = 0;
    for (let i = 0;i < bank.capacitors.length; i++) {
      for (const b of bank.capacitors.slice(i + 1)) {
        const a = bank.capacitors[i];
        const gap = Math.hypot(Math.max(0, Math.abs(a.schX - b.schX) - (a.width + b.width) / 2), Math.max(0, Math.abs(a.schY - b.schY) - (a.height + b.height) / 2));
        maxBodyGap = Math.max(maxBodyGap, gap);
      }
    }
    if (maxBodyGap <= maxRecommendedBodyGap + 0.000001)
      return;
    const railName = this.netNames.get(bank.power) ?? bank.power;
    const groundName = this.netNames.get(bank.ground) ?? bank.ground;
    this.params.issues.push({
      lineItemType: "DecouplingCapacitorsNotCloseTogether",
      railName,
      groundName,
      capacitorSchematicBoxes: bank.capacitors,
      maxBodyGap,
      maxRecommendedBodyGap,
      message: `Group the decoupling capacitors between ${railName} and ${groundName} closer together in this schematic block. Preserve their net connections.`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "rail", issue.railName);
    addAttr(attrs, "ground", issue.groundName);
    addAttr(attrs, "capacitorNames", issue.capacitorSchematicBoxes.map((box) => box.sourceComponentName ?? box.schematicComponentId).join(", "));
    addAttr(attrs, "maxBodyGap", issue.maxBodyGap);
    addAttr(attrs, "maxRecommendedBodyGap", issue.maxRecommendedBodyGap);
    addAttr(attrs, "message", issue.message);
    return `<DecouplingCapacitorsNotCloseTogether ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/utils/net-label-bounds.ts
function getNetLabelBounds(label) {
  const anchorSide = label.anchor_side;
  const isVertical = anchorSide === "top" || anchorSide === "bottom";
  if (isVertical) {
    const anchorY = label.anchor_position?.y ?? label.center.y;
    const textHalfExtent = (label.text?.length ?? 8) * 0.13 / 2 + 0.1;
    const left = label.center.x - 0.1;
    const right = label.center.x + 0.1;
    if (anchorSide === "top") {
      return {
        left,
        right,
        top: anchorY,
        bottom: anchorY - textHalfExtent * 2
      };
    }
    return { left, right, top: anchorY + textHalfExtent * 2, bottom: anchorY };
  }
  const anchorX = label.anchor_position?.x ?? label.center.x;
  const halfWidth = Math.abs(label.center.x - anchorX);
  const farHalfWidth = halfWidth + 0.1;
  const top = label.center.y + 0.1;
  const bottom = label.center.y - 0.1;
  if (label.center.x >= anchorX) {
    return {
      left: anchorX,
      right: label.center.x + farHalfWidth,
      top,
      bottom
    };
  }
  return { left: label.center.x - farHalfWidth, right: anchorX, top, bottom };
}

// ../../work/placement-analysis/lib/solvers/ComponentNetLabelCollisionSolver/ComponentNetLabelCollisionSolver.ts
class ComponentNetLabelCollisionSolver extends BaseSolver {
  params;
  placements;
  netLabelsByComponentId;
  rawCollisions = [];
  firstIndex = 0;
  secondIndex = 1;
  constructor(params) {
    super();
    this.params = params;
    this.placements = params.ctx.componentPlacements;
    this.netLabelsByComponentId = this.buildNetLabelsByComponentId(params.ctx.circuitJson);
    this.solved = this.placements.length < 2;
  }
  _step() {
    if (this.firstIndex >= this.placements.length - 1) {
      this.buildAndPushIssues();
      this.solved = true;
      return;
    }
    const compA = this.placements[this.firstIndex];
    const compB = this.placements[this.secondIndex];
    this.detectPair(compA, compB);
    this.secondIndex++;
    if (this.secondIndex >= this.placements.length) {
      this.firstIndex++;
      this.secondIndex = this.firstIndex + 1;
    }
  }
  detectPair(compA, compB) {
    if (compA.schematicSheetId !== compB.schematicSheetId)
      return;
    this.rawCollisions.push(...this.detectLabelLabel(compA, compB));
    this.rawCollisions.push(...this.detectBoxLabel(compA, compB));
    this.rawCollisions.push(...this.detectBoxLabel(compB, compA));
  }
  detectLabelLabel(firstComponent, secondComponent) {
    let leftComp = firstComponent;
    let rightComp = secondComponent;
    if (firstComponent.schX > secondComponent.schX) {
      leftComp = secondComponent;
      rightComp = firstComponent;
    }
    const leftId = leftComp.schematicComponentId;
    const rightId = rightComp.schematicComponentId;
    if (!leftId || !rightId)
      return [];
    const leftLabels = this.netLabelsByComponentId.get(leftId) ?? [];
    const rightLabels = this.netLabelsByComponentId.get(rightId) ?? [];
    if (leftLabels.length === 0 || rightLabels.length === 0)
      return [];
    const hits = [];
    for (const leftLabel of leftLabels) {
      for (const rightLabel of rightLabels) {
        const leftBounds = getNetLabelBounds(leftLabel);
        const rightBounds = getNetLabelBounds(rightLabel);
        if (rectOverlap(leftBounds, rightBounds)) {
          hits.push({
            type: "label-label",
            bounds: {
              left: Math.max(leftBounds.left, rightBounds.left),
              right: Math.min(leftBounds.right, rightBounds.right),
              top: Math.min(leftBounds.top, rightBounds.top),
              bottom: Math.max(leftBounds.bottom, rightBounds.bottom)
            },
            leftComp,
            rightComp,
            leftId,
            rightId,
            xSeparation: leftBounds.right - rightBounds.left + 0.1
          });
        }
      }
    }
    return hits;
  }
  detectBoxLabel(boxComp, labelComp) {
    const boxId = boxComp.schematicComponentId;
    const labelId = labelComp.schematicComponentId;
    if (!boxId || !labelId)
      return [];
    const labels = this.netLabelsByComponentId.get(labelId) ?? [];
    if (labels.length === 0)
      return [];
    const boxBounds = centeredRect(boxComp.schX, boxComp.schY, boxComp.width, boxComp.height);
    const boxIsLeft = boxComp.schX <= labelComp.schX;
    const hits = [];
    for (const label of labels) {
      const labelBounds = getNetLabelBounds(label);
      if (!rectOverlap(boxBounds, labelBounds))
        continue;
      let xSeparation;
      if (boxIsLeft) {
        xSeparation = boxBounds.right - labelBounds.left + 0.1;
      } else {
        xSeparation = labelBounds.right - boxBounds.left + 0.1;
      }
      hits.push({
        type: "box-label",
        bounds: {
          left: Math.max(boxBounds.left, labelBounds.left),
          right: Math.min(boxBounds.right, labelBounds.right),
          top: Math.min(boxBounds.top, labelBounds.top),
          bottom: Math.max(boxBounds.bottom, labelBounds.bottom)
        },
        boxComp,
        labelComp,
        boxId,
        labelId,
        xSeparation
      });
    }
    return hits;
  }
  buildAndPushIssues() {
    if (this.rawCollisions.length === 0)
      return;
    const collisionsBySheet = new Map;
    for (const collision of this.rawCollisions) {
      const placement = collision.type === "label-label" ? collision.leftComp : collision.boxComp;
      const sheetKey = placement.schematicSheetId ?? "";
      const sheetCollisions = collisionsBySheet.get(sheetKey);
      if (sheetCollisions)
        sheetCollisions.push(collision);
      else
        collisionsBySheet.set(sheetKey, [collision]);
    }
    for (const collisions of collisionsBySheet.values()) {
      this.buildAndPushIssueForSheet(collisions);
    }
  }
  buildAndPushIssueForSheet(collisions) {
    const globalFixes = this.computeGlobalFixes(collisions);
    if (globalFixes.size === 0)
      return;
    const seenPairs = new Set;
    const pairs = [];
    for (const collision of collisions) {
      let comp1Name;
      let comp2Name;
      if (collision.type === "label-label") {
        comp1Name = collision.leftComp.sourceComponentName ?? "";
        comp2Name = collision.rightComp.sourceComponentName ?? "";
      } else {
        comp1Name = collision.boxComp.sourceComponentName ?? "";
        comp2Name = collision.labelComp.sourceComponentName ?? "";
      }
      const key = `${comp1Name}/${comp2Name}`;
      if (!seenPairs.has(key)) {
        seenPairs.add(key);
        pairs.push({ comp1Name, comp2Name });
      }
    }
    const firstCollision = collisions[0];
    const firstPlacement = firstCollision.type === "label-label" ? firstCollision.leftComp : firstCollision.boxComp;
    this.params.issues.push({
      lineItemType: "NetLabelCollision",
      schematicSheetId: firstPlacement.schematicSheetId,
      schematicSheetName: firstPlacement.schematicSheetName,
      pairs,
      collisionBounds: collisions.map((collision) => collision.bounds),
      moves: Array.from(globalFixes.values())
    });
  }
  computeGlobalFixes(collisions) {
    const compById = new Map;
    for (const placement of this.placements) {
      if (placement.schematicComponentId)
        compById.set(placement.schematicComponentId, placement);
    }
    const constraintMap = new Map;
    const addConstraint = (leftId, rightId, xSeparation) => {
      const leftComp = compById.get(leftId);
      const rightComp = compById.get(rightId);
      if (!leftComp || !rightComp)
        return;
      const minSep = rightComp.schX - leftComp.schX + xSeparation;
      const key = `${leftId}|${rightId}`;
      constraintMap.set(key, Math.max(constraintMap.get(key) ?? 0, minSep));
    };
    for (const collision of collisions) {
      if (collision.type === "label-label") {
        addConstraint(collision.leftId, collision.rightId, collision.xSeparation);
      } else if (collision.boxComp.schX <= collision.labelComp.schX) {
        addConstraint(collision.boxId, collision.labelId, collision.xSeparation);
      } else {
        addConstraint(collision.labelId, collision.boxId, collision.xSeparation);
      }
    }
    const constraints = [...constraintMap.entries()].map(([key, minSep]) => {
      const pipeIndex = key.indexOf("|");
      return {
        leftId: key.slice(0, pipeIndex),
        rightId: key.slice(pipeIndex + 1),
        minSep
      };
    });
    const allIds = new Set;
    const adjacency = new Map;
    for (const { leftId, rightId } of constraints) {
      allIds.add(leftId);
      allIds.add(rightId);
      if (!adjacency.has(leftId))
        adjacency.set(leftId, new Set);
      if (!adjacency.has(rightId))
        adjacency.set(rightId, new Set);
      adjacency.get(leftId).add(rightId);
      adjacency.get(rightId).add(leftId);
    }
    const visited = new Set;
    const result = new Map;
    for (const startId of allIds) {
      if (visited.has(startId))
        continue;
      const group = [];
      const queue = [startId];
      visited.add(startId);
      while (queue.length) {
        const compId = queue.shift();
        group.push(compId);
        for (const neighbor of adjacency.get(compId) ?? []) {
          if (!visited.has(neighbor)) {
            visited.add(neighbor);
            queue.push(neighbor);
          }
        }
      }
      group.sort((idA, idB) => (compById.get(idA)?.schX ?? 0) - (compById.get(idB)?.schX ?? 0));
      const groupIds = new Set(group);
      const groupConstraints = constraints.filter((c) => groupIds.has(c.leftId) && groupIds.has(c.rightId));
      const assigned = new Map;
      for (const compId of group) {
        let newX = compById.get(compId)?.schX ?? 0;
        for (const { leftId, rightId, minSep } of groupConstraints) {
          if (rightId === compId && assigned.has(leftId)) {
            newX = Math.max(newX, assigned.get(leftId) + minSep);
          }
        }
        assigned.set(compId, newX);
      }
      const totalPush = [...assigned.entries()].reduce((sum, [compId, newX]) => sum + (newX - (compById.get(compId)?.schX ?? 0)), 0);
      if (totalPush > 0.000000001) {
        const pullBack = totalPush / group.length;
        const shifted = new Map;
        for (const compId of group) {
          let newX = (compById.get(compId)?.schX ?? 0) - pullBack;
          for (const { leftId, rightId, minSep } of groupConstraints) {
            if (rightId === compId && shifted.has(leftId)) {
              newX = Math.max(newX, shifted.get(leftId) + minSep);
            }
          }
          shifted.set(compId, newX);
        }
        const maxDisplacement = (positions) => [...positions.entries()].reduce((currentMax, [compId, newX]) => Math.max(currentMax, Math.abs(newX - (compById.get(compId)?.schX ?? 0))), 0);
        if (maxDisplacement(shifted) < maxDisplacement(assigned)) {
          for (const [compId, newX] of shifted)
            assigned.set(compId, newX);
        }
      }
      for (const [compId, newX] of assigned) {
        const comp = compById.get(compId);
        if (!comp || Math.abs(newX - comp.schX) < 0.000000001)
          continue;
        result.set(compId, {
          componentName: comp.sourceComponentName ?? compId,
          newSchX: Math.round(newX * 100) / 100,
          newSchY: Math.round(comp.schY * 100) / 100
        });
      }
    }
    return result;
  }
  buildNetLabelsByComponentId(circuitJson) {
    const MATCH_EPSILON = 0.0001;
    const portPositions = [];
    for (const element of circuitJson) {
      if (element.type !== "schematic_port")
        continue;
      const port = element;
      if (!port.schematic_component_id)
        continue;
      portPositions.push({
        componentId: port.schematic_component_id,
        cx: port.center.x,
        cy: port.center.y,
        schematicSheetId: port.schematic_sheet_id
      });
    }
    const result = new Map;
    for (const element of circuitJson) {
      if (element.type !== "schematic_net_label")
        continue;
      const label = element;
      if (!label.anchor_position)
        continue;
      const { x: anchorX, y: anchorY } = label.anchor_position;
      const matches = portPositions.filter((port) => port.schematicSheetId === label.schematic_sheet_id && Math.hypot(port.cx - anchorX, port.cy - anchorY) < MATCH_EPSILON);
      if (matches.length === 0)
        continue;
      const componentIds = new Set(matches.map((match) => match.componentId));
      if (componentIds.size !== 1)
        continue;
      const componentId = matches[0].componentId;
      const labels = result.get(componentId) ?? [];
      labels.push(label);
      result.set(componentId, labels);
    }
    return result;
  }
  static netLabelCollisionToString(issue) {
    const pairAttrs = issue.pairs.map((pair, i) => `pair${i + 1}="${pair.comp1Name}/${pair.comp2Name}"`).join(" ");
    const moves = issue.moves.map((move) => `    <Move componentName="${move.componentName}" newSchX="${move.newSchX}" newSchY="${move.newSchY}" />`);
    return [
      `<ComponentNetLabelCollision ${pairAttrs}>`,
      `  <SuggestedFix note="Apply all moves simultaneously. Set schAutoLayoutEnabled on your circuit.">`,
      ...moves,
      `  </SuggestedFix>`,
      `</ComponentNetLabelCollision>`
    ].join(`
`);
  }
}

// ../../work/placement-analysis/lib/solvers/ComponentPinAlignmentSolver/ComponentPinAlignmentSolver.ts
class ComponentPinAlignmentSolver extends BaseSolver {
  static ALIGNMENT_EPSILON = 0.01;
  ctx;
  out;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.ctx = ctx;
    this.out = issues;
  }
  _step() {
    const portsById = new Map(this.ctx.circuitJson.filter((el) => el.type === "schematic_port").map((port) => [port.schematic_port_id, port]));
    const placementBySchematicComponentId = new Map(this.ctx.componentPlacements.flatMap((placement) => placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));
    const pinPairsByComponentPair = new Map;
    for (const trace of this.ctx.circuitJson.filter((el) => el.type === "schematic_trace")) {
      const pinPair = this.getTracePinPair(trace, portsById);
      if (!pinPair)
        continue;
      const firstComponentId = pinPair.firstPort.schematic_component_id;
      const secondComponentId = pinPair.secondPort.schematic_component_id;
      if (!firstComponentId || !secondComponentId || firstComponentId === secondComponentId) {
        continue;
      }
      const orderedPair = firstComponentId < secondComponentId ? pinPair : {
        firstPort: pinPair.secondPort,
        secondPort: pinPair.firstPort
      };
      const key = [firstComponentId, secondComponentId].sort().join("\x00");
      const pairs = pinPairsByComponentPair.get(key) ?? [];
      const isDuplicate = pairs.some((pair) => pair.firstPort.schematic_port_id === orderedPair.firstPort.schematic_port_id && pair.secondPort.schematic_port_id === orderedPair.secondPort.schematic_port_id);
      if (!isDuplicate)
        pairs.push(orderedPair);
      pinPairsByComponentPair.set(key, pairs);
    }
    for (const pinPairs of pinPairsByComponentPair.values()) {
      const issue = this.findVerticalShiftIssue(pinPairs, placementBySchematicComponentId);
      if (issue)
        this.out.push(issue);
    }
    this.solved = true;
  }
  getTracePinPair(trace, portsById) {
    const firstEdge = trace.edges?.[0];
    const lastEdge = trace.edges?.at(-1);
    if (!firstEdge || !lastEdge)
      return;
    const firstPortId = firstEdge.from_schematic_port_id ?? firstEdge.to_schematic_port_id;
    const secondPortId = lastEdge.to_schematic_port_id ?? lastEdge.from_schematic_port_id;
    const ports = [...portsById.values()];
    const firstPort = firstPortId ? portsById.get(firstPortId) : this.findPortAtPoint(ports, firstEdge.from, trace.schematic_sheet_id);
    const secondPort = secondPortId ? portsById.get(secondPortId) : this.findPortAtPoint(ports, lastEdge.to, trace.schematic_sheet_id);
    if (!firstPort || !secondPort)
      return;
    if (firstPort.schematic_port_id === secondPort.schematic_port_id)
      return;
    if (firstPort.schematic_sheet_id !== secondPort.schematic_sheet_id)
      return;
    return { firstPort, secondPort };
  }
  findPortAtPoint(ports, point, schematicSheetId) {
    const { ALIGNMENT_EPSILON } = ComponentPinAlignmentSolver;
    return ports.find((port) => port.schematic_sheet_id === schematicSheetId && Math.abs(port.center.x - point.x) <= ALIGNMENT_EPSILON && Math.abs(port.center.y - point.y) <= ALIGNMENT_EPSILON);
  }
  findVerticalShiftIssue(pinPairs, placementBySchematicComponentId) {
    const firstPair = pinPairs[0];
    if (!firstPair)
      return;
    const firstPlacement = placementBySchematicComponentId.get(firstPair.firstPort.schematic_component_id);
    const secondPlacement = placementBySchematicComponentId.get(firstPair.secondPort.schematic_component_id);
    if (!firstPlacement || !secondPlacement)
      return;
    const [leftPlacement, rightPlacement] = firstPlacement.schX <= secondPlacement.schX ? [firstPlacement, secondPlacement] : [secondPlacement, firstPlacement];
    const horizontalPairs = pinPairs.flatMap((pair) => {
      const [leftPort, rightPort] = pair.firstPort.center.x <= pair.secondPort.center.x ? [pair.firstPort, pair.secondPort] : [pair.secondPort, pair.firstPort];
      return leftPort.facing_direction === "right" && rightPort.facing_direction === "left" ? [{ leftPort, rightPort }] : [];
    });
    if (horizontalPairs.length < 2)
      return;
    const { ALIGNMENT_EPSILON } = ComponentPinAlignmentSolver;
    const currentlyAlignedPinCount = horizontalPairs.filter(({ leftPort, rightPort }) => Math.abs(leftPort.center.y - rightPort.center.y) <= ALIGNMENT_EPSILON).length;
    const candidateGroups = [];
    for (const pair of horizontalPairs) {
      const deltaSchY2 = pair.leftPort.center.y - pair.rightPort.center.y;
      if (Math.abs(deltaSchY2) <= ALIGNMENT_EPSILON)
        continue;
      const group = candidateGroups.find((candidate) => Math.abs(candidate.deltaSchY - deltaSchY2) <= ALIGNMENT_EPSILON);
      if (group)
        group.pairs.push(pair);
      else
        candidateGroups.push({ deltaSchY: deltaSchY2, pairs: [pair] });
    }
    const bestCandidate = candidateGroups.sort((a, b) => b.pairs.length - a.pairs.length || Math.abs(a.deltaSchY) - Math.abs(b.deltaSchY))[0];
    if (!bestCandidate || bestCandidate.pairs.length < 2 || bestCandidate.pairs.length <= currentlyAlignedPinCount) {
      return;
    }
    const targetName = rightPlacement.sourceComponentName ?? rightPlacement.schematicComponentId ?? "component";
    const deltaSchY = bestCandidate.deltaSchY;
    const newSchY = rightPlacement.schY + deltaSchY;
    return {
      lineItemType: "ComponentPinsWouldAlignWithVerticalShift",
      firstComponent: leftPlacement,
      secondComponent: rightPlacement,
      targetComponent: rightPlacement,
      deltaSchY,
      newSchY,
      currentlyAlignedPinCount,
      alignedPinCount: bestCandidate.pairs.length,
      alignedPinPairs: bestCandidate.pairs.map(({ leftPort, rightPort }) => ({
        firstPin: this.getPinLabel(leftPort),
        secondPin: this.getPinLabel(rightPort)
      })),
      message: `shift ${targetName} vertically by ${fmtDelta(deltaSchY)} to align ${bestCandidate.pairs.length} connected pin pairs`
    };
  }
  getPinLabel(port) {
    return port.display_pin_label ?? port.pin_number?.toString();
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "firstComponentName", issue.firstComponent.sourceComponentName);
    addAttr(attrs, "secondComponentName", issue.secondComponent.sourceComponentName);
    addAttr(attrs, "targetComponentName", issue.targetComponent.sourceComponentName);
    addAttr(attrs, "deltaSchY", issue.deltaSchY);
    addAttr(attrs, "newSchY", issue.newSchY);
    addAttr(attrs, "currentlyAlignedPinCount", issue.currentlyAlignedPinCount);
    addAttr(attrs, "alignedPinCount", issue.alignedPinCount);
    addAttr(attrs, "message", issue.message);
    return `<ComponentPinsWouldAlignWithVerticalShift ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/CrystalLoadCapacitorPlacementSolver/CrystalLoadCapacitorPlacementSolver.ts
class CrystalLoadCapacitorPlacementSolver extends BaseSolver {
  static ALIGNMENT_TOLERANCE = 0.1;
  issues;
  networks;
  currentNetworkIndex = 0;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.issues = issues;
    this.networks = this.findCrystalLoadNetworks(ctx);
    this.solved = this.networks.length === 0;
  }
  _step() {
    const network = this.networks[this.currentNetworkIndex];
    if (!network) {
      this.solved = true;
      return;
    }
    this.currentNetworkIndex += 1;
    this.solved = this.currentNetworkIndex >= this.networks.length;
    const deltaSchX = round3(network.newSchX - network.crystal.schX);
    const deltaSchY = round3(network.newSchY - network.crystal.schY);
    if (Math.abs(deltaSchX) <= CrystalLoadCapacitorPlacementSolver.ALIGNMENT_TOLERANCE && Math.abs(deltaSchY) <= CrystalLoadCapacitorPlacementSolver.ALIGNMENT_TOLERANCE) {
      return;
    }
    const crystalName = network.crystal.sourceComponentName ?? "the crystal";
    const firstCapacitorName = network.firstLoadCapacitor.sourceComponentName ?? "the first load capacitor";
    const secondCapacitorName = network.secondLoadCapacitor.sourceComponentName ?? "the second load capacitor";
    this.issues.push({
      lineItemType: "CrystalNotCenteredOverLoadCapacitors",
      crystalSchematicBox: network.crystal,
      firstLoadCapacitorSchematicBox: network.firstLoadCapacitor,
      secondLoadCapacitorSchematicBox: network.secondLoadCapacitor,
      deltaSchX,
      deltaSchY,
      newSchX: network.newSchX,
      newSchY: network.newSchY,
      message: `move ${crystalName} to schX=${network.newSchX}, schY=${network.newSchY} so it is centered between ${firstCapacitorName} and ${secondCapacitorName} and aligned with their load-side pins`
    });
  }
  findCrystalLoadNetworks(ctx) {
    const sourceComponents = new Map;
    const sourcePortsByComponentId = new Map;
    const schematicPortsBySourcePortId = new Map;
    const placementBySourceComponentId = new Map(ctx.componentPlacements.flatMap((placement) => placement.sourceComponentId ? [[placement.sourceComponentId, placement]] : []));
    for (const element of ctx.circuitJson) {
      if (element.type === "source_component") {
        sourceComponents.set(element.source_component_id, {
          sourceComponentId: element.source_component_id,
          ftype: "ftype" in element && typeof element.ftype === "string" ? element.ftype : undefined
        });
      }
      if (element.type === "source_port" && typeof element.source_component_id === "string" && typeof element.subcircuit_connectivity_map_key === "string") {
        const sourcePort = {
          sourcePortId: element.source_port_id,
          sourceComponentId: element.source_component_id,
          connectivityKey: element.subcircuit_connectivity_map_key
        };
        const componentPorts = sourcePortsByComponentId.get(element.source_component_id) ?? [];
        componentPorts.push(sourcePort);
        sourcePortsByComponentId.set(element.source_component_id, componentPorts);
      }
      if (element.type === "schematic_port" && element.source_port_id) {
        schematicPortsBySourcePortId.set(element.source_port_id, element);
      }
    }
    const capacitorConnectionsByConnectivityKey = new Map;
    for (const sourceComponent of sourceComponents.values()) {
      if (sourceComponent.ftype !== "simple_capacitor")
        continue;
      const capacitorPorts = sourcePortsByComponentId.get(sourceComponent.sourceComponentId) ?? [];
      if (capacitorPorts.length !== 2)
        continue;
      const firstCapacitorPort = capacitorPorts[0];
      const secondCapacitorPort = capacitorPorts[1];
      const capacitorPlacement = placementBySourceComponentId.get(sourceComponent.sourceComponentId);
      if (!capacitorPlacement)
        continue;
      for (const [loadPort, returnPort] of [
        [firstCapacitorPort, secondCapacitorPort],
        [secondCapacitorPort, firstCapacitorPort]
      ]) {
        const schematicLoadPort = schematicPortsBySourcePortId.get(loadPort.sourcePortId);
        if (!schematicLoadPort)
          continue;
        const connections = capacitorConnectionsByConnectivityKey.get(loadPort.connectivityKey) ?? [];
        connections.push({
          capacitor: capacitorPlacement,
          loadPort: schematicLoadPort,
          returnConnectivityKey: returnPort.connectivityKey
        });
        capacitorConnectionsByConnectivityKey.set(loadPort.connectivityKey, connections);
      }
    }
    const networks = [];
    for (const sourceComponent of sourceComponents.values()) {
      if (sourceComponent.ftype !== "simple_crystal" && sourceComponent.ftype !== "simple_chip") {
        continue;
      }
      const crystalPorts = sourcePortsByComponentId.get(sourceComponent.sourceComponentId) ?? [];
      if (crystalPorts.length !== 2 || crystalPorts[0].connectivityKey === crystalPorts[1].connectivityKey) {
        continue;
      }
      const firstCrystalConnectivityKey = crystalPorts[0].connectivityKey;
      const secondCrystalConnectivityKey = crystalPorts[1].connectivityKey;
      const hasOscillatorHost = [...sourcePortsByComponentId.entries()].some(([sourceComponentId, sourcePorts]) => sourceComponentId !== sourceComponent.sourceComponentId && sourcePorts.length > 2 && sourcePorts.some((port) => port.connectivityKey === firstCrystalConnectivityKey) && sourcePorts.some((port) => port.connectivityKey === secondCrystalConnectivityKey));
      if (!hasOscillatorHost)
        continue;
      const crystalPlacement = placementBySourceComponentId.get(sourceComponent.sourceComponentId);
      if (!crystalPlacement)
        continue;
      const firstConnections = capacitorConnectionsByConnectivityKey.get(crystalPorts[0].connectivityKey) ?? [];
      const secondConnections = capacitorConnectionsByConnectivityKey.get(crystalPorts[1].connectivityKey) ?? [];
      const candidatePairs = firstConnections.flatMap((firstConnection) => secondConnections.flatMap((secondConnection) => {
        if (firstConnection.capacitor.sourceComponentId === secondConnection.capacitor.sourceComponentId || firstConnection.returnConnectivityKey !== secondConnection.returnConnectivityKey || firstConnection.returnConnectivityKey === firstCrystalConnectivityKey || firstConnection.returnConnectivityKey === secondCrystalConnectivityKey || firstConnection.capacitor.schematicSheetId !== crystalPlacement.schematicSheetId || secondConnection.capacitor.schematicSheetId !== crystalPlacement.schematicSheetId) {
          return [];
        }
        return [{ firstConnection, secondConnection }];
      }));
      if (candidatePairs.length === 0)
        continue;
      const bestPair = candidatePairs.toSorted((a, b) => pairDistance(a, crystalPlacement) - pairDistance(b, crystalPlacement))[0];
      const loadPorts = [
        bestPair.firstConnection.loadPort,
        bestPair.secondConnection.loadPort
      ];
      const capacitors = [
        bestPair.firstConnection.capacitor,
        bestPair.secondConnection.capacitor
      ].toSorted((a, b) => a.schX - b.schX);
      networks.push({
        crystal: crystalPlacement,
        firstLoadCapacitor: capacitors[0],
        secondLoadCapacitor: capacitors[1],
        newSchX: round3((loadPorts[0].center.x + loadPorts[1].center.x) / 2),
        newSchY: round3((loadPorts[0].center.y + loadPorts[1].center.y) / 2)
      });
    }
    return networks;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "crystalName", issue.crystalSchematicBox.sourceComponentName);
    addAttr(attrs, "firstLoadCapacitorName", issue.firstLoadCapacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "secondLoadCapacitorName", issue.secondLoadCapacitorSchematicBox.sourceComponentName);
    addAttr(attrs, "newSchX", issue.newSchX);
    addAttr(attrs, "newSchY", issue.newSchY);
    addAttr(attrs, "deltaSchX", issue.deltaSchX, { formatDelta: true });
    addAttr(attrs, "deltaSchY", issue.deltaSchY, { formatDelta: true });
    addAttr(attrs, "message", issue.message);
    return `<CrystalNotCenteredOverLoadCapacitors ${attrs.join(" ")} />`;
  }
}
var pairDistance = (pair, crystal) => distance2(pair.firstConnection.capacitor, crystal) + distance2(pair.secondConnection.capacitor, crystal);
var distance2 = (first, second) => Math.hypot(first.schX - second.schX, first.schY - second.schY);
var round3 = (value) => Math.round(value * 100) / 100;

// ../../work/placement-analysis/node_modules/circuit-json-to-connectivity-map/dist/index.js
function findConnectedNetworks(connections) {
  const networks = /* @__PURE__ */ new Map;
  let netCounter = 0;
  function getOrCreateNetwork(nodeId) {
    for (const [, network] of networks) {
      if (network.has(nodeId)) {
        return network;
      }
    }
    const newNetwork = /* @__PURE__ */ new Set;
    networks.set(`connectivity_net${netCounter++}`, newNetwork);
    return newNetwork;
  }
  for (const connection of connections) {
    let network = null;
    for (const nodeId of connection) {
      if (!network) {
        network = getOrCreateNetwork(nodeId);
      } else if (!network.has(nodeId)) {
        const existingNetwork = getOrCreateNetwork(nodeId);
        if (existingNetwork !== network) {
          for (const node of existingNetwork) {
            network.add(node);
          }
          networks.delete(Array.from(networks.entries()).find(([, net]) => net === existingNetwork)[0]);
        }
      }
      network.add(nodeId);
    }
  }
  return Object.fromEntries(Array.from(networks.entries()).map(([netId, connectedNodes]) => [
    netId,
    Array.from(connectedNodes)
  ]));
}
var ConnectivityMap = class {
  netMap;
  idToNetMap;
  constructor(netMap) {
    this.netMap = netMap;
    this.idToNetMap = {};
    for (const [netId, ids] of Object.entries(netMap)) {
      for (const id of ids) {
        this.idToNetMap[id] = netId;
      }
    }
  }
  addConnections(connections) {
    for (const connection of connections) {
      const existingNets = /* @__PURE__ */ new Set;
      for (const id of connection) {
        const existingNetId = this.idToNetMap[id];
        if (existingNetId) {
          existingNets.add(existingNetId);
        }
      }
      let targetNetId;
      if (existingNets.size === 0) {
        targetNetId = `connectivity_net${Object.keys(this.netMap).length}`;
        this.netMap[targetNetId] = [];
      } else if (existingNets.size === 1) {
        targetNetId = existingNets.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
      } else {
        targetNetId = existingNets.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
        for (const netId of existingNets) {
          if (netId !== targetNetId) {
            this.netMap[targetNetId].push(...this.netMap[netId]);
            this.netMap[netId] = this.netMap[targetNetId];
            for (const id of this.netMap[targetNetId]) {
              this.idToNetMap[id] = targetNetId;
            }
          }
        }
      }
      for (const id of connection) {
        if (!this.netMap[targetNetId].includes(id)) {
          this.netMap[targetNetId].push(id);
        }
        this.idToNetMap[id] = targetNetId;
      }
    }
  }
  getIdsConnectedToNet(netId) {
    return this.netMap[netId] || [];
  }
  getNetConnectedToId(id) {
    return this.idToNetMap[id];
  }
  areIdsConnected(id1, id2) {
    if (id1 === id2)
      return true;
    const netId1 = this.getNetConnectedToId(id1);
    if (!netId1)
      return false;
    const netId2 = this.getNetConnectedToId(id2);
    if (!netId2)
      return false;
    return netId1 === netId2 || netId2 === id1 || netId2 === id1;
  }
  areAllIdsConnected(ids) {
    const netId = this.getNetConnectedToId(ids[0]);
    for (const id of ids) {
      const nextNetId = this.getNetConnectedToId(id);
      if (nextNetId === undefined) {
        return false;
      }
      if (nextNetId !== netId) {
        return false;
      }
    }
    return true;
  }
};
var getSourcePortConnectivityMapFromCircuitJson = (circuitJson) => {
  const connections = [];
  for (const element of circuitJson) {
    if (element.type === "source_trace") {
      connections.push([
        ...element.connected_source_port_ids ?? [],
        ...element.connected_source_net_ids ?? []
      ]);
    } else if (element.type === "source_component") {
      if (element.internally_connected_source_port_ids) {
        for (const portGroup of element.internally_connected_source_port_ids) {
          connections.push(portGroup);
        }
      }
    } else if (element.type === "source_component_internal_connection") {
      connections.push(element.source_port_ids);
    }
  }
  const netMap = findConnectedNetworks(connections);
  return new ConnectivityMap(netMap);
};

// ../../work/placement-analysis/lib/solvers/DiodeResistorAlignmentSolver/DiodeResistorAlignmentSolver.ts
class DiodeResistorAlignmentSolver extends BaseSolver {
  static DIODE_FTYPES = new Set(["simple_led", "simple_diode"]);
  ctx;
  out;
  schematicTraces;
  currentIndex = 0;
  sourceConnectivity;
  sourceComponentFtypeById;
  sourceComponentIdBySourcePortId;
  schematicPorts;
  schematicBoxBySourceComponentId;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.ctx = ctx;
    this.out = issues;
    const { circuitJson } = ctx;
    this.sourceConnectivity = getSourcePortConnectivityMapFromCircuitJson(circuitJson);
    this.sourceComponentFtypeById = this.buildSourceComponentFtypeById(circuitJson);
    this.sourceComponentIdBySourcePortId = this.buildSourceComponentIdBySourcePortId(circuitJson);
    this.schematicPorts = circuitJson.filter((el) => el.type === "schematic_port");
    this.schematicBoxBySourceComponentId = this.buildSchematicBoxBySourceComponentId();
    this.schematicTraces = circuitJson.filter((el) => el.type === "schematic_trace");
    this.solved = this.schematicTraces.length === 0;
  }
  _step() {
    const trace = this.schematicTraces[this.currentIndex];
    if (!trace) {
      this.solved = true;
      return;
    }
    this.currentIndex++;
    this.solved = this.currentIndex >= this.schematicTraces.length;
    if (!trace.edges || trace.edges.length === 0)
      return;
    const firstEdge = trace.edges[0];
    const lastEdge = trace.edges[trace.edges.length - 1];
    if (!firstEdge || !lastEdge)
      return;
    const start = firstEdge.from;
    const end = lastEdge.to;
    const schematicSheetId = trace.schematic_sheet_id;
    const startSourceCompId = this.findSourceComponentIdNearPoint(start, schematicSheetId);
    const endSourceCompId = this.findSourceComponentIdNearPoint(end, schematicSheetId);
    if (!startSourceCompId || !endSourceCompId)
      return;
    const startFtype = this.sourceComponentFtypeById.get(startSourceCompId);
    const endFtype = this.sourceComponentFtypeById.get(endSourceCompId);
    const { DIODE_FTYPES } = DiodeResistorAlignmentSolver;
    const isDiodeResistorPair = DIODE_FTYPES.has(startFtype) && endFtype === "simple_resistor" || startFtype === "simple_resistor" && DIODE_FTYPES.has(endFtype);
    if (!isDiodeResistorPair)
      return;
    const diodeCompId = DIODE_FTYPES.has(startFtype) ? startSourceCompId : endSourceCompId;
    const resistorCompId = startFtype === "simple_resistor" ? startSourceCompId : endSourceCompId;
    const diodeBox = this.schematicBoxBySourceComponentId.get(diodeCompId);
    const resistorBox = this.schematicBoxBySourceComponentId.get(resistorCompId);
    if (!diodeBox || !resistorBox)
      return;
    const diodePort = this.findNearestPort(DIODE_FTYPES.has(startFtype) ? start : end, schematicSheetId);
    const resistorPort = this.findNearestPort(startFtype === "simple_resistor" ? start : end, schematicSheetId);
    if (!diodePort?.center || !resistorPort?.center)
      return;
    if (!this.sourceConnectivity.areIdsConnected(diodePort.source_port_id, resistorPort.source_port_id))
      return;
    const diodeName = diodeBox.sourceComponentName ?? diodeCompId;
    const resistorName = resistorBox.sourceComponentName ?? resistorCompId;
    const diodePin = diodePort?.display_pin_label ?? diodePort?.pin_number?.toString();
    const resistorPin = resistorPort?.display_pin_label ?? resistorPort?.pin_number?.toString();
    const diodeFacing = diodePort?.facing_direction;
    const resistorFacing = resistorPort?.facing_direction;
    const diodePinDesc = diodePin ? `${diodeName}.${diodePin}` : diodeName;
    const resistorPinDesc = resistorPin ? `${resistorName}.${resistorPin}` : resistorName;
    const makeIssue = (message) => ({
      lineItemType: "DiodeResistorNotAligned",
      diodeSchematicBox: diodeBox,
      resistorSchematicBox: resistorBox,
      diodePin,
      resistorPin,
      diodePinFacingDirection: diodeFacing,
      resistorPinFacingDirection: resistorFacing,
      message
    });
    if (!DiodeResistorAlignmentSolver.isCoLinear(diodePort.center, resistorPort.center)) {
      this.out.push(makeIssue(`trace has corners — align ${diodeName} and ${resistorName} on same axis and rotate so ${diodePinDesc} faces ${resistorPinDesc}`));
      return;
    }
    if (diodeFacing && resistorFacing && !DiodeResistorAlignmentSolver.pinsFacingEachOther(diodePort.center, diodeFacing, resistorPort.center, resistorFacing)) {
      this.out.push(makeIssue(`${diodePinDesc} and ${resistorPinDesc} face away from each other — rotate ${diodeName} so ${diodePinDesc} faces ${resistorPinDesc}`));
    }
  }
  static isCoLinear(a, b, epsilon = 0.01) {
    return Math.abs(a.x - b.x) < epsilon || Math.abs(a.y - b.y) < epsilon;
  }
  static pinsFacingEachOther(aCenter, aFacing, bCenter, bFacing) {
    const dx = bCenter.x - aCenter.x;
    const dy = bCenter.y - aCenter.y;
    const aToward = aFacing === "right" && dx > 0 || aFacing === "left" && dx < 0 || aFacing === "up" && dy > 0 || aFacing === "down" && dy < 0;
    const bToward = bFacing === "right" && dx < 0 || bFacing === "left" && dx > 0 || bFacing === "up" && dy < 0 || bFacing === "down" && dy > 0;
    return aToward && bToward;
  }
  static dist(a, b) {
    return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
  }
  findNearestPort(point, schematicSheetId) {
    let nearest;
    let minDist = Infinity;
    for (const port of this.schematicPorts) {
      if (port.schematic_sheet_id !== schematicSheetId)
        continue;
      if (!port.center)
        continue;
      const d = DiodeResistorAlignmentSolver.dist(point, port.center);
      if (d < minDist) {
        minDist = d;
        nearest = port;
      }
    }
    return nearest;
  }
  findSourceComponentIdNearPoint(point, schematicSheetId) {
    const nearest = this.findNearestPort(point, schematicSheetId);
    if (!nearest || !nearest.source_port_id)
      return;
    return this.sourceComponentIdBySourcePortId.get(nearest.source_port_id);
  }
  buildSourceComponentFtypeById(circuitJson) {
    const map = new Map;
    for (const el of circuitJson) {
      if (el.type === "source_component" && "source_component_id" in el && "ftype" in el && typeof el.ftype === "string") {
        map.set(el.source_component_id, el.ftype);
      }
    }
    return map;
  }
  buildSourceComponentIdBySourcePortId(circuitJson) {
    const map = new Map;
    for (const el of circuitJson) {
      if (el.type === "source_port" && "source_port_id" in el && "source_component_id" in el && typeof el.source_port_id === "string" && typeof el.source_component_id === "string") {
        map.set(el.source_port_id, el.source_component_id);
      }
    }
    return map;
  }
  buildSchematicBoxBySourceComponentId() {
    const map = new Map;
    for (const placement of this.ctx.componentPlacements) {
      if (placement.sourceComponentId) {
        map.set(placement.sourceComponentId, placement);
      }
    }
    return map;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "diodeComponentName", issue.diodeSchematicBox.sourceComponentName);
    addAttr(attrs, "diodePin", issue.diodePin);
    addAttr(attrs, "resistorComponentName", issue.resistorSchematicBox.sourceComponentName);
    addAttr(attrs, "resistorPin", issue.resistorPin);
    addAttr(attrs, "message", issue.message);
    return `<DiodeResistorNotAligned ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/FeedbackNetworkPlacementSolver/FeedbackNetworkPlacementSolver.ts
class FeedbackNetworkPlacementSolver extends BaseSolver {
  static MIN_BODY_GAP = 4;
  index;
  amplifierIds;
  issues;
  currentIndex = 0;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.issues = issues;
    this.index = new PlacementNetworkIndex(ctx);
    this.amplifierIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_op_amp").map((component) => component.source_component_id);
    this.solved = this.amplifierIds.length === 0;
  }
  _step() {
    const id = this.amplifierIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.amplifierIds.length;
    if (!id)
      return;
    const index = this.index;
    const amplifier = index.placement(id);
    const output = index.namedPort(id, "output");
    const input = index.namedPort(id, "inverting_input");
    if (!amplifier || !output || !input || !index.port(output) || !index.port(input))
      return;
    const outputNet = index.connected(output.source_port_id);
    const inputNet = index.connected(input.source_port_id);
    if (outputNet === inputNet || index.isRail(outputNet) || index.isRail(inputNet))
      return;
    if ((index.portsByNet.get(inputNet) ?? []).some((port) => port.source_component_id !== id && index.components.get(port.source_component_id)?.ftype === "simple_op_amp"))
      return;
    const feedbackComponents = [];
    const seen = new Set;
    for (const port of index.portsByNet.get(outputNet) ?? []) {
      const componentId = port.source_component_id;
      if (seen.has(componentId))
        continue;
      seen.add(componentId);
      const component = index.components.get(componentId);
      if (component?.ftype !== "simple_resistor" && component?.ftype !== "simple_capacitor")
        continue;
      if (component.ftype === "simple_resistor" && !(component.resistance > 0))
        continue;
      const nets = index.twoTerminalNets(componentId);
      if (!nets?.includes(inputNet) || !nets.includes(outputNet))
        continue;
      const placement = index.placement(componentId);
      if (!placement || !index.sameLocalScope(amplifier, placement))
        return;
      feedbackComponents.push(placement);
    }
    const distantComponents = feedbackComponents.flatMap((schematicBox) => {
      const bodyGap2 = distanceBetweenBoxes(amplifier, schematicBox);
      const maxRecommendedBodyGap = Math.max(FeedbackNetworkPlacementSolver.MIN_BODY_GAP, 3 * Math.max(schematicBox.width, schematicBox.height));
      return bodyGap2 > maxRecommendedBodyGap ? [{ schematicBox, bodyGap: bodyGap2, maxRecommendedBodyGap }] : [];
    });
    if (distantComponents.length === 0)
      return;
    const names = distantComponents.map(({ schematicBox }) => schematicBox.sourceComponentName ?? schematicBox.sourceComponentId).join(", ");
    this.issues.push({
      lineItemType: "FeedbackNetworkNotCompact",
      amplifierSchematicBox: amplifier,
      feedbackComponents,
      distantComponents,
      outputSourcePortId: output.source_port_id,
      invertingInputSourcePortId: input.source_port_id,
      message: `consider grouping ${names} closer to ${amplifier.sourceComponentName ?? id}, with a compact feedback return path above or below the amplifier`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "amplifierName", issue.amplifierSchematicBox.sourceComponentName);
    addAttr(attrs, "feedbackComponentNames", issue.feedbackComponents.map((box) => box.sourceComponentName ?? box.sourceComponentId).join(", "));
    addAttr(attrs, "distantComponentNames", issue.distantComponents.map(({ schematicBox }) => schematicBox.sourceComponentName ?? schematicBox.sourceComponentId).join(", "));
    addAttr(attrs, "message", issue.message);
    return `<FeedbackNetworkNotCompact ${attrs.join(" ")} />`;
  }
}
function distanceBetweenBoxes(a, b) {
  return Math.hypot(Math.max(0, Math.abs(a.schX - b.schX) - (a.width + b.width) / 2), Math.max(0, Math.abs(a.schY - b.schY) - (a.height + b.height) / 2));
}

// ../../work/placement-analysis/lib/utils/switch-pull-resistor-pairs.ts
function getSwitchPullResistorPairs(index) {
  const pairs = [];
  const isHorizontal = (id) => {
    const ports = index.portsByComponent.get(id);
    if (ports?.length !== 2)
      return false;
    const a = index.port(ports[0]);
    const b = index.port(ports[1]);
    return !!a && !!b && Math.abs(a.center.y - b.center.y) < 0.01 && Math.abs(a.center.x - b.center.x) > 0.01;
  };
  for (const component of index.components.values()) {
    if (component.ftype !== "simple_resistor" || component.resistance <= 0)
      continue;
    const id = component.source_component_id;
    const nets = index.twoTerminalNets(id);
    if (!nets || nets.filter((net) => index.isRail(net)).length !== 1)
      continue;
    const rail = nets.find((net) => index.isRail(net));
    if (index.powerNets.has(rail) && index.groundNets.has(rail))
      continue;
    const signal = nets.find((net) => net !== rail);
    const peers = index.portsByNet.get(signal) ?? [];
    const switches = peers.filter((port) => {
      const type = index.components.get(port.source_component_id)?.ftype;
      return type === "simple_switch" || type === "simple_push_button";
    });
    if (switches.length !== 1 || peers.filter((port) => index.components.get(port.source_component_id)?.ftype === "simple_resistor").length !== 1)
      continue;
    const signalPort = switches[0];
    const switchId = signalPort.source_component_id;
    const switchType = index.components.get(switchId)?.ftype;
    const switchNets = index.twoTerminalNets(switchId);
    const otherRail = switchNets?.find((net) => net !== signal);
    if (!otherRail)
      continue;
    const pullDirection = index.powerNets.has(rail) ? "up" : "down";
    if (pullDirection === "up" ? !index.groundNets.has(otherRail) || index.powerNets.has(otherRail) : !index.powerNets.has(otherRail) || index.groundNets.has(otherRail))
      continue;
    if ([id, switchId].some((componentId) => index.portsByComponent.get(componentId)?.some((port) => port.do_not_connect)))
      continue;
    const resistor = index.placement(id);
    const switchBox = index.placement(switchId);
    const pin = index.port(signalPort);
    if (!resistor || !switchBox || !pin || !index.sameLocalScope(resistor, switchBox))
      continue;
    pairs.push({
      resistor,
      switchBox,
      signalPort,
      signalSchY: pin.center.y,
      pullDirection,
      horizontalPushbutton: switchType === "simple_push_button" && isHorizontal(id) && isHorizontal(switchId)
    });
  }
  return pairs;
}
function getHorizontalPushbuttonComponentIds(index) {
  return new Set(getSwitchPullResistorPairs(index).flatMap((pair) => pair.horizontalPushbutton ? [pair.resistor.sourceComponentId, pair.switchBox.sourceComponentId] : []));
}

// ../../work/placement-analysis/lib/solvers/PullResistorPlacementSolver/PullResistorPlacementSolver.ts
class PullResistorPlacementSolver extends BaseSolver {
  static MIN_WRONG_SIDE_GAP = 1.5;
  index;
  resistorIds;
  horizontalPushbuttonComponentIds;
  issues;
  currentIndex = 0;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.issues = issues;
    this.index = new PlacementNetworkIndex(ctx);
    this.horizontalPushbuttonComponentIds = getHorizontalPushbuttonComponentIds(this.index);
    this.resistorIds = [...this.index.components.values()].filter((component) => component.ftype === "simple_resistor" && component.resistance > 0).map((component) => component.source_component_id);
    this.solved = this.resistorIds.length === 0;
  }
  _step() {
    const id = this.resistorIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.resistorIds.length;
    if (!id)
      return;
    if (this.horizontalPushbuttonComponentIds.has(id))
      return;
    const index = this.index;
    const resistor = index.placement(id);
    const nets = index.twoTerminalNets(id);
    if (!resistor || !nets)
      return;
    const rails = nets.filter((net) => index.isRail(net));
    if (rails.length !== 1)
      return;
    const rail = rails[0];
    if (index.powerNets.has(rail) && index.groundNets.has(rail))
      return;
    const pullDirection = index.groundNets.has(rail) ? "down" : "up";
    const signal = nets.find((net) => net !== rail);
    const signalPorts = index.portsByNet.get(signal) ?? [];
    const requiringPorts = signalPorts.filter((port) => port.needs_external_pullup || port.needs_external_pulldown);
    if (requiringPorts.length !== 1)
      return;
    const signalPort = requiringPorts[0];
    if (signalPort.needs_external_pullup && signalPort.needs_external_pulldown)
      return;
    if (pullDirection === "up" ? !signalPort.needs_external_pullup : !signalPort.needs_external_pulldown)
      return;
    const host = index.placement(signalPort.source_component_id);
    const schematicPin = index.port(signalPort);
    if (!host || !schematicPin || !index.sameLocalScope(host, resistor))
      return;
    if (signalPorts.some((port) => {
      const otherId = port.source_component_id;
      if (otherId === id || otherId === signalPort.source_component_id)
        return false;
      const type = index.components.get(otherId)?.ftype;
      if (type !== "simple_capacitor")
        return true;
      const capacitorNets = index.twoTerminalNets(otherId);
      const returnNet = capacitorNets?.find((net) => net !== signal);
      if (!returnNet || !index.groundNets.has(returnNet) || index.powerNets.has(returnNet))
        return true;
      const capacitor = index.placement(otherId);
      return !capacitor || !index.sameLocalScope(host, capacitor);
    }))
      return;
    const signalSchY = schematicPin.center.y;
    const wrongSideGap = pullDirection === "up" ? signalSchY - (resistor.schY + resistor.height / 2) : resistor.schY - resistor.height / 2 - signalSchY;
    if (wrongSideGap <= PullResistorPlacementSolver.MIN_WRONG_SIDE_GAP)
      return;
    const preferredSide = pullDirection === "up" ? "above" : "below";
    this.issues.push({
      lineItemType: "PullResistorOnWrongSide",
      resistorSchematicBox: resistor,
      hostSchematicBox: host,
      signalSourcePortId: signalPort.source_port_id,
      signalPinName: signalPort.name,
      signalSchY,
      pullDirection,
      preferredSide,
      wrongSideGap,
      maxRecommendedWrongSideGap: PullResistorPlacementSolver.MIN_WRONG_SIDE_GAP,
      message: `consider placing ${resistor.sourceComponentName ?? id} ${preferredSide} ${host.sourceComponentName ?? signalPort.source_component_id}.${signalPort.name} so the pull-${pullDirection} branch reads toward ${pullDirection === "up" ? "power" : "ground"}`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "resistorName", issue.resistorSchematicBox.sourceComponentName);
    addAttr(attrs, "hostName", issue.hostSchematicBox.sourceComponentName);
    addAttr(attrs, "signalPin", issue.signalPinName);
    addAttr(attrs, "pullDirection", issue.pullDirection);
    addAttr(attrs, "preferredSide", issue.preferredSide);
    addAttr(attrs, "signalSchY", issue.signalSchY);
    addAttr(attrs, "wrongSideGap", issue.wrongSideGap);
    addAttr(attrs, "message", issue.message);
    return `<PullResistorOnWrongSide ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/TwoPinComponentRailOrientationSolver/TwoPinComponentRailOrientationSolver.ts
class TwoPinComponentRailOrientationSolver extends BaseSolver {
  static EPSILON = 0.01;
  index;
  powerNets;
  groundNets;
  positiveVoltageNets = new Set;
  componentIds;
  horizontalPushbuttonComponentIds;
  issues;
  currentIndex = 0;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.issues = issues;
    this.index = new PlacementNetworkIndex(ctx);
    this.horizontalPushbuttonComponentIds = getHorizontalPushbuttonComponentIds(this.index);
    this.powerNets = new Set(this.index.powerNets);
    this.groundNets = new Set(this.index.groundNets);
    for (const element of ctx.circuitJson) {
      if (element.type === "source_net" && element.is_positive_voltage_source)
        this.positiveVoltageNets.add(this.index.connected(element.source_net_id));
      if (element.type !== "source_port")
        continue;
      const net = this.index.connected(element.source_port_id);
      if (element.provides_power || element.requires_power)
        this.powerNets.add(net);
      if (element.provides_ground || element.requires_ground)
        this.groundNets.add(net);
    }
    this.componentIds = [...this.index.components.keys()].filter((id) => this.index.portsByComponent.get(id)?.length === 2);
    this.solved = this.componentIds.length === 0;
  }
  _step() {
    const id = this.componentIds[this.currentIndex++];
    this.solved = this.currentIndex >= this.componentIds.length;
    if (!id)
      return;
    const index = this.index;
    const component = index.placement(id);
    const sourceComponent = index.components.get(id);
    const nets = index.twoTerminalNets(id);
    if (!component || !nets)
      return;
    if (sourceComponent?.ftype === "simple_inductor" && !nets.some((net) => this.groundNets.has(net)))
      return;
    if (sourceComponent?.ftype === "simple_diode" && nets.every((net) => this.powerNets.has(net)))
      return;
    if (nets.some((net) => this.powerNets.has(net) && this.groundNets.has(net)))
      return;
    const railTypes = nets.map((net) => this.powerNets.has(net) ? "power" : this.groundNets.has(net) ? "ground" : undefined);
    if (railTypes.every((type) => type === undefined))
      return;
    const railType = railTypes.includes("power") ? "power" : "ground";
    const candidates = nets.flatMap((net, i) => railTypes[i] === railType ? [{ net, index: i }] : []);
    const railIndex = (candidates.find(({ net }) => index.portsByNet.get(net)?.some((port) => railType === "power" ? port.provides_power : port.provides_ground)) ?? candidates.find(({ net }) => (railType === "power" ? index.powerNets : index.groundNets).has(net)) ?? candidates[0]).index;
    const rail = nets[railIndex];
    const sourcePorts = index.portsByComponent.get(id);
    const railSourcePort = sourcePorts.find((port) => index.connected(port.source_port_id) === rail);
    const otherSourcePort = sourcePorts.find((port) => port !== railSourcePort);
    const railPort = index.port(railSourcePort);
    const otherPort = index.port(otherSourcePort);
    if (!railPort || !otherPort)
      return;
    const otherNet = index.connected(otherSourcePort.source_port_id);
    const otherIsGround = this.groundNets.has(otherNet);
    const isSupplyToSignalResistor = sourceComponent?.ftype === "simple_resistor" && !this.powerNets.has(otherNet) && !otherIsGround;
    const invertedRails = this.positiveVoltageNets.has(rail) && (otherIsGround || isSupplyToSignalResistor) && Math.abs(railPort.center.x - otherPort.center.x) <= TwoPinComponentRailOrientationSolver.EPSILON && railPort.center.y < otherPort.center.y - TwoPinComponentRailOrientationSolver.EPSILON && railPort.facing_direction === "down" && otherPort.facing_direction === "up";
    if (invertedRails) {
      this.issues.push({
        lineItemType: "TwoPinComponentHasInvertedRails",
        schematicBox: component,
        railSourcePortId: railSourcePort.source_port_id,
        railPinName: railSourcePort.name,
        railType: "power",
        deltaSchRotation: 180,
        suggestedRailFacingDirection: "up",
        message: `rotate ${component.sourceComponentName ?? id} by 180° so its positive-supply pin faces up and its ${otherIsGround ? "ground" : "signal"} pin faces down; preserve pin connections and reroute attached traces`
      });
      return;
    }
    const horizontal = Math.abs(railPort.center.y - otherPort.center.y) <= TwoPinComponentRailOrientationSolver.EPSILON && Math.abs(railPort.center.x - otherPort.center.x) > TwoPinComponentRailOrientationSolver.EPSILON && (railPort.facing_direction === "left" && otherPort.facing_direction === "right" || railPort.facing_direction === "right" && otherPort.facing_direction === "left");
    if (!horizontal)
      return;
    if (this.horizontalPushbuttonComponentIds.has(id))
      return;
    const suggestedRailFacingDirection = railType === "power" ? "up" : "down";
    const deltaSchRotation = railPort.facing_direction === "left" === (railType === "power") ? -90 : 90;
    this.issues.push({
      lineItemType: "TwoPinComponentShouldBeVertical",
      schematicBox: component,
      railSourcePortId: railSourcePort.source_port_id,
      railPinName: railSourcePort.name,
      railType,
      deltaSchRotation,
      suggestedRailFacingDirection,
      message: `rotate ${component.sourceComponentName ?? id} by ${deltaSchRotation}° so its ${railType}-connected pin faces ${suggestedRailFacingDirection} and the component is vertical`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
    addAttr(attrs, "railPin", issue.railPinName);
    addAttr(attrs, "railType", issue.railType);
    addAttr(attrs, "deltaSchRotation", issue.deltaSchRotation);
    addAttr(attrs, "suggestedRailFacingDirection", issue.suggestedRailFacingDirection);
    addAttr(attrs, "message", issue.message);
    return `<${issue.lineItemType} ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/utils/schematic-box-components.ts
function getSchematicBoxComponentIds(circuitJson) {
  return new Set(circuitJson.flatMap((element) => element.type === "schematic_component" && element.is_box_with_pins !== false && !element.symbol_name && !element.schematic_symbol_id ? [element.schematic_component_id] : []));
}

// ../../work/placement-analysis/lib/solvers/SchematicBoxInnerLabelCollisionSolver/SchematicBoxInnerLabelCollisionSolver.ts
class SchematicBoxInnerLabelCollisionSolver extends BaseSolver {
  params;
  MESSAGE = "Inner labels are colliding. Increase the schWidth or schHeight.";
  PIN_LABEL_EDGE_PADDING = 0.1;
  PIN_LABEL_TEXT_HEIGHT = 0.15;
  PIN_NAME_CHARACTER_WIDTH = 0.095;
  FALLBACK_CHARACTER_WIDTH = 0.13;
  INNER_LABEL_COLLISION_PADDING = 0.02;
  COLLISION_COMPARISON_EPSILON = 0.000000001;
  entries;
  placementById;
  sourcePortById;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    const { circuitJson, componentPlacements } = params.ctx;
    this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);
    this.sourcePortById = this.getSourcePortById(circuitJson);
    const boxIds = getSchematicBoxComponentIds(circuitJson);
    this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson)).filter(([id]) => boxIds.has(id));
    this.solved = this.entries.length === 0;
  }
  _step() {
    const entry = this.entries[this.currentIndex++];
    if (!entry) {
      this.solved = true;
      return;
    }
    this.solved = this.currentIndex >= this.entries.length;
    const [schematicComponentId, ports] = entry;
    const schematicBox = this.placementById.get(schematicComponentId);
    if (!schematicBox)
      return;
    const bounds = this.getCenteredRectBounds(schematicBox);
    const labelRects = this.getLabelRects(bounds, ports, this.sourcePortById);
    if (labelRects.length === 0)
      return;
    const collisionSummary = this.getCollisionSummary(labelRects);
    if (collisionSummary.overlappingSides.length === 0)
      return;
    this.params.issues.push({
      lineItemType: "SchematicBoxInnerLabelCollision",
      schematicBox,
      overlappingSides: collisionSummary.overlappingSides,
      message: this.MESSAGE
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "message", issue.message);
    addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
    addAttr(attrs, "currentSchWidth", issue.schematicBox.width);
    addAttr(attrs, "currentSchHeight", issue.schematicBox.height);
    addAttr(attrs, "overlappingSides", issue.overlappingSides.join(","));
    return `<SchematicBoxInnerLabelCollision ${attrs.join(" ")} />`;
  }
  isSchematicPort(el) {
    return el.type === "schematic_port";
  }
  isSourcePort(el) {
    return el.type === "source_port";
  }
  isSchematicSide(side) {
    return side === "left" || side === "right" || side === "top" || side === "bottom";
  }
  isPinNameLabel(label, sourcePort) {
    if (!sourcePort)
      return false;
    return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);
  }
  estimateLabelLength(label, sourcePort) {
    return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);
  }
  hasCollision(requiredGrowth) {
    return requiredGrowth > this.COLLISION_COMPARISON_EPSILON;
  }
  getCenteredRectBounds(box) {
    return {
      left: box.schX - box.width / 2,
      right: box.schX + box.width / 2,
      top: box.schY + box.height / 2,
      bottom: box.schY - box.height / 2
    };
  }
  getSourcePortById(circuitJson) {
    return new Map(circuitJson.filter((el) => this.isSourcePort(el)).map((sp) => [sp.source_port_id, sp]));
  }
  getPlacementBySchematicComponentId(componentPlacements) {
    return new Map(componentPlacements.filter((p) => p.schematicComponentId).map((p) => [p.schematicComponentId, p]));
  }
  getPortsBySchematicComponentId(circuitJson) {
    const map = new Map;
    for (const port of circuitJson.filter((el) => this.isSchematicPort(el))) {
      if (!port.schematic_component_id)
        continue;
      if (!this.isSchematicSide(port.side_of_component))
        continue;
      const ports = map.get(port.schematic_component_id);
      if (ports)
        ports.push(port);
      else
        map.set(port.schematic_component_id, [port]);
    }
    return map;
  }
  getLabelRects(bounds, ports, sourcePortById) {
    const rects = [];
    for (const port of ports) {
      if (!this.isSchematicSide(port.side_of_component))
        continue;
      if (!port.display_pin_label)
        continue;
      const labelLength = this.estimateLabelLength(port.display_pin_label, sourcePortById.get(port.source_port_id));
      const halfTextHeight = this.PIN_LABEL_TEXT_HEIGHT / 2;
      switch (port.side_of_component) {
        case "left": {
          const xMin = bounds.left + this.PIN_LABEL_EDGE_PADDING;
          rects.push({
            side: port.side_of_component,
            xMin,
            xMax: xMin + labelLength,
            yMin: port.center.y - halfTextHeight,
            yMax: port.center.y + halfTextHeight
          });
          break;
        }
        case "right": {
          const xMax = bounds.right - this.PIN_LABEL_EDGE_PADDING;
          rects.push({
            side: port.side_of_component,
            xMin: xMax - labelLength,
            xMax,
            yMin: port.center.y - halfTextHeight,
            yMax: port.center.y + halfTextHeight
          });
          break;
        }
        case "top": {
          const yMax = bounds.top - this.PIN_LABEL_EDGE_PADDING;
          rects.push({
            side: port.side_of_component,
            xMin: port.center.x - halfTextHeight,
            xMax: port.center.x + halfTextHeight,
            yMin: yMax - labelLength,
            yMax
          });
          break;
        }
        case "bottom": {
          const yMin = bounds.bottom + this.PIN_LABEL_EDGE_PADDING;
          rects.push({
            side: port.side_of_component,
            xMin: port.center.x - halfTextHeight,
            xMax: port.center.x + halfTextHeight,
            yMin,
            yMax: yMin + labelLength
          });
          break;
        }
      }
    }
    return rects;
  }
  getCollisionSummary(rects) {
    const overlappingSides = new Set;
    for (let i = 0;i < rects.length; i++) {
      for (let j = i + 1;j < rects.length; j++) {
        const a = rects[i];
        const b = rects[j];
        if (a.side === b.side)
          continue;
        if (!this.rectsOverlap(a, b))
          continue;
        overlappingSides.add(a.side);
        overlappingSides.add(b.side);
      }
    }
    return {
      overlappingSides: this.sortSides(Array.from(overlappingSides))
    };
  }
  rectsOverlap(a, b) {
    return this.hasCollision(Math.min(a.xMax, b.xMax) - Math.max(a.xMin, b.xMin) + this.INNER_LABEL_COLLISION_PADDING) && this.hasCollision(Math.min(a.yMax, b.yMax) - Math.max(a.yMin, b.yMin) + this.INNER_LABEL_COLLISION_PADDING);
  }
  sortSides(sides) {
    const order = {
      left: 0,
      right: 1,
      top: 2,
      bottom: 3
    };
    return sides.sort((a, b) => order[a] - order[b]);
  }
}

// ../../work/placement-analysis/lib/solvers/SchematicBoxOverlapSolver/SchematicBoxOverlapSolver.ts
class SchematicBoxOverlapSolver extends BaseSolver {
  params;
  placements;
  firstIndex = 0;
  secondIndex = 1;
  constructor(params) {
    super();
    this.params = params;
    this.placements = params.ctx.componentPlacements;
    this.solved = this.placements.length < 2;
  }
  _step() {
    if (this.firstIndex >= this.placements.length - 1) {
      this.solved = true;
      return;
    }
    const overlap = this.getComponentOverlap(this.placements[this.firstIndex], this.placements[this.secondIndex]);
    if (overlap)
      this.params.issues.push(overlap);
    this.secondIndex++;
    if (this.secondIndex >= this.placements.length) {
      this.firstIndex++;
      this.secondIndex = this.firstIndex + 1;
    }
    this.solved = this.firstIndex >= this.placements.length - 1;
  }
  getCenteredRectBounds(box) {
    return {
      left: box.schX - box.width / 2,
      right: box.schX + box.width / 2,
      top: box.schY - box.height / 2,
      bottom: box.schY + box.height / 2
    };
  }
  getOverlapCorrectionSuggestions({
    firstComponent,
    secondComponent,
    overlapWidth,
    overlapHeight
  }) {
    const firstArea = firstComponent.width * firstComponent.height;
    const secondArea = secondComponent.width * secondComponent.height;
    const target = firstArea <= secondArea ? firstComponent : secondComponent;
    const other = target === firstComponent ? secondComponent : firstComponent;
    const deltaSchX = target.schX <= other.schX ? -overlapWidth : overlapWidth;
    const deltaSchY = target.schY <= other.schY ? -overlapHeight : overlapHeight;
    return [
      {
        targetComponentName: target.sourceComponentName,
        deltaSchX,
        deltaSchY: 0,
        newSchX: target.schX + deltaSchX,
        newSchY: target.schY
      },
      {
        targetComponentName: target.sourceComponentName,
        deltaSchX: 0,
        deltaSchY,
        newSchX: target.schX,
        newSchY: target.schY + deltaSchY
      }
    ];
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "component1Name", issue.firstComponent.sourceComponentName);
    addAttr(attrs, "component2Name", issue.secondComponent.sourceComponentName);
    addAttr(attrs, "component1SchX", issue.firstComponent.schX);
    addAttr(attrs, "component1SchY", issue.firstComponent.schY);
    addAttr(attrs, "component2SchX", issue.secondComponent.schX);
    addAttr(attrs, "component2SchY", issue.secondComponent.schY);
    addAttr(attrs, "overlapWidth", issue.overlapWidth);
    addAttr(attrs, "overlapHeight", issue.overlapHeight);
    return [
      `<ComponentOverlap ${attrs.join(" ")}>`,
      ...issue.correctionSuggestions.map(SchematicBoxOverlapSolver.correctionSuggestionToString),
      "</ComponentOverlap>"
    ].join(`
`);
  }
  static correctionSuggestionToString(suggestion) {
    const attrs = [];
    addAttr(attrs, "target", suggestion.targetComponentName);
    if (suggestion.deltaSchX !== 0) {
      addAttr(attrs, "newSchX", suggestion.newSchX);
      addAttr(attrs, "deltaSchX", suggestion.deltaSchX, { formatDelta: true });
    }
    if (suggestion.deltaSchY !== 0) {
      addAttr(attrs, "newSchY", suggestion.newSchY);
      addAttr(attrs, "deltaSchY", suggestion.deltaSchY, { formatDelta: true });
    }
    return `<OverlapCorrectionSuggestion ${attrs.join(" ")} />`;
  }
  getComponentOverlap(firstComponent, secondComponent) {
    if (firstComponent.schematicSheetId !== secondComponent.schematicSheetId)
      return null;
    const a = this.getCenteredRectBounds(firstComponent);
    const b = this.getCenteredRectBounds(secondComponent);
    const overlapWidth = Math.min(a.right, b.right) - Math.max(a.left, b.left);
    const overlapHeight = Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top);
    if (overlapWidth <= 0 || overlapHeight <= 0)
      return null;
    return {
      lineItemType: "ComponentOverlap",
      firstComponent,
      secondComponent,
      overlapWidth,
      overlapHeight,
      correctionSuggestions: this.getOverlapCorrectionSuggestions({
        firstComponent,
        secondComponent,
        overlapWidth,
        overlapHeight
      })
    };
  }
}

// ../../work/placement-analysis/lib/solvers/SchematicBoxTooWideSolver/SchematicBoxTooWideSolver.ts
class SchematicBoxTooWideSolver extends BaseSolver {
  params;
  SCHEMATIC_BOX_TOO_WIDE_MESSAGE = "Shrink schematic box width";
  PIN_HEADER_MAX_ALLOWED_GAP = 0.1;
  GENERIC_MAX_ALLOWED_GAP = 1;
  PIN_LABEL_EDGE_PADDING = 0.1;
  PIN_NAME_CHARACTER_WIDTH = 0.095;
  FALLBACK_CHARACTER_WIDTH = 0.13;
  GAP_COMPARISON_EPSILON = 0.000000001;
  entries;
  placementById;
  sourcePortById;
  sourceComponentById;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    const { circuitJson, componentPlacements } = params.ctx;
    this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);
    this.sourcePortById = this.getSourcePortById(circuitJson);
    this.sourceComponentById = this.getSourceComponentById(circuitJson);
    const boxIds = getSchematicBoxComponentIds(circuitJson);
    this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson)).filter(([id]) => boxIds.has(id));
    this.solved = this.entries.length === 0;
  }
  _step() {
    const entry = this.entries[this.currentIndex++];
    if (!entry) {
      this.solved = true;
      return;
    }
    this.solved = this.currentIndex >= this.entries.length;
    const [schematicComponentId, ports] = entry;
    const schematicBox = this.placementById.get(schematicComponentId);
    if (!schematicBox)
      return;
    const sourceComponent = schematicBox.sourceComponentId ? this.sourceComponentById.get(schematicBox.sourceComponentId) : undefined;
    if (sourceComponent?.ftype === "simple_connector" && sourceComponent.standard === "usb_c")
      return;
    const bounds = this.getCenteredRectBounds(schematicBox);
    const leftCol = this.getLabelColumn("left", ports, this.sourcePortById);
    const rightCol = this.getLabelColumn("right", ports, this.sourcePortById);
    const ftype = this.getSourceComponentFtype(schematicBox, this.sourceComponentById);
    let measuredSpace;
    if (leftCol && rightCol) {
      measuredSpace = this.getInnerLabelEdge(bounds, rightCol) - this.getInnerLabelEdge(bounds, leftCol);
    } else if (leftCol && leftCol.labelCount >= 4) {
      measuredSpace = bounds.right - this.getInnerLabelEdge(bounds, leftCol);
    } else if (rightCol && rightCol.labelCount >= 4) {
      measuredSpace = this.getInnerLabelEdge(bounds, rightCol) - bounds.left;
    }
    if (measuredSpace === undefined)
      return;
    const maxAllowed = ftype === "simple_pin_header" ? this.PIN_HEADER_MAX_ALLOWED_GAP : this.GENERIC_MAX_ALLOWED_GAP;
    if (!this.exceedsMaxAllowedGap(measuredSpace, maxAllowed))
      return;
    const suggestedSchWidth = this.getSuggestedWidth({
      measuredInnerLabelHorizontalEmptySpace: measuredSpace,
      maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,
      currentWidth: schematicBox.width
    });
    if (ftype === "simple_pin_header") {
      this.params.issues.push({
        lineItemType: "PinHeaderSchematicBoxTooWide",
        schematicBox,
        measuredInnerLabelHorizontalEmptySpace: measuredSpace,
        maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,
        suggestedSchWidth,
        message: this.SCHEMATIC_BOX_TOO_WIDE_MESSAGE
      });
    } else {
      this.params.issues.push({
        lineItemType: "GenericSchematicBoxTooWide",
        schematicBox,
        measuredInnerLabelHorizontalEmptySpace: measuredSpace,
        maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,
        suggestedSchWidth,
        message: this.SCHEMATIC_BOX_TOO_WIDE_MESSAGE
      });
    }
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "message", issue.message);
    addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
    addAttr(attrs, "currentSchWidth", issue.schematicBox.width);
    addAttr(attrs, "measuredInnerLabelHorizontalEmptySpace", issue.measuredInnerLabelHorizontalEmptySpace);
    addAttr(attrs, "maxAllowedInnerLabelHorizontalEmptySpace", issue.maxAllowedInnerLabelHorizontalEmptySpace);
    addAttr(attrs, "suggestedSchWidth", issue.suggestedSchWidth);
    return `<${issue.lineItemType} ${attrs.join(" ")} />`;
  }
  isSchematicPort(el) {
    return el.type === "schematic_port";
  }
  isSourcePort(el) {
    return el.type === "source_port";
  }
  isHorizontalSide(side) {
    return side === "left" || side === "right";
  }
  getSourceComponentWithFtype(el) {
    if (el.type !== "source_component" || !("source_component_id" in el) || typeof el.source_component_id !== "string")
      return null;
    return {
      type: "source_component",
      source_component_id: el.source_component_id,
      standard: "standard" in el && typeof el.standard === "string" ? el.standard : undefined,
      ftype: "ftype" in el && typeof el.ftype === "string" ? el.ftype : undefined
    };
  }
  isPinNameLabel(label, sourcePort) {
    if (!sourcePort)
      return false;
    return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);
  }
  estimateLabelWidth(label, sourcePort) {
    return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);
  }
  exceedsMaxAllowedGap(measured, maxAllowed) {
    return measured - maxAllowed > this.GAP_COMPARISON_EPSILON;
  }
  getCenteredRectBounds(box) {
    return {
      left: box.schX - box.width / 2,
      right: box.schX + box.width / 2,
      top: box.schY + box.height / 2,
      bottom: box.schY - box.height / 2
    };
  }
  getSourcePortById(circuitJson) {
    return new Map(circuitJson.filter((el) => this.isSourcePort(el)).map((sp) => [sp.source_port_id, sp]));
  }
  getSourceComponentById(circuitJson) {
    return new Map(circuitJson.flatMap((el) => {
      const sc = this.getSourceComponentWithFtype(el);
      return sc ? [sc] : [];
    }).map((sc) => [sc.source_component_id, sc]));
  }
  getPlacementBySchematicComponentId(componentPlacements) {
    return new Map(componentPlacements.filter((p) => p.schematicComponentId).map((p) => [p.schematicComponentId, p]));
  }
  getPortsBySchematicComponentId(circuitJson) {
    const map = new Map;
    for (const port of circuitJson.filter((el) => this.isSchematicPort(el))) {
      if (!port.schematic_component_id)
        continue;
      if (!this.isHorizontalSide(port.side_of_component))
        continue;
      const ports = map.get(port.schematic_component_id);
      if (ports)
        ports.push(port);
      else
        map.set(port.schematic_component_id, [port]);
    }
    return map;
  }
  getSourceComponentFtype(schematicBox, sourceComponentById) {
    return schematicBox.sourceComponentId ? sourceComponentById.get(schematicBox.sourceComponentId)?.ftype : undefined;
  }
  getLabelColumn(side, ports, sourcePortById) {
    const widths = ports.filter((p) => p.side_of_component === side).flatMap((p) => p.display_pin_label ? [
      this.estimateLabelWidth(p.display_pin_label, sourcePortById.get(p.source_port_id))
    ] : []);
    if (widths.length === 0)
      return null;
    return {
      side,
      labelCount: widths.length,
      maxLabelWidth: Math.max(...widths)
    };
  }
  getInnerLabelEdge(bounds, col) {
    return col.side === "left" ? bounds.left + this.PIN_LABEL_EDGE_PADDING + col.maxLabelWidth : bounds.right - this.PIN_LABEL_EDGE_PADDING - col.maxLabelWidth;
  }
  getSuggestedWidth(input) {
    return input.currentWidth - input.measuredInnerLabelHorizontalEmptySpace + input.maxAllowedInnerLabelHorizontalEmptySpace;
  }
}

// ../../work/placement-analysis/lib/solvers/SchematicPinPaddingToEdgeSolver/SchematicPinPaddingToEdgeSolver.ts
class SchematicPinPaddingToEdgeSolver extends BaseSolver {
  params;
  MESSAGE = "Move schematic pins closer to the box edge or change the schematic box";
  PIN_NAME_CHARACTER_WIDTH = 0.095;
  FALLBACK_CHARACTER_WIDTH = 0.13;
  GAP_COMPARISON_EPSILON = 0.000000001;
  entries;
  placementById;
  schematicComponentById;
  sourcePortById;
  currentIndex = 0;
  constructor(params) {
    super();
    this.params = params;
    const { circuitJson, componentPlacements } = params.ctx;
    this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);
    this.schematicComponentById = this.getSchematicComponentById(circuitJson);
    this.sourcePortById = this.getSourcePortById(circuitJson);
    const boxIds = getSchematicBoxComponentIds(circuitJson);
    this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson)).filter(([id]) => boxIds.has(id));
    this.solved = this.entries.length === 0;
  }
  _step() {
    const entry = this.entries[this.currentIndex++];
    if (!entry) {
      this.solved = true;
      return;
    }
    this.solved = this.currentIndex >= this.entries.length;
    const [schematicComponentId, ports] = entry;
    const schematicBox = this.placementById.get(schematicComponentId);
    if (!schematicBox)
      return;
    const pinSpacing = this.getPinSpacing(schematicBox, this.schematicComponentById);
    if (pinSpacing === null)
      return;
    const maxLabelLengthBySide = this.getMaxLabelLengthBySide(ports, this.sourcePortById);
    const portsBySide = new Map;
    for (const port of ports) {
      if (!this.isSchematicSide(port.side_of_component))
        continue;
      const sidePorts = portsBySide.get(port.side_of_component) ?? [];
      sidePorts.push(port);
      portsBySide.set(port.side_of_component, sidePorts);
    }
    const useLabelAwareMaxPadding = this.hasPinsOnAllSides(portsBySide);
    const candidates = [];
    for (const [pinSide, sidePorts] of portsBySide) {
      if (sidePorts.length === 1)
        continue;
      for (const edgeSide of this.getBoxEdgeSidesForPinSide(pinSide)) {
        const outerPin = this.getOuterPinBySide(edgeSide, sidePorts);
        if (!outerPin)
          continue;
        const measuredPadding = this.getPinPaddingToEdge(schematicBox, outerPin, edgeSide);
        const maxAllowedPadding = useLabelAwareMaxPadding ? this.getMaxAllowedPinPadding(pinSpacing, edgeSide, maxLabelLengthBySide) : pinSpacing;
        if (!this.exceedsMaxAllowedGap(measuredPadding, maxAllowedPadding + pinSpacing))
          continue;
        candidates.push({
          schematicBox,
          pinSide,
          edgeSide,
          pinName: this.getPinName(outerPin, this.sourcePortById),
          measuredPadding,
          maxAllowedPadding
        });
      }
    }
    if (!candidates.length)
      return;
    const details = candidates.map((candidate) => this.createIssue(candidate));
    const representative = details.reduce((a, b) => b.excessPadding > a.excessPadding ? b : a);
    const widths = details.flatMap((detail) => detail.suggestedSchWidth === undefined ? [] : [detail.suggestedSchWidth]);
    const heights = details.flatMap((detail) => detail.suggestedSchHeight === undefined ? [] : [detail.suggestedSchHeight]);
    const dimensions = [
      widths.length ? "width" : "",
      heights.length ? "height" : ""
    ].filter(Boolean).join(" and ");
    this.params.issues.push({
      ...representative,
      paddingDetails: details.map(({
        pinSide,
        edgeSide,
        pinName,
        measuredPadding,
        maxAllowedPadding,
        excessPadding
      }) => ({
        pinSide,
        edgeSide,
        pinName,
        measuredPadding,
        maxAllowedPadding,
        excessPadding
      })),
      suggestedSchWidth: widths.length ? Math.max(...widths) : undefined,
      suggestedSchHeight: heights.length ? Math.max(...heights) : undefined,
      message: `${this.MESSAGE} ${dimensions}`
    });
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "message", issue.message);
    addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
    if (issue.paddingDetails) {
      addAttr(attrs, "pinSides", [...new Set(issue.paddingDetails.map((detail) => detail.pinSide))].join(","));
      addAttr(attrs, "edgeSides", [
        ...new Set(issue.paddingDetails.map((detail) => detail.edgeSide))
      ].join(","));
    } else {
      addAttr(attrs, "pinSide", issue.pinSide);
      addAttr(attrs, "edgeSide", issue.edgeSide);
      addAttr(attrs, "pinName", issue.pinName);
      addAttr(attrs, "measuredPadding", issue.measuredPadding);
      addAttr(attrs, "maxAllowedPadding", issue.maxAllowedPadding);
      addAttr(attrs, "excessPadding", issue.excessPadding);
    }
    addAttr(attrs, "suggestedSchWidth", issue.suggestedSchWidth);
    addAttr(attrs, "suggestedSchHeight", issue.suggestedSchHeight);
    return `<SchematicPinPaddingToEdgeTooLarge ${attrs.join(" ")} />`;
  }
  isSchematicPort(el) {
    return el.type === "schematic_port";
  }
  isSourcePort(el) {
    return el.type === "source_port";
  }
  isSchematicComponent(el) {
    return el.type === "schematic_component";
  }
  isHorizontalSide(side) {
    return side === "left" || side === "right";
  }
  isVerticalSide(side) {
    return side === "top" || side === "bottom";
  }
  isSchematicSide(side) {
    return this.isHorizontalSide(side) || this.isVerticalSide(side);
  }
  isPinNameLabel(label, sourcePort) {
    if (!sourcePort)
      return false;
    return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);
  }
  estimateLabelWidth(label, sourcePort) {
    return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);
  }
  exceedsMaxAllowedGap(measured, maxAllowed) {
    return measured - maxAllowed > this.GAP_COMPARISON_EPSILON;
  }
  getCenteredRectBounds(box) {
    return {
      left: box.schX - box.width / 2,
      right: box.schX + box.width / 2,
      top: box.schY + box.height / 2,
      bottom: box.schY - box.height / 2
    };
  }
  getSourcePortById(circuitJson) {
    return new Map(circuitJson.filter((el) => this.isSourcePort(el)).map((sp) => [sp.source_port_id, sp]));
  }
  getSchematicComponentById(circuitJson) {
    return new Map(circuitJson.filter((el) => this.isSchematicComponent(el)).map((sc) => [sc.schematic_component_id, sc]));
  }
  getPlacementBySchematicComponentId(componentPlacements) {
    return new Map(componentPlacements.filter((p) => p.schematicComponentId).map((p) => [p.schematicComponentId, p]));
  }
  getPortsBySchematicComponentId(circuitJson) {
    const map = new Map;
    for (const port of circuitJson.filter((el) => this.isSchematicPort(el))) {
      if (!port.schematic_component_id)
        continue;
      if (!this.isSchematicSide(port.side_of_component))
        continue;
      const ports = map.get(port.schematic_component_id);
      if (ports)
        ports.push(port);
      else
        map.set(port.schematic_component_id, [port]);
    }
    return map;
  }
  getPinSpacing(schematicBox, schematicComponentById) {
    if (!schematicBox.schematicComponentId)
      return null;
    const sc = schematicComponentById.get(schematicBox.schematicComponentId);
    return typeof sc?.pin_spacing === "number" ? sc.pin_spacing : null;
  }
  getPinName(port, sourcePortById) {
    const sp = sourcePortById.get(port.source_port_id);
    if (sp?.name)
      return sp.name;
    if (port.display_pin_label)
      return port.display_pin_label;
    if (sp?.pin_number !== undefined)
      return String(sp.pin_number);
    return;
  }
  getMaxLabelLengthBySide(ports, sourcePortById) {
    const result = {
      left: 0,
      right: 0,
      top: 0,
      bottom: 0
    };
    for (const port of ports) {
      if (!this.isSchematicSide(port.side_of_component))
        continue;
      if (!port.display_pin_label)
        continue;
      result[port.side_of_component] = Math.max(result[port.side_of_component], this.estimateLabelWidth(port.display_pin_label, sourcePortById.get(port.source_port_id)));
    }
    return result;
  }
  getOuterPinBySide(edgeSide, ports) {
    if (ports.length === 0)
      return null;
    switch (edgeSide) {
      case "top":
        return ports.reduce((a, b) => b.center.y > a.center.y ? b : a);
      case "bottom":
        return ports.reduce((a, b) => b.center.y < a.center.y ? b : a);
      case "left":
        return ports.reduce((a, b) => b.center.x < a.center.x ? b : a);
      case "right":
        return ports.reduce((a, b) => b.center.x > a.center.x ? b : a);
    }
  }
  getPinPaddingToEdge(schematicBox, port, edgeSide) {
    const bounds = this.getCenteredRectBounds(schematicBox);
    switch (edgeSide) {
      case "top":
        return Math.max(0, bounds.top - port.center.y);
      case "bottom":
        return Math.max(0, port.center.y - bounds.bottom);
      case "left":
        return Math.max(0, port.center.x - bounds.left);
      case "right":
        return Math.max(0, bounds.right - port.center.x);
    }
  }
  getBoxEdgeSidesForPinSide(pinSide) {
    return this.isHorizontalSide(pinSide) ? ["top", "bottom"] : ["left", "right"];
  }
  hasPinsOnAllSides(portsBySide) {
    return portsBySide.has("left") && portsBySide.has("right") && portsBySide.has("top") && portsBySide.has("bottom");
  }
  getMaxAllowedPinPadding(spacing, edgeSide, maxLabelLengthBySide) {
    const sides = this.isHorizontalSide(edgeSide) ? ["left", "right"] : ["top", "bottom"];
    return (maxLabelLengthBySide[sides[0]] + maxLabelLengthBySide[sides[1]] + spacing) / 2;
  }
  createIssue(candidate) {
    const excessPadding = Math.max(0, candidate.measuredPadding - candidate.maxAllowedPadding);
    const reduction = excessPadding * 2;
    return {
      lineItemType: "SchematicPinPaddingToEdgeTooLarge",
      pinSide: candidate.pinSide,
      edgeSide: candidate.edgeSide,
      pinName: candidate.pinName,
      schematicBox: candidate.schematicBox,
      measuredPadding: candidate.measuredPadding,
      maxAllowedPadding: candidate.maxAllowedPadding,
      excessPadding,
      suggestedSchWidth: this.isHorizontalSide(candidate.pinSide) ? undefined : Math.max(0, candidate.schematicBox.width - reduction),
      suggestedSchHeight: this.isHorizontalSide(candidate.pinSide) ? Math.max(0, candidate.schematicBox.height - reduction) : undefined,
      message: this.isHorizontalSide(candidate.pinSide) ? `${this.MESSAGE} height` : `${this.MESSAGE} width`
    };
  }
}

// ../../work/placement-analysis/node_modules/circuit-json/dist/index.mjs
var exports_dist = {};
__export(exports_dist, {
  wave_shape: () => wave_shape,
  voltage: () => voltage,
  visible_layer: () => visible_layer,
  unknown_error_finding_part: () => unknown_error_finding_part,
  timestamp: () => timestamp,
  time: () => time,
  supplier_name: () => supplier_name,
  supplier_footprint_mismatch_warning: () => supplier_footprint_mismatch_warning,
  spice_simulation_options: () => spice_simulation_options,
  source_unnamed_trace_warning: () => source_unnamed_trace_warning,
  source_trace_not_connected_error: () => source_trace_not_connected_error,
  source_trace: () => source_trace,
  source_simple_voltage_source: () => source_simple_voltage_source,
  source_simple_voltage_probe: () => source_simple_voltage_probe,
  source_simple_transistor: () => source_simple_transistor,
  source_simple_test_point: () => source_simple_test_point,
  source_simple_switch: () => source_simple_switch,
  source_simple_resonator: () => source_simple_resonator,
  source_simple_resistor: () => source_simple_resistor,
  source_simple_push_button: () => source_simple_push_button,
  source_simple_power_source: () => source_simple_power_source,
  source_simple_potentiometer: () => source_simple_potentiometer,
  source_simple_pinout: () => source_simple_pinout,
  source_simple_pin_header: () => source_simple_pin_header,
  source_simple_op_amp: () => source_simple_op_amp,
  source_simple_mosfet: () => source_simple_mosfet,
  source_simple_led: () => source_simple_led,
  source_simple_inductor: () => source_simple_inductor,
  source_simple_ground: () => source_simple_ground,
  source_simple_fiducial: () => source_simple_fiducial,
  source_simple_diode: () => source_simple_diode,
  source_simple_current_source: () => source_simple_current_source,
  source_simple_crystal: () => source_simple_crystal,
  source_simple_connector: () => source_simple_connector,
  source_simple_chip: () => source_simple_chip,
  source_simple_capacitor: () => source_simple_capacitor,
  source_simple_battery: () => source_simple_battery,
  source_simple_ammeter: () => source_simple_ammeter,
  source_property_ignored_warning: () => source_property_ignored_warning,
  source_project_metadata: () => source_project_metadata,
  source_port: () => source_port,
  source_pin_must_be_connected_error: () => source_pin_must_be_connected_error,
  source_pin_missing_trace_warning: () => source_pin_missing_trace_warning,
  source_pin_attributes: () => source_pin_attributes,
  source_pcb_ground_plane: () => source_pcb_ground_plane,
  source_no_power_pin_defined_warning: () => source_no_power_pin_defined_warning,
  source_no_ground_pin_defined_warning: () => source_no_ground_pin_defined_warning,
  source_net: () => source_net,
  source_missing_property_error: () => source_missing_property_error,
  source_missing_manufacturer_part_number_warning: () => source_missing_manufacturer_part_number_warning,
  source_manually_placed_via: () => source_manually_placed_via,
  source_invalid_component_property_error: () => source_invalid_component_property_error,
  source_interconnect: () => source_interconnect,
  source_i2c_misconfigured_error: () => source_i2c_misconfigured_error,
  source_group: () => source_group,
  source_failed_to_create_component_error: () => source_failed_to_create_component_error,
  source_component_pins_underspecified_warning: () => source_component_pins_underspecified_warning,
  source_component_misconfigured_error: () => source_component_misconfigured_error,
  source_component_internal_connection: () => source_component_internal_connection,
  source_component_base: () => source_component_base,
  source_board: () => source_board,
  source_ambiguous_port_reference: () => source_ambiguous_port_reference,
  size: () => size,
  simulation_voltage_source: () => simulation_voltage_source,
  simulation_voltage_probe: () => simulation_voltage_probe,
  simulation_unknown_experiment_error: () => simulation_unknown_experiment_error,
  simulation_transient_voltage_graph: () => simulation_transient_voltage_graph,
  simulation_transient_current_graph: () => simulation_transient_current_graph,
  simulation_switch: () => simulation_switch,
  simulation_spice_subcircuit: () => simulation_spice_subcircuit,
  simulation_oscilloscope_trace: () => simulation_oscilloscope_trace,
  simulation_op_amp: () => simulation_op_amp,
  simulation_experiment: () => simulation_experiment,
  simulation_dc_voltage_source: () => simulation_dc_voltage_source,
  simulation_dc_current_source: () => simulation_dc_current_source,
  simulation_current_source: () => simulation_current_source,
  simulation_current_probe: () => simulation_current_probe,
  simulation_ac_voltage_source: () => simulation_ac_voltage_source,
  simulation_ac_current_source: () => simulation_ac_current_source,
  schematic_voltage_probe: () => schematic_voltage_probe,
  schematic_trace: () => schematic_trace,
  schematic_text: () => schematic_text,
  schematic_table_cell: () => schematic_table_cell,
  schematic_table: () => schematic_table,
  schematic_symbol: () => schematic_symbol,
  schematic_sheet: () => schematic_sheet,
  schematic_rect: () => schematic_rect,
  schematic_port: () => schematic_port,
  schematic_pin_styles: () => schematic_pin_styles,
  schematic_path: () => schematic_path,
  schematic_net_label: () => schematic_net_label,
  schematic_manual_edit_conflict_warning: () => schematic_manual_edit_conflict_warning,
  schematic_line: () => schematic_line,
  schematic_layout_error: () => schematic_layout_error,
  schematic_group: () => schematic_group,
  schematic_error: () => schematic_error,
  schematic_debug_rect: () => schematic_debug_rect,
  schematic_debug_point: () => schematic_debug_point,
  schematic_debug_object_base: () => schematic_debug_object_base,
  schematic_debug_object: () => schematic_debug_object,
  schematic_debug_line: () => schematic_debug_line,
  schematic_component_port_arrangement_by_size: () => schematic_component_port_arrangement_by_size,
  schematic_component_port_arrangement_by_sides: () => schematic_component_port_arrangement_by_sides,
  schematic_component: () => schematic_component,
  schematic_circle: () => schematic_circle,
  schematic_box: () => schematic_box,
  schematic_arc: () => schematic_arc,
  route_hint_point: () => route_hint_point,
  rotation: () => rotation,
  ring: () => ring,
  resistance: () => resistance,
  position3: () => position3,
  position: () => position,
  port_arrangement: () => port_arrangement,
  point_with_bulge: () => point_with_bulge,
  point3: () => point3,
  point: () => point,
  pcb_via_trace_clearance_error: () => pcb_via_trace_clearance_error,
  pcb_via_clearance_error: () => pcb_via_clearance_error,
  pcb_via: () => pcb_via,
  pcb_trace_warning: () => pcb_trace_warning,
  pcb_trace_route_point_wire: () => pcb_trace_route_point_wire,
  pcb_trace_route_point_via: () => pcb_trace_route_point_via,
  pcb_trace_route_point_through_pad: () => pcb_trace_route_point_through_pad,
  pcb_trace_route_point: () => pcb_trace_route_point,
  pcb_trace_missing_error: () => pcb_trace_missing_error,
  pcb_trace_hint: () => pcb_trace_hint,
  pcb_trace_error: () => pcb_trace_error,
  pcb_trace: () => pcb_trace,
  pcb_thermal_spoke: () => pcb_thermal_spoke,
  pcb_text: () => pcb_text,
  pcb_solder_paste: () => pcb_solder_paste,
  pcb_smtpad_pill: () => pcb_smtpad_pill,
  pcb_smtpad: () => pcb_smtpad,
  pcb_silkscreen_text: () => pcb_silkscreen_text,
  pcb_silkscreen_rect: () => pcb_silkscreen_rect,
  pcb_silkscreen_pill: () => pcb_silkscreen_pill,
  pcb_silkscreen_path: () => pcb_silkscreen_path,
  pcb_silkscreen_oval: () => pcb_silkscreen_oval,
  pcb_silkscreen_line: () => pcb_silkscreen_line,
  pcb_silkscreen_graphic_brep: () => pcb_silkscreen_graphic_brep,
  pcb_silkscreen_graphic: () => pcb_silkscreen_graphic,
  pcb_silkscreen_circle: () => pcb_silkscreen_circle,
  pcb_route_hints: () => pcb_route_hints,
  pcb_route_hint: () => pcb_route_hint,
  pcb_port_not_matched_error: () => pcb_port_not_matched_error,
  pcb_port_not_connected_error: () => pcb_port_not_connected_error,
  pcb_port: () => pcb_port,
  pcb_plated_hole: () => pcb_plated_hole,
  pcb_placement_error: () => pcb_placement_error,
  pcb_panelization_placement_error: () => pcb_panelization_placement_error,
  pcb_panel: () => pcb_panel,
  pcb_pad_trace_clearance_error: () => pcb_pad_trace_clearance_error,
  pcb_pad_pad_clearance_error: () => pcb_pad_pad_clearance_error,
  pcb_note_text: () => pcb_note_text,
  pcb_note_rect: () => pcb_note_rect,
  pcb_note_path: () => pcb_note_path,
  pcb_note_line: () => pcb_note_line,
  pcb_note_dimension: () => pcb_note_dimension,
  pcb_net: () => pcb_net,
  pcb_missing_footprint_error: () => pcb_missing_footprint_error,
  pcb_manual_edit_conflict_warning: () => pcb_manual_edit_conflict_warning,
  pcb_keepout: () => pcb_keepout,
  pcb_hole_rotated_pill_shape: () => pcb_hole_rotated_pill_shape,
  pcb_hole_rect_shape: () => pcb_hole_rect_shape,
  pcb_hole_pill_shape: () => pcb_hole_pill_shape,
  pcb_hole_oval_shape: () => pcb_hole_oval_shape,
  pcb_hole_circle_shape: () => pcb_hole_circle_shape,
  pcb_hole_circle_or_square_shape: () => pcb_hole_circle_or_square_shape,
  pcb_hole: () => pcb_hole,
  pcb_group: () => pcb_group,
  pcb_ground_plane_region: () => pcb_ground_plane_region,
  pcb_ground_plane: () => pcb_ground_plane,
  pcb_footprint_overlap_error: () => pcb_footprint_overlap_error,
  pcb_fabrication_note_text: () => pcb_fabrication_note_text,
  pcb_fabrication_note_rect: () => pcb_fabrication_note_rect,
  pcb_fabrication_note_path: () => pcb_fabrication_note_path,
  pcb_fabrication_note_dimension: () => pcb_fabrication_note_dimension,
  pcb_cutout_rect: () => pcb_cutout_rect,
  pcb_cutout_polygon: () => pcb_cutout_polygon,
  pcb_cutout_path: () => pcb_cutout_path,
  pcb_cutout_circle: () => pcb_cutout_circle,
  pcb_cutout: () => pcb_cutout,
  pcb_courtyard_rect: () => pcb_courtyard_rect,
  pcb_courtyard_polygon: () => pcb_courtyard_polygon,
  pcb_courtyard_pill: () => pcb_courtyard_pill,
  pcb_courtyard_overlap_error: () => pcb_courtyard_overlap_error,
  pcb_courtyard_outline: () => pcb_courtyard_outline,
  pcb_courtyard_circle: () => pcb_courtyard_circle,
  pcb_copper_text: () => pcb_copper_text,
  pcb_copper_pour_rect: () => pcb_copper_pour_rect,
  pcb_copper_pour_polygon: () => pcb_copper_pour_polygon,
  pcb_copper_pour_brep: () => pcb_copper_pour_brep,
  pcb_copper_pour: () => pcb_copper_pour,
  pcb_connector_not_in_accessible_orientation_warning: () => pcb_connector_not_in_accessible_orientation_warning,
  pcb_component_outside_board_error: () => pcb_component_outside_board_error,
  pcb_component_not_on_board_edge_error: () => pcb_component_not_on_board_edge_error,
  pcb_component_invalid_layer_error: () => pcb_component_invalid_layer_error,
  pcb_component: () => pcb_component,
  pcb_breakout_point: () => pcb_breakout_point,
  pcb_board: () => pcb_board,
  pcb_autorouting_error: () => pcb_autorouting_error,
  pcbRenderLayer: () => pcbRenderLayer,
  parseAndConvertSiUnit: () => parseAndConvertSiUnit,
  ninePointAnchor: () => ninePointAnchor,
  ms: () => ms,
  manufacturing_drc_properties: () => manufacturing_drc_properties,
  length: () => length,
  layer_string: () => layer_string,
  layer_ref: () => layer_ref,
  kicadSymbolProperty: () => kicadSymbolProperty,
  kicadSymbolProperties: () => kicadSymbolProperties,
  kicadSymbolPinNumbers: () => kicadSymbolPinNumbers,
  kicadSymbolPinNames: () => kicadSymbolPinNames,
  kicadSymbolMetadata: () => kicadSymbolMetadata,
  kicadSymbolEffects: () => kicadSymbolEffects,
  kicadProperty: () => kicadProperty,
  kicadFootprintProperties: () => kicadFootprintProperties,
  kicadFootprintPad: () => kicadFootprintPad,
  kicadFootprintModel: () => kicadFootprintModel,
  kicadFootprintMetadata: () => kicadFootprintMetadata,
  kicadFootprintAttributes: () => kicadFootprintAttributes,
  kicadFont: () => kicadFont,
  kicadEffects: () => kicadEffects,
  kicadAt: () => kicadAt,
  inductance: () => inductance,
  getZodPrefixedIdWithDefault: () => getZodPrefixedIdWithDefault,
  frequency: () => frequency,
  external_footprint_load_error: () => external_footprint_load_error,
  experiment_type: () => experiment_type,
  duration_ms: () => duration_ms,
  distance: () => distance4,
  current: () => current,
  circuit_json_footprint_load_error: () => circuit_json_footprint_load_error,
  capacitance: () => capacitance,
  cad_model_formats: () => cad_model_formats,
  cad_model_axis_directions: () => cad_model_axis_directions,
  cad_component: () => cad_component,
  cadModelDefaultDirectionMap: () => cadModelDefaultDirectionMap,
  brep_shape: () => brep_shape,
  battery_capacity: () => battery_capacity,
  base_circuit_json_error: () => base_circuit_json_error,
  asset: () => asset,
  any_source_component: () => any_source_component,
  any_soup_element: () => any_soup_element,
  any_circuit_element: () => any_circuit_element,
  all_layers: () => all_layers
});

// ../../work/placement-analysis/node_modules/format-si-unit/dist/index.js
var SI_PREFIX_VALUES = /* @__PURE__ */ new Map([
  ["T", 1000000000000],
  ["G", 1e9],
  ["M", 1e6],
  ["K", 1000],
  ["k", 1000],
  ["", 1],
  ["m", 0.001],
  ["µ", 0.000001],
  ["u", 0.000001],
  ["n", 0.000000001],
  ["p", 0.000000000001],
  ["f", 0.000000000000001]
]);
var SI_PREFIXES = [...SI_PREFIX_VALUES.keys()];
function getSiPrefixMultiplier(prefix) {
  return SI_PREFIX_VALUES.get(prefix);
}
var unitMappings = {
  Hz: {
    baseUnit: "Hz",
    variants: {
      MHz: 1e6,
      kHz: 1000,
      Hz: 1
    }
  },
  g: {
    baseUnit: "g",
    variants: {
      kg: 1000,
      g: 1
    }
  },
  Ω: {
    baseUnit: "Ω",
    variants: {
      mΩ: 0.001,
      mohm: 0.001,
      mOhm: 0.001,
      milliohm: 0.001,
      Ω: 1,
      ohm: 1,
      Ohm: 1,
      kΩ: 1000,
      KΩ: 1000,
      kohm: 1000,
      kOhm: 1000,
      KOhm: 1000,
      Kohm: 1000,
      MΩ: 1e6,
      Mohm: 1e6,
      MOhm: 1e6,
      megohm: 1e6,
      Megohm: 1e6,
      GΩ: 1e9,
      Gohm: 1e9,
      GOhm: 1e9,
      TΩ: 1000000000000,
      Tohm: 1000000000000,
      TOhm: 1000000000000
    }
  },
  V: {
    baseUnit: "V",
    variants: {
      mV: 0.001,
      V: 1,
      kV: 1000,
      KV: 1000,
      MV: 1e6,
      GV: 1e9,
      TV: 1000000000000
    }
  },
  A: {
    baseUnit: "A",
    variants: {
      µA: 0.000001,
      mA: 0.001,
      ma: 0.001,
      A: 1,
      kA: 1000,
      MA: 1e6
    }
  },
  F: {
    baseUnit: "F",
    variants: {
      pF: 0.000000000001,
      nF: 0.000000001,
      µF: 0.000001,
      uF: 0.000001,
      mF: 0.001,
      F: 1,
      kF: 1000,
      KF: 1000,
      MF: 1e6
    }
  },
  H: {
    baseUnit: "H",
    variants: {
      pH: 0.000000000001,
      nH: 0.000000001,
      µH: 0.000001,
      uH: 0.000001,
      mH: 0.001,
      H: 1,
      kH: 1000,
      KH: 1000,
      MH: 1e6
    }
  },
  ml: {
    baseUnit: "ml",
    variants: {
      ml: 1,
      mL: 1,
      l: 1000,
      L: 1000
    }
  },
  deg: {
    baseUnit: "deg",
    variants: {
      rad: 180 / Math.PI
    }
  },
  ms: {
    baseUnit: "ms",
    variants: {
      fs: 0.000000000001,
      ps: 0.000000001,
      ns: 0.000001,
      us: 0.001,
      µs: 0.001,
      ms: 1,
      s: 1000
    }
  },
  mm: {
    baseUnit: "mm",
    variants: {
      nm: 0.000001,
      µm: 0.001,
      um: 0.001,
      mm: 1,
      cm: 10,
      dm: 100,
      m: 1000,
      km: 1e6,
      in: 25.4,
      ft: 304.8,
      IN: 25.4,
      FT: 304.8,
      yd: 914.4,
      mi: 1609344,
      mil: 0.0254
    }
  }
};
var unitMappingAndVariantSuffixes = /* @__PURE__ */ new Set;
for (const [baseUnit, info] of Object.entries(unitMappings)) {
  unitMappingAndVariantSuffixes.add(baseUnit);
  for (const variant of Object.keys(info.variants)) {
    unitMappingAndVariantSuffixes.add(variant);
  }
}
function getBaseTscircuitUnit(unit) {
  for (const info of Object.values(unitMappings)) {
    if (unit in info.variants) {
      return {
        baseUnit: info.baseUnit,
        conversionFactor: info.variants[unit]
      };
    }
    for (const [variant, conversionFactor] of Object.entries(info.variants)) {
      if (!unit.endsWith(variant))
        continue;
      const prefix = unit.slice(0, -variant.length);
      const prefixMultiplier = getSiPrefixMultiplier(prefix);
      if (prefixMultiplier == null)
        continue;
      return {
        baseUnit: info.baseUnit,
        conversionFactor: prefixMultiplier * conversionFactor
      };
    }
  }
  return {
    baseUnit: unit,
    conversionFactor: 1
  };
}
function parseAndConvertSiUnit(v, unitOfValue) {
  if (v === undefined || v === null)
    return { parsedUnit: null, unitOfValue: null, value: null };
  if (typeof v === "string" && v.match(/^-?[\d.]+$/))
    return {
      value: Number.parseFloat(v),
      parsedUnit: null,
      unitOfValue: null
    };
  if (typeof v === "number")
    return { value: v, parsedUnit: null, unitOfValue: null };
  if (typeof v === "object" && "x" in v && "y" in v) {
    const firstResult = parseAndConvertSiUnit(v.x, unitOfValue);
    const xResult = parseAndConvertSiUnit(v.x, unitOfValue);
    const yResult = parseAndConvertSiUnit(v.y, unitOfValue);
    if (xResult.value === null || yResult.value === null) {
      return { parsedUnit: null, unitOfValue: null, value: null };
    }
    return {
      parsedUnit: firstResult.parsedUnit,
      unitOfValue: firstResult.unitOfValue,
      value: {
        x: xResult.value,
        y: yResult.value
      }
    };
  }
  const reversedInputString = v.toString().split("").reverse().join("");
  const unitReversed = reversedInputString.match(/[^\d\s]+/)?.[0];
  if (!unitReversed) {
    throw new Error(`Could not determine unit: "${v}"`);
  }
  const unit = unitReversed.split("").reverse().join("");
  const numberPart = v.slice(0, -unit.length);
  const bareSiPrefixMultiplier = getSiPrefixMultiplier(unit);
  if (unitOfValue && bareSiPrefixMultiplier != null) {
    return {
      parsedUnit: null,
      unitOfValue,
      value: Number.parseFloat(numberPart) * bareSiPrefixMultiplier
    };
  }
  if (bareSiPrefixMultiplier != null && !unitMappingAndVariantSuffixes.has(unit)) {
    return {
      parsedUnit: null,
      unitOfValue: null,
      value: Number.parseFloat(numberPart) * bareSiPrefixMultiplier
    };
  }
  const { baseUnit, conversionFactor } = getBaseTscircuitUnit(unit);
  return {
    parsedUnit: unit,
    unitOfValue: baseUnit,
    value: conversionFactor * Number.parseFloat(numberPart)
  };
}
var SI_PREFIX_PATTERN = SI_PREFIXES.filter((prefix) => prefix !== "").sort((a, b) => b.length - a.length).map((prefix) => prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
var SI_UNIT_PATTERN = new RegExp(`^([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)(?:(${SI_PREFIX_PATTERN}))?$`);
var SI_PREFIXES2 = [
  { value: 1000000000000, symbol: "T" },
  { value: 1e9, symbol: "G" },
  { value: 1e6, symbol: "M" },
  { value: 1000, symbol: "k" },
  { value: 1, symbol: "" },
  { value: 0.001, symbol: "m" },
  { value: 0.000001, symbol: "µ" },
  { value: 0.000000001, symbol: "n" },
  { value: 0.000000000001, symbol: "p" }
];
var FALLBACK_PREFIX = SI_PREFIXES2[SI_PREFIXES2.length - 1];

// ../../work/placement-analysis/node_modules/zod/v3/external.js
var exports_external = {};
__export(exports_external, {
  void: () => voidType,
  util: () => util,
  unknown: () => unknownType,
  union: () => unionType,
  undefined: () => undefinedType,
  tuple: () => tupleType,
  transformer: () => effectsType,
  symbol: () => symbolType,
  string: () => stringType,
  strictObject: () => strictObjectType,
  setErrorMap: () => setErrorMap,
  set: () => setType,
  record: () => recordType,
  quotelessJson: () => quotelessJson,
  promise: () => promiseType,
  preprocess: () => preprocessType,
  pipeline: () => pipelineType,
  ostring: () => ostring,
  optional: () => optionalType,
  onumber: () => onumber,
  oboolean: () => oboolean,
  objectUtil: () => objectUtil,
  object: () => objectType,
  number: () => numberType,
  nullable: () => nullableType,
  null: () => nullType,
  never: () => neverType,
  nativeEnum: () => nativeEnumType,
  nan: () => nanType,
  map: () => mapType,
  makeIssue: () => makeIssue,
  literal: () => literalType,
  lazy: () => lazyType,
  late: () => late,
  isValid: () => isValid,
  isDirty: () => isDirty,
  isAsync: () => isAsync,
  isAborted: () => isAborted,
  intersection: () => intersectionType,
  instanceof: () => instanceOfType,
  getParsedType: () => getParsedType,
  getErrorMap: () => getErrorMap,
  function: () => functionType,
  enum: () => enumType,
  effect: () => effectsType,
  discriminatedUnion: () => discriminatedUnionType,
  defaultErrorMap: () => en_default,
  datetimeRegex: () => datetimeRegex,
  date: () => dateType,
  custom: () => custom,
  coerce: () => coerce,
  boolean: () => booleanType,
  bigint: () => bigIntType,
  array: () => arrayType,
  any: () => anyType,
  addIssueToContext: () => addIssueToContext,
  ZodVoid: () => ZodVoid,
  ZodUnknown: () => ZodUnknown,
  ZodUnion: () => ZodUnion,
  ZodUndefined: () => ZodUndefined,
  ZodType: () => ZodType,
  ZodTuple: () => ZodTuple,
  ZodTransformer: () => ZodEffects,
  ZodSymbol: () => ZodSymbol,
  ZodString: () => ZodString,
  ZodSet: () => ZodSet,
  ZodSchema: () => ZodType,
  ZodRecord: () => ZodRecord,
  ZodReadonly: () => ZodReadonly,
  ZodPromise: () => ZodPromise,
  ZodPipeline: () => ZodPipeline,
  ZodParsedType: () => ZodParsedType,
  ZodOptional: () => ZodOptional,
  ZodObject: () => ZodObject,
  ZodNumber: () => ZodNumber,
  ZodNullable: () => ZodNullable,
  ZodNull: () => ZodNull,
  ZodNever: () => ZodNever,
  ZodNativeEnum: () => ZodNativeEnum,
  ZodNaN: () => ZodNaN,
  ZodMap: () => ZodMap,
  ZodLiteral: () => ZodLiteral,
  ZodLazy: () => ZodLazy,
  ZodIssueCode: () => ZodIssueCode,
  ZodIntersection: () => ZodIntersection,
  ZodFunction: () => ZodFunction,
  ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
  ZodError: () => ZodError,
  ZodEnum: () => ZodEnum,
  ZodEffects: () => ZodEffects,
  ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
  ZodDefault: () => ZodDefault,
  ZodDate: () => ZodDate,
  ZodCatch: () => ZodCatch,
  ZodBranded: () => ZodBranded,
  ZodBoolean: () => ZodBoolean,
  ZodBigInt: () => ZodBigInt,
  ZodArray: () => ZodArray,
  ZodAny: () => ZodAny,
  Schema: () => ZodType,
  ParseStatus: () => ParseStatus,
  OK: () => OK,
  NEVER: () => NEVER,
  INVALID: () => INVALID,
  EMPTY_PATH: () => EMPTY_PATH,
  DIRTY: () => DIRTY,
  BRAND: () => BRAND
});

// ../../work/placement-analysis/node_modules/zod/v3/helpers/util.js
var util;
(function(util2) {
  util2.assertEqual = (_) => {};
  function assertIs(_arg) {}
  util2.assertIs = assertIs;
  function assertNever(_x) {
    throw new Error;
  }
  util2.assertNever = assertNever;
  util2.arrayToEnum = (items) => {
    const obj = {};
    for (const item of items) {
      obj[item] = item;
    }
    return obj;
  };
  util2.getValidEnumValues = (obj) => {
    const validKeys = util2.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
    const filtered = {};
    for (const k of validKeys) {
      filtered[k] = obj[k];
    }
    return util2.objectValues(filtered);
  };
  util2.objectValues = (obj) => {
    return util2.objectKeys(obj).map(function(e) {
      return obj[e];
    });
  };
  util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
    const keys = [];
    for (const key in object) {
      if (Object.prototype.hasOwnProperty.call(object, key)) {
        keys.push(key);
      }
    }
    return keys;
  };
  util2.find = (arr, checker) => {
    for (const item of arr) {
      if (checker(item))
        return item;
    }
    return;
  };
  util2.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
  function joinValues(array, separator = " | ") {
    return array.map((val) => typeof val === "string" ? `'${val}'` : val).join(separator);
  }
  util2.joinValues = joinValues;
  util2.jsonStringifyReplacer = (_, value) => {
    if (typeof value === "bigint") {
      return value.toString();
    }
    return value;
  };
})(util || (util = {}));
var objectUtil;
(function(objectUtil2) {
  objectUtil2.mergeShapes = (first, second) => {
    return {
      ...first,
      ...second
    };
  };
})(objectUtil || (objectUtil = {}));
var ZodParsedType = util.arrayToEnum([
  "string",
  "nan",
  "number",
  "integer",
  "float",
  "boolean",
  "date",
  "bigint",
  "symbol",
  "function",
  "undefined",
  "null",
  "array",
  "object",
  "unknown",
  "promise",
  "void",
  "never",
  "map",
  "set"
]);
var getParsedType = (data) => {
  const t = typeof data;
  switch (t) {
    case "undefined":
      return ZodParsedType.undefined;
    case "string":
      return ZodParsedType.string;
    case "number":
      return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
    case "boolean":
      return ZodParsedType.boolean;
    case "function":
      return ZodParsedType.function;
    case "bigint":
      return ZodParsedType.bigint;
    case "symbol":
      return ZodParsedType.symbol;
    case "object":
      if (Array.isArray(data)) {
        return ZodParsedType.array;
      }
      if (data === null) {
        return ZodParsedType.null;
      }
      if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
        return ZodParsedType.promise;
      }
      if (typeof Map !== "undefined" && data instanceof Map) {
        return ZodParsedType.map;
      }
      if (typeof Set !== "undefined" && data instanceof Set) {
        return ZodParsedType.set;
      }
      if (typeof Date !== "undefined" && data instanceof Date) {
        return ZodParsedType.date;
      }
      return ZodParsedType.object;
    default:
      return ZodParsedType.unknown;
  }
};

// ../../work/placement-analysis/node_modules/zod/v3/ZodError.js
var ZodIssueCode = util.arrayToEnum([
  "invalid_type",
  "invalid_literal",
  "custom",
  "invalid_union",
  "invalid_union_discriminator",
  "invalid_enum_value",
  "unrecognized_keys",
  "invalid_arguments",
  "invalid_return_type",
  "invalid_date",
  "invalid_string",
  "too_small",
  "too_big",
  "invalid_intersection_types",
  "not_multiple_of",
  "not_finite"
]);
var quotelessJson = (obj) => {
  const json = JSON.stringify(obj, null, 2);
  return json.replace(/"([^"]+)":/g, "$1:");
};

class ZodError extends Error {
  get errors() {
    return this.issues;
  }
  constructor(issues) {
    super();
    this.issues = [];
    this.addIssue = (sub) => {
      this.issues = [...this.issues, sub];
    };
    this.addIssues = (subs = []) => {
      this.issues = [...this.issues, ...subs];
    };
    const actualProto = new.target.prototype;
    if (Object.setPrototypeOf) {
      Object.setPrototypeOf(this, actualProto);
    } else {
      this.__proto__ = actualProto;
    }
    this.name = "ZodError";
    this.issues = issues;
  }
  format(_mapper) {
    const mapper = _mapper || function(issue) {
      return issue.message;
    };
    const fieldErrors = { _errors: [] };
    const processError = (error) => {
      for (const issue of error.issues) {
        if (issue.code === "invalid_union") {
          issue.unionErrors.map(processError);
        } else if (issue.code === "invalid_return_type") {
          processError(issue.returnTypeError);
        } else if (issue.code === "invalid_arguments") {
          processError(issue.argumentsError);
        } else if (issue.path.length === 0) {
          fieldErrors._errors.push(mapper(issue));
        } else {
          let curr = fieldErrors;
          let i = 0;
          while (i < issue.path.length) {
            const el = issue.path[i];
            const terminal = i === issue.path.length - 1;
            if (!terminal) {
              curr[el] = curr[el] || { _errors: [] };
            } else {
              curr[el] = curr[el] || { _errors: [] };
              curr[el]._errors.push(mapper(issue));
            }
            curr = curr[el];
            i++;
          }
        }
      }
    };
    processError(this);
    return fieldErrors;
  }
  static assert(value) {
    if (!(value instanceof ZodError)) {
      throw new Error(`Not a ZodError: ${value}`);
    }
  }
  toString() {
    return this.message;
  }
  get message() {
    return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
  }
  get isEmpty() {
    return this.issues.length === 0;
  }
  flatten(mapper = (issue) => issue.message) {
    const fieldErrors = {};
    const formErrors = [];
    for (const sub of this.issues) {
      if (sub.path.length > 0) {
        const firstEl = sub.path[0];
        fieldErrors[firstEl] = fieldErrors[firstEl] || [];
        fieldErrors[firstEl].push(mapper(sub));
      } else {
        formErrors.push(mapper(sub));
      }
    }
    return { formErrors, fieldErrors };
  }
  get formErrors() {
    return this.flatten();
  }
}
ZodError.create = (issues) => {
  const error = new ZodError(issues);
  return error;
};

// ../../work/placement-analysis/node_modules/zod/v3/locales/en.js
var errorMap = (issue, _ctx) => {
  let message;
  switch (issue.code) {
    case ZodIssueCode.invalid_type:
      if (issue.received === ZodParsedType.undefined) {
        message = "Required";
      } else {
        message = `Expected ${issue.expected}, received ${issue.received}`;
      }
      break;
    case ZodIssueCode.invalid_literal:
      message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
      break;
    case ZodIssueCode.unrecognized_keys:
      message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
      break;
    case ZodIssueCode.invalid_union:
      message = `Invalid input`;
      break;
    case ZodIssueCode.invalid_union_discriminator:
      message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
      break;
    case ZodIssueCode.invalid_enum_value:
      message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
      break;
    case ZodIssueCode.invalid_arguments:
      message = `Invalid function arguments`;
      break;
    case ZodIssueCode.invalid_return_type:
      message = `Invalid function return type`;
      break;
    case ZodIssueCode.invalid_date:
      message = `Invalid date`;
      break;
    case ZodIssueCode.invalid_string:
      if (typeof issue.validation === "object") {
        if ("includes" in issue.validation) {
          message = `Invalid input: must include "${issue.validation.includes}"`;
          if (typeof issue.validation.position === "number") {
            message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
          }
        } else if ("startsWith" in issue.validation) {
          message = `Invalid input: must start with "${issue.validation.startsWith}"`;
        } else if ("endsWith" in issue.validation) {
          message = `Invalid input: must end with "${issue.validation.endsWith}"`;
        } else {
          util.assertNever(issue.validation);
        }
      } else if (issue.validation !== "regex") {
        message = `Invalid ${issue.validation}`;
      } else {
        message = "Invalid";
      }
      break;
    case ZodIssueCode.too_small:
      if (issue.type === "array")
        message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;
      else if (issue.type === "string")
        message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
      else if (issue.type === "number")
        message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
      else if (issue.type === "bigint")
        message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
      else if (issue.type === "date")
        message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
      else
        message = "Invalid input";
      break;
    case ZodIssueCode.too_big:
      if (issue.type === "array")
        message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;
      else if (issue.type === "string")
        message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
      else if (issue.type === "number")
        message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
      else if (issue.type === "bigint")
        message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
      else if (issue.type === "date")
        message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
      else
        message = "Invalid input";
      break;
    case ZodIssueCode.custom:
      message = `Invalid input`;
      break;
    case ZodIssueCode.invalid_intersection_types:
      message = `Intersection results could not be merged`;
      break;
    case ZodIssueCode.not_multiple_of:
      message = `Number must be a multiple of ${issue.multipleOf}`;
      break;
    case ZodIssueCode.not_finite:
      message = "Number must be finite";
      break;
    default:
      message = _ctx.defaultError;
      util.assertNever(issue);
  }
  return { message };
};
var en_default = errorMap;

// ../../work/placement-analysis/node_modules/zod/v3/errors.js
var overrideErrorMap = en_default;
function setErrorMap(map) {
  overrideErrorMap = map;
}
function getErrorMap() {
  return overrideErrorMap;
}
// ../../work/placement-analysis/node_modules/zod/v3/helpers/parseUtil.js
var makeIssue = (params) => {
  const { data, path, errorMaps, issueData } = params;
  const fullPath = [...path, ...issueData.path || []];
  const fullIssue = {
    ...issueData,
    path: fullPath
  };
  if (issueData.message !== undefined) {
    return {
      ...issueData,
      path: fullPath,
      message: issueData.message
    };
  }
  let errorMessage = "";
  const maps = errorMaps.filter((m) => !!m).slice().reverse();
  for (const map of maps) {
    errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
  }
  return {
    ...issueData,
    path: fullPath,
    message: errorMessage
  };
};
var EMPTY_PATH = [];
function addIssueToContext(ctx, issueData) {
  const overrideMap = getErrorMap();
  const issue = makeIssue({
    issueData,
    data: ctx.data,
    path: ctx.path,
    errorMaps: [
      ctx.common.contextualErrorMap,
      ctx.schemaErrorMap,
      overrideMap,
      overrideMap === en_default ? undefined : en_default
    ].filter((x) => !!x)
  });
  ctx.common.issues.push(issue);
}

class ParseStatus {
  constructor() {
    this.value = "valid";
  }
  dirty() {
    if (this.value === "valid")
      this.value = "dirty";
  }
  abort() {
    if (this.value !== "aborted")
      this.value = "aborted";
  }
  static mergeArray(status, results) {
    const arrayValue = [];
    for (const s of results) {
      if (s.status === "aborted")
        return INVALID;
      if (s.status === "dirty")
        status.dirty();
      arrayValue.push(s.value);
    }
    return { status: status.value, value: arrayValue };
  }
  static async mergeObjectAsync(status, pairs) {
    const syncPairs = [];
    for (const pair of pairs) {
      const key = await pair.key;
      const value = await pair.value;
      syncPairs.push({
        key,
        value
      });
    }
    return ParseStatus.mergeObjectSync(status, syncPairs);
  }
  static mergeObjectSync(status, pairs) {
    const finalObject = {};
    for (const pair of pairs) {
      const { key, value } = pair;
      if (key.status === "aborted")
        return INVALID;
      if (value.status === "aborted")
        return INVALID;
      if (key.status === "dirty")
        status.dirty();
      if (value.status === "dirty")
        status.dirty();
      if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
        finalObject[key.value] = value.value;
      }
    }
    return { status: status.value, value: finalObject };
  }
}
var INVALID = Object.freeze({
  status: "aborted"
});
var DIRTY = (value) => ({ status: "dirty", value });
var OK = (value) => ({ status: "valid", value });
var isAborted = (x) => x.status === "aborted";
var isDirty = (x) => x.status === "dirty";
var isValid = (x) => x.status === "valid";
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
// ../../work/placement-analysis/node_modules/zod/v3/helpers/errorUtil.js
var errorUtil;
(function(errorUtil2) {
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
})(errorUtil || (errorUtil = {}));

// ../../work/placement-analysis/node_modules/zod/v3/types.js
class ParseInputLazyPath {
  constructor(parent, value, path, key) {
    this._cachedPath = [];
    this.parent = parent;
    this.data = value;
    this._path = path;
    this._key = key;
  }
  get path() {
    if (!this._cachedPath.length) {
      if (Array.isArray(this._key)) {
        this._cachedPath.push(...this._path, ...this._key);
      } else {
        this._cachedPath.push(...this._path, this._key);
      }
    }
    return this._cachedPath;
  }
}
var handleResult = (ctx, result) => {
  if (isValid(result)) {
    return { success: true, data: result.value };
  } else {
    if (!ctx.common.issues.length) {
      throw new Error("Validation failed but no issues detected.");
    }
    return {
      success: false,
      get error() {
        if (this._error)
          return this._error;
        const error = new ZodError(ctx.common.issues);
        this._error = error;
        return this._error;
      }
    };
  }
};
function processCreateParams(params) {
  if (!params)
    return {};
  const { errorMap: errorMap2, invalid_type_error, required_error, description } = params;
  if (errorMap2 && (invalid_type_error || required_error)) {
    throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);
  }
  if (errorMap2)
    return { errorMap: errorMap2, description };
  const customMap = (iss, ctx) => {
    const { message } = params;
    if (iss.code === "invalid_enum_value") {
      return { message: message ?? ctx.defaultError };
    }
    if (typeof ctx.data === "undefined") {
      return { message: message ?? required_error ?? ctx.defaultError };
    }
    if (iss.code !== "invalid_type")
      return { message: ctx.defaultError };
    return { message: message ?? invalid_type_error ?? ctx.defaultError };
  };
  return { errorMap: customMap, description };
}

class ZodType {
  get description() {
    return this._def.description;
  }
  _getType(input) {
    return getParsedType(input.data);
  }
  _getOrReturnCtx(input, ctx) {
    return ctx || {
      common: input.parent.common,
      data: input.data,
      parsedType: getParsedType(input.data),
      schemaErrorMap: this._def.errorMap,
      path: input.path,
      parent: input.parent
    };
  }
  _processInputParams(input) {
    return {
      status: new ParseStatus,
      ctx: {
        common: input.parent.common,
        data: input.data,
        parsedType: getParsedType(input.data),
        schemaErrorMap: this._def.errorMap,
        path: input.path,
        parent: input.parent
      }
    };
  }
  _parseSync(input) {
    const result = this._parse(input);
    if (isAsync(result)) {
      throw new Error("Synchronous parse encountered promise.");
    }
    return result;
  }
  _parseAsync(input) {
    const result = this._parse(input);
    return Promise.resolve(result);
  }
  parse(data, params) {
    const result = this.safeParse(data, params);
    if (result.success)
      return result.data;
    throw result.error;
  }
  safeParse(data, params) {
    const ctx = {
      common: {
        issues: [],
        async: params?.async ?? false,
        contextualErrorMap: params?.errorMap
      },
      path: params?.path || [],
      schemaErrorMap: this._def.errorMap,
      parent: null,
      data,
      parsedType: getParsedType(data)
    };
    const result = this._parseSync({ data, path: ctx.path, parent: ctx });
    return handleResult(ctx, result);
  }
  "~validate"(data) {
    const ctx = {
      common: {
        issues: [],
        async: !!this["~standard"].async
      },
      path: [],
      schemaErrorMap: this._def.errorMap,
      parent: null,
      data,
      parsedType: getParsedType(data)
    };
    if (!this["~standard"].async) {
      try {
        const result = this._parseSync({ data, path: [], parent: ctx });
        return isValid(result) ? {
          value: result.value
        } : {
          issues: ctx.common.issues
        };
      } catch (err) {
        if (err?.message?.toLowerCase()?.includes("encountered")) {
          this["~standard"].async = true;
        }
        ctx.common = {
          issues: [],
          async: true
        };
      }
    }
    return this._parseAsync({ data, path: [], parent: ctx }).then((result) => isValid(result) ? {
      value: result.value
    } : {
      issues: ctx.common.issues
    });
  }
  async parseAsync(data, params) {
    const result = await this.safeParseAsync(data, params);
    if (result.success)
      return result.data;
    throw result.error;
  }
  async safeParseAsync(data, params) {
    const ctx = {
      common: {
        issues: [],
        contextualErrorMap: params?.errorMap,
        async: true
      },
      path: params?.path || [],
      schemaErrorMap: this._def.errorMap,
      parent: null,
      data,
      parsedType: getParsedType(data)
    };
    const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });
    const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
    return handleResult(ctx, result);
  }
  refine(check, message) {
    const getIssueProperties = (val) => {
      if (typeof message === "string" || typeof message === "undefined") {
        return { message };
      } else if (typeof message === "function") {
        return message(val);
      } else {
        return message;
      }
    };
    return this._refinement((val, ctx) => {
      const result = check(val);
      const setError = () => ctx.addIssue({
        code: ZodIssueCode.custom,
        ...getIssueProperties(val)
      });
      if (typeof Promise !== "undefined" && result instanceof Promise) {
        return result.then((data) => {
          if (!data) {
            setError();
            return false;
          } else {
            return true;
          }
        });
      }
      if (!result) {
        setError();
        return false;
      } else {
        return true;
      }
    });
  }
  refinement(check, refinementData) {
    return this._refinement((val, ctx) => {
      if (!check(val)) {
        ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData);
        return false;
      } else {
        return true;
      }
    });
  }
  _refinement(refinement) {
    return new ZodEffects({
      schema: this,
      typeName: ZodFirstPartyTypeKind.ZodEffects,
      effect: { type: "refinement", refinement }
    });
  }
  superRefine(refinement) {
    return this._refinement(refinement);
  }
  constructor(def) {
    this.spa = this.safeParseAsync;
    this._def = def;
    this.parse = this.parse.bind(this);
    this.safeParse = this.safeParse.bind(this);
    this.parseAsync = this.parseAsync.bind(this);
    this.safeParseAsync = this.safeParseAsync.bind(this);
    this.spa = this.spa.bind(this);
    this.refine = this.refine.bind(this);
    this.refinement = this.refinement.bind(this);
    this.superRefine = this.superRefine.bind(this);
    this.optional = this.optional.bind(this);
    this.nullable = this.nullable.bind(this);
    this.nullish = this.nullish.bind(this);
    this.array = this.array.bind(this);
    this.promise = this.promise.bind(this);
    this.or = this.or.bind(this);
    this.and = this.and.bind(this);
    this.transform = this.transform.bind(this);
    this.brand = this.brand.bind(this);
    this.default = this.default.bind(this);
    this.catch = this.catch.bind(this);
    this.describe = this.describe.bind(this);
    this.pipe = this.pipe.bind(this);
    this.readonly = this.readonly.bind(this);
    this.isNullable = this.isNullable.bind(this);
    this.isOptional = this.isOptional.bind(this);
    this["~standard"] = {
      version: 1,
      vendor: "zod",
      validate: (data) => this["~validate"](data)
    };
  }
  optional() {
    return ZodOptional.create(this, this._def);
  }
  nullable() {
    return ZodNullable.create(this, this._def);
  }
  nullish() {
    return this.nullable().optional();
  }
  array() {
    return ZodArray.create(this);
  }
  promise() {
    return ZodPromise.create(this, this._def);
  }
  or(option) {
    return ZodUnion.create([this, option], this._def);
  }
  and(incoming) {
    return ZodIntersection.create(this, incoming, this._def);
  }
  transform(transform3) {
    return new ZodEffects({
      ...processCreateParams(this._def),
      schema: this,
      typeName: ZodFirstPartyTypeKind.ZodEffects,
      effect: { type: "transform", transform: transform3 }
    });
  }
  default(def) {
    const defaultValueFunc = typeof def === "function" ? def : () => def;
    return new ZodDefault({
      ...processCreateParams(this._def),
      innerType: this,
      defaultValue: defaultValueFunc,
      typeName: ZodFirstPartyTypeKind.ZodDefault
    });
  }
  brand() {
    return new ZodBranded({
      typeName: ZodFirstPartyTypeKind.ZodBranded,
      type: this,
      ...processCreateParams(this._def)
    });
  }
  catch(def) {
    const catchValueFunc = typeof def === "function" ? def : () => def;
    return new ZodCatch({
      ...processCreateParams(this._def),
      innerType: this,
      catchValue: catchValueFunc,
      typeName: ZodFirstPartyTypeKind.ZodCatch
    });
  }
  describe(description) {
    const This = this.constructor;
    return new This({
      ...this._def,
      description
    });
  }
  pipe(target) {
    return ZodPipeline.create(this, target);
  }
  readonly() {
    return ZodReadonly.create(this);
  }
  isOptional() {
    return this.safeParse(undefined).success;
  }
  isNullable() {
    return this.safeParse(null).success;
  }
}
var cuidRegex = /^c[^\s-]{8,}$/i;
var cuid2Regex = /^[0-9a-z]+$/;
var ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
var uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
var nanoidRegex = /^[a-z0-9_-]{21}$/i;
var jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/;
var durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
var emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i;
var _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
var emojiRegex;
var ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
var ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/;
var ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
var ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
var base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;
var dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
var dateRegex = new RegExp(`^${dateRegexSource}$`);
function timeRegexSource(args) {
  let secondsRegexSource = `[0-5]\\d`;
  if (args.precision) {
    secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`;
  } else if (args.precision == null) {
    secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
  }
  const secondsQuantifier = args.precision ? "+" : "?";
  return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
}
function timeRegex(args) {
  return new RegExp(`^${timeRegexSource(args)}$`);
}
function datetimeRegex(args) {
  let regex = `${dateRegexSource}T${timeRegexSource(args)}`;
  const opts = [];
  opts.push(args.local ? `Z?` : `Z`);
  if (args.offset)
    opts.push(`([+-]\\d{2}:?\\d{2})`);
  regex = `${regex}(${opts.join("|")})`;
  return new RegExp(`^${regex}$`);
}
function isValidIP(ip, version) {
  if ((version === "v4" || !version) && ipv4Regex.test(ip)) {
    return true;
  }
  if ((version === "v6" || !version) && ipv6Regex.test(ip)) {
    return true;
  }
  return false;
}
function isValidJWT(jwt, alg) {
  if (!jwtRegex.test(jwt))
    return false;
  try {
    const [header] = jwt.split(".");
    if (!header)
      return false;
    const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
    const decoded = JSON.parse(atob(base64));
    if (typeof decoded !== "object" || decoded === null)
      return false;
    if ("typ" in decoded && decoded?.typ !== "JWT")
      return false;
    if (!decoded.alg)
      return false;
    if (alg && decoded.alg !== alg)
      return false;
    return true;
  } catch {
    return false;
  }
}
function isValidCidr(ip, version) {
  if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) {
    return true;
  }
  if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) {
    return true;
  }
  return false;
}

class ZodString extends ZodType {
  _parse(input) {
    if (this._def.coerce) {
      input.data = String(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.string) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.string,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const status = new ParseStatus;
    let ctx = undefined;
    for (const check of this._def.checks) {
      if (check.kind === "min") {
        if (input.data.length < check.value) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_small,
            minimum: check.value,
            type: "string",
            inclusive: true,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        if (input.data.length > check.value) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_big,
            maximum: check.value,
            type: "string",
            inclusive: true,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "length") {
        const tooBig = input.data.length > check.value;
        const tooSmall = input.data.length < check.value;
        if (tooBig || tooSmall) {
          ctx = this._getOrReturnCtx(input, ctx);
          if (tooBig) {
            addIssueToContext(ctx, {
              code: ZodIssueCode.too_big,
              maximum: check.value,
              type: "string",
              inclusive: true,
              exact: true,
              message: check.message
            });
          } else if (tooSmall) {
            addIssueToContext(ctx, {
              code: ZodIssueCode.too_small,
              minimum: check.value,
              type: "string",
              inclusive: true,
              exact: true,
              message: check.message
            });
          }
          status.dirty();
        }
      } else if (check.kind === "email") {
        if (!emailRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "email",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "emoji") {
        if (!emojiRegex) {
          emojiRegex = new RegExp(_emojiRegex, "u");
        }
        if (!emojiRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "emoji",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "uuid") {
        if (!uuidRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "uuid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "nanoid") {
        if (!nanoidRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "nanoid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "cuid") {
        if (!cuidRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "cuid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "cuid2") {
        if (!cuid2Regex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "cuid2",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "ulid") {
        if (!ulidRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "ulid",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "url") {
        try {
          new URL(input.data);
        } catch {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "url",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "regex") {
        check.regex.lastIndex = 0;
        const testResult = check.regex.test(input.data);
        if (!testResult) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "regex",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "trim") {
        input.data = input.data.trim();
      } else if (check.kind === "includes") {
        if (!input.data.includes(check.value, check.position)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_string,
            validation: { includes: check.value, position: check.position },
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "toLowerCase") {
        input.data = input.data.toLowerCase();
      } else if (check.kind === "toUpperCase") {
        input.data = input.data.toUpperCase();
      } else if (check.kind === "startsWith") {
        if (!input.data.startsWith(check.value)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_string,
            validation: { startsWith: check.value },
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "endsWith") {
        if (!input.data.endsWith(check.value)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_string,
            validation: { endsWith: check.value },
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "datetime") {
        const regex = datetimeRegex(check);
        if (!regex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_string,
            validation: "datetime",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "date") {
        const regex = dateRegex;
        if (!regex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_string,
            validation: "date",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "time") {
        const regex = timeRegex(check);
        if (!regex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_string,
            validation: "time",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "duration") {
        if (!durationRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "duration",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "ip") {
        if (!isValidIP(input.data, check.version)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "ip",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "jwt") {
        if (!isValidJWT(input.data, check.alg)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "jwt",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "cidr") {
        if (!isValidCidr(input.data, check.version)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "cidr",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "base64") {
        if (!base64Regex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "base64",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "base64url") {
        if (!base64urlRegex.test(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            validation: "base64url",
            code: ZodIssueCode.invalid_string,
            message: check.message
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return { status: status.value, value: input.data };
  }
  _regex(regex, validation, message) {
    return this.refinement((data) => regex.test(data), {
      validation,
      code: ZodIssueCode.invalid_string,
      ...errorUtil.errToObj(message)
    });
  }
  _addCheck(check) {
    return new ZodString({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  email(message) {
    return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) });
  }
  url(message) {
    return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) });
  }
  emoji(message) {
    return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) });
  }
  uuid(message) {
    return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) });
  }
  nanoid(message) {
    return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) });
  }
  cuid(message) {
    return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) });
  }
  cuid2(message) {
    return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) });
  }
  ulid(message) {
    return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) });
  }
  base64(message) {
    return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) });
  }
  base64url(message) {
    return this._addCheck({
      kind: "base64url",
      ...errorUtil.errToObj(message)
    });
  }
  jwt(options) {
    return this._addCheck({ kind: "jwt", ...errorUtil.errToObj(options) });
  }
  ip(options) {
    return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) });
  }
  cidr(options) {
    return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) });
  }
  datetime(options) {
    if (typeof options === "string") {
      return this._addCheck({
        kind: "datetime",
        precision: null,
        offset: false,
        local: false,
        message: options
      });
    }
    return this._addCheck({
      kind: "datetime",
      precision: typeof options?.precision === "undefined" ? null : options?.precision,
      offset: options?.offset ?? false,
      local: options?.local ?? false,
      ...errorUtil.errToObj(options?.message)
    });
  }
  date(message) {
    return this._addCheck({ kind: "date", message });
  }
  time(options) {
    if (typeof options === "string") {
      return this._addCheck({
        kind: "time",
        precision: null,
        message: options
      });
    }
    return this._addCheck({
      kind: "time",
      precision: typeof options?.precision === "undefined" ? null : options?.precision,
      ...errorUtil.errToObj(options?.message)
    });
  }
  duration(message) {
    return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) });
  }
  regex(regex, message) {
    return this._addCheck({
      kind: "regex",
      regex,
      ...errorUtil.errToObj(message)
    });
  }
  includes(value, options) {
    return this._addCheck({
      kind: "includes",
      value,
      position: options?.position,
      ...errorUtil.errToObj(options?.message)
    });
  }
  startsWith(value, message) {
    return this._addCheck({
      kind: "startsWith",
      value,
      ...errorUtil.errToObj(message)
    });
  }
  endsWith(value, message) {
    return this._addCheck({
      kind: "endsWith",
      value,
      ...errorUtil.errToObj(message)
    });
  }
  min(minLength, message) {
    return this._addCheck({
      kind: "min",
      value: minLength,
      ...errorUtil.errToObj(message)
    });
  }
  max(maxLength, message) {
    return this._addCheck({
      kind: "max",
      value: maxLength,
      ...errorUtil.errToObj(message)
    });
  }
  length(len, message) {
    return this._addCheck({
      kind: "length",
      value: len,
      ...errorUtil.errToObj(message)
    });
  }
  nonempty(message) {
    return this.min(1, errorUtil.errToObj(message));
  }
  trim() {
    return new ZodString({
      ...this._def,
      checks: [...this._def.checks, { kind: "trim" }]
    });
  }
  toLowerCase() {
    return new ZodString({
      ...this._def,
      checks: [...this._def.checks, { kind: "toLowerCase" }]
    });
  }
  toUpperCase() {
    return new ZodString({
      ...this._def,
      checks: [...this._def.checks, { kind: "toUpperCase" }]
    });
  }
  get isDatetime() {
    return !!this._def.checks.find((ch) => ch.kind === "datetime");
  }
  get isDate() {
    return !!this._def.checks.find((ch) => ch.kind === "date");
  }
  get isTime() {
    return !!this._def.checks.find((ch) => ch.kind === "time");
  }
  get isDuration() {
    return !!this._def.checks.find((ch) => ch.kind === "duration");
  }
  get isEmail() {
    return !!this._def.checks.find((ch) => ch.kind === "email");
  }
  get isURL() {
    return !!this._def.checks.find((ch) => ch.kind === "url");
  }
  get isEmoji() {
    return !!this._def.checks.find((ch) => ch.kind === "emoji");
  }
  get isUUID() {
    return !!this._def.checks.find((ch) => ch.kind === "uuid");
  }
  get isNANOID() {
    return !!this._def.checks.find((ch) => ch.kind === "nanoid");
  }
  get isCUID() {
    return !!this._def.checks.find((ch) => ch.kind === "cuid");
  }
  get isCUID2() {
    return !!this._def.checks.find((ch) => ch.kind === "cuid2");
  }
  get isULID() {
    return !!this._def.checks.find((ch) => ch.kind === "ulid");
  }
  get isIP() {
    return !!this._def.checks.find((ch) => ch.kind === "ip");
  }
  get isCIDR() {
    return !!this._def.checks.find((ch) => ch.kind === "cidr");
  }
  get isBase64() {
    return !!this._def.checks.find((ch) => ch.kind === "base64");
  }
  get isBase64url() {
    return !!this._def.checks.find((ch) => ch.kind === "base64url");
  }
  get minLength() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min;
  }
  get maxLength() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max;
  }
}
ZodString.create = (params) => {
  return new ZodString({
    checks: [],
    typeName: ZodFirstPartyTypeKind.ZodString,
    coerce: params?.coerce ?? false,
    ...processCreateParams(params)
  });
};
function floatSafeRemainder(val, step) {
  const valDecCount = (val.toString().split(".")[1] || "").length;
  const stepDecCount = (step.toString().split(".")[1] || "").length;
  const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
  const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
  return valInt % stepInt / 10 ** decCount;
}

class ZodNumber extends ZodType {
  constructor() {
    super(...arguments);
    this.min = this.gte;
    this.max = this.lte;
    this.step = this.multipleOf;
  }
  _parse(input) {
    if (this._def.coerce) {
      input.data = Number(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.number) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.number,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    let ctx = undefined;
    const status = new ParseStatus;
    for (const check of this._def.checks) {
      if (check.kind === "int") {
        if (!util.isInteger(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.invalid_type,
            expected: "integer",
            received: "float",
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "min") {
        const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
        if (tooSmall) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_small,
            minimum: check.value,
            type: "number",
            inclusive: check.inclusive,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
        if (tooBig) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_big,
            maximum: check.value,
            type: "number",
            inclusive: check.inclusive,
            exact: false,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "multipleOf") {
        if (floatSafeRemainder(input.data, check.value) !== 0) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.not_multiple_of,
            multipleOf: check.value,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "finite") {
        if (!Number.isFinite(input.data)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.not_finite,
            message: check.message
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return { status: status.value, value: input.data };
  }
  gte(value, message) {
    return this.setLimit("min", value, true, errorUtil.toString(message));
  }
  gt(value, message) {
    return this.setLimit("min", value, false, errorUtil.toString(message));
  }
  lte(value, message) {
    return this.setLimit("max", value, true, errorUtil.toString(message));
  }
  lt(value, message) {
    return this.setLimit("max", value, false, errorUtil.toString(message));
  }
  setLimit(kind, value, inclusive, message) {
    return new ZodNumber({
      ...this._def,
      checks: [
        ...this._def.checks,
        {
          kind,
          value,
          inclusive,
          message: errorUtil.toString(message)
        }
      ]
    });
  }
  _addCheck(check) {
    return new ZodNumber({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  int(message) {
    return this._addCheck({
      kind: "int",
      message: errorUtil.toString(message)
    });
  }
  positive(message) {
    return this._addCheck({
      kind: "min",
      value: 0,
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  negative(message) {
    return this._addCheck({
      kind: "max",
      value: 0,
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  nonpositive(message) {
    return this._addCheck({
      kind: "max",
      value: 0,
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  nonnegative(message) {
    return this._addCheck({
      kind: "min",
      value: 0,
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  multipleOf(value, message) {
    return this._addCheck({
      kind: "multipleOf",
      value,
      message: errorUtil.toString(message)
    });
  }
  finite(message) {
    return this._addCheck({
      kind: "finite",
      message: errorUtil.toString(message)
    });
  }
  safe(message) {
    return this._addCheck({
      kind: "min",
      inclusive: true,
      value: Number.MIN_SAFE_INTEGER,
      message: errorUtil.toString(message)
    })._addCheck({
      kind: "max",
      inclusive: true,
      value: Number.MAX_SAFE_INTEGER,
      message: errorUtil.toString(message)
    });
  }
  get minValue() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min;
  }
  get maxValue() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max;
  }
  get isInt() {
    return !!this._def.checks.find((ch) => ch.kind === "int" || ch.kind === "multipleOf" && util.isInteger(ch.value));
  }
  get isFinite() {
    let max = null;
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") {
        return true;
      } else if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      } else if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return Number.isFinite(min) && Number.isFinite(max);
  }
}
ZodNumber.create = (params) => {
  return new ZodNumber({
    checks: [],
    typeName: ZodFirstPartyTypeKind.ZodNumber,
    coerce: params?.coerce || false,
    ...processCreateParams(params)
  });
};

class ZodBigInt extends ZodType {
  constructor() {
    super(...arguments);
    this.min = this.gte;
    this.max = this.lte;
  }
  _parse(input) {
    if (this._def.coerce) {
      try {
        input.data = BigInt(input.data);
      } catch {
        return this._getInvalidInput(input);
      }
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.bigint) {
      return this._getInvalidInput(input);
    }
    let ctx = undefined;
    const status = new ParseStatus;
    for (const check of this._def.checks) {
      if (check.kind === "min") {
        const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
        if (tooSmall) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_small,
            type: "bigint",
            minimum: check.value,
            inclusive: check.inclusive,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
        if (tooBig) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_big,
            type: "bigint",
            maximum: check.value,
            inclusive: check.inclusive,
            message: check.message
          });
          status.dirty();
        }
      } else if (check.kind === "multipleOf") {
        if (input.data % check.value !== BigInt(0)) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.not_multiple_of,
            multipleOf: check.value,
            message: check.message
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return { status: status.value, value: input.data };
  }
  _getInvalidInput(input) {
    const ctx = this._getOrReturnCtx(input);
    addIssueToContext(ctx, {
      code: ZodIssueCode.invalid_type,
      expected: ZodParsedType.bigint,
      received: ctx.parsedType
    });
    return INVALID;
  }
  gte(value, message) {
    return this.setLimit("min", value, true, errorUtil.toString(message));
  }
  gt(value, message) {
    return this.setLimit("min", value, false, errorUtil.toString(message));
  }
  lte(value, message) {
    return this.setLimit("max", value, true, errorUtil.toString(message));
  }
  lt(value, message) {
    return this.setLimit("max", value, false, errorUtil.toString(message));
  }
  setLimit(kind, value, inclusive, message) {
    return new ZodBigInt({
      ...this._def,
      checks: [
        ...this._def.checks,
        {
          kind,
          value,
          inclusive,
          message: errorUtil.toString(message)
        }
      ]
    });
  }
  _addCheck(check) {
    return new ZodBigInt({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  positive(message) {
    return this._addCheck({
      kind: "min",
      value: BigInt(0),
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  negative(message) {
    return this._addCheck({
      kind: "max",
      value: BigInt(0),
      inclusive: false,
      message: errorUtil.toString(message)
    });
  }
  nonpositive(message) {
    return this._addCheck({
      kind: "max",
      value: BigInt(0),
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  nonnegative(message) {
    return this._addCheck({
      kind: "min",
      value: BigInt(0),
      inclusive: true,
      message: errorUtil.toString(message)
    });
  }
  multipleOf(value, message) {
    return this._addCheck({
      kind: "multipleOf",
      value,
      message: errorUtil.toString(message)
    });
  }
  get minValue() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min;
  }
  get maxValue() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max;
  }
}
ZodBigInt.create = (params) => {
  return new ZodBigInt({
    checks: [],
    typeName: ZodFirstPartyTypeKind.ZodBigInt,
    coerce: params?.coerce ?? false,
    ...processCreateParams(params)
  });
};

class ZodBoolean extends ZodType {
  _parse(input) {
    if (this._def.coerce) {
      input.data = Boolean(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.boolean) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.boolean,
        received: ctx.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
}
ZodBoolean.create = (params) => {
  return new ZodBoolean({
    typeName: ZodFirstPartyTypeKind.ZodBoolean,
    coerce: params?.coerce || false,
    ...processCreateParams(params)
  });
};

class ZodDate extends ZodType {
  _parse(input) {
    if (this._def.coerce) {
      input.data = new Date(input.data);
    }
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.date) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.date,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    if (Number.isNaN(input.data.getTime())) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_date
      });
      return INVALID;
    }
    const status = new ParseStatus;
    let ctx = undefined;
    for (const check of this._def.checks) {
      if (check.kind === "min") {
        if (input.data.getTime() < check.value) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_small,
            message: check.message,
            inclusive: true,
            exact: false,
            minimum: check.value,
            type: "date"
          });
          status.dirty();
        }
      } else if (check.kind === "max") {
        if (input.data.getTime() > check.value) {
          ctx = this._getOrReturnCtx(input, ctx);
          addIssueToContext(ctx, {
            code: ZodIssueCode.too_big,
            message: check.message,
            inclusive: true,
            exact: false,
            maximum: check.value,
            type: "date"
          });
          status.dirty();
        }
      } else {
        util.assertNever(check);
      }
    }
    return {
      status: status.value,
      value: new Date(input.data.getTime())
    };
  }
  _addCheck(check) {
    return new ZodDate({
      ...this._def,
      checks: [...this._def.checks, check]
    });
  }
  min(minDate, message) {
    return this._addCheck({
      kind: "min",
      value: minDate.getTime(),
      message: errorUtil.toString(message)
    });
  }
  max(maxDate, message) {
    return this._addCheck({
      kind: "max",
      value: maxDate.getTime(),
      message: errorUtil.toString(message)
    });
  }
  get minDate() {
    let min = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "min") {
        if (min === null || ch.value > min)
          min = ch.value;
      }
    }
    return min != null ? new Date(min) : null;
  }
  get maxDate() {
    let max = null;
    for (const ch of this._def.checks) {
      if (ch.kind === "max") {
        if (max === null || ch.value < max)
          max = ch.value;
      }
    }
    return max != null ? new Date(max) : null;
  }
}
ZodDate.create = (params) => {
  return new ZodDate({
    checks: [],
    coerce: params?.coerce || false,
    typeName: ZodFirstPartyTypeKind.ZodDate,
    ...processCreateParams(params)
  });
};

class ZodSymbol extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.symbol) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.symbol,
        received: ctx.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
}
ZodSymbol.create = (params) => {
  return new ZodSymbol({
    typeName: ZodFirstPartyTypeKind.ZodSymbol,
    ...processCreateParams(params)
  });
};

class ZodUndefined extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.undefined) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.undefined,
        received: ctx.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
}
ZodUndefined.create = (params) => {
  return new ZodUndefined({
    typeName: ZodFirstPartyTypeKind.ZodUndefined,
    ...processCreateParams(params)
  });
};

class ZodNull extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.null) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.null,
        received: ctx.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
}
ZodNull.create = (params) => {
  return new ZodNull({
    typeName: ZodFirstPartyTypeKind.ZodNull,
    ...processCreateParams(params)
  });
};

class ZodAny extends ZodType {
  constructor() {
    super(...arguments);
    this._any = true;
  }
  _parse(input) {
    return OK(input.data);
  }
}
ZodAny.create = (params) => {
  return new ZodAny({
    typeName: ZodFirstPartyTypeKind.ZodAny,
    ...processCreateParams(params)
  });
};

class ZodUnknown extends ZodType {
  constructor() {
    super(...arguments);
    this._unknown = true;
  }
  _parse(input) {
    return OK(input.data);
  }
}
ZodUnknown.create = (params) => {
  return new ZodUnknown({
    typeName: ZodFirstPartyTypeKind.ZodUnknown,
    ...processCreateParams(params)
  });
};

class ZodNever extends ZodType {
  _parse(input) {
    const ctx = this._getOrReturnCtx(input);
    addIssueToContext(ctx, {
      code: ZodIssueCode.invalid_type,
      expected: ZodParsedType.never,
      received: ctx.parsedType
    });
    return INVALID;
  }
}
ZodNever.create = (params) => {
  return new ZodNever({
    typeName: ZodFirstPartyTypeKind.ZodNever,
    ...processCreateParams(params)
  });
};

class ZodVoid extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.undefined) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.void,
        received: ctx.parsedType
      });
      return INVALID;
    }
    return OK(input.data);
  }
}
ZodVoid.create = (params) => {
  return new ZodVoid({
    typeName: ZodFirstPartyTypeKind.ZodVoid,
    ...processCreateParams(params)
  });
};

class ZodArray extends ZodType {
  _parse(input) {
    const { ctx, status } = this._processInputParams(input);
    const def = this._def;
    if (ctx.parsedType !== ZodParsedType.array) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.array,
        received: ctx.parsedType
      });
      return INVALID;
    }
    if (def.exactLength !== null) {
      const tooBig = ctx.data.length > def.exactLength.value;
      const tooSmall = ctx.data.length < def.exactLength.value;
      if (tooBig || tooSmall) {
        addIssueToContext(ctx, {
          code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small,
          minimum: tooSmall ? def.exactLength.value : undefined,
          maximum: tooBig ? def.exactLength.value : undefined,
          type: "array",
          inclusive: true,
          exact: true,
          message: def.exactLength.message
        });
        status.dirty();
      }
    }
    if (def.minLength !== null) {
      if (ctx.data.length < def.minLength.value) {
        addIssueToContext(ctx, {
          code: ZodIssueCode.too_small,
          minimum: def.minLength.value,
          type: "array",
          inclusive: true,
          exact: false,
          message: def.minLength.message
        });
        status.dirty();
      }
    }
    if (def.maxLength !== null) {
      if (ctx.data.length > def.maxLength.value) {
        addIssueToContext(ctx, {
          code: ZodIssueCode.too_big,
          maximum: def.maxLength.value,
          type: "array",
          inclusive: true,
          exact: false,
          message: def.maxLength.message
        });
        status.dirty();
      }
    }
    if (ctx.common.async) {
      return Promise.all([...ctx.data].map((item, i) => {
        return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i));
      })).then((result2) => {
        return ParseStatus.mergeArray(status, result2);
      });
    }
    const result = [...ctx.data].map((item, i) => {
      return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i));
    });
    return ParseStatus.mergeArray(status, result);
  }
  get element() {
    return this._def.type;
  }
  min(minLength, message) {
    return new ZodArray({
      ...this._def,
      minLength: { value: minLength, message: errorUtil.toString(message) }
    });
  }
  max(maxLength, message) {
    return new ZodArray({
      ...this._def,
      maxLength: { value: maxLength, message: errorUtil.toString(message) }
    });
  }
  length(len, message) {
    return new ZodArray({
      ...this._def,
      exactLength: { value: len, message: errorUtil.toString(message) }
    });
  }
  nonempty(message) {
    return this.min(1, message);
  }
}
ZodArray.create = (schema, params) => {
  return new ZodArray({
    type: schema,
    minLength: null,
    maxLength: null,
    exactLength: null,
    typeName: ZodFirstPartyTypeKind.ZodArray,
    ...processCreateParams(params)
  });
};
function deepPartialify(schema) {
  if (schema instanceof ZodObject) {
    const newShape = {};
    for (const key in schema.shape) {
      const fieldSchema = schema.shape[key];
      newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));
    }
    return new ZodObject({
      ...schema._def,
      shape: () => newShape
    });
  } else if (schema instanceof ZodArray) {
    return new ZodArray({
      ...schema._def,
      type: deepPartialify(schema.element)
    });
  } else if (schema instanceof ZodOptional) {
    return ZodOptional.create(deepPartialify(schema.unwrap()));
  } else if (schema instanceof ZodNullable) {
    return ZodNullable.create(deepPartialify(schema.unwrap()));
  } else if (schema instanceof ZodTuple) {
    return ZodTuple.create(schema.items.map((item) => deepPartialify(item)));
  } else {
    return schema;
  }
}

class ZodObject extends ZodType {
  constructor() {
    super(...arguments);
    this._cached = null;
    this.nonstrict = this.passthrough;
    this.augment = this.extend;
  }
  _getCached() {
    if (this._cached !== null)
      return this._cached;
    const shape = this._def.shape();
    const keys = util.objectKeys(shape);
    this._cached = { shape, keys };
    return this._cached;
  }
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.object) {
      const ctx2 = this._getOrReturnCtx(input);
      addIssueToContext(ctx2, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.object,
        received: ctx2.parsedType
      });
      return INVALID;
    }
    const { status, ctx } = this._processInputParams(input);
    const { shape, keys: shapeKeys } = this._getCached();
    const extraKeys = [];
    if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
      for (const key in ctx.data) {
        if (!shapeKeys.includes(key)) {
          extraKeys.push(key);
        }
      }
    }
    const pairs = [];
    for (const key of shapeKeys) {
      const keyValidator = shape[key];
      const value = ctx.data[key];
      pairs.push({
        key: { status: "valid", value: key },
        value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),
        alwaysSet: key in ctx.data
      });
    }
    if (this._def.catchall instanceof ZodNever) {
      const unknownKeys = this._def.unknownKeys;
      if (unknownKeys === "passthrough") {
        for (const key of extraKeys) {
          pairs.push({
            key: { status: "valid", value: key },
            value: { status: "valid", value: ctx.data[key] }
          });
        }
      } else if (unknownKeys === "strict") {
        if (extraKeys.length > 0) {
          addIssueToContext(ctx, {
            code: ZodIssueCode.unrecognized_keys,
            keys: extraKeys
          });
          status.dirty();
        }
      } else if (unknownKeys === "strip") {} else {
        throw new Error(`Internal ZodObject error: invalid unknownKeys value.`);
      }
    } else {
      const catchall = this._def.catchall;
      for (const key of extraKeys) {
        const value = ctx.data[key];
        pairs.push({
          key: { status: "valid", value: key },
          value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),
          alwaysSet: key in ctx.data
        });
      }
    }
    if (ctx.common.async) {
      return Promise.resolve().then(async () => {
        const syncPairs = [];
        for (const pair of pairs) {
          const key = await pair.key;
          const value = await pair.value;
          syncPairs.push({
            key,
            value,
            alwaysSet: pair.alwaysSet
          });
        }
        return syncPairs;
      }).then((syncPairs) => {
        return ParseStatus.mergeObjectSync(status, syncPairs);
      });
    } else {
      return ParseStatus.mergeObjectSync(status, pairs);
    }
  }
  get shape() {
    return this._def.shape();
  }
  strict(message) {
    errorUtil.errToObj;
    return new ZodObject({
      ...this._def,
      unknownKeys: "strict",
      ...message !== undefined ? {
        errorMap: (issue, ctx) => {
          const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError;
          if (issue.code === "unrecognized_keys")
            return {
              message: errorUtil.errToObj(message).message ?? defaultError
            };
          return {
            message: defaultError
          };
        }
      } : {}
    });
  }
  strip() {
    return new ZodObject({
      ...this._def,
      unknownKeys: "strip"
    });
  }
  passthrough() {
    return new ZodObject({
      ...this._def,
      unknownKeys: "passthrough"
    });
  }
  extend(augmentation) {
    return new ZodObject({
      ...this._def,
      shape: () => ({
        ...this._def.shape(),
        ...augmentation
      })
    });
  }
  merge(merging) {
    const merged = new ZodObject({
      unknownKeys: merging._def.unknownKeys,
      catchall: merging._def.catchall,
      shape: () => ({
        ...this._def.shape(),
        ...merging._def.shape()
      }),
      typeName: ZodFirstPartyTypeKind.ZodObject
    });
    return merged;
  }
  setKey(key, schema) {
    return this.augment({ [key]: schema });
  }
  catchall(index) {
    return new ZodObject({
      ...this._def,
      catchall: index
    });
  }
  pick(mask) {
    const shape = {};
    for (const key of util.objectKeys(mask)) {
      if (mask[key] && this.shape[key]) {
        shape[key] = this.shape[key];
      }
    }
    return new ZodObject({
      ...this._def,
      shape: () => shape
    });
  }
  omit(mask) {
    const shape = {};
    for (const key of util.objectKeys(this.shape)) {
      if (!mask[key]) {
        shape[key] = this.shape[key];
      }
    }
    return new ZodObject({
      ...this._def,
      shape: () => shape
    });
  }
  deepPartial() {
    return deepPartialify(this);
  }
  partial(mask) {
    const newShape = {};
    for (const key of util.objectKeys(this.shape)) {
      const fieldSchema = this.shape[key];
      if (mask && !mask[key]) {
        newShape[key] = fieldSchema;
      } else {
        newShape[key] = fieldSchema.optional();
      }
    }
    return new ZodObject({
      ...this._def,
      shape: () => newShape
    });
  }
  required(mask) {
    const newShape = {};
    for (const key of util.objectKeys(this.shape)) {
      if (mask && !mask[key]) {
        newShape[key] = this.shape[key];
      } else {
        const fieldSchema = this.shape[key];
        let newField = fieldSchema;
        while (newField instanceof ZodOptional) {
          newField = newField._def.innerType;
        }
        newShape[key] = newField;
      }
    }
    return new ZodObject({
      ...this._def,
      shape: () => newShape
    });
  }
  keyof() {
    return createZodEnum(util.objectKeys(this.shape));
  }
}
ZodObject.create = (shape, params) => {
  return new ZodObject({
    shape: () => shape,
    unknownKeys: "strip",
    catchall: ZodNever.create(),
    typeName: ZodFirstPartyTypeKind.ZodObject,
    ...processCreateParams(params)
  });
};
ZodObject.strictCreate = (shape, params) => {
  return new ZodObject({
    shape: () => shape,
    unknownKeys: "strict",
    catchall: ZodNever.create(),
    typeName: ZodFirstPartyTypeKind.ZodObject,
    ...processCreateParams(params)
  });
};
ZodObject.lazycreate = (shape, params) => {
  return new ZodObject({
    shape,
    unknownKeys: "strip",
    catchall: ZodNever.create(),
    typeName: ZodFirstPartyTypeKind.ZodObject,
    ...processCreateParams(params)
  });
};

class ZodUnion extends ZodType {
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    const options = this._def.options;
    function handleResults(results) {
      for (const result of results) {
        if (result.result.status === "valid") {
          return result.result;
        }
      }
      for (const result of results) {
        if (result.result.status === "dirty") {
          ctx.common.issues.push(...result.ctx.common.issues);
          return result.result;
        }
      }
      const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues));
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_union,
        unionErrors
      });
      return INVALID;
    }
    if (ctx.common.async) {
      return Promise.all(options.map(async (option) => {
        const childCtx = {
          ...ctx,
          common: {
            ...ctx.common,
            issues: []
          },
          parent: null
        };
        return {
          result: await option._parseAsync({
            data: ctx.data,
            path: ctx.path,
            parent: childCtx
          }),
          ctx: childCtx
        };
      })).then(handleResults);
    } else {
      let dirty = undefined;
      const issues = [];
      for (const option of options) {
        const childCtx = {
          ...ctx,
          common: {
            ...ctx.common,
            issues: []
          },
          parent: null
        };
        const result = option._parseSync({
          data: ctx.data,
          path: ctx.path,
          parent: childCtx
        });
        if (result.status === "valid") {
          return result;
        } else if (result.status === "dirty" && !dirty) {
          dirty = { result, ctx: childCtx };
        }
        if (childCtx.common.issues.length) {
          issues.push(childCtx.common.issues);
        }
      }
      if (dirty) {
        ctx.common.issues.push(...dirty.ctx.common.issues);
        return dirty.result;
      }
      const unionErrors = issues.map((issues2) => new ZodError(issues2));
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_union,
        unionErrors
      });
      return INVALID;
    }
  }
  get options() {
    return this._def.options;
  }
}
ZodUnion.create = (types2, params) => {
  return new ZodUnion({
    options: types2,
    typeName: ZodFirstPartyTypeKind.ZodUnion,
    ...processCreateParams(params)
  });
};
var getDiscriminator = (type) => {
  if (type instanceof ZodLazy) {
    return getDiscriminator(type.schema);
  } else if (type instanceof ZodEffects) {
    return getDiscriminator(type.innerType());
  } else if (type instanceof ZodLiteral) {
    return [type.value];
  } else if (type instanceof ZodEnum) {
    return type.options;
  } else if (type instanceof ZodNativeEnum) {
    return util.objectValues(type.enum);
  } else if (type instanceof ZodDefault) {
    return getDiscriminator(type._def.innerType);
  } else if (type instanceof ZodUndefined) {
    return [undefined];
  } else if (type instanceof ZodNull) {
    return [null];
  } else if (type instanceof ZodOptional) {
    return [undefined, ...getDiscriminator(type.unwrap())];
  } else if (type instanceof ZodNullable) {
    return [null, ...getDiscriminator(type.unwrap())];
  } else if (type instanceof ZodBranded) {
    return getDiscriminator(type.unwrap());
  } else if (type instanceof ZodReadonly) {
    return getDiscriminator(type.unwrap());
  } else if (type instanceof ZodCatch) {
    return getDiscriminator(type._def.innerType);
  } else {
    return [];
  }
};

class ZodDiscriminatedUnion extends ZodType {
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.object) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.object,
        received: ctx.parsedType
      });
      return INVALID;
    }
    const discriminator = this.discriminator;
    const discriminatorValue = ctx.data[discriminator];
    const option = this.optionsMap.get(discriminatorValue);
    if (!option) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_union_discriminator,
        options: Array.from(this.optionsMap.keys()),
        path: [discriminator]
      });
      return INVALID;
    }
    if (ctx.common.async) {
      return option._parseAsync({
        data: ctx.data,
        path: ctx.path,
        parent: ctx
      });
    } else {
      return option._parseSync({
        data: ctx.data,
        path: ctx.path,
        parent: ctx
      });
    }
  }
  get discriminator() {
    return this._def.discriminator;
  }
  get options() {
    return this._def.options;
  }
  get optionsMap() {
    return this._def.optionsMap;
  }
  static create(discriminator, options, params) {
    const optionsMap = new Map;
    for (const type of options) {
      const discriminatorValues = getDiscriminator(type.shape[discriminator]);
      if (!discriminatorValues.length) {
        throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);
      }
      for (const value of discriminatorValues) {
        if (optionsMap.has(value)) {
          throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);
        }
        optionsMap.set(value, type);
      }
    }
    return new ZodDiscriminatedUnion({
      typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,
      discriminator,
      options,
      optionsMap,
      ...processCreateParams(params)
    });
  }
}
function mergeValues(a, b) {
  const aType = getParsedType(a);
  const bType = getParsedType(b);
  if (a === b) {
    return { valid: true, data: a };
  } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
    const bKeys = util.objectKeys(b);
    const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);
    const newObj = { ...a, ...b };
    for (const key of sharedKeys) {
      const sharedValue = mergeValues(a[key], b[key]);
      if (!sharedValue.valid) {
        return { valid: false };
      }
      newObj[key] = sharedValue.data;
    }
    return { valid: true, data: newObj };
  } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {
    if (a.length !== b.length) {
      return { valid: false };
    }
    const newArray = [];
    for (let index = 0;index < a.length; index++) {
      const itemA = a[index];
      const itemB = b[index];
      const sharedValue = mergeValues(itemA, itemB);
      if (!sharedValue.valid) {
        return { valid: false };
      }
      newArray.push(sharedValue.data);
    }
    return { valid: true, data: newArray };
  } else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) {
    return { valid: true, data: a };
  } else {
    return { valid: false };
  }
}

class ZodIntersection extends ZodType {
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    const handleParsed = (parsedLeft, parsedRight) => {
      if (isAborted(parsedLeft) || isAborted(parsedRight)) {
        return INVALID;
      }
      const merged = mergeValues(parsedLeft.value, parsedRight.value);
      if (!merged.valid) {
        addIssueToContext(ctx, {
          code: ZodIssueCode.invalid_intersection_types
        });
        return INVALID;
      }
      if (isDirty(parsedLeft) || isDirty(parsedRight)) {
        status.dirty();
      }
      return { status: status.value, value: merged.data };
    };
    if (ctx.common.async) {
      return Promise.all([
        this._def.left._parseAsync({
          data: ctx.data,
          path: ctx.path,
          parent: ctx
        }),
        this._def.right._parseAsync({
          data: ctx.data,
          path: ctx.path,
          parent: ctx
        })
      ]).then(([left, right]) => handleParsed(left, right));
    } else {
      return handleParsed(this._def.left._parseSync({
        data: ctx.data,
        path: ctx.path,
        parent: ctx
      }), this._def.right._parseSync({
        data: ctx.data,
        path: ctx.path,
        parent: ctx
      }));
    }
  }
}
ZodIntersection.create = (left, right, params) => {
  return new ZodIntersection({
    left,
    right,
    typeName: ZodFirstPartyTypeKind.ZodIntersection,
    ...processCreateParams(params)
  });
};

class ZodTuple extends ZodType {
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.array) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.array,
        received: ctx.parsedType
      });
      return INVALID;
    }
    if (ctx.data.length < this._def.items.length) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.too_small,
        minimum: this._def.items.length,
        inclusive: true,
        exact: false,
        type: "array"
      });
      return INVALID;
    }
    const rest = this._def.rest;
    if (!rest && ctx.data.length > this._def.items.length) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.too_big,
        maximum: this._def.items.length,
        inclusive: true,
        exact: false,
        type: "array"
      });
      status.dirty();
    }
    const items = [...ctx.data].map((item, itemIndex) => {
      const schema = this._def.items[itemIndex] || this._def.rest;
      if (!schema)
        return null;
      return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex));
    }).filter((x) => !!x);
    if (ctx.common.async) {
      return Promise.all(items).then((results) => {
        return ParseStatus.mergeArray(status, results);
      });
    } else {
      return ParseStatus.mergeArray(status, items);
    }
  }
  get items() {
    return this._def.items;
  }
  rest(rest) {
    return new ZodTuple({
      ...this._def,
      rest
    });
  }
}
ZodTuple.create = (schemas, params) => {
  if (!Array.isArray(schemas)) {
    throw new Error("You must pass an array of schemas to z.tuple([ ... ])");
  }
  return new ZodTuple({
    items: schemas,
    typeName: ZodFirstPartyTypeKind.ZodTuple,
    rest: null,
    ...processCreateParams(params)
  });
};

class ZodRecord extends ZodType {
  get keySchema() {
    return this._def.keyType;
  }
  get valueSchema() {
    return this._def.valueType;
  }
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.object) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.object,
        received: ctx.parsedType
      });
      return INVALID;
    }
    const pairs = [];
    const keyType = this._def.keyType;
    const valueType = this._def.valueType;
    for (const key in ctx.data) {
      pairs.push({
        key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),
        value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)),
        alwaysSet: key in ctx.data
      });
    }
    if (ctx.common.async) {
      return ParseStatus.mergeObjectAsync(status, pairs);
    } else {
      return ParseStatus.mergeObjectSync(status, pairs);
    }
  }
  get element() {
    return this._def.valueType;
  }
  static create(first, second, third) {
    if (second instanceof ZodType) {
      return new ZodRecord({
        keyType: first,
        valueType: second,
        typeName: ZodFirstPartyTypeKind.ZodRecord,
        ...processCreateParams(third)
      });
    }
    return new ZodRecord({
      keyType: ZodString.create(),
      valueType: first,
      typeName: ZodFirstPartyTypeKind.ZodRecord,
      ...processCreateParams(second)
    });
  }
}

class ZodMap extends ZodType {
  get keySchema() {
    return this._def.keyType;
  }
  get valueSchema() {
    return this._def.valueType;
  }
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.map) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.map,
        received: ctx.parsedType
      });
      return INVALID;
    }
    const keyType = this._def.keyType;
    const valueType = this._def.valueType;
    const pairs = [...ctx.data.entries()].map(([key, value], index) => {
      return {
        key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
        value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"]))
      };
    });
    if (ctx.common.async) {
      const finalMap = new Map;
      return Promise.resolve().then(async () => {
        for (const pair of pairs) {
          const key = await pair.key;
          const value = await pair.value;
          if (key.status === "aborted" || value.status === "aborted") {
            return INVALID;
          }
          if (key.status === "dirty" || value.status === "dirty") {
            status.dirty();
          }
          finalMap.set(key.value, value.value);
        }
        return { status: status.value, value: finalMap };
      });
    } else {
      const finalMap = new Map;
      for (const pair of pairs) {
        const key = pair.key;
        const value = pair.value;
        if (key.status === "aborted" || value.status === "aborted") {
          return INVALID;
        }
        if (key.status === "dirty" || value.status === "dirty") {
          status.dirty();
        }
        finalMap.set(key.value, value.value);
      }
      return { status: status.value, value: finalMap };
    }
  }
}
ZodMap.create = (keyType, valueType, params) => {
  return new ZodMap({
    valueType,
    keyType,
    typeName: ZodFirstPartyTypeKind.ZodMap,
    ...processCreateParams(params)
  });
};

class ZodSet extends ZodType {
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.set) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.set,
        received: ctx.parsedType
      });
      return INVALID;
    }
    const def = this._def;
    if (def.minSize !== null) {
      if (ctx.data.size < def.minSize.value) {
        addIssueToContext(ctx, {
          code: ZodIssueCode.too_small,
          minimum: def.minSize.value,
          type: "set",
          inclusive: true,
          exact: false,
          message: def.minSize.message
        });
        status.dirty();
      }
    }
    if (def.maxSize !== null) {
      if (ctx.data.size > def.maxSize.value) {
        addIssueToContext(ctx, {
          code: ZodIssueCode.too_big,
          maximum: def.maxSize.value,
          type: "set",
          inclusive: true,
          exact: false,
          message: def.maxSize.message
        });
        status.dirty();
      }
    }
    const valueType = this._def.valueType;
    function finalizeSet(elements2) {
      const parsedSet = new Set;
      for (const element of elements2) {
        if (element.status === "aborted")
          return INVALID;
        if (element.status === "dirty")
          status.dirty();
        parsedSet.add(element.value);
      }
      return { status: status.value, value: parsedSet };
    }
    const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)));
    if (ctx.common.async) {
      return Promise.all(elements).then((elements2) => finalizeSet(elements2));
    } else {
      return finalizeSet(elements);
    }
  }
  min(minSize, message) {
    return new ZodSet({
      ...this._def,
      minSize: { value: minSize, message: errorUtil.toString(message) }
    });
  }
  max(maxSize, message) {
    return new ZodSet({
      ...this._def,
      maxSize: { value: maxSize, message: errorUtil.toString(message) }
    });
  }
  size(size, message) {
    return this.min(size, message).max(size, message);
  }
  nonempty(message) {
    return this.min(1, message);
  }
}
ZodSet.create = (valueType, params) => {
  return new ZodSet({
    valueType,
    minSize: null,
    maxSize: null,
    typeName: ZodFirstPartyTypeKind.ZodSet,
    ...processCreateParams(params)
  });
};

class ZodFunction extends ZodType {
  constructor() {
    super(...arguments);
    this.validate = this.implement;
  }
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.function) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.function,
        received: ctx.parsedType
      });
      return INVALID;
    }
    function makeArgsIssue(args, error) {
      return makeIssue({
        data: args,
        path: ctx.path,
        errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x),
        issueData: {
          code: ZodIssueCode.invalid_arguments,
          argumentsError: error
        }
      });
    }
    function makeReturnsIssue(returns, error) {
      return makeIssue({
        data: returns,
        path: ctx.path,
        errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x),
        issueData: {
          code: ZodIssueCode.invalid_return_type,
          returnTypeError: error
        }
      });
    }
    const params = { errorMap: ctx.common.contextualErrorMap };
    const fn = ctx.data;
    if (this._def.returns instanceof ZodPromise) {
      const me = this;
      return OK(async function(...args) {
        const error = new ZodError([]);
        const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) => {
          error.addIssue(makeArgsIssue(args, e));
          throw error;
        });
        const result = await Reflect.apply(fn, this, parsedArgs);
        const parsedReturns = await me._def.returns._def.type.parseAsync(result, params).catch((e) => {
          error.addIssue(makeReturnsIssue(result, e));
          throw error;
        });
        return parsedReturns;
      });
    } else {
      const me = this;
      return OK(function(...args) {
        const parsedArgs = me._def.args.safeParse(args, params);
        if (!parsedArgs.success) {
          throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);
        }
        const result = Reflect.apply(fn, this, parsedArgs.data);
        const parsedReturns = me._def.returns.safeParse(result, params);
        if (!parsedReturns.success) {
          throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);
        }
        return parsedReturns.data;
      });
    }
  }
  parameters() {
    return this._def.args;
  }
  returnType() {
    return this._def.returns;
  }
  args(...items) {
    return new ZodFunction({
      ...this._def,
      args: ZodTuple.create(items).rest(ZodUnknown.create())
    });
  }
  returns(returnType) {
    return new ZodFunction({
      ...this._def,
      returns: returnType
    });
  }
  implement(func) {
    const validatedFunc = this.parse(func);
    return validatedFunc;
  }
  strictImplement(func) {
    const validatedFunc = this.parse(func);
    return validatedFunc;
  }
  static create(args, returns, params) {
    return new ZodFunction({
      args: args ? args : ZodTuple.create([]).rest(ZodUnknown.create()),
      returns: returns || ZodUnknown.create(),
      typeName: ZodFirstPartyTypeKind.ZodFunction,
      ...processCreateParams(params)
    });
  }
}

class ZodLazy extends ZodType {
  get schema() {
    return this._def.getter();
  }
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    const lazySchema = this._def.getter();
    return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx });
  }
}
ZodLazy.create = (getter, params) => {
  return new ZodLazy({
    getter,
    typeName: ZodFirstPartyTypeKind.ZodLazy,
    ...processCreateParams(params)
  });
};

class ZodLiteral extends ZodType {
  _parse(input) {
    if (input.data !== this._def.value) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        received: ctx.data,
        code: ZodIssueCode.invalid_literal,
        expected: this._def.value
      });
      return INVALID;
    }
    return { status: "valid", value: input.data };
  }
  get value() {
    return this._def.value;
  }
}
ZodLiteral.create = (value, params) => {
  return new ZodLiteral({
    value,
    typeName: ZodFirstPartyTypeKind.ZodLiteral,
    ...processCreateParams(params)
  });
};
function createZodEnum(values, params) {
  return new ZodEnum({
    values,
    typeName: ZodFirstPartyTypeKind.ZodEnum,
    ...processCreateParams(params)
  });
}

class ZodEnum extends ZodType {
  _parse(input) {
    if (typeof input.data !== "string") {
      const ctx = this._getOrReturnCtx(input);
      const expectedValues = this._def.values;
      addIssueToContext(ctx, {
        expected: util.joinValues(expectedValues),
        received: ctx.parsedType,
        code: ZodIssueCode.invalid_type
      });
      return INVALID;
    }
    if (!this._cache) {
      this._cache = new Set(this._def.values);
    }
    if (!this._cache.has(input.data)) {
      const ctx = this._getOrReturnCtx(input);
      const expectedValues = this._def.values;
      addIssueToContext(ctx, {
        received: ctx.data,
        code: ZodIssueCode.invalid_enum_value,
        options: expectedValues
      });
      return INVALID;
    }
    return OK(input.data);
  }
  get options() {
    return this._def.values;
  }
  get enum() {
    const enumValues = {};
    for (const val of this._def.values) {
      enumValues[val] = val;
    }
    return enumValues;
  }
  get Values() {
    const enumValues = {};
    for (const val of this._def.values) {
      enumValues[val] = val;
    }
    return enumValues;
  }
  get Enum() {
    const enumValues = {};
    for (const val of this._def.values) {
      enumValues[val] = val;
    }
    return enumValues;
  }
  extract(values, newDef = this._def) {
    return ZodEnum.create(values, {
      ...this._def,
      ...newDef
    });
  }
  exclude(values, newDef = this._def) {
    return ZodEnum.create(this.options.filter((opt) => !values.includes(opt)), {
      ...this._def,
      ...newDef
    });
  }
}
ZodEnum.create = createZodEnum;

class ZodNativeEnum extends ZodType {
  _parse(input) {
    const nativeEnumValues = util.getValidEnumValues(this._def.values);
    const ctx = this._getOrReturnCtx(input);
    if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) {
      const expectedValues = util.objectValues(nativeEnumValues);
      addIssueToContext(ctx, {
        expected: util.joinValues(expectedValues),
        received: ctx.parsedType,
        code: ZodIssueCode.invalid_type
      });
      return INVALID;
    }
    if (!this._cache) {
      this._cache = new Set(util.getValidEnumValues(this._def.values));
    }
    if (!this._cache.has(input.data)) {
      const expectedValues = util.objectValues(nativeEnumValues);
      addIssueToContext(ctx, {
        received: ctx.data,
        code: ZodIssueCode.invalid_enum_value,
        options: expectedValues
      });
      return INVALID;
    }
    return OK(input.data);
  }
  get enum() {
    return this._def.values;
  }
}
ZodNativeEnum.create = (values, params) => {
  return new ZodNativeEnum({
    values,
    typeName: ZodFirstPartyTypeKind.ZodNativeEnum,
    ...processCreateParams(params)
  });
};

class ZodPromise extends ZodType {
  unwrap() {
    return this._def.type;
  }
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) {
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.promise,
        received: ctx.parsedType
      });
      return INVALID;
    }
    const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data);
    return OK(promisified.then((data) => {
      return this._def.type.parseAsync(data, {
        path: ctx.path,
        errorMap: ctx.common.contextualErrorMap
      });
    }));
  }
}
ZodPromise.create = (schema, params) => {
  return new ZodPromise({
    type: schema,
    typeName: ZodFirstPartyTypeKind.ZodPromise,
    ...processCreateParams(params)
  });
};

class ZodEffects extends ZodType {
  innerType() {
    return this._def.schema;
  }
  sourceType() {
    return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects ? this._def.schema.sourceType() : this._def.schema;
  }
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    const effect = this._def.effect || null;
    const checkCtx = {
      addIssue: (arg) => {
        addIssueToContext(ctx, arg);
        if (arg.fatal) {
          status.abort();
        } else {
          status.dirty();
        }
      },
      get path() {
        return ctx.path;
      }
    };
    checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);
    if (effect.type === "preprocess") {
      const processed = effect.transform(ctx.data, checkCtx);
      if (ctx.common.async) {
        return Promise.resolve(processed).then(async (processed2) => {
          if (status.value === "aborted")
            return INVALID;
          const result = await this._def.schema._parseAsync({
            data: processed2,
            path: ctx.path,
            parent: ctx
          });
          if (result.status === "aborted")
            return INVALID;
          if (result.status === "dirty")
            return DIRTY(result.value);
          if (status.value === "dirty")
            return DIRTY(result.value);
          return result;
        });
      } else {
        if (status.value === "aborted")
          return INVALID;
        const result = this._def.schema._parseSync({
          data: processed,
          path: ctx.path,
          parent: ctx
        });
        if (result.status === "aborted")
          return INVALID;
        if (result.status === "dirty")
          return DIRTY(result.value);
        if (status.value === "dirty")
          return DIRTY(result.value);
        return result;
      }
    }
    if (effect.type === "refinement") {
      const executeRefinement = (acc) => {
        const result = effect.refinement(acc, checkCtx);
        if (ctx.common.async) {
          return Promise.resolve(result);
        }
        if (result instanceof Promise) {
          throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");
        }
        return acc;
      };
      if (ctx.common.async === false) {
        const inner = this._def.schema._parseSync({
          data: ctx.data,
          path: ctx.path,
          parent: ctx
        });
        if (inner.status === "aborted")
          return INVALID;
        if (inner.status === "dirty")
          status.dirty();
        executeRefinement(inner.value);
        return { status: status.value, value: inner.value };
      } else {
        return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => {
          if (inner.status === "aborted")
            return INVALID;
          if (inner.status === "dirty")
            status.dirty();
          return executeRefinement(inner.value).then(() => {
            return { status: status.value, value: inner.value };
          });
        });
      }
    }
    if (effect.type === "transform") {
      if (ctx.common.async === false) {
        const base = this._def.schema._parseSync({
          data: ctx.data,
          path: ctx.path,
          parent: ctx
        });
        if (!isValid(base))
          return INVALID;
        const result = effect.transform(base.value, checkCtx);
        if (result instanceof Promise) {
          throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
        }
        return { status: status.value, value: result };
      } else {
        return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
          if (!isValid(base))
            return INVALID;
          return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
            status: status.value,
            value: result
          }));
        });
      }
    }
    util.assertNever(effect);
  }
}
ZodEffects.create = (schema, effect, params) => {
  return new ZodEffects({
    schema,
    typeName: ZodFirstPartyTypeKind.ZodEffects,
    effect,
    ...processCreateParams(params)
  });
};
ZodEffects.createWithPreprocess = (preprocess, schema, params) => {
  return new ZodEffects({
    schema,
    effect: { type: "preprocess", transform: preprocess },
    typeName: ZodFirstPartyTypeKind.ZodEffects,
    ...processCreateParams(params)
  });
};
class ZodOptional extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType === ZodParsedType.undefined) {
      return OK(undefined);
    }
    return this._def.innerType._parse(input);
  }
  unwrap() {
    return this._def.innerType;
  }
}
ZodOptional.create = (type, params) => {
  return new ZodOptional({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodOptional,
    ...processCreateParams(params)
  });
};

class ZodNullable extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType === ZodParsedType.null) {
      return OK(null);
    }
    return this._def.innerType._parse(input);
  }
  unwrap() {
    return this._def.innerType;
  }
}
ZodNullable.create = (type, params) => {
  return new ZodNullable({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodNullable,
    ...processCreateParams(params)
  });
};

class ZodDefault extends ZodType {
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    let data = ctx.data;
    if (ctx.parsedType === ZodParsedType.undefined) {
      data = this._def.defaultValue();
    }
    return this._def.innerType._parse({
      data,
      path: ctx.path,
      parent: ctx
    });
  }
  removeDefault() {
    return this._def.innerType;
  }
}
ZodDefault.create = (type, params) => {
  return new ZodDefault({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodDefault,
    defaultValue: typeof params.default === "function" ? params.default : () => params.default,
    ...processCreateParams(params)
  });
};

class ZodCatch extends ZodType {
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    const newCtx = {
      ...ctx,
      common: {
        ...ctx.common,
        issues: []
      }
    };
    const result = this._def.innerType._parse({
      data: newCtx.data,
      path: newCtx.path,
      parent: {
        ...newCtx
      }
    });
    if (isAsync(result)) {
      return result.then((result2) => {
        return {
          status: "valid",
          value: result2.status === "valid" ? result2.value : this._def.catchValue({
            get error() {
              return new ZodError(newCtx.common.issues);
            },
            input: newCtx.data
          })
        };
      });
    } else {
      return {
        status: "valid",
        value: result.status === "valid" ? result.value : this._def.catchValue({
          get error() {
            return new ZodError(newCtx.common.issues);
          },
          input: newCtx.data
        })
      };
    }
  }
  removeCatch() {
    return this._def.innerType;
  }
}
ZodCatch.create = (type, params) => {
  return new ZodCatch({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodCatch,
    catchValue: typeof params.catch === "function" ? params.catch : () => params.catch,
    ...processCreateParams(params)
  });
};

class ZodNaN extends ZodType {
  _parse(input) {
    const parsedType = this._getType(input);
    if (parsedType !== ZodParsedType.nan) {
      const ctx = this._getOrReturnCtx(input);
      addIssueToContext(ctx, {
        code: ZodIssueCode.invalid_type,
        expected: ZodParsedType.nan,
        received: ctx.parsedType
      });
      return INVALID;
    }
    return { status: "valid", value: input.data };
  }
}
ZodNaN.create = (params) => {
  return new ZodNaN({
    typeName: ZodFirstPartyTypeKind.ZodNaN,
    ...processCreateParams(params)
  });
};
var BRAND = Symbol("zod_brand");

class ZodBranded extends ZodType {
  _parse(input) {
    const { ctx } = this._processInputParams(input);
    const data = ctx.data;
    return this._def.type._parse({
      data,
      path: ctx.path,
      parent: ctx
    });
  }
  unwrap() {
    return this._def.type;
  }
}

class ZodPipeline extends ZodType {
  _parse(input) {
    const { status, ctx } = this._processInputParams(input);
    if (ctx.common.async) {
      const handleAsync = async () => {
        const inResult = await this._def.in._parseAsync({
          data: ctx.data,
          path: ctx.path,
          parent: ctx
        });
        if (inResult.status === "aborted")
          return INVALID;
        if (inResult.status === "dirty") {
          status.dirty();
          return DIRTY(inResult.value);
        } else {
          return this._def.out._parseAsync({
            data: inResult.value,
            path: ctx.path,
            parent: ctx
          });
        }
      };
      return handleAsync();
    } else {
      const inResult = this._def.in._parseSync({
        data: ctx.data,
        path: ctx.path,
        parent: ctx
      });
      if (inResult.status === "aborted")
        return INVALID;
      if (inResult.status === "dirty") {
        status.dirty();
        return {
          status: "dirty",
          value: inResult.value
        };
      } else {
        return this._def.out._parseSync({
          data: inResult.value,
          path: ctx.path,
          parent: ctx
        });
      }
    }
  }
  static create(a, b) {
    return new ZodPipeline({
      in: a,
      out: b,
      typeName: ZodFirstPartyTypeKind.ZodPipeline
    });
  }
}

class ZodReadonly extends ZodType {
  _parse(input) {
    const result = this._def.innerType._parse(input);
    const freeze = (data) => {
      if (isValid(data)) {
        data.value = Object.freeze(data.value);
      }
      return data;
    };
    return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result);
  }
  unwrap() {
    return this._def.innerType;
  }
}
ZodReadonly.create = (type, params) => {
  return new ZodReadonly({
    innerType: type,
    typeName: ZodFirstPartyTypeKind.ZodReadonly,
    ...processCreateParams(params)
  });
};
function cleanParams(params, data) {
  const p = typeof params === "function" ? params(data) : typeof params === "string" ? { message: params } : params;
  const p2 = typeof p === "string" ? { message: p } : p;
  return p2;
}
function custom(check, _params = {}, fatal) {
  if (check)
    return ZodAny.create().superRefine((data, ctx) => {
      const r = check(data);
      if (r instanceof Promise) {
        return r.then((r2) => {
          if (!r2) {
            const params = cleanParams(_params, data);
            const _fatal = params.fatal ?? fatal ?? true;
            ctx.addIssue({ code: "custom", ...params, fatal: _fatal });
          }
        });
      }
      if (!r) {
        const params = cleanParams(_params, data);
        const _fatal = params.fatal ?? fatal ?? true;
        ctx.addIssue({ code: "custom", ...params, fatal: _fatal });
      }
      return;
    });
  return ZodAny.create();
}
var late = {
  object: ZodObject.lazycreate
};
var ZodFirstPartyTypeKind;
(function(ZodFirstPartyTypeKind2) {
  ZodFirstPartyTypeKind2["ZodString"] = "ZodString";
  ZodFirstPartyTypeKind2["ZodNumber"] = "ZodNumber";
  ZodFirstPartyTypeKind2["ZodNaN"] = "ZodNaN";
  ZodFirstPartyTypeKind2["ZodBigInt"] = "ZodBigInt";
  ZodFirstPartyTypeKind2["ZodBoolean"] = "ZodBoolean";
  ZodFirstPartyTypeKind2["ZodDate"] = "ZodDate";
  ZodFirstPartyTypeKind2["ZodSymbol"] = "ZodSymbol";
  ZodFirstPartyTypeKind2["ZodUndefined"] = "ZodUndefined";
  ZodFirstPartyTypeKind2["ZodNull"] = "ZodNull";
  ZodFirstPartyTypeKind2["ZodAny"] = "ZodAny";
  ZodFirstPartyTypeKind2["ZodUnknown"] = "ZodUnknown";
  ZodFirstPartyTypeKind2["ZodNever"] = "ZodNever";
  ZodFirstPartyTypeKind2["ZodVoid"] = "ZodVoid";
  ZodFirstPartyTypeKind2["ZodArray"] = "ZodArray";
  ZodFirstPartyTypeKind2["ZodObject"] = "ZodObject";
  ZodFirstPartyTypeKind2["ZodUnion"] = "ZodUnion";
  ZodFirstPartyTypeKind2["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion";
  ZodFirstPartyTypeKind2["ZodIntersection"] = "ZodIntersection";
  ZodFirstPartyTypeKind2["ZodTuple"] = "ZodTuple";
  ZodFirstPartyTypeKind2["ZodRecord"] = "ZodRecord";
  ZodFirstPartyTypeKind2["ZodMap"] = "ZodMap";
  ZodFirstPartyTypeKind2["ZodSet"] = "ZodSet";
  ZodFirstPartyTypeKind2["ZodFunction"] = "ZodFunction";
  ZodFirstPartyTypeKind2["ZodLazy"] = "ZodLazy";
  ZodFirstPartyTypeKind2["ZodLiteral"] = "ZodLiteral";
  ZodFirstPartyTypeKind2["ZodEnum"] = "ZodEnum";
  ZodFirstPartyTypeKind2["ZodEffects"] = "ZodEffects";
  ZodFirstPartyTypeKind2["ZodNativeEnum"] = "ZodNativeEnum";
  ZodFirstPartyTypeKind2["ZodOptional"] = "ZodOptional";
  ZodFirstPartyTypeKind2["ZodNullable"] = "ZodNullable";
  ZodFirstPartyTypeKind2["ZodDefault"] = "ZodDefault";
  ZodFirstPartyTypeKind2["ZodCatch"] = "ZodCatch";
  ZodFirstPartyTypeKind2["ZodPromise"] = "ZodPromise";
  ZodFirstPartyTypeKind2["ZodBranded"] = "ZodBranded";
  ZodFirstPartyTypeKind2["ZodPipeline"] = "ZodPipeline";
  ZodFirstPartyTypeKind2["ZodReadonly"] = "ZodReadonly";
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
var instanceOfType = (cls, params = {
  message: `Input not instance of ${cls.name}`
}) => custom((data) => data instanceof cls, params);
var stringType = ZodString.create;
var numberType = ZodNumber.create;
var nanType = ZodNaN.create;
var bigIntType = ZodBigInt.create;
var booleanType = ZodBoolean.create;
var dateType = ZodDate.create;
var symbolType = ZodSymbol.create;
var undefinedType = ZodUndefined.create;
var nullType = ZodNull.create;
var anyType = ZodAny.create;
var unknownType = ZodUnknown.create;
var neverType = ZodNever.create;
var voidType = ZodVoid.create;
var arrayType = ZodArray.create;
var objectType = ZodObject.create;
var strictObjectType = ZodObject.strictCreate;
var unionType = ZodUnion.create;
var discriminatedUnionType = ZodDiscriminatedUnion.create;
var intersectionType = ZodIntersection.create;
var tupleType = ZodTuple.create;
var recordType = ZodRecord.create;
var mapType = ZodMap.create;
var setType = ZodSet.create;
var functionType = ZodFunction.create;
var lazyType = ZodLazy.create;
var literalType = ZodLiteral.create;
var enumType = ZodEnum.create;
var nativeEnumType = ZodNativeEnum.create;
var promiseType = ZodPromise.create;
var effectsType = ZodEffects.create;
var optionalType = ZodOptional.create;
var nullableType = ZodNullable.create;
var preprocessType = ZodEffects.createWithPreprocess;
var pipelineType = ZodPipeline.create;
var ostring = () => stringType().optional();
var onumber = () => numberType().optional();
var oboolean = () => booleanType().optional();
var coerce = {
  string: (arg) => ZodString.create({ ...arg, coerce: true }),
  number: (arg) => ZodNumber.create({ ...arg, coerce: true }),
  boolean: (arg) => ZodBoolean.create({
    ...arg,
    coerce: true
  }),
  bigint: (arg) => ZodBigInt.create({ ...arg, coerce: true }),
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
};
var NEVER = INVALID;
// ../../work/placement-analysis/node_modules/circuit-json/dist/index.mjs
var resistance = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v, "Ω").value);
var capacitance = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v, "F").value).transform((value) => {
  return Number.parseFloat(value.toPrecision(12));
});
var inductance = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v, "H").value);
var voltage = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v, "V").value);
var length = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v).value);
var frequency = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v, "Hz").value);
var distance4 = length;
var current = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v, "A").value);
var duration_ms = exports_external.string().or(exports_external.number()).transform((v) => parseAndConvertSiUnit(v).value);
var time = duration_ms;
var ms = duration_ms;
var timestamp = exports_external.string().datetime();
var rotation = exports_external.string().or(exports_external.number()).transform((arg) => {
  if (typeof arg === "number")
    return arg;
  if (arg.endsWith("deg")) {
    return Number.parseFloat(arg.split("deg")[0]);
  }
  if (arg.endsWith("rad")) {
    return Number.parseFloat(arg.split("rad")[0]) * 180 / Math.PI;
  }
  return Number.parseFloat(arg);
});
var battery_capacity = exports_external.number().or(exports_external.string().endsWith("mAh")).transform((v) => {
  if (typeof v === "string") {
    const valString = v.replace("mAh", "");
    const num = Number.parseFloat(valString);
    if (Number.isNaN(num)) {
      throw new Error("Invalid capacity");
    }
    return num;
  }
  return v;
}).describe("Battery capacity in mAh");
var expectTypesMatch = (shouldBe) => {};
expectTypesMatch("extra props b");
expectTypesMatch("missing props b");
expectTypesMatch(true);
expectTypesMatch("mismatched prop types: a");
var expectStringUnionsMatch = (shouldBe) => {};
expectStringUnionsMatch(true);
expectStringUnionsMatch('T1 has extra: "c", T2 has extra: "d"');
expectStringUnionsMatch('T1 has extra: "c"');
expectStringUnionsMatch('T2 has extra: "c"');
expectStringUnionsMatch('T1 has extra: "d", T2 has extra: "c"');
expectStringUnionsMatch(true);
var point = exports_external.object({
  x: distance4,
  y: distance4
});
var position = point;
expectTypesMatch(true);
expectTypesMatch(true);
var point3 = exports_external.object({
  x: distance4,
  y: distance4,
  z: distance4
});
var position3 = point3;
expectTypesMatch(true);
var size = exports_external.object({
  width: exports_external.number(),
  height: exports_external.number()
});
expectTypesMatch(true);
var randomId = (length4) => {
  const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  return Array.from({ length: length4 }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
};
var getZodPrefixedIdWithDefault = (prefix) => {
  return exports_external.string().optional().default(() => `${prefix}_${randomId(10)}`);
};
var ninePointAnchor = exports_external.enum([
  "top_left",
  "top_center",
  "top_right",
  "center_left",
  "center",
  "center_right",
  "bottom_left",
  "bottom_center",
  "bottom_right"
]);
expectTypesMatch(true);
var pcbRenderLayer = exports_external.enum([
  "top_silkscreen",
  "bottom_silkscreen",
  "top_copper",
  "bottom_copper",
  "top_soldermask",
  "bottom_soldermask",
  "top_fabrication_note",
  "bottom_fabrication_note",
  "top_user_note",
  "bottom_user_note",
  "top_courtyard",
  "bottom_courtyard",
  "inner1_copper",
  "inner2_copper",
  "inner3_copper",
  "inner4_copper",
  "inner5_copper",
  "inner6_copper",
  "edge_cuts",
  "drill"
]);
expectTypesMatch(true);
var asset = exports_external.object({
  project_relative_path: exports_external.string(),
  url: exports_external.string(),
  mimetype: exports_external.string()
});
expectTypesMatch(true);
var kicadAt = point.extend({
  rotation: rotation.optional()
});
expectTypesMatch(true);
var kicadFont = exports_external.object({
  size: point.optional(),
  thickness: distance4.optional()
});
expectTypesMatch(true);
var kicadEffects = exports_external.object({
  font: kicadFont.optional()
});
expectTypesMatch(true);
var kicadProperty = exports_external.object({
  value: exports_external.string(),
  at: kicadAt.optional(),
  layer: exports_external.string().optional(),
  uuid: exports_external.string().optional(),
  hide: exports_external.boolean().optional(),
  effects: kicadEffects.optional()
});
expectTypesMatch(true);
var kicadFootprintProperties = exports_external.object({
  Reference: kicadProperty.optional(),
  Value: kicadProperty.optional(),
  Datasheet: kicadProperty.optional(),
  Description: kicadProperty.optional()
});
expectTypesMatch(true);
var kicadFootprintAttributes = exports_external.object({
  through_hole: exports_external.boolean().optional(),
  smd: exports_external.boolean().optional(),
  exclude_from_pos_files: exports_external.boolean().optional(),
  exclude_from_bom: exports_external.boolean().optional()
});
expectTypesMatch(true);
var kicadFootprintPad = exports_external.object({
  name: exports_external.string(),
  type: exports_external.string(),
  shape: exports_external.string().optional(),
  at: kicadAt.optional(),
  size: point.optional(),
  drill: distance4.optional(),
  layers: exports_external.array(exports_external.string()).optional(),
  removeUnusedLayers: exports_external.boolean().optional(),
  uuid: exports_external.string().optional()
});
expectTypesMatch(true);
var kicadFootprintModel = exports_external.object({
  path: exports_external.string(),
  offset: point3.optional(),
  scale: point3.optional(),
  rotate: point3.optional()
});
expectTypesMatch(true);
var kicadFootprintMetadata = exports_external.object({
  footprintName: exports_external.string().optional(),
  version: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  generator: exports_external.string().optional(),
  generatorVersion: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  layer: exports_external.string().optional(),
  properties: kicadFootprintProperties.optional(),
  attributes: kicadFootprintAttributes.optional(),
  pads: exports_external.array(kicadFootprintPad).optional(),
  embeddedFonts: exports_external.boolean().optional(),
  model: kicadFootprintModel.optional()
});
expectTypesMatch(true);
var kicadSymbolPinNumbers = exports_external.object({
  hide: exports_external.boolean().optional()
});
expectTypesMatch(true);
var kicadSymbolPinNames = exports_external.object({
  offset: distance4.optional(),
  hide: exports_external.boolean().optional()
});
expectTypesMatch(true);
var kicadSymbolEffects = exports_external.object({
  font: kicadFont.optional(),
  justify: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional(),
  hide: exports_external.boolean().optional()
});
expectTypesMatch(true);
var kicadSymbolProperty = exports_external.object({
  value: exports_external.string(),
  id: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  at: kicadAt.optional(),
  effects: kicadSymbolEffects.optional()
});
expectTypesMatch(true);
var kicadSymbolProperties = exports_external.object({
  Reference: kicadSymbolProperty.optional(),
  Value: kicadSymbolProperty.optional(),
  Footprint: kicadSymbolProperty.optional(),
  Datasheet: kicadSymbolProperty.optional(),
  Description: kicadSymbolProperty.optional(),
  ki_keywords: kicadSymbolProperty.optional(),
  ki_fp_filters: kicadSymbolProperty.optional()
});
expectTypesMatch(true);
var kicadSymbolMetadata = exports_external.object({
  symbolName: exports_external.string().optional(),
  extends: exports_external.string().optional(),
  pinNumbers: kicadSymbolPinNumbers.optional(),
  pinNames: kicadSymbolPinNames.optional(),
  excludeFromSim: exports_external.boolean().optional(),
  inBom: exports_external.boolean().optional(),
  onBoard: exports_external.boolean().optional(),
  properties: kicadSymbolProperties.optional(),
  embeddedFonts: exports_external.boolean().optional()
});
expectTypesMatch(true);
var base_circuit_json_error = exports_external.object({
  error_type: exports_external.string(),
  message: exports_external.string(),
  is_fatal: exports_external.boolean().optional()
});
expectTypesMatch(true);
var supplier_name = exports_external.enum([
  "jlcpcb",
  "macrofab",
  "pcbway",
  "digikey",
  "mouser",
  "lcsc"
]);
expectTypesMatch(true);
var source_component_base = exports_external.object({
  type: exports_external.literal("source_component"),
  ftype: exports_external.string().optional(),
  source_component_id: exports_external.string(),
  name: exports_external.string(),
  manufacturer_part_number: exports_external.string().optional(),
  supplier_part_numbers: exports_external.record(supplier_name, exports_external.array(exports_external.string())).optional(),
  display_value: exports_external.string().optional(),
  display_name: exports_external.string().optional(),
  are_pins_interchangeable: exports_external.boolean().optional(),
  internally_connected_source_port_ids: exports_external.array(exports_external.array(exports_external.string())).optional(),
  source_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
});
expectTypesMatch(true);
var source_simple_capacitor = source_component_base.extend({
  ftype: exports_external.literal("simple_capacitor"),
  capacitance,
  max_voltage_rating: voltage.optional(),
  display_capacitance: exports_external.string().optional(),
  max_decoupling_trace_length: distance4.optional()
});
expectTypesMatch(true);
var source_simple_resistor = source_component_base.extend({
  ftype: exports_external.literal("simple_resistor"),
  resistance,
  display_resistance: exports_external.string().optional()
});
expectTypesMatch(true);
var source_simple_diode = source_component_base.extend({
  ftype: exports_external.literal("simple_diode")
});
expectTypesMatch(true);
var source_simple_fiducial = source_component_base.extend({
  ftype: exports_external.literal("simple_fiducial")
});
expectTypesMatch(true);
var source_simple_led = source_simple_diode.extend({
  ftype: exports_external.literal("simple_led"),
  color: exports_external.string().optional(),
  wavelength: exports_external.string().optional()
});
expectTypesMatch(true);
var source_simple_ground = source_component_base.extend({
  ftype: exports_external.literal("simple_ground")
});
expectTypesMatch(true);
var source_simple_chip = source_component_base.extend({
  ftype: exports_external.literal("simple_chip")
});
expectTypesMatch(true);
var source_simple_power_source = source_component_base.extend({
  ftype: exports_external.literal("simple_power_source"),
  voltage
});
expectTypesMatch(true);
var source_simple_current_source = source_component_base.extend({
  ftype: exports_external.literal("simple_current_source"),
  current,
  frequency: frequency.optional(),
  peak_to_peak_current: current.optional(),
  wave_shape: exports_external.enum(["sine", "square", "triangle", "sawtooth", "dc"]).optional().default("dc"),
  phase: exports_external.number().optional(),
  duty_cycle: exports_external.number().min(0).max(1).optional()
});
expectTypesMatch(true);
var source_simple_ammeter = source_component_base.extend({
  ftype: exports_external.literal("simple_ammeter")
});
expectTypesMatch(true);
var source_pin_attributes = exports_external.object({
  must_be_connected: exports_external.boolean().optional(),
  provides_power: exports_external.boolean().optional(),
  requires_power: exports_external.boolean().optional(),
  provides_ground: exports_external.boolean().optional(),
  requires_ground: exports_external.boolean().optional(),
  provides_voltage: exports_external.union([exports_external.string(), exports_external.number()]).optional(),
  requires_voltage: exports_external.union([exports_external.string(), exports_external.number()]).optional(),
  do_not_connect: exports_external.boolean().optional(),
  include_in_board_pinout: exports_external.boolean().optional(),
  can_use_internal_pullup: exports_external.boolean().optional(),
  is_using_internal_pullup: exports_external.boolean().optional(),
  needs_external_pullup: exports_external.boolean().optional(),
  can_use_internal_pulldown: exports_external.boolean().optional(),
  is_using_internal_pulldown: exports_external.boolean().optional(),
  needs_external_pulldown: exports_external.boolean().optional(),
  can_use_open_drain: exports_external.boolean().optional(),
  is_using_open_drain: exports_external.boolean().optional(),
  can_use_push_pull: exports_external.boolean().optional(),
  is_using_push_pull: exports_external.boolean().optional(),
  should_have_decoupling_capacitor: exports_external.boolean().optional(),
  recommended_decoupling_capacitor_capacitance: exports_external.union([exports_external.string(), exports_external.number()]).optional(),
  is_configured_for_i2c_sda: exports_external.boolean().optional(),
  is_configured_for_i2c_scl: exports_external.boolean().optional(),
  is_configured_for_spi_mosi: exports_external.boolean().optional(),
  is_configured_for_spi_miso: exports_external.boolean().optional(),
  is_configured_for_spi_sck: exports_external.boolean().optional(),
  is_configured_for_spi_cs: exports_external.boolean().optional(),
  is_configured_for_uart_tx: exports_external.boolean().optional(),
  is_configured_for_uart_rx: exports_external.boolean().optional(),
  supports_i2c_sda: exports_external.boolean().optional(),
  supports_i2c_scl: exports_external.boolean().optional(),
  supports_spi_mosi: exports_external.boolean().optional(),
  supports_spi_miso: exports_external.boolean().optional(),
  supports_spi_sck: exports_external.boolean().optional(),
  supports_spi_cs: exports_external.boolean().optional(),
  supports_uart_tx: exports_external.boolean().optional(),
  supports_uart_rx: exports_external.boolean().optional()
});
expectTypesMatch(true);
var source_simple_fuse = source_component_base.extend({
  ftype: exports_external.literal("simple_fuse"),
  current_rating_amps: exports_external.number().describe("Nominal current in amps the fuse is rated for"),
  voltage_rating_volts: exports_external.number().describe("Voltage rating in volts, e.g. ±5V would be 5")
});
expectTypesMatch(true);
var source_simple_battery = source_component_base.extend({
  ftype: exports_external.literal("simple_battery"),
  capacity: battery_capacity
});
expectTypesMatch(true);
var source_simple_inductor = source_component_base.extend({
  ftype: exports_external.literal("simple_inductor"),
  inductance,
  display_inductance: exports_external.string().optional(),
  max_current_rating: exports_external.number().optional()
});
expectTypesMatch(true);
var source_simple_push_button = source_component_base.extend({
  ftype: exports_external.literal("simple_push_button")
});
expectTypesMatch(true);
var source_simple_potentiometer = source_component_base.extend({
  ftype: exports_external.literal("simple_potentiometer"),
  max_resistance: resistance,
  display_max_resistance: exports_external.string().optional()
});
expectTypesMatch(true);
var source_simple_crystal = source_component_base.extend({
  ftype: exports_external.literal("simple_crystal"),
  frequency: exports_external.number().describe("Frequency in Hz"),
  load_capacitance: exports_external.number().optional().describe("Load capacitance in pF"),
  pin_variant: exports_external.enum(["two_pin", "four_pin"]).optional()
});
expectTypesMatch(true);
var source_simple_pin_header = source_component_base.extend({
  ftype: exports_external.literal("simple_pin_header"),
  pin_count: exports_external.number(),
  gender: exports_external.enum(["male", "female"]).optional().default("male")
});
expectTypesMatch(true);
var source_simple_connector = source_component_base.extend({
  ftype: exports_external.literal("simple_connector"),
  standard: exports_external.enum(["usb_c", "m2"]).optional()
});
expectTypesMatch(true);
var source_simple_pinout = source_component_base.extend({
  ftype: exports_external.literal("simple_pinout")
});
expectTypesMatch(true);
var source_simple_resonator = source_component_base.extend({
  ftype: exports_external.literal("simple_resonator"),
  load_capacitance: capacitance,
  equivalent_series_resistance: resistance.optional(),
  frequency
});
expectTypesMatch(true);
var source_simple_transistor = source_component_base.extend({
  ftype: exports_external.literal("simple_transistor"),
  transistor_type: exports_external.enum(["npn", "pnp"])
});
expectTypesMatch(true);
var source_simple_test_point = source_component_base.extend({
  ftype: exports_external.literal("simple_test_point"),
  footprint_variant: exports_external.enum(["pad", "through_hole"]).optional(),
  pad_shape: exports_external.enum(["rect", "circle"]).optional(),
  pad_diameter: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  hole_diameter: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  width: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  height: exports_external.union([exports_external.number(), exports_external.string()]).optional()
});
expectTypesMatch(true);
var source_simple_mosfet = source_component_base.extend({
  ftype: exports_external.literal("simple_mosfet"),
  channel_type: exports_external.enum(["n", "p"]),
  mosfet_mode: exports_external.enum(["enhancement", "depletion"])
});
expectTypesMatch(true);
var source_simple_op_amp = source_component_base.extend({
  ftype: exports_external.literal("simple_op_amp")
});
expectTypesMatch(true);
var source_simple_switch = source_component_base.extend({
  ftype: exports_external.literal("simple_switch")
});
expectTypesMatch(true);
var source_project_metadata = exports_external.object({
  type: exports_external.literal("source_project_metadata"),
  name: exports_external.string().optional(),
  software_used_string: exports_external.string().optional(),
  project_url: exports_external.string().optional(),
  created_at: timestamp.optional()
});
expectTypesMatch(true);
var source_missing_property_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_missing_property_error"),
  source_missing_property_error_id: getZodPrefixedIdWithDefault("source_missing_property_error"),
  source_component_id: exports_external.string(),
  property_name: exports_external.string(),
  subcircuit_id: exports_external.string().optional(),
  error_type: exports_external.literal("source_missing_property_error").default("source_missing_property_error")
}).describe("The source code is missing a property");
expectTypesMatch(true);
var source_failed_to_create_component_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_failed_to_create_component_error"),
  source_failed_to_create_component_error_id: getZodPrefixedIdWithDefault("source_failed_to_create_component_error"),
  error_type: exports_external.literal("source_failed_to_create_component_error").default("source_failed_to_create_component_error"),
  component_name: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  parent_source_component_id: exports_external.string().optional(),
  pcb_center: exports_external.object({
    x: exports_external.number().optional(),
    y: exports_external.number().optional()
  }).optional(),
  schematic_center: exports_external.object({
    x: exports_external.number().optional(),
    y: exports_external.number().optional()
  }).optional()
}).describe("Error emitted when a component fails to be constructed");
expectTypesMatch(true);
var source_invalid_component_property_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_invalid_component_property_error"),
  source_invalid_component_property_error_id: getZodPrefixedIdWithDefault("source_invalid_component_property_error"),
  source_component_id: exports_external.string(),
  property_name: exports_external.string(),
  property_value: exports_external.unknown().optional(),
  expected_format: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  error_type: exports_external.literal("source_invalid_component_property_error").default("source_invalid_component_property_error")
}).describe("The source component property is invalid");
expectTypesMatch(true);
var source_trace_not_connected_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_trace_not_connected_error"),
  source_trace_not_connected_error_id: getZodPrefixedIdWithDefault("source_trace_not_connected_error"),
  error_type: exports_external.literal("source_trace_not_connected_error").default("source_trace_not_connected_error"),
  subcircuit_id: exports_external.string().optional(),
  source_group_id: exports_external.string().optional(),
  source_trace_id: exports_external.string().optional(),
  connected_source_port_ids: exports_external.array(exports_external.string()).optional(),
  selectors_not_found: exports_external.array(exports_external.string()).optional()
}).describe("Occurs when a source trace selector does not match any ports");
expectTypesMatch(true);
var source_property_ignored_warning = exports_external.object({
  type: exports_external.literal("source_property_ignored_warning"),
  source_property_ignored_warning_id: getZodPrefixedIdWithDefault("source_property_ignored_warning"),
  source_component_id: exports_external.string(),
  property_name: exports_external.string(),
  subcircuit_id: exports_external.string().optional(),
  error_type: exports_external.literal("source_property_ignored_warning").default("source_property_ignored_warning"),
  message: exports_external.string()
}).describe("The source property was ignored");
expectTypesMatch(true);
var source_pin_missing_trace_warning = exports_external.object({
  type: exports_external.literal("source_pin_missing_trace_warning"),
  source_pin_missing_trace_warning_id: getZodPrefixedIdWithDefault("source_pin_missing_trace_warning"),
  warning_type: exports_external.literal("source_pin_missing_trace_warning").default("source_pin_missing_trace_warning"),
  message: exports_external.string(),
  source_component_id: exports_external.string(),
  source_port_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when a source component pin is missing a trace connection");
expectTypesMatch(true);
var source_missing_manufacturer_part_number_warning = exports_external.object({
  type: exports_external.literal("source_missing_manufacturer_part_number_warning"),
  source_missing_manufacturer_part_number_warning_id: getZodPrefixedIdWithDefault("source_missing_manufacturer_part_number_warning"),
  warning_type: exports_external.literal("source_missing_manufacturer_part_number_warning").default("source_missing_manufacturer_part_number_warning"),
  message: exports_external.string(),
  source_component_id: exports_external.string(),
  standard: exports_external.string(),
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when a standard connector is missing manufacturer part number");
expectTypesMatch(true);
var source_simple_voltage_probe = source_component_base.extend({
  ftype: exports_external.literal("simple_voltage_probe")
});
expectTypesMatch(true);
var source_interconnect = source_component_base.extend({
  ftype: exports_external.literal("interconnect")
});
expectTypesMatch(true);
var source_i2c_misconfigured_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_i2c_misconfigured_error"),
  source_i2c_misconfigured_error_id: getZodPrefixedIdWithDefault("source_i2c_misconfigured_error"),
  error_type: exports_external.literal("source_i2c_misconfigured_error").default("source_i2c_misconfigured_error"),
  source_port_ids: exports_external.array(exports_external.string())
}).describe("Error emitted when incompatible I2C pins (e.g. SDA and SCL) are connected to the same net");
expectTypesMatch(true);
var source_component_misconfigured_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_component_misconfigured_error"),
  source_component_misconfigured_error_id: getZodPrefixedIdWithDefault("source_component_misconfigured_error"),
  error_type: exports_external.literal("source_component_misconfigured_error").default("source_component_misconfigured_error"),
  source_component_ids: exports_external.array(exports_external.string()),
  source_port_ids: exports_external.array(exports_external.string()).optional()
}).describe("Error emitted when one or more source components have an invalid or conflicting configuration");
expectTypesMatch(true);
var source_simple_voltage_source = source_component_base.extend({
  ftype: exports_external.literal("simple_voltage_source"),
  voltage,
  frequency: frequency.optional(),
  peak_to_peak_voltage: voltage.optional(),
  wave_shape: exports_external.enum(["sinewave", "square", "triangle", "sawtooth"]).optional(),
  phase: rotation.optional(),
  duty_cycle: exports_external.number().optional().describe("Duty cycle as a fraction (0 to 1)"),
  pulse_delay: ms.optional(),
  rise_time: ms.optional(),
  fall_time: ms.optional(),
  pulse_width: ms.optional(),
  period: ms.optional()
});
expectTypesMatch(true);
var any_source_component = exports_external.union([
  source_simple_resistor,
  source_simple_capacitor,
  source_simple_diode,
  source_simple_fiducial,
  source_simple_led,
  source_simple_ground,
  source_simple_chip,
  source_simple_power_source,
  source_simple_current_source,
  source_simple_ammeter,
  source_simple_battery,
  source_simple_inductor,
  source_simple_push_button,
  source_simple_potentiometer,
  source_simple_crystal,
  source_simple_pin_header,
  source_simple_connector,
  source_simple_pinout,
  source_simple_resonator,
  source_simple_switch,
  source_simple_transistor,
  source_simple_test_point,
  source_simple_mosfet,
  source_simple_op_amp,
  source_simple_fuse,
  source_simple_voltage_probe,
  source_interconnect,
  source_simple_voltage_source,
  source_project_metadata,
  source_missing_property_error,
  source_invalid_component_property_error,
  source_failed_to_create_component_error,
  source_trace_not_connected_error,
  source_property_ignored_warning,
  source_pin_missing_trace_warning,
  source_missing_manufacturer_part_number_warning,
  source_i2c_misconfigured_error,
  source_component_misconfigured_error
]);
expectTypesMatch(true);
var source_port = exports_external.object({
  type: exports_external.literal("source_port"),
  pin_number: exports_external.number().optional(),
  port_hints: exports_external.array(exports_external.string()).optional(),
  name: exports_external.string(),
  source_port_id: exports_external.string(),
  source_component_id: exports_external.string().optional(),
  source_group_id: exports_external.string().optional(),
  most_frequently_referenced_by_name: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional()
}).merge(source_pin_attributes);
expectTypesMatch(true);
var source_component_internal_connection = exports_external.object({
  type: exports_external.literal("source_component_internal_connection"),
  source_component_internal_connection_id: exports_external.string(),
  source_component_id: exports_external.string(),
  source_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
});
expectTypesMatch(true);
var source_trace = exports_external.object({
  type: exports_external.literal("source_trace"),
  source_trace_id: exports_external.string(),
  connected_source_port_ids: exports_external.array(exports_external.string()),
  connected_source_net_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional(),
  max_length: exports_external.number().optional(),
  name: exports_external.string().optional(),
  min_trace_thickness: exports_external.number().optional(),
  display_name: exports_external.string().optional()
});
expectTypesMatch(true);
var source_group = exports_external.object({
  type: exports_external.literal("source_group"),
  source_group_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional(),
  parent_subcircuit_id: exports_external.string().optional(),
  parent_source_group_id: exports_external.string().optional(),
  is_subcircuit: exports_external.boolean().optional(),
  show_as_schematic_box: exports_external.boolean().optional(),
  name: exports_external.string().optional(),
  was_automatically_named: exports_external.boolean().optional()
});
expectTypesMatch(true);
var source_net = exports_external.object({
  type: exports_external.literal("source_net"),
  source_net_id: exports_external.string(),
  name: exports_external.string(),
  member_source_group_ids: exports_external.array(exports_external.string()),
  is_power: exports_external.boolean().optional(),
  is_ground: exports_external.boolean().optional(),
  is_digital_signal: exports_external.boolean().optional(),
  is_analog_signal: exports_external.boolean().optional(),
  is_positive_voltage_source: exports_external.boolean().optional(),
  trace_width: exports_external.number().optional(),
  subcircuit_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional()
});
expectTypesMatch(true);
var source_board = exports_external.object({
  type: exports_external.literal("source_board"),
  source_board_id: exports_external.string(),
  source_group_id: exports_external.string(),
  title: exports_external.string().optional()
}).describe("Defines a board in the source domain");
expectTypesMatch(true);
var source_ambiguous_port_reference = base_circuit_json_error.extend({
  type: exports_external.literal("source_ambiguous_port_reference"),
  source_ambiguous_port_reference_id: getZodPrefixedIdWithDefault("source_ambiguous_port_reference"),
  error_type: exports_external.literal("source_ambiguous_port_reference").default("source_ambiguous_port_reference"),
  source_port_id: exports_external.string().optional(),
  source_component_id: exports_external.string().optional()
}).describe("Error emitted when a port hint matches multiple non-overlapping pads, making the port reference ambiguous");
expectTypesMatch(true);
var source_pcb_ground_plane = exports_external.object({
  type: exports_external.literal("source_pcb_ground_plane"),
  source_pcb_ground_plane_id: exports_external.string(),
  source_group_id: exports_external.string(),
  source_net_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a ground plane in the source domain");
expectTypesMatch(true);
var all_layers = [
  "top",
  "bottom",
  "inner1",
  "inner2",
  "inner3",
  "inner4",
  "inner5",
  "inner6"
];
var layer_string = exports_external.enum(all_layers);
var layer_ref = layer_string.or(exports_external.object({
  name: layer_string
})).transform((layer) => {
  if (typeof layer === "string") {
    return layer;
  }
  return layer.name;
});
expectTypesMatch(true);
var visible_layer = exports_external.enum(["top", "bottom"]);
var source_manually_placed_via = exports_external.object({
  type: exports_external.literal("source_manually_placed_via"),
  source_manually_placed_via_id: exports_external.string(),
  source_group_id: exports_external.string(),
  source_net_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional(),
  source_trace_id: exports_external.string().optional()
}).describe("Defines a via that is manually placed in the source domain");
expectTypesMatch(true);
var source_unnamed_trace_warning = exports_external.object({
  type: exports_external.literal("source_unnamed_trace_warning"),
  source_unnamed_trace_warning_id: getZodPrefixedIdWithDefault("source_unnamed_trace_warning"),
  warning_type: exports_external.literal("source_unnamed_trace_warning").default("source_unnamed_trace_warning"),
  message: exports_external.string(),
  source_trace_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when a source trace is missing a name");
expectTypesMatch(true);
var source_no_power_pin_defined_warning = exports_external.object({
  type: exports_external.literal("source_no_power_pin_defined_warning"),
  source_no_power_pin_defined_warning_id: getZodPrefixedIdWithDefault("source_no_power_pin_defined_warning"),
  warning_type: exports_external.literal("source_no_power_pin_defined_warning").default("source_no_power_pin_defined_warning"),
  message: exports_external.string(),
  source_component_id: exports_external.string(),
  source_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when a chip has no source ports with requires_power=true");
expectTypesMatch(true);
var source_no_ground_pin_defined_warning = exports_external.object({
  type: exports_external.literal("source_no_ground_pin_defined_warning"),
  source_no_ground_pin_defined_warning_id: getZodPrefixedIdWithDefault("source_no_ground_pin_defined_warning"),
  warning_type: exports_external.literal("source_no_ground_pin_defined_warning").default("source_no_ground_pin_defined_warning"),
  message: exports_external.string(),
  source_component_id: exports_external.string(),
  source_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when a chip has no source ports marked as ground pins");
expectTypesMatch(true);
var source_component_pins_underspecified_warning = exports_external.object({
  type: exports_external.literal("source_component_pins_underspecified_warning"),
  source_component_pins_underspecified_warning_id: getZodPrefixedIdWithDefault("source_component_pins_underspecified_warning"),
  warning_type: exports_external.literal("source_component_pins_underspecified_warning").default("source_component_pins_underspecified_warning"),
  message: exports_external.string(),
  source_component_id: exports_external.string(),
  source_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when all ports on a source component are underspecified");
expectTypesMatch(true);
var source_pin_must_be_connected_error = base_circuit_json_error.extend({
  type: exports_external.literal("source_pin_must_be_connected_error"),
  source_pin_must_be_connected_error_id: getZodPrefixedIdWithDefault("source_pin_must_be_connected_error"),
  error_type: exports_external.literal("source_pin_must_be_connected_error").default("source_pin_must_be_connected_error"),
  source_component_id: exports_external.string(),
  source_port_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when a pin with mustBeConnected attribute is not connected to any trace");
expectTypesMatch(true);
var unknown_error_finding_part = base_circuit_json_error.extend({
  type: exports_external.literal("unknown_error_finding_part"),
  unknown_error_finding_part_id: getZodPrefixedIdWithDefault("unknown_error_finding_part"),
  error_type: exports_external.literal("unknown_error_finding_part").default("unknown_error_finding_part"),
  source_component_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when an unexpected error occurs while finding a part");
expectTypesMatch(true);
var schematic_box = exports_external.object({
  type: exports_external.literal("schematic_box"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  width: distance4,
  height: distance4,
  is_dashed: exports_external.boolean().default(false),
  x: distance4,
  y: distance4,
  subcircuit_id: exports_external.string().optional()
}).describe("Draws a box on the schematic");
expectTypesMatch(true);
var schematic_path = exports_external.object({
  type: exports_external.literal("schematic_path"),
  schematic_path_id: getZodPrefixedIdWithDefault("schematic_path"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  fill_color: exports_external.string().optional(),
  is_filled: exports_external.boolean().optional(),
  is_dashed: exports_external.boolean().default(false),
  stroke_width: distance4.nullable().optional(),
  stroke_color: exports_external.string().optional(),
  dash_length: distance4.optional(),
  dash_gap: distance4.optional(),
  points: exports_external.array(point),
  subcircuit_id: exports_external.string().optional()
});
expectTypesMatch(true);
var schematic_pin_styles = exports_external.record(exports_external.object({
  left_margin: length.optional(),
  right_margin: length.optional(),
  top_margin: length.optional(),
  bottom_margin: length.optional()
}));
var schematic_component_port_arrangement_by_size = exports_external.object({
  left_size: exports_external.number(),
  right_size: exports_external.number(),
  top_size: exports_external.number().optional(),
  bottom_size: exports_external.number().optional()
});
expectTypesMatch(true);
var schematic_component_port_arrangement_by_sides = exports_external.object({
  left_side: exports_external.object({
    pins: exports_external.array(exports_external.number()),
    direction: exports_external.enum(["top-to-bottom", "bottom-to-top"]).optional()
  }).optional(),
  right_side: exports_external.object({
    pins: exports_external.array(exports_external.number()),
    direction: exports_external.enum(["top-to-bottom", "bottom-to-top"]).optional()
  }).optional(),
  top_side: exports_external.object({
    pins: exports_external.array(exports_external.number()),
    direction: exports_external.enum(["left-to-right", "right-to-left"]).optional()
  }).optional(),
  bottom_side: exports_external.object({
    pins: exports_external.array(exports_external.number()),
    direction: exports_external.enum(["left-to-right", "right-to-left"]).optional()
  }).optional()
});
expectTypesMatch(true);
var port_arrangement = exports_external.union([
  schematic_component_port_arrangement_by_size,
  schematic_component_port_arrangement_by_sides
]);
var schematic_component = exports_external.object({
  type: exports_external.literal("schematic_component"),
  size,
  center: point,
  source_component_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string(),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  pin_spacing: length.optional(),
  pin_styles: schematic_pin_styles.optional(),
  box_width: length.optional(),
  symbol_name: exports_external.string().optional(),
  port_arrangement: port_arrangement.optional(),
  port_labels: exports_external.record(exports_external.string()).optional(),
  symbol_display_value: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  schematic_group_id: exports_external.string().optional(),
  is_schematic_group: exports_external.boolean().optional(),
  source_group_id: exports_external.string().optional(),
  is_box_with_pins: exports_external.boolean().optional().default(true)
});
expectTypesMatch(true);
var schematicSymbolMetadata = exports_external.object({
  kicad_symbol: kicadSymbolMetadata.optional()
}).catchall(exports_external.unknown());
var schematic_symbol = exports_external.object({
  type: exports_external.literal("schematic_symbol"),
  schematic_symbol_id: exports_external.string(),
  name: exports_external.string().optional(),
  metadata: schematicSymbolMetadata.optional()
}).describe("Defines a named schematic symbol that can be referenced by components.");
expectTypesMatch(true);
var schematic_line = exports_external.object({
  type: exports_external.literal("schematic_line"),
  schematic_line_id: getZodPrefixedIdWithDefault("schematic_line"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  x1: distance4,
  y1: distance4,
  x2: distance4,
  y2: distance4,
  stroke_width: distance4.nullable().optional(),
  color: exports_external.string().default("#000000"),
  is_dashed: exports_external.boolean().default(false),
  dash_length: distance4.optional(),
  dash_gap: distance4.optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Draws a styled line on the schematic");
expectTypesMatch(true);
var schematic_rect = exports_external.object({
  type: exports_external.literal("schematic_rect"),
  schematic_rect_id: getZodPrefixedIdWithDefault("schematic_rect"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  center: point,
  width: distance4,
  height: distance4,
  rotation: rotation.default(0),
  stroke_width: distance4.nullable().optional(),
  color: exports_external.string().default("#000000"),
  is_filled: exports_external.boolean().default(false),
  fill_color: exports_external.string().optional(),
  is_dashed: exports_external.boolean().default(false),
  subcircuit_id: exports_external.string().optional()
}).describe("Draws a styled rectangle on the schematic");
expectTypesMatch(true);
var schematic_circle = exports_external.object({
  type: exports_external.literal("schematic_circle"),
  schematic_circle_id: getZodPrefixedIdWithDefault("schematic_circle"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  center: point,
  radius: distance4,
  stroke_width: distance4.nullable().optional(),
  color: exports_external.string().default("#000000"),
  is_filled: exports_external.boolean().default(false),
  fill_color: exports_external.string().optional(),
  is_dashed: exports_external.boolean().default(false),
  subcircuit_id: exports_external.string().optional()
}).describe("Draws a styled circle on the schematic");
expectTypesMatch(true);
var schematic_arc = exports_external.object({
  type: exports_external.literal("schematic_arc"),
  schematic_arc_id: getZodPrefixedIdWithDefault("schematic_arc"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  center: point,
  radius: distance4,
  start_angle_degrees: rotation,
  end_angle_degrees: rotation,
  direction: exports_external.enum(["clockwise", "counterclockwise"]).default("counterclockwise"),
  stroke_width: distance4.nullable().optional(),
  color: exports_external.string().default("#000000"),
  is_dashed: exports_external.boolean().default(false),
  subcircuit_id: exports_external.string().optional()
}).describe("Draws a styled arc on the schematic");
expectTypesMatch(true);
var schematic_trace = exports_external.object({
  type: exports_external.literal("schematic_trace"),
  schematic_trace_id: exports_external.string(),
  schematic_sheet_id: exports_external.string().optional(),
  source_trace_id: exports_external.string().optional(),
  junctions: exports_external.array(exports_external.object({
    x: exports_external.number(),
    y: exports_external.number()
  })),
  edges: exports_external.array(exports_external.object({
    from: exports_external.object({
      x: exports_external.number(),
      y: exports_external.number()
    }),
    to: exports_external.object({
      x: exports_external.number(),
      y: exports_external.number()
    }),
    is_crossing: exports_external.boolean().optional(),
    from_schematic_port_id: exports_external.string().optional(),
    to_schematic_port_id: exports_external.string().optional()
  })),
  subcircuit_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional()
});
expectTypesMatch(true);
var fivePointAnchor = exports_external.enum([
  "center",
  "left",
  "right",
  "top",
  "bottom"
]);
expectTypesMatch(true);
var schematic_text = exports_external.object({
  type: exports_external.literal("schematic_text"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  schematic_symbol_id: exports_external.string().optional(),
  schematic_text_id: exports_external.string(),
  text: exports_external.string(),
  font_size: exports_external.number().default(0.18),
  position: exports_external.object({
    x: distance4,
    y: distance4
  }),
  rotation: exports_external.number().default(0),
  anchor: exports_external.union([fivePointAnchor.describe("legacy"), ninePointAnchor]).default("center"),
  color: exports_external.string().default("#000000"),
  subcircuit_id: exports_external.string().optional()
});
expectTypesMatch(true);
var schematic_port = exports_external.object({
  type: exports_external.literal("schematic_port"),
  schematic_port_id: exports_external.string(),
  source_port_id: exports_external.string(),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  center: point,
  facing_direction: exports_external.enum(["up", "down", "left", "right"]).optional(),
  distance_from_component_edge: exports_external.number().optional(),
  side_of_component: exports_external.enum(["top", "bottom", "left", "right"]).optional(),
  true_ccw_index: exports_external.number().optional(),
  pin_number: exports_external.number().optional(),
  display_pin_label: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  is_connected: exports_external.boolean().optional(),
  has_input_arrow: exports_external.boolean().optional(),
  has_output_arrow: exports_external.boolean().optional(),
  is_drawn_with_inversion_circle: exports_external.boolean().optional()
}).describe("Defines a port on a schematic component");
expectTypesMatch(true);
var schematic_net_label = exports_external.object({
  type: exports_external.literal("schematic_net_label"),
  schematic_net_label_id: getZodPrefixedIdWithDefault("schematic_net_label"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_trace_id: exports_external.string().optional(),
  source_trace_id: exports_external.string().optional(),
  source_net_id: exports_external.string(),
  center: point,
  anchor_position: point.optional(),
  anchor_side: exports_external.enum(["top", "bottom", "left", "right"]),
  text: exports_external.string(),
  symbol_name: exports_external.string().optional(),
  is_movable: exports_external.boolean().optional(),
  subcircuit_id: exports_external.string().optional()
});
expectTypesMatch(true);
var schematic_error = base_circuit_json_error.extend({
  type: exports_external.literal("schematic_error"),
  schematic_error_id: exports_external.string(),
  error_type: exports_external.literal("schematic_port_not_found").default("schematic_port_not_found"),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a schematic error on the schematic");
expectTypesMatch(true);
var schematic_layout_error = base_circuit_json_error.extend({
  type: exports_external.literal("schematic_layout_error"),
  schematic_layout_error_id: getZodPrefixedIdWithDefault("schematic_layout_error"),
  error_type: exports_external.literal("schematic_layout_error").default("schematic_layout_error"),
  source_group_id: exports_external.string(),
  schematic_group_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when schematic layout fails for a group");
expectTypesMatch(true);
var schematic_debug_object_base = exports_external.object({
  type: exports_external.literal("schematic_debug_object"),
  label: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
});
var schematic_debug_rect = schematic_debug_object_base.extend({
  shape: exports_external.literal("rect"),
  center: point,
  size
});
var schematic_debug_line = schematic_debug_object_base.extend({
  shape: exports_external.literal("line"),
  start: point,
  end: point
});
var schematic_debug_point = schematic_debug_object_base.extend({
  shape: exports_external.literal("point"),
  center: point
});
var schematic_debug_object = exports_external.discriminatedUnion("shape", [
  schematic_debug_rect,
  schematic_debug_line,
  schematic_debug_point
]);
expectTypesMatch(true);
var schematic_voltage_probe = exports_external.object({
  type: exports_external.literal("schematic_voltage_probe"),
  schematic_voltage_probe_id: exports_external.string(),
  schematic_sheet_id: exports_external.string().optional(),
  source_component_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  position: point,
  schematic_trace_id: exports_external.string(),
  voltage: voltage.optional(),
  subcircuit_id: exports_external.string().optional(),
  color: exports_external.string().optional(),
  label_alignment: ninePointAnchor.optional()
}).describe("Defines a voltage probe measurement point on a schematic trace");
expectTypesMatch(true);
var schematic_manual_edit_conflict_warning = exports_external.object({
  type: exports_external.literal("schematic_manual_edit_conflict_warning"),
  schematic_manual_edit_conflict_warning_id: getZodPrefixedIdWithDefault("schematic_manual_edit_conflict_warning"),
  warning_type: exports_external.literal("schematic_manual_edit_conflict_warning").default("schematic_manual_edit_conflict_warning"),
  message: exports_external.string(),
  schematic_component_id: exports_external.string(),
  schematic_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  source_component_id: exports_external.string()
}).describe("Warning emitted when a component has both manual placement and explicit schX/schY coordinates");
expectTypesMatch(true);
var schematic_group = exports_external.object({
  type: exports_external.literal("schematic_group"),
  schematic_group_id: getZodPrefixedIdWithDefault("schematic_group"),
  schematic_sheet_id: exports_external.string().optional(),
  source_group_id: exports_external.string(),
  is_subcircuit: exports_external.boolean().optional(),
  subcircuit_id: exports_external.string().optional(),
  width: length,
  height: length,
  center: point,
  schematic_component_ids: exports_external.array(exports_external.string()),
  show_as_schematic_box: exports_external.boolean().optional(),
  name: exports_external.string().optional(),
  description: exports_external.string().optional()
}).describe("Defines a group of components on the schematic");
expectTypesMatch(true);
var schematic_table = exports_external.object({
  type: exports_external.literal("schematic_table"),
  schematic_table_id: getZodPrefixedIdWithDefault("schematic_table"),
  schematic_sheet_id: exports_external.string().optional(),
  anchor_position: point,
  column_widths: exports_external.array(distance4),
  row_heights: exports_external.array(distance4),
  cell_padding: distance4.optional(),
  border_width: distance4.optional(),
  subcircuit_id: exports_external.string().optional(),
  schematic_component_id: exports_external.string().optional(),
  anchor: ninePointAnchor.optional()
}).describe("Defines a table on the schematic");
expectTypesMatch(true);
var schematic_table_cell = exports_external.object({
  type: exports_external.literal("schematic_table_cell"),
  schematic_table_cell_id: getZodPrefixedIdWithDefault("schematic_table_cell"),
  schematic_sheet_id: exports_external.string().optional(),
  schematic_table_id: exports_external.string(),
  start_row_index: exports_external.number(),
  end_row_index: exports_external.number(),
  start_column_index: exports_external.number(),
  end_column_index: exports_external.number(),
  text: exports_external.string().optional(),
  center: point,
  width: distance4,
  height: distance4,
  horizontal_align: exports_external.enum(["left", "center", "right"]).optional(),
  vertical_align: exports_external.enum(["top", "middle", "bottom"]).optional(),
  font_size: distance4.optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a cell within a schematic_table");
expectTypesMatch(true);
var schematic_sheet = exports_external.object({
  type: exports_external.literal("schematic_sheet"),
  schematic_sheet_id: getZodPrefixedIdWithDefault("schematic_sheet"),
  name: exports_external.string().optional(),
  sheet_index: exports_external.number().optional(),
  subcircuit_id: exports_external.string().optional(),
  outline_color: exports_external.string().optional()
}).describe("Defines a schematic sheet or page that components can be placed on");
expectTypesMatch(true);
var point_with_bulge = exports_external.object({
  x: distance4,
  y: distance4,
  bulge: exports_external.number().optional()
});
expectTypesMatch(true);
var ring = exports_external.object({
  vertices: exports_external.array(point_with_bulge)
});
expectTypesMatch(true);
var brep_shape = exports_external.object({
  outer_ring: ring,
  inner_rings: exports_external.array(ring).default([])
});
expectTypesMatch(true);
var pcb_route_hint = exports_external.object({
  x: distance4,
  y: distance4,
  via: exports_external.boolean().optional(),
  via_to_layer: layer_ref.optional()
});
var pcb_route_hints = exports_external.array(pcb_route_hint);
expectTypesMatch(true);
expectTypesMatch(true);
var route_hint_point = exports_external.object({
  x: distance4,
  y: distance4,
  via: exports_external.boolean().optional(),
  to_layer: layer_ref.optional(),
  trace_width: distance4.optional()
});
expectTypesMatch(true);
var manufacturing_drc_properties = exports_external.object({
  min_trace_width: length.optional(),
  min_board_edge_clearance: length.optional(),
  min_via_hole_edge_to_via_hole_edge_clearance: length.optional(),
  min_plated_hole_drill_edge_to_drill_edge_clearance: length.optional(),
  min_trace_to_pad_edge_clearance: length.optional(),
  min_pad_edge_to_pad_edge_clearance: length.optional(),
  min_same_net_trace_edge_to_trace_edge_clearance: length.optional(),
  min_different_net_trace_edge_to_trace_edge_clearance: length.optional(),
  min_via_edge_to_pad_edge_clearance: length.optional(),
  min_via_hole_diameter: length.optional(),
  min_via_pad_diameter: length.optional()
});
var pcb_component = exports_external.object({
  type: exports_external.literal("pcb_component"),
  pcb_component_id: getZodPrefixedIdWithDefault("pcb_component"),
  source_component_id: exports_external.string(),
  center: point,
  layer: layer_ref,
  rotation,
  display_offset_x: exports_external.string().optional().describe("How to display the x offset for this part, usually corresponding with how the user specified it"),
  display_offset_y: exports_external.string().optional().describe("How to display the y offset for this part, usually corresponding with how the user specified it"),
  width: length,
  height: length,
  do_not_place: exports_external.boolean().optional(),
  is_allowed_to_be_off_board: exports_external.boolean().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  position_mode: exports_external.enum([
    "packed",
    "relative_to_group_anchor",
    "relative_to_another_component",
    "none"
  ]).optional(),
  anchor_position: point.optional(),
  anchor_alignment: ninePointAnchor.optional(),
  positioned_relative_to_pcb_group_id: exports_external.string().optional(),
  positioned_relative_to_pcb_board_id: exports_external.string().optional(),
  cable_insertion_center: point.optional(),
  insertion_direction: exports_external.enum([
    "from_above",
    "from_left",
    "from_right",
    "from_front",
    "from_back"
  ]).optional(),
  metadata: exports_external.object({
    kicad_footprint: kicadFootprintMetadata.optional()
  }).optional(),
  obstructs_within_bounds: exports_external.boolean().default(true).describe("Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath")
}).describe("Defines a component on the PCB");
expectTypesMatch(true);
var pcb_hole_circle = exports_external.object({
  type: exports_external.literal("pcb_hole"),
  pcb_hole_id: getZodPrefixedIdWithDefault("pcb_hole"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("circle"),
  hole_diameter: exports_external.number(),
  x: distance4,
  y: distance4,
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_circle_shape = pcb_hole_circle.describe("Defines a circular hole on the PCB");
expectTypesMatch(true);
var pcb_hole_rect = exports_external.object({
  type: exports_external.literal("pcb_hole"),
  pcb_hole_id: getZodPrefixedIdWithDefault("pcb_hole"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("rect"),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  x: distance4,
  y: distance4,
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_rect_shape = pcb_hole_rect.describe("Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square.");
expectTypesMatch(true);
var pcb_hole_circle_or_square = exports_external.object({
  type: exports_external.literal("pcb_hole"),
  pcb_hole_id: getZodPrefixedIdWithDefault("pcb_hole"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  hole_shape: exports_external.enum(["circle", "square"]),
  hole_diameter: exports_external.number(),
  x: distance4,
  y: distance4,
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_circle_or_square_shape = pcb_hole_circle_or_square.describe("Defines a circular or square hole on the PCB");
expectTypesMatch(true);
var pcb_hole_oval = exports_external.object({
  type: exports_external.literal("pcb_hole"),
  pcb_hole_id: getZodPrefixedIdWithDefault("pcb_hole"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("oval"),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  x: distance4,
  y: distance4,
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_oval_shape = pcb_hole_oval.describe("Defines an oval hole on the PCB");
expectTypesMatch(true);
var pcb_hole_pill = exports_external.object({
  type: exports_external.literal("pcb_hole"),
  pcb_hole_id: getZodPrefixedIdWithDefault("pcb_hole"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("pill"),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  x: distance4,
  y: distance4,
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_pill_shape = pcb_hole_pill.describe("Defines a pill-shaped hole on the PCB");
expectTypesMatch(true);
var pcb_hole_rotated_pill = exports_external.object({
  type: exports_external.literal("pcb_hole"),
  pcb_hole_id: getZodPrefixedIdWithDefault("pcb_hole"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("rotated_pill"),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  x: distance4,
  y: distance4,
  ccw_rotation: rotation,
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_rotated_pill_shape = pcb_hole_rotated_pill.describe("Defines a rotated pill-shaped hole on the PCB");
expectTypesMatch(true);
var pcb_hole = pcb_hole_circle_or_square.or(pcb_hole_oval).or(pcb_hole_pill).or(pcb_hole_rotated_pill).or(pcb_hole_circle).or(pcb_hole_rect);
var pcb_plated_hole_circle = exports_external.object({
  type: exports_external.literal("pcb_plated_hole"),
  shape: exports_external.literal("circle"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  outer_diameter: exports_external.number(),
  hole_diameter: exports_external.number(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  x: distance4,
  y: distance4,
  layers: exports_external.array(layer_ref),
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
  soldermask_margin: exports_external.number().optional()
});
var pcb_plated_hole_oval = exports_external.object({
  type: exports_external.literal("pcb_plated_hole"),
  shape: exports_external.enum(["oval", "pill"]),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  outer_width: exports_external.number(),
  outer_height: exports_external.number(),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  x: distance4,
  y: distance4,
  ccw_rotation: rotation,
  layers: exports_external.array(layer_ref),
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
  soldermask_margin: exports_external.number().optional()
});
var pcb_circular_hole_with_rect_pad = exports_external.object({
  type: exports_external.literal("pcb_plated_hole"),
  shape: exports_external.literal("circular_hole_with_rect_pad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("circle"),
  pad_shape: exports_external.literal("rect"),
  hole_diameter: exports_external.number(),
  rect_pad_width: exports_external.number(),
  rect_pad_height: exports_external.number(),
  rect_border_radius: exports_external.number().optional(),
  hole_offset_x: distance4.default(0),
  hole_offset_y: distance4.default(0),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  x: distance4,
  y: distance4,
  layers: exports_external.array(layer_ref),
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
  soldermask_margin: exports_external.number().optional(),
  rect_ccw_rotation: rotation.optional()
});
var pcb_pill_hole_with_rect_pad = exports_external.object({
  type: exports_external.literal("pcb_plated_hole"),
  shape: exports_external.literal("pill_hole_with_rect_pad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("pill"),
  pad_shape: exports_external.literal("rect"),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  rect_pad_width: exports_external.number(),
  rect_pad_height: exports_external.number(),
  rect_border_radius: exports_external.number().optional(),
  hole_offset_x: distance4.default(0),
  hole_offset_y: distance4.default(0),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  x: distance4,
  y: distance4,
  layers: exports_external.array(layer_ref),
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
  soldermask_margin: exports_external.number().optional()
});
var pcb_rotated_pill_hole_with_rect_pad = exports_external.object({
  type: exports_external.literal("pcb_plated_hole"),
  shape: exports_external.literal("rotated_pill_hole_with_rect_pad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  hole_shape: exports_external.literal("rotated_pill"),
  pad_shape: exports_external.literal("rect"),
  hole_width: exports_external.number(),
  hole_height: exports_external.number(),
  hole_ccw_rotation: rotation,
  rect_pad_width: exports_external.number(),
  rect_pad_height: exports_external.number(),
  rect_border_radius: exports_external.number().optional(),
  rect_ccw_rotation: rotation,
  hole_offset_x: distance4.default(0),
  hole_offset_y: distance4.default(0),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  x: distance4,
  y: distance4,
  layers: exports_external.array(layer_ref),
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
  soldermask_margin: exports_external.number().optional()
});
var pcb_hole_with_polygon_pad = exports_external.object({
  type: exports_external.literal("pcb_plated_hole"),
  shape: exports_external.literal("hole_with_polygon_pad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  hole_shape: exports_external.enum(["circle", "oval", "pill", "rotated_pill"]),
  hole_diameter: exports_external.number().optional(),
  hole_width: exports_external.number().optional(),
  hole_height: exports_external.number().optional(),
  pad_outline: exports_external.array(exports_external.object({
    x: distance4,
    y: distance4
  })).min(3),
  hole_offset_x: distance4.default(0),
  hole_offset_y: distance4.default(0),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  x: distance4,
  y: distance4,
  layers: exports_external.array(layer_ref),
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
  soldermask_margin: exports_external.number().optional(),
  ccw_rotation: rotation.optional()
});
var pcb_plated_hole = exports_external.union([
  pcb_plated_hole_circle,
  pcb_plated_hole_oval,
  pcb_circular_hole_with_rect_pad,
  pcb_pill_hole_with_rect_pad,
  pcb_rotated_pill_hole_with_rect_pad,
  pcb_hole_with_polygon_pad
]);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
var pcb_port = exports_external.object({
  type: exports_external.literal("pcb_port"),
  pcb_port_id: getZodPrefixedIdWithDefault("pcb_port"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  source_port_id: exports_external.string(),
  pcb_component_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  layers: exports_external.array(layer_ref),
  is_board_pinout: exports_external.boolean().optional()
}).describe("Defines a port on the PCB");
expectTypesMatch(true);
var pcb_smtpad_circle = exports_external.object({
  type: exports_external.literal("pcb_smtpad"),
  shape: exports_external.literal("circle"),
  pcb_smtpad_id: getZodPrefixedIdWithDefault("pcb_smtpad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  radius: exports_external.number(),
  layer: layer_ref,
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_smtpad_rect = exports_external.object({
  type: exports_external.literal("pcb_smtpad"),
  shape: exports_external.literal("rect"),
  pcb_smtpad_id: getZodPrefixedIdWithDefault("pcb_smtpad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  rect_border_radius: exports_external.number().optional(),
  corner_radius: exports_external.number().optional(),
  layer: layer_ref,
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional(),
  soldermask_margin_left: exports_external.number().optional(),
  soldermask_margin_top: exports_external.number().optional(),
  soldermask_margin_right: exports_external.number().optional(),
  soldermask_margin_bottom: exports_external.number().optional()
});
var pcb_smtpad_rotated_rect = exports_external.object({
  type: exports_external.literal("pcb_smtpad"),
  shape: exports_external.literal("rotated_rect"),
  pcb_smtpad_id: getZodPrefixedIdWithDefault("pcb_smtpad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  rect_border_radius: exports_external.number().optional(),
  corner_radius: exports_external.number().optional(),
  ccw_rotation: rotation,
  layer: layer_ref,
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional(),
  soldermask_margin_left: exports_external.number().optional(),
  soldermask_margin_top: exports_external.number().optional(),
  soldermask_margin_right: exports_external.number().optional(),
  soldermask_margin_bottom: exports_external.number().optional()
});
var pcb_smtpad_pill = exports_external.object({
  type: exports_external.literal("pcb_smtpad"),
  shape: exports_external.literal("pill"),
  pcb_smtpad_id: getZodPrefixedIdWithDefault("pcb_smtpad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  radius: exports_external.number(),
  layer: layer_ref,
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_smtpad_rotated_pill = exports_external.object({
  type: exports_external.literal("pcb_smtpad"),
  shape: exports_external.literal("rotated_pill"),
  pcb_smtpad_id: getZodPrefixedIdWithDefault("pcb_smtpad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  radius: exports_external.number(),
  ccw_rotation: rotation,
  layer: layer_ref,
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_smtpad_polygon = exports_external.object({
  type: exports_external.literal("pcb_smtpad"),
  shape: exports_external.literal("polygon"),
  pcb_smtpad_id: getZodPrefixedIdWithDefault("pcb_smtpad"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  points: exports_external.array(point),
  layer: layer_ref,
  port_hints: exports_external.array(exports_external.string()).optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_port_id: exports_external.string().optional(),
  is_covered_with_solder_mask: exports_external.boolean().optional(),
  soldermask_margin: exports_external.number().optional()
});
var pcb_smtpad = exports_external.discriminatedUnion("shape", [
  pcb_smtpad_circle,
  pcb_smtpad_rect,
  pcb_smtpad_rotated_rect,
  pcb_smtpad_rotated_pill,
  pcb_smtpad_pill,
  pcb_smtpad_polygon
]).describe("Defines an SMT pad on the PCB");
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
var pcb_solder_paste_circle = exports_external.object({
  type: exports_external.literal("pcb_solder_paste"),
  shape: exports_external.literal("circle"),
  pcb_solder_paste_id: getZodPrefixedIdWithDefault("pcb_solder_paste"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  radius: exports_external.number(),
  layer: layer_ref,
  pcb_component_id: exports_external.string().optional(),
  pcb_smtpad_id: exports_external.string().optional()
});
var pcb_solder_paste_rect = exports_external.object({
  type: exports_external.literal("pcb_solder_paste"),
  shape: exports_external.literal("rect"),
  pcb_solder_paste_id: getZodPrefixedIdWithDefault("pcb_solder_paste"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  layer: layer_ref,
  pcb_component_id: exports_external.string().optional(),
  pcb_smtpad_id: exports_external.string().optional()
});
var pcb_solder_paste_pill = exports_external.object({
  type: exports_external.literal("pcb_solder_paste"),
  shape: exports_external.literal("pill"),
  pcb_solder_paste_id: getZodPrefixedIdWithDefault("pcb_solder_paste"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  radius: exports_external.number(),
  layer: layer_ref,
  pcb_component_id: exports_external.string().optional(),
  pcb_smtpad_id: exports_external.string().optional()
});
var pcb_solder_paste_rotated_rect = exports_external.object({
  type: exports_external.literal("pcb_solder_paste"),
  shape: exports_external.literal("rotated_rect"),
  pcb_solder_paste_id: getZodPrefixedIdWithDefault("pcb_solder_paste"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  ccw_rotation: distance4,
  layer: layer_ref,
  pcb_component_id: exports_external.string().optional(),
  pcb_smtpad_id: exports_external.string().optional()
});
var pcb_solder_paste_oval = exports_external.object({
  type: exports_external.literal("pcb_solder_paste"),
  shape: exports_external.literal("oval"),
  pcb_solder_paste_id: getZodPrefixedIdWithDefault("pcb_solder_paste"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  width: exports_external.number(),
  height: exports_external.number(),
  layer: layer_ref,
  pcb_component_id: exports_external.string().optional(),
  pcb_smtpad_id: exports_external.string().optional()
});
var pcb_solder_paste = exports_external.union([
  pcb_solder_paste_circle,
  pcb_solder_paste_rect,
  pcb_solder_paste_pill,
  pcb_solder_paste_rotated_rect,
  pcb_solder_paste_oval
]).describe("Defines solderpaste on the PCB");
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
var pcb_text = exports_external.object({
  type: exports_external.literal("pcb_text"),
  pcb_text_id: getZodPrefixedIdWithDefault("pcb_text"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  text: exports_external.string(),
  center: point,
  layer: layer_ref,
  width: length,
  height: length,
  lines: exports_external.number(),
  align: exports_external.enum(["bottom-left"])
}).describe("Defines text on the PCB");
expectTypesMatch(true);
var pcb_trace_route_point_wire = exports_external.object({
  route_type: exports_external.literal("wire"),
  x: distance4,
  y: distance4,
  width: distance4,
  copper_pour_id: exports_external.string().optional(),
  is_inside_copper_pour: exports_external.boolean().optional(),
  start_pcb_port_id: exports_external.string().optional(),
  end_pcb_port_id: exports_external.string().optional(),
  layer: layer_ref
});
var pcb_trace_route_point_via = exports_external.object({
  route_type: exports_external.literal("via"),
  x: distance4,
  y: distance4,
  copper_pour_id: exports_external.string().optional(),
  is_inside_copper_pour: exports_external.boolean().optional(),
  hole_diameter: distance4.optional(),
  outer_diameter: distance4.optional(),
  from_layer: layer_ref,
  to_layer: layer_ref
});
var pcb_trace_route_point_through_pad = exports_external.object({
  route_type: exports_external.literal("through_pad"),
  start: point,
  end: point,
  width: distance4,
  start_layer: layer_ref,
  end_layer: layer_ref,
  pcb_smtpad_id: exports_external.string().optional(),
  pcb_plated_hole_id: exports_external.string().optional()
});
var pcb_trace_route_point = exports_external.union([
  pcb_trace_route_point_wire,
  pcb_trace_route_point_via,
  pcb_trace_route_point_through_pad
]);
var pcb_trace = exports_external.object({
  type: exports_external.literal("pcb_trace"),
  source_trace_id: exports_external.string().optional(),
  pcb_component_id: exports_external.string().optional(),
  pcb_trace_id: getZodPrefixedIdWithDefault("pcb_trace"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  route_thickness_mode: exports_external.enum(["constant", "interpolated"]).default("constant").optional(),
  route_order_index: exports_external.number().optional(),
  should_round_corners: exports_external.boolean().optional(),
  trace_length: exports_external.number().optional(),
  highlight_color: exports_external.string().optional(),
  route: exports_external.array(pcb_trace_route_point)
}).describe("Defines a trace on the PCB");
expectTypesMatch(true);
expectTypesMatch(true);
var pcb_trace_warning = exports_external.object({
  type: exports_external.literal("pcb_trace_warning"),
  pcb_trace_warning_id: getZodPrefixedIdWithDefault("pcb_trace_warning"),
  warning_type: exports_external.literal("pcb_trace_warning").default("pcb_trace_warning"),
  message: exports_external.string(),
  center: point.optional(),
  pcb_trace_id: exports_external.string(),
  source_trace_id: exports_external.string(),
  pcb_component_ids: exports_external.array(exports_external.string()),
  pcb_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a trace warning on the PCB");
expectTypesMatch(true);
var pcb_trace_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_trace_error"),
  pcb_trace_error_id: getZodPrefixedIdWithDefault("pcb_trace_error"),
  error_type: exports_external.literal("pcb_trace_error").default("pcb_trace_error"),
  center: point.optional(),
  pcb_trace_id: exports_external.string(),
  source_trace_id: exports_external.string(),
  pcb_component_ids: exports_external.array(exports_external.string()),
  pcb_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a trace error on the PCB");
expectTypesMatch(true);
var pcb_trace_missing_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_trace_missing_error"),
  pcb_trace_missing_error_id: getZodPrefixedIdWithDefault("pcb_trace_missing_error"),
  error_type: exports_external.literal("pcb_trace_missing_error").default("pcb_trace_missing_error"),
  center: point.optional(),
  source_trace_id: exports_external.string(),
  pcb_component_ids: exports_external.array(exports_external.string()),
  pcb_port_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines an error when a source trace has no corresponding PCB trace");
expectTypesMatch(true);
var pcb_port_not_matched_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_port_not_matched_error"),
  pcb_error_id: getZodPrefixedIdWithDefault("pcb_error"),
  error_type: exports_external.literal("pcb_port_not_matched_error").default("pcb_port_not_matched_error"),
  pcb_component_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a trace error on the PCB where a port is not matched");
expectTypesMatch(true);
var pcb_port_not_connected_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_port_not_connected_error"),
  pcb_port_not_connected_error_id: getZodPrefixedIdWithDefault("pcb_port_not_connected_error"),
  error_type: exports_external.literal("pcb_port_not_connected_error").default("pcb_port_not_connected_error"),
  pcb_port_ids: exports_external.array(exports_external.string()),
  pcb_component_ids: exports_external.array(exports_external.string()),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines an error when a pcb port is not connected to any trace");
expectTypesMatch(true);
var pcb_net = exports_external.object({
  type: exports_external.literal("pcb_net"),
  pcb_net_id: getZodPrefixedIdWithDefault("pcb_net"),
  source_net_id: exports_external.string().optional(),
  highlight_color: exports_external.string().optional()
}).describe("Defines a net on the PCB");
expectTypesMatch(true);
var pcb_via = exports_external.object({
  type: exports_external.literal("pcb_via"),
  pcb_via_id: getZodPrefixedIdWithDefault("pcb_via"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional(),
  x: distance4,
  y: distance4,
  outer_diameter: distance4.default("0.6mm"),
  hole_diameter: distance4.default("0.25mm"),
  from_layer: layer_ref.optional(),
  to_layer: layer_ref.optional(),
  layers: exports_external.array(layer_ref),
  pcb_trace_id: exports_external.string().optional(),
  net_is_assignable: exports_external.boolean().optional(),
  net_assigned: exports_external.boolean().optional(),
  is_tented: exports_external.boolean().optional()
}).describe("Defines a via on the PCB");
expectTypesMatch(true);
var pcb_board = exports_external.object({
  type: exports_external.literal("pcb_board"),
  pcb_board_id: getZodPrefixedIdWithDefault("pcb_board"),
  pcb_panel_id: exports_external.string().optional(),
  carrier_pcb_board_id: exports_external.string().optional(),
  is_subcircuit: exports_external.boolean().optional(),
  subcircuit_id: exports_external.string().optional(),
  is_mounted_to_carrier_board: exports_external.boolean().optional(),
  width: length.optional(),
  height: length.optional(),
  center: point,
  display_offset_x: exports_external.string().optional().describe("How to display the x offset for this board, usually corresponding with how the user specified it"),
  display_offset_y: exports_external.string().optional().describe("How to display the y offset for this board, usually corresponding with how the user specified it"),
  thickness: length.optional().default(1.4),
  num_layers: exports_external.number().optional().default(4),
  outline: exports_external.array(point).optional(),
  shape: exports_external.enum(["rect", "polygon"]).optional(),
  material: exports_external.enum(["fr4", "fr1"]).default("fr4"),
  solder_mask_color: exports_external.string().optional(),
  silkscreen_color: exports_external.string().optional(),
  anchor_position: point.optional(),
  anchor_alignment: ninePointAnchor.optional(),
  position_mode: exports_external.enum(["relative_to_panel_anchor", "none"]).optional()
}).merge(manufacturing_drc_properties).describe("Defines the board outline of the PCB");
expectTypesMatch(true);
var pcb_panel = exports_external.object({
  type: exports_external.literal("pcb_panel"),
  pcb_panel_id: getZodPrefixedIdWithDefault("pcb_panel"),
  width: length,
  height: length,
  center: point,
  thickness: length.optional().default(1.4),
  covered_with_solder_mask: exports_external.boolean().optional().default(true)
}).describe("Defines a PCB panel that can contain multiple boards");
expectTypesMatch(true);
var pcb_placement_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_placement_error"),
  pcb_placement_error_id: getZodPrefixedIdWithDefault("pcb_placement_error"),
  error_type: exports_external.literal("pcb_placement_error").default("pcb_placement_error"),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a placement error on the PCB");
expectTypesMatch(true);
var pcb_panelization_placement_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_panelization_placement_error"),
  pcb_panelization_placement_error_id: getZodPrefixedIdWithDefault("pcb_panelization_placement_error"),
  error_type: exports_external.literal("pcb_panelization_placement_error").default("pcb_panelization_placement_error"),
  pcb_panel_id: exports_external.string().optional(),
  pcb_board_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a panelization placement error on the PCB");
expectTypesMatch(true);
var pcb_trace_hint = exports_external.object({
  type: exports_external.literal("pcb_trace_hint"),
  pcb_trace_hint_id: getZodPrefixedIdWithDefault("pcb_trace_hint"),
  pcb_port_id: exports_external.string(),
  pcb_component_id: exports_external.string(),
  route: exports_external.array(route_hint_point),
  subcircuit_id: exports_external.string().optional()
}).describe("A hint that can be used during generation of a PCB trace");
expectTypesMatch(true);
var pcb_silkscreen_line = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_line"),
  pcb_silkscreen_line_id: getZodPrefixedIdWithDefault("pcb_silkscreen_line"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  stroke_width: distance4.default("0.1mm"),
  x1: distance4,
  y1: distance4,
  x2: distance4,
  y2: distance4,
  layer: visible_layer
}).describe("Defines a silkscreen line on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_path = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_path"),
  pcb_silkscreen_path_id: getZodPrefixedIdWithDefault("pcb_silkscreen_path"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: visible_layer,
  route: exports_external.array(point),
  stroke_width: length
}).describe("Defines a silkscreen path on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_text = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_text"),
  pcb_silkscreen_text_id: getZodPrefixedIdWithDefault("pcb_silkscreen_text"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  font: exports_external.literal("tscircuit2024").default("tscircuit2024"),
  font_size: distance4.default("0.2mm"),
  pcb_component_id: exports_external.string(),
  text: exports_external.string(),
  is_knockout: exports_external.boolean().default(false).optional(),
  knockout_padding: exports_external.object({
    left: length,
    top: length,
    bottom: length,
    right: length
  }).default({
    left: "0.2mm",
    top: "0.2mm",
    bottom: "0.2mm",
    right: "0.2mm"
  }).optional(),
  ccw_rotation: exports_external.number().optional(),
  layer: layer_ref,
  is_mirrored: exports_external.boolean().default(false).optional(),
  anchor_position: point.default({ x: 0, y: 0 }),
  anchor_alignment: ninePointAnchor.default("center")
}).describe("Defines silkscreen text on the PCB");
expectTypesMatch(true);
var pcb_copper_text = exports_external.object({
  type: exports_external.literal("pcb_copper_text"),
  pcb_copper_text_id: getZodPrefixedIdWithDefault("pcb_copper_text"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  font: exports_external.literal("tscircuit2024").default("tscircuit2024"),
  font_size: distance4.default("0.2mm"),
  pcb_component_id: exports_external.string(),
  text: exports_external.string(),
  is_knockout: exports_external.boolean().default(false).optional(),
  knockout_padding: exports_external.object({
    left: length,
    top: length,
    bottom: length,
    right: length
  }).default({
    left: "0.2mm",
    top: "0.2mm",
    bottom: "0.2mm",
    right: "0.2mm"
  }).optional(),
  ccw_rotation: exports_external.number().optional(),
  layer: layer_ref,
  is_mirrored: exports_external.boolean().default(false).optional(),
  anchor_position: point.default({ x: 0, y: 0 }),
  anchor_alignment: ninePointAnchor.default("center")
}).describe("Defines copper text on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_rect = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_rect"),
  pcb_silkscreen_rect_id: getZodPrefixedIdWithDefault("pcb_silkscreen_rect"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  width: length,
  height: length,
  layer: layer_ref,
  stroke_width: length.default("1mm"),
  corner_radius: length.optional(),
  is_filled: exports_external.boolean().default(true).optional(),
  has_stroke: exports_external.boolean().optional(),
  is_stroke_dashed: exports_external.boolean().optional(),
  ccw_rotation: exports_external.number().optional()
}).describe("Defines a silkscreen rect on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_circle = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_circle"),
  pcb_silkscreen_circle_id: getZodPrefixedIdWithDefault("pcb_silkscreen_circle"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  radius: length,
  layer: visible_layer,
  stroke_width: length.default("1mm"),
  is_filled: exports_external.boolean().optional()
}).describe("Defines a silkscreen circle on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_oval = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_oval"),
  pcb_silkscreen_oval_id: getZodPrefixedIdWithDefault("pcb_silkscreen_oval"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  radius_x: distance4,
  radius_y: distance4,
  layer: visible_layer,
  ccw_rotation: rotation.optional()
}).describe("Defines a silkscreen oval on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_graphic_base = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_graphic"),
  pcb_silkscreen_graphic_id: getZodPrefixedIdWithDefault("pcb_silkscreen_graphic"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: visible_layer,
  image_asset: asset.optional()
});
var pcb_silkscreen_graphic_brep = pcb_silkscreen_graphic_base.extend({
  shape: exports_external.literal("brep"),
  brep_shape
}).describe("Defines a BRep silkscreen graphic on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_graphic = exports_external.discriminatedUnion("shape", [pcb_silkscreen_graphic_brep]).describe("Defines a silkscreen graphic on the PCB");
expectTypesMatch(true);
var pcb_silkscreen_pill = exports_external.object({
  type: exports_external.literal("pcb_silkscreen_pill"),
  pcb_silkscreen_pill_id: getZodPrefixedIdWithDefault("pcb_silkscreen_pill"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  width: length,
  height: length,
  layer: layer_ref,
  ccw_rotation: exports_external.number().optional()
}).describe("Defines a silkscreen pill on the PCB");
expectTypesMatch(true);
var pcb_fabrication_note_text = exports_external.object({
  type: exports_external.literal("pcb_fabrication_note_text"),
  pcb_fabrication_note_text_id: getZodPrefixedIdWithDefault("pcb_fabrication_note_text"),
  subcircuit_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  font: exports_external.literal("tscircuit2024").default("tscircuit2024"),
  font_size: distance4.default("1mm"),
  pcb_component_id: exports_external.string(),
  text: exports_external.string(),
  ccw_rotation: exports_external.number().optional(),
  layer: visible_layer,
  anchor_position: point.default({ x: 0, y: 0 }),
  anchor_alignment: exports_external.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"),
  color: exports_external.string().optional()
}).describe("Defines a fabrication note in text on the PCB, useful for leaving notes for assemblers or fabricators");
expectTypesMatch(true);
var pcb_fabrication_note_path = exports_external.object({
  type: exports_external.literal("pcb_fabrication_note_path"),
  pcb_fabrication_note_path_id: getZodPrefixedIdWithDefault("pcb_fabrication_note_path"),
  pcb_component_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional(),
  layer: layer_ref,
  route: exports_external.array(point),
  stroke_width: length,
  color: exports_external.string().optional()
}).describe("Defines a fabrication path on the PCB for fabricators or assemblers");
expectTypesMatch(true);
var pcb_fabrication_note_rect = exports_external.object({
  type: exports_external.literal("pcb_fabrication_note_rect"),
  pcb_fabrication_note_rect_id: getZodPrefixedIdWithDefault("pcb_fabrication_note_rect"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  width: length,
  height: length,
  layer: visible_layer,
  stroke_width: length.default("0.1mm"),
  corner_radius: length.optional(),
  is_filled: exports_external.boolean().optional(),
  has_stroke: exports_external.boolean().optional(),
  is_stroke_dashed: exports_external.boolean().optional(),
  color: exports_external.string().optional()
}).describe("Defines a fabrication note rectangle on the PCB");
expectTypesMatch(true);
var pcb_fabrication_note_dimension = exports_external.object({
  type: exports_external.literal("pcb_fabrication_note_dimension"),
  pcb_fabrication_note_dimension_id: getZodPrefixedIdWithDefault("pcb_fabrication_note_dimension"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: visible_layer,
  from: point,
  to: point,
  text: exports_external.string().optional(),
  text_ccw_rotation: exports_external.number().optional(),
  offset: length.optional(),
  offset_distance: length.optional(),
  offset_direction: exports_external.object({
    x: exports_external.number(),
    y: exports_external.number()
  }).optional(),
  font: exports_external.literal("tscircuit2024").default("tscircuit2024"),
  font_size: length.default("1mm"),
  color: exports_external.string().optional(),
  arrow_size: length.default("1mm")
}).describe("Defines a measurement annotation within PCB fabrication notes");
expectTypesMatch(true);
var pcb_note_text = exports_external.object({
  type: exports_external.literal("pcb_note_text"),
  pcb_note_text_id: getZodPrefixedIdWithDefault("pcb_note_text"),
  pcb_component_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  font: exports_external.literal("tscircuit2024").default("tscircuit2024"),
  font_size: distance4.default("1mm"),
  text: exports_external.string().optional(),
  anchor_position: point.default({ x: 0, y: 0 }),
  anchor_alignment: exports_external.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"),
  layer: visible_layer.default("top"),
  is_mirrored_from_top_view: exports_external.boolean().optional(),
  color: exports_external.string().optional()
}).describe("Defines a documentation note in text on the PCB");
expectTypesMatch(true);
var pcb_note_rect = exports_external.object({
  type: exports_external.literal("pcb_note_rect"),
  pcb_note_rect_id: getZodPrefixedIdWithDefault("pcb_note_rect"),
  pcb_component_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  text: exports_external.string().optional(),
  center: point,
  width: length,
  height: length,
  layer: visible_layer.default("top"),
  stroke_width: length.default("0.1mm"),
  corner_radius: length.optional(),
  is_filled: exports_external.boolean().optional(),
  has_stroke: exports_external.boolean().optional(),
  is_stroke_dashed: exports_external.boolean().optional(),
  color: exports_external.string().optional()
}).describe("Defines a rectangular documentation note on the PCB");
expectTypesMatch(true);
var pcb_note_path = exports_external.object({
  type: exports_external.literal("pcb_note_path"),
  pcb_note_path_id: getZodPrefixedIdWithDefault("pcb_note_path"),
  pcb_component_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  text: exports_external.string().optional(),
  route: exports_external.array(point),
  layer: visible_layer.default("top"),
  stroke_width: length.default("0.1mm"),
  color: exports_external.string().optional()
}).describe("Defines a polyline documentation note on the PCB");
expectTypesMatch(true);
var pcb_note_line = exports_external.object({
  type: exports_external.literal("pcb_note_line"),
  pcb_note_line_id: getZodPrefixedIdWithDefault("pcb_note_line"),
  pcb_component_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  text: exports_external.string().optional(),
  x1: distance4,
  y1: distance4,
  x2: distance4,
  y2: distance4,
  layer: visible_layer.default("top"),
  stroke_width: distance4.default("0.1mm"),
  color: exports_external.string().optional(),
  is_dashed: exports_external.boolean().optional()
}).describe("Defines a straight documentation note line on the PCB");
expectTypesMatch(true);
var pcb_note_dimension = exports_external.object({
  type: exports_external.literal("pcb_note_dimension"),
  pcb_note_dimension_id: getZodPrefixedIdWithDefault("pcb_note_dimension"),
  pcb_component_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  from: point,
  to: point,
  text: exports_external.string().optional(),
  text_ccw_rotation: exports_external.number().optional(),
  offset_distance: length.optional(),
  offset_direction: exports_external.object({
    x: exports_external.number(),
    y: exports_external.number()
  }).optional(),
  font: exports_external.literal("tscircuit2024").default("tscircuit2024"),
  font_size: length.default("1mm"),
  layer: visible_layer.default("top"),
  color: exports_external.string().optional(),
  arrow_size: length.default("1mm")
}).describe("Defines a measurement annotation within PCB documentation notes");
expectTypesMatch(true);
var pcb_footprint_overlap_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_footprint_overlap_error"),
  pcb_error_id: getZodPrefixedIdWithDefault("pcb_error"),
  error_type: exports_external.literal("pcb_footprint_overlap_error").default("pcb_footprint_overlap_error"),
  pcb_smtpad_ids: exports_external.array(exports_external.string()).optional(),
  pcb_plated_hole_ids: exports_external.array(exports_external.string()).optional(),
  pcb_hole_ids: exports_external.array(exports_external.string()).optional(),
  pcb_keepout_ids: exports_external.array(exports_external.string()).optional()
}).describe("Error emitted when a pcb footprint overlaps with another element");
expectTypesMatch(true);
var pcb_courtyard_overlap_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_courtyard_overlap_error"),
  pcb_error_id: getZodPrefixedIdWithDefault("pcb_error"),
  error_type: exports_external.literal("pcb_courtyard_overlap_error").default("pcb_courtyard_overlap_error"),
  pcb_component_ids: exports_external.tuple([exports_external.string(), exports_external.string()])
}).describe("Error emitted when the courtyard (CrtYd) of one PCB component overlaps with the courtyard of another");
expectTypesMatch(true);
var pcb_keepout = exports_external.object({
  type: exports_external.literal("pcb_keepout"),
  shape: exports_external.literal("rect"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  width: distance4,
  height: distance4,
  pcb_keepout_id: exports_external.string(),
  layers: exports_external.array(exports_external.string()),
  description: exports_external.string().optional()
}).or(exports_external.object({
  type: exports_external.literal("pcb_keepout"),
  shape: exports_external.literal("circle"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  radius: distance4,
  pcb_keepout_id: exports_external.string(),
  layers: exports_external.array(exports_external.string()),
  description: exports_external.string().optional()
}));
expectTypesMatch(true);
var pcb_cutout_base = exports_external.object({
  type: exports_external.literal("pcb_cutout"),
  pcb_cutout_id: getZodPrefixedIdWithDefault("pcb_cutout"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  pcb_board_id: exports_external.string().optional(),
  pcb_panel_id: exports_external.string().optional()
});
var pcb_cutout_rect = pcb_cutout_base.extend({
  shape: exports_external.literal("rect"),
  center: point,
  width: length,
  height: length,
  rotation: rotation.optional(),
  corner_radius: length.optional()
});
expectTypesMatch(true);
var pcb_cutout_circle = pcb_cutout_base.extend({
  shape: exports_external.literal("circle"),
  center: point,
  radius: length
});
expectTypesMatch(true);
var pcb_cutout_polygon = pcb_cutout_base.extend({
  shape: exports_external.literal("polygon"),
  points: exports_external.array(point)
});
expectTypesMatch(true);
var pcb_cutout_path = pcb_cutout_base.extend({
  shape: exports_external.literal("path"),
  route: exports_external.array(point),
  slot_width: length,
  slot_length: length.optional(),
  space_between_slots: length.optional(),
  slot_corner_radius: length.optional()
});
expectTypesMatch(true);
var pcb_cutout = exports_external.discriminatedUnion("shape", [
  pcb_cutout_rect,
  pcb_cutout_circle,
  pcb_cutout_polygon,
  pcb_cutout_path
]).describe("Defines a cutout on the PCB, removing board material.");
expectTypesMatch(true);
var pcb_missing_footprint_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_missing_footprint_error"),
  pcb_missing_footprint_error_id: getZodPrefixedIdWithDefault("pcb_missing_footprint_error"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  error_type: exports_external.literal("pcb_missing_footprint_error").default("pcb_missing_footprint_error"),
  source_component_id: exports_external.string()
}).describe("Defines a missing footprint error on the PCB");
expectTypesMatch(true);
var external_footprint_load_error = base_circuit_json_error.extend({
  type: exports_external.literal("external_footprint_load_error"),
  external_footprint_load_error_id: getZodPrefixedIdWithDefault("external_footprint_load_error"),
  pcb_component_id: exports_external.string(),
  source_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  footprinter_string: exports_external.string().optional(),
  error_type: exports_external.literal("external_footprint_load_error").default("external_footprint_load_error")
}).describe("Defines an error when an external footprint fails to load");
expectTypesMatch(true);
var circuit_json_footprint_load_error = base_circuit_json_error.extend({
  type: exports_external.literal("circuit_json_footprint_load_error"),
  circuit_json_footprint_load_error_id: getZodPrefixedIdWithDefault("circuit_json_footprint_load_error"),
  pcb_component_id: exports_external.string(),
  source_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  error_type: exports_external.literal("circuit_json_footprint_load_error").default("circuit_json_footprint_load_error"),
  circuit_json: exports_external.array(exports_external.any()).optional()
}).describe("Defines an error when a circuit JSON footprint fails to load");
expectTypesMatch(true);
var pcb_group = exports_external.object({
  type: exports_external.literal("pcb_group"),
  pcb_group_id: getZodPrefixedIdWithDefault("pcb_group"),
  source_group_id: exports_external.string(),
  is_subcircuit: exports_external.boolean().optional(),
  subcircuit_id: exports_external.string().optional(),
  width: length.optional(),
  height: length.optional(),
  center: point,
  display_offset_x: exports_external.string().optional().describe("How to display the x offset for this group, usually corresponding with how the user specified it"),
  display_offset_y: exports_external.string().optional().describe("How to display the y offset for this group, usually corresponding with how the user specified it"),
  outline: exports_external.array(point).optional(),
  anchor_position: point.optional(),
  anchor_alignment: ninePointAnchor.default("center"),
  position_mode: exports_external.enum(["packed", "relative_to_group_anchor", "none"]).optional(),
  positioned_relative_to_pcb_group_id: exports_external.string().optional(),
  positioned_relative_to_pcb_board_id: exports_external.string().optional(),
  pcb_component_ids: exports_external.array(exports_external.string()),
  child_layout_mode: exports_external.enum(["packed", "none"]).optional(),
  name: exports_external.string().optional(),
  description: exports_external.string().optional(),
  layout_mode: exports_external.string().optional(),
  autorouter_configuration: exports_external.object({
    trace_clearance: length
  }).optional(),
  autorouter_used_string: exports_external.string().optional()
}).describe("Defines a group of components on the PCB");
expectTypesMatch(true);
var pcb_autorouting_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_autorouting_error"),
  pcb_error_id: getZodPrefixedIdWithDefault("pcb_autorouting_error"),
  error_type: exports_external.literal("pcb_autorouting_error").default("pcb_autorouting_error"),
  subcircuit_id: exports_external.string().optional()
}).describe("The autorouting has failed to route a portion of the board");
expectTypesMatch(true);
var pcb_manual_edit_conflict_warning = exports_external.object({
  type: exports_external.literal("pcb_manual_edit_conflict_warning"),
  pcb_manual_edit_conflict_warning_id: getZodPrefixedIdWithDefault("pcb_manual_edit_conflict_warning"),
  warning_type: exports_external.literal("pcb_manual_edit_conflict_warning").default("pcb_manual_edit_conflict_warning"),
  message: exports_external.string(),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  source_component_id: exports_external.string()
}).describe("Warning emitted when a component has both manual placement and explicit pcbX/pcbY coordinates");
expectTypesMatch(true);
var connectorOrientationDirection = exports_external.enum(["x-", "x+", "y+", "y-"]);
var pcb_connector_not_in_accessible_orientation_warning = exports_external.object({
  type: exports_external.literal("pcb_connector_not_in_accessible_orientation_warning"),
  pcb_connector_not_in_accessible_orientation_warning_id: getZodPrefixedIdWithDefault("pcb_connector_not_in_accessible_orientation_warning"),
  warning_type: exports_external.literal("pcb_connector_not_in_accessible_orientation_warning").default("pcb_connector_not_in_accessible_orientation_warning"),
  message: exports_external.string(),
  pcb_component_id: exports_external.string(),
  source_component_id: exports_external.string().optional(),
  pcb_board_id: exports_external.string().optional(),
  facing_direction: connectorOrientationDirection,
  recommended_facing_direction: connectorOrientationDirection,
  subcircuit_id: exports_external.string().optional()
}).describe("Warning emitted when a connector PCB component is facing inward toward the board and should be reoriented to an outward-facing direction");
expectTypesMatch(true);
var supplier_footprint_mismatch_warning = exports_external.object({
  type: exports_external.literal("supplier_footprint_mismatch_warning"),
  supplier_footprint_mismatch_warning_id: getZodPrefixedIdWithDefault("supplier_footprint_mismatch_warning"),
  warning_type: exports_external.literal("supplier_footprint_mismatch_warning").default("supplier_footprint_mismatch_warning"),
  message: exports_external.string(),
  source_component_id: exports_external.string(),
  pcb_component_id: exports_external.string().optional(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  supplier_name: supplier_name.optional(),
  supplier_part_number: exports_external.string().optional(),
  supplier_footprint_url: exports_external.string().optional(),
  footprint_copper_intersection_over_union: exports_external.number()
}).describe("Warning emitted when a supplier part footprint does not match the expected footprint");
expectTypesMatch(true);
var pcb_breakout_point = exports_external.object({
  type: exports_external.literal("pcb_breakout_point"),
  pcb_breakout_point_id: getZodPrefixedIdWithDefault("pcb_breakout_point"),
  pcb_group_id: exports_external.string(),
  subcircuit_id: exports_external.string().optional(),
  source_trace_id: exports_external.string().optional(),
  source_port_id: exports_external.string().optional(),
  source_net_id: exports_external.string().optional(),
  x: distance4,
  y: distance4
}).describe("Defines a routing target within a pcb_group for a source_trace or source_net");
expectTypesMatch(true);
var pcb_ground_plane = exports_external.object({
  type: exports_external.literal("pcb_ground_plane"),
  pcb_ground_plane_id: getZodPrefixedIdWithDefault("pcb_ground_plane"),
  source_pcb_ground_plane_id: exports_external.string(),
  source_net_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Defines a ground plane on the PCB");
expectTypesMatch(true);
var pcb_ground_plane_region = exports_external.object({
  type: exports_external.literal("pcb_ground_plane_region"),
  pcb_ground_plane_region_id: getZodPrefixedIdWithDefault("pcb_ground_plane_region"),
  pcb_ground_plane_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: layer_ref,
  points: exports_external.array(point)
}).describe("Defines a polygon region of a ground plane");
expectTypesMatch(true);
var pcb_thermal_spoke = exports_external.object({
  type: exports_external.literal("pcb_thermal_spoke"),
  pcb_thermal_spoke_id: getZodPrefixedIdWithDefault("pcb_thermal_spoke"),
  pcb_ground_plane_id: exports_external.string(),
  shape: exports_external.string(),
  spoke_count: exports_external.number(),
  spoke_thickness: distance4,
  spoke_inner_diameter: distance4,
  spoke_outer_diameter: distance4,
  pcb_plated_hole_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Pattern for connecting a ground plane to a plated hole");
expectTypesMatch(true);
var pcb_copper_pour_base = exports_external.object({
  type: exports_external.literal("pcb_copper_pour"),
  pcb_copper_pour_id: getZodPrefixedIdWithDefault("pcb_copper_pour"),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: layer_ref,
  source_net_id: exports_external.string().optional(),
  covered_with_solder_mask: exports_external.boolean().optional().default(true)
});
var pcb_copper_pour_rect = pcb_copper_pour_base.extend({
  shape: exports_external.literal("rect"),
  center: point,
  width: length,
  height: length,
  rotation: rotation.optional()
});
expectTypesMatch(true);
var pcb_copper_pour_brep = pcb_copper_pour_base.extend({
  shape: exports_external.literal("brep"),
  brep_shape
});
expectTypesMatch(true);
var pcb_copper_pour_polygon = pcb_copper_pour_base.extend({
  shape: exports_external.literal("polygon"),
  points: exports_external.array(point)
});
expectTypesMatch(true);
var pcb_copper_pour = exports_external.discriminatedUnion("shape", [
  pcb_copper_pour_rect,
  pcb_copper_pour_brep,
  pcb_copper_pour_polygon
]).describe("Defines a copper pour on the PCB.");
expectTypesMatch(true);
var pcb_component_outside_board_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_component_outside_board_error"),
  pcb_component_outside_board_error_id: getZodPrefixedIdWithDefault("pcb_component_outside_board_error"),
  error_type: exports_external.literal("pcb_component_outside_board_error").default("pcb_component_outside_board_error"),
  pcb_component_id: exports_external.string(),
  pcb_board_id: exports_external.string(),
  component_center: point,
  component_bounds: exports_external.object({
    min_x: exports_external.number(),
    max_x: exports_external.number(),
    min_y: exports_external.number(),
    max_y: exports_external.number()
  }),
  subcircuit_id: exports_external.string().optional(),
  source_component_id: exports_external.string().optional()
}).describe("Error emitted when a PCB component is placed outside the board boundaries");
expectTypesMatch(true);
var pcb_component_not_on_board_edge_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_component_not_on_board_edge_error"),
  pcb_component_not_on_board_edge_error_id: getZodPrefixedIdWithDefault("pcb_component_not_on_board_edge_error"),
  error_type: exports_external.literal("pcb_component_not_on_board_edge_error").default("pcb_component_not_on_board_edge_error"),
  pcb_component_id: exports_external.string(),
  pcb_board_id: exports_external.string(),
  component_center: point,
  pad_to_nearest_board_edge_distance: exports_external.number(),
  source_component_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when a component that must be placed on the board edge is centered away from the edge");
expectTypesMatch(true);
var pcb_component_invalid_layer_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_component_invalid_layer_error"),
  pcb_component_invalid_layer_error_id: getZodPrefixedIdWithDefault("pcb_component_invalid_layer_error"),
  error_type: exports_external.literal("pcb_component_invalid_layer_error").default("pcb_component_invalid_layer_error"),
  pcb_component_id: exports_external.string().optional(),
  source_component_id: exports_external.string(),
  layer: layer_ref,
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when a component is placed on an invalid layer (components can only be on 'top' or 'bottom' layers)");
expectTypesMatch(true);
var pcb_via_clearance_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_via_clearance_error"),
  pcb_error_id: getZodPrefixedIdWithDefault("pcb_error"),
  error_type: exports_external.literal("pcb_via_clearance_error").default("pcb_via_clearance_error"),
  pcb_via_ids: exports_external.array(exports_external.string()).min(2),
  minimum_clearance: distance4.optional(),
  actual_clearance: distance4.optional(),
  pcb_center: exports_external.object({
    x: exports_external.number().optional(),
    y: exports_external.number().optional()
  }).optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when vias are closer than the allowed clearance");
expectTypesMatch(true);
var pcb_via_trace_clearance_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_via_trace_clearance_error"),
  pcb_via_trace_clearance_error_id: getZodPrefixedIdWithDefault("pcb_via_trace_clearance_error"),
  error_type: exports_external.literal("pcb_via_trace_clearance_error").default("pcb_via_trace_clearance_error"),
  pcb_via_id: exports_external.string(),
  pcb_trace_id: exports_external.string(),
  minimum_clearance: distance4.optional(),
  actual_clearance: distance4.optional(),
  center: exports_external.object({
    x: exports_external.number().optional(),
    y: exports_external.number().optional()
  }).optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when a via and trace are closer than the allowed clearance");
expectTypesMatch(true);
var pcb_pad_pad_clearance_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_pad_pad_clearance_error"),
  pcb_pad_pad_clearance_error_id: getZodPrefixedIdWithDefault("pcb_pad_pad_clearance_error"),
  error_type: exports_external.literal("pcb_pad_pad_clearance_error").default("pcb_pad_pad_clearance_error"),
  pcb_pad_ids: exports_external.array(exports_external.string()).min(2),
  minimum_clearance: distance4.optional(),
  actual_clearance: distance4.optional(),
  center: exports_external.object({
    x: exports_external.number().optional(),
    y: exports_external.number().optional()
  }).optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when pads are closer than the allowed clearance");
expectTypesMatch(true);
var pcb_pad_trace_clearance_error = base_circuit_json_error.extend({
  type: exports_external.literal("pcb_pad_trace_clearance_error"),
  pcb_pad_trace_clearance_error_id: getZodPrefixedIdWithDefault("pcb_pad_trace_clearance_error"),
  error_type: exports_external.literal("pcb_pad_trace_clearance_error").default("pcb_pad_trace_clearance_error"),
  pcb_pad_id: exports_external.string(),
  pcb_trace_id: exports_external.string(),
  minimum_clearance: distance4.optional(),
  actual_clearance: distance4.optional(),
  center: exports_external.object({
    x: exports_external.number().optional(),
    y: exports_external.number().optional()
  }).optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("Error emitted when a pad and trace are closer than allowed clearance");
expectTypesMatch(true);
var pcb_courtyard_rect = exports_external.object({
  type: exports_external.literal("pcb_courtyard_rect"),
  pcb_courtyard_rect_id: getZodPrefixedIdWithDefault("pcb_courtyard_rect"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  width: length,
  height: length,
  layer: visible_layer,
  ccw_rotation: rotation.optional(),
  color: exports_external.string().optional()
}).describe("Defines a courtyard rectangle on the PCB");
expectTypesMatch(true);
var pcb_courtyard_outline = exports_external.object({
  type: exports_external.literal("pcb_courtyard_outline"),
  pcb_courtyard_outline_id: getZodPrefixedIdWithDefault("pcb_courtyard_outline"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: visible_layer,
  outline: exports_external.array(point).min(2)
}).describe("Defines a courtyard outline on the PCB");
expectTypesMatch(true);
var pcb_courtyard_polygon = exports_external.object({
  type: exports_external.literal("pcb_courtyard_polygon"),
  pcb_courtyard_polygon_id: getZodPrefixedIdWithDefault("pcb_courtyard_polygon"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  layer: visible_layer,
  points: exports_external.array(point).min(3),
  color: exports_external.string().optional()
}).describe("Defines a courtyard polygon on the PCB");
expectTypesMatch(true);
var pcb_courtyard_circle = exports_external.object({
  type: exports_external.literal("pcb_courtyard_circle"),
  pcb_courtyard_circle_id: getZodPrefixedIdWithDefault("pcb_courtyard_circle"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  radius: length,
  layer: visible_layer,
  color: exports_external.string().optional()
}).describe("Defines a courtyard circle on the PCB");
expectTypesMatch(true);
var pcb_courtyard_pill = exports_external.object({
  type: exports_external.literal("pcb_courtyard_pill"),
  pcb_courtyard_pill_id: getZodPrefixedIdWithDefault("pcb_courtyard_pill"),
  pcb_component_id: exports_external.string(),
  pcb_group_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  center: point,
  width: length,
  height: length,
  radius: length,
  layer: visible_layer,
  color: exports_external.string().optional()
}).describe("Defines a courtyard pill on the PCB");
expectTypesMatch(true);
var cad_model_formats = [
  "obj",
  "stl",
  "3mf",
  "gltf",
  "glb",
  "step",
  "wrl"
];
var cad_model_axis_directions = [
  "x+",
  "x-",
  "y+",
  "y-",
  "z+",
  "z-"
];
var cadModelDefaultDirectionMap = {
  obj: "z+",
  stl: "z+",
  "3mf": "z+",
  gltf: "y+",
  glb: "y+",
  step: "z+",
  wrl: "y+"
};
var cad_component = exports_external.object({
  type: exports_external.literal("cad_component"),
  cad_component_id: exports_external.string(),
  pcb_component_id: exports_external.string(),
  source_component_id: exports_external.string(),
  position: point3,
  rotation: point3.optional(),
  size: point3.optional(),
  layer: layer_ref.optional(),
  subcircuit_id: exports_external.string().optional(),
  footprinter_string: exports_external.string().optional(),
  model_obj_url: exports_external.string().optional(),
  model_stl_url: exports_external.string().optional(),
  model_3mf_url: exports_external.string().optional(),
  model_gltf_url: exports_external.string().optional(),
  model_glb_url: exports_external.string().optional(),
  model_step_url: exports_external.string().optional(),
  model_wrl_url: exports_external.string().optional(),
  model_asset: asset.optional(),
  model_unit_to_mm_scale_factor: exports_external.number().optional(),
  model_board_normal_direction: exports_external.enum(cad_model_axis_directions).optional().describe(`The direction in the model's coordinate space that is considered "up" or "coming out of the board surface"`),
  model_origin_position: point3.optional(),
  model_origin_alignment: exports_external.enum([
    "unknown",
    "center",
    "center_of_component_on_board_surface",
    "bottom_center_of_component"
  ]).optional(),
  model_object_fit: exports_external.enum(["contain_within_bounds", "fill_bounds"]).optional().default("contain_within_bounds"),
  model_jscad: exports_external.any().optional(),
  show_as_translucent_model: exports_external.boolean().optional(),
  show_as_bounding_box: exports_external.boolean().optional(),
  anchor_alignment: exports_external.enum(["center", "center_of_component_on_board_surface"]).optional().default("center")
}).describe("Defines a component on the PCB");
expectTypesMatch(true);
var wave_shape = exports_external.enum(["sinewave", "square", "triangle", "sawtooth"]);
var percentage = exports_external.union([exports_external.string(), exports_external.number()]).transform((val) => {
  if (typeof val === "string") {
    if (val.endsWith("%")) {
      return parseFloat(val.slice(0, -1)) / 100;
    }
    return parseFloat(val);
  }
  return val;
}).pipe(exports_external.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var simulation_dc_voltage_source = exports_external.object({
  type: exports_external.literal("simulation_voltage_source"),
  simulation_voltage_source_id: getZodPrefixedIdWithDefault("simulation_voltage_source"),
  is_dc_source: exports_external.literal(true).optional().default(true),
  positive_source_port_id: exports_external.string().optional(),
  negative_source_port_id: exports_external.string().optional(),
  positive_source_net_id: exports_external.string().optional(),
  negative_source_net_id: exports_external.string().optional(),
  voltage
}).describe("Defines a DC voltage source for simulation");
var simulation_ac_voltage_source = exports_external.object({
  type: exports_external.literal("simulation_voltage_source"),
  simulation_voltage_source_id: getZodPrefixedIdWithDefault("simulation_voltage_source"),
  is_dc_source: exports_external.literal(false),
  terminal1_source_port_id: exports_external.string().optional(),
  terminal2_source_port_id: exports_external.string().optional(),
  terminal1_source_net_id: exports_external.string().optional(),
  terminal2_source_net_id: exports_external.string().optional(),
  voltage: voltage.optional(),
  frequency: frequency.optional(),
  peak_to_peak_voltage: voltage.optional(),
  wave_shape: wave_shape.optional(),
  phase: rotation.optional(),
  duty_cycle: percentage.optional(),
  pulse_delay: ms.optional(),
  rise_time: ms.optional(),
  fall_time: ms.optional(),
  pulse_width: ms.optional(),
  period: ms.optional()
}).describe("Defines an AC voltage source for simulation");
var simulation_voltage_source = exports_external.union([simulation_dc_voltage_source, simulation_ac_voltage_source]).describe("Defines a voltage source for simulation");
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
var percentage2 = exports_external.union([exports_external.string(), exports_external.number()]).transform((val) => {
  if (typeof val === "string") {
    if (val.endsWith("%")) {
      return parseFloat(val.slice(0, -1)) / 100;
    }
    return parseFloat(val);
  }
  return val;
}).pipe(exports_external.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var simulation_dc_current_source = exports_external.object({
  type: exports_external.literal("simulation_current_source"),
  simulation_current_source_id: getZodPrefixedIdWithDefault("simulation_current_source"),
  is_dc_source: exports_external.literal(true).optional().default(true),
  positive_source_port_id: exports_external.string().optional(),
  negative_source_port_id: exports_external.string().optional(),
  positive_source_net_id: exports_external.string().optional(),
  negative_source_net_id: exports_external.string().optional(),
  current
}).describe("Defines a DC current source for simulation");
var simulation_ac_current_source = exports_external.object({
  type: exports_external.literal("simulation_current_source"),
  simulation_current_source_id: getZodPrefixedIdWithDefault("simulation_current_source"),
  is_dc_source: exports_external.literal(false),
  terminal1_source_port_id: exports_external.string().optional(),
  terminal2_source_port_id: exports_external.string().optional(),
  terminal1_source_net_id: exports_external.string().optional(),
  terminal2_source_net_id: exports_external.string().optional(),
  current: current.optional(),
  frequency: frequency.optional(),
  peak_to_peak_current: current.optional(),
  wave_shape: wave_shape.optional(),
  phase: rotation.optional(),
  duty_cycle: percentage2.optional()
}).describe("Defines an AC current source for simulation");
var simulation_current_source = exports_external.union([simulation_dc_current_source, simulation_ac_current_source]).describe("Defines a current source for simulation");
expectTypesMatch(true);
expectTypesMatch(true);
expectTypesMatch(true);
var experiment_type = exports_external.union([
  exports_external.literal("spice_dc_sweep"),
  exports_external.literal("spice_dc_operating_point"),
  exports_external.literal("spice_transient_analysis"),
  exports_external.literal("spice_ac_analysis")
]);
var spice_simulation_options = exports_external.object({
  method: exports_external.enum(["trap", "gear"]).optional(),
  reltol: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  abstol: exports_external.union([exports_external.number(), exports_external.string()]).optional(),
  vntol: exports_external.union([exports_external.number(), exports_external.string()]).optional()
}).describe("SPICE solver options for a simulation experiment");
var simulation_experiment = exports_external.object({
  type: exports_external.literal("simulation_experiment"),
  simulation_experiment_id: getZodPrefixedIdWithDefault("simulation_experiment"),
  name: exports_external.string(),
  experiment_type,
  time_per_step: duration_ms.optional(),
  start_time_ms: ms.optional(),
  end_time_ms: ms.optional(),
  spice_options: spice_simulation_options.optional()
}).describe("Defines a simulation experiment configuration");
expectTypesMatch(true);
var simulation_transient_voltage_graph = exports_external.object({
  type: exports_external.literal("simulation_transient_voltage_graph"),
  simulation_transient_voltage_graph_id: getZodPrefixedIdWithDefault("simulation_transient_voltage_graph"),
  simulation_experiment_id: exports_external.string(),
  timestamps_ms: exports_external.array(exports_external.number()).optional(),
  voltage_levels: exports_external.array(exports_external.number()),
  source_component_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional(),
  time_per_step: duration_ms,
  start_time_ms: ms,
  end_time_ms: ms,
  name: exports_external.string().optional(),
  color: exports_external.string().optional()
}).describe("Stores voltage measurements over time for a simulation");
expectTypesMatch(true);
var simulation_transient_current_graph = exports_external.object({
  type: exports_external.literal("simulation_transient_current_graph"),
  simulation_transient_current_graph_id: getZodPrefixedIdWithDefault("simulation_transient_current_graph"),
  simulation_experiment_id: exports_external.string(),
  timestamps_ms: exports_external.array(exports_external.number()).optional(),
  current_levels: exports_external.array(exports_external.number()),
  source_component_id: exports_external.string().optional(),
  subcircuit_connectivity_map_key: exports_external.string().optional(),
  time_per_step: duration_ms,
  start_time_ms: ms,
  end_time_ms: ms,
  name: exports_external.string().optional(),
  color: exports_external.string().optional()
}).describe("Stores current measurements over time for a simulation");
expectTypesMatch(true);
var simulation_switch = exports_external.object({
  type: exports_external.literal("simulation_switch"),
  simulation_switch_id: getZodPrefixedIdWithDefault("simulation_switch"),
  source_component_id: exports_external.string().optional(),
  closes_at: ms.optional(),
  opens_at: ms.optional(),
  starts_closed: exports_external.boolean().optional(),
  switching_frequency: frequency.optional()
}).describe("Defines a switch for simulation timing control");
expectTypesMatch(true);
var simulation_voltage_probe = exports_external.object({
  type: exports_external.literal("simulation_voltage_probe"),
  simulation_voltage_probe_id: getZodPrefixedIdWithDefault("simulation_voltage_probe"),
  source_component_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  signal_input_source_port_id: exports_external.string().optional(),
  signal_input_source_net_id: exports_external.string().optional(),
  reference_input_source_port_id: exports_external.string().optional(),
  reference_input_source_net_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  color: exports_external.string().optional()
}).describe("Defines a voltage probe for simulation. If a reference input is not provided, it measures against ground. If a reference input is provided, it measures the differential voltage between two points.").superRefine((data, ctx) => {
  const is_differential = data.reference_input_source_port_id || data.reference_input_source_net_id;
  if (is_differential) {
    const has_ports = !!data.signal_input_source_port_id || !!data.reference_input_source_port_id;
    const has_nets = !!data.signal_input_source_net_id || !!data.reference_input_source_net_id;
    if (has_ports && has_nets) {
      ctx.addIssue({
        code: exports_external.ZodIssueCode.custom,
        message: "Cannot mix port and net connections in a differential probe."
      });
    } else if (has_ports) {
      if (!data.signal_input_source_port_id || !data.reference_input_source_port_id) {
        ctx.addIssue({
          code: exports_external.ZodIssueCode.custom,
          message: "Differential port probe requires both signal_input_source_port_id and reference_input_source_port_id."
        });
      }
    } else if (has_nets) {
      if (!data.signal_input_source_net_id || !data.reference_input_source_net_id) {
        ctx.addIssue({
          code: exports_external.ZodIssueCode.custom,
          message: "Differential net probe requires both signal_input_source_net_id and reference_input_source_net_id."
        });
      }
    }
  } else {
    if (!!data.signal_input_source_port_id === !!data.signal_input_source_net_id) {
      ctx.addIssue({
        code: exports_external.ZodIssueCode.custom,
        message: "A voltage probe must have exactly one of signal_input_source_port_id or signal_input_source_net_id."
      });
    }
  }
});
expectTypesMatch(true);
var simulation_current_probe = exports_external.object({
  type: exports_external.literal("simulation_current_probe"),
  simulation_current_probe_id: getZodPrefixedIdWithDefault("simulation_current_probe"),
  source_component_id: exports_external.string().optional(),
  name: exports_external.string().optional(),
  positive_source_port_id: exports_external.string().optional(),
  negative_source_port_id: exports_external.string().optional(),
  positive_source_net_id: exports_external.string().optional(),
  negative_source_net_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional(),
  color: exports_external.string().optional()
}).describe("Defines a current probe for simulation. It measures current flowing from the positive endpoint to the negative endpoint.").superRefine((data, ctx) => {
  const hasPositivePort = !!data.positive_source_port_id;
  const hasNegativePort = !!data.negative_source_port_id;
  const hasPositiveNet = !!data.positive_source_net_id;
  const hasNegativeNet = !!data.negative_source_net_id;
  const hasPorts = hasPositivePort || hasNegativePort;
  const hasNets = hasPositiveNet || hasNegativeNet;
  if (hasPorts && hasNets) {
    ctx.addIssue({
      code: exports_external.ZodIssueCode.custom,
      message: "Cannot mix port and net connections in a current probe."
    });
    return;
  }
  if (hasPorts) {
    if (!hasPositivePort || !hasNegativePort) {
      ctx.addIssue({
        code: exports_external.ZodIssueCode.custom,
        message: "Current probe using source ports requires both positive_source_port_id and negative_source_port_id."
      });
    }
    return;
  }
  if (hasNets) {
    if (!hasPositiveNet || !hasNegativeNet) {
      ctx.addIssue({
        code: exports_external.ZodIssueCode.custom,
        message: "Current probe using source nets requires both positive_source_net_id and negative_source_net_id."
      });
    }
    return;
  }
  ctx.addIssue({
    code: exports_external.ZodIssueCode.custom,
    message: "A current probe must have either positive/negative source port ids or positive/negative source net ids."
  });
});
expectTypesMatch(true);
var simulation_unknown_experiment_error = base_circuit_json_error.extend({
  type: exports_external.literal("simulation_unknown_experiment_error"),
  simulation_unknown_experiment_error_id: getZodPrefixedIdWithDefault("simulation_unknown_experiment_error"),
  error_type: exports_external.literal("simulation_unknown_experiment_error").default("simulation_unknown_experiment_error"),
  simulation_experiment_id: exports_external.string().optional(),
  subcircuit_id: exports_external.string().optional()
}).describe("An unknown error occurred during the simulation experiment.");
expectTypesMatch(true);
var simulation_op_amp = exports_external.object({
  type: exports_external.literal("simulation_op_amp"),
  simulation_op_amp_id: getZodPrefixedIdWithDefault("simulation_op_amp"),
  source_component_id: exports_external.string().optional(),
  inverting_input_source_port_id: exports_external.string(),
  non_inverting_input_source_port_id: exports_external.string(),
  output_source_port_id: exports_external.string(),
  positive_supply_source_port_id: exports_external.string(),
  negative_supply_source_port_id: exports_external.string()
}).describe("Defines a simple ideal operational amplifier for simulation");
expectTypesMatch(true);
var simulation_spice_subcircuit = exports_external.object({
  type: exports_external.literal("simulation_spice_subcircuit"),
  simulation_spice_subcircuit_id: getZodPrefixedIdWithDefault("simulation_spice_subcircuit"),
  source_component_id: exports_external.string(),
  spice_pin_to_source_port_map: exports_external.record(exports_external.string(), exports_external.string()),
  subcircuit_source: exports_external.string()
}).describe("Defines a custom SPICE subcircuit model for simulation");
expectTypesMatch(true);
var hasValue = (value) => value !== undefined;
var simulation_oscilloscope_trace = exports_external.object({
  type: exports_external.literal("simulation_oscilloscope_trace"),
  simulation_oscilloscope_trace_id: getZodPrefixedIdWithDefault("simulation_oscilloscope_trace"),
  simulation_transient_voltage_graph_id: exports_external.string().optional(),
  simulation_transient_current_graph_id: exports_external.string().optional(),
  simulation_voltage_probe_id: exports_external.string().optional(),
  simulation_current_probe_id: exports_external.string().optional(),
  display_name: exports_external.string().optional(),
  color: exports_external.string().optional(),
  display_center_value: exports_external.number().optional(),
  display_center_offset_divs: exports_external.number().optional(),
  volts_per_div: exports_external.number().positive().optional(),
  amps_per_div: exports_external.number().positive().optional()
}).describe("Defines how a simulation measurement is rendered as an oscilloscope-style trace.").superRefine((data, ctx) => {
  const voltageReferences = [
    data.simulation_transient_voltage_graph_id,
    data.simulation_voltage_probe_id
  ].filter(hasValue).length;
  const currentReferences = [
    data.simulation_transient_current_graph_id,
    data.simulation_current_probe_id
  ].filter(hasValue).length;
  if (voltageReferences + currentReferences !== 1) {
    ctx.addIssue({
      code: exports_external.ZodIssueCode.custom,
      message: "An oscilloscope trace must reference exactly one voltage graph, current graph, voltage probe, or current probe."
    });
  }
  if (voltageReferences > 0 && data.amps_per_div !== undefined) {
    ctx.addIssue({
      code: exports_external.ZodIssueCode.custom,
      message: "Voltage oscilloscope traces must use volts_per_div, not amps_per_div."
    });
  }
  if (currentReferences > 0 && data.volts_per_div !== undefined) {
    ctx.addIssue({
      code: exports_external.ZodIssueCode.custom,
      message: "Current oscilloscope traces must use amps_per_div, not volts_per_div."
    });
  }
});
expectTypesMatch(true);
var any_circuit_element = exports_external.union([
  source_trace,
  source_port,
  source_component_internal_connection,
  any_source_component,
  source_net,
  source_group,
  source_simple_chip,
  source_simple_capacitor,
  source_simple_diode,
  source_simple_led,
  source_simple_resistor,
  source_simple_power_source,
  source_simple_battery,
  source_simple_inductor,
  source_simple_pin_header,
  source_simple_pinout,
  source_simple_resonator,
  source_simple_switch,
  source_simple_transistor,
  source_simple_test_point,
  source_simple_mosfet,
  source_simple_op_amp,
  source_simple_potentiometer,
  source_simple_push_button,
  source_pcb_ground_plane,
  source_manually_placed_via,
  source_board,
  source_project_metadata,
  source_invalid_component_property_error,
  source_trace_not_connected_error,
  source_pin_missing_trace_warning,
  source_unnamed_trace_warning,
  source_missing_manufacturer_part_number_warning,
  source_no_power_pin_defined_warning,
  source_no_ground_pin_defined_warning,
  source_component_pins_underspecified_warning,
  source_pin_must_be_connected_error,
  unknown_error_finding_part,
  source_i2c_misconfigured_error,
  source_component_misconfigured_error,
  source_ambiguous_port_reference,
  pcb_component,
  pcb_hole,
  pcb_missing_footprint_error,
  external_footprint_load_error,
  circuit_json_footprint_load_error,
  pcb_manual_edit_conflict_warning,
  pcb_connector_not_in_accessible_orientation_warning,
  supplier_footprint_mismatch_warning,
  pcb_plated_hole,
  pcb_keepout,
  pcb_port,
  pcb_net,
  pcb_text,
  pcb_trace,
  pcb_trace_warning,
  pcb_via,
  pcb_smtpad,
  pcb_solder_paste,
  pcb_board,
  pcb_panel,
  pcb_group,
  pcb_trace_hint,
  pcb_silkscreen_line,
  pcb_silkscreen_path,
  pcb_silkscreen_text,
  pcb_silkscreen_pill,
  pcb_copper_text,
  pcb_silkscreen_rect,
  pcb_silkscreen_circle,
  pcb_silkscreen_oval,
  pcb_silkscreen_graphic,
  pcb_trace_error,
  pcb_trace_missing_error,
  pcb_placement_error,
  pcb_panelization_placement_error,
  pcb_port_not_matched_error,
  pcb_port_not_connected_error,
  pcb_via_clearance_error,
  pcb_via_trace_clearance_error,
  pcb_pad_pad_clearance_error,
  pcb_pad_trace_clearance_error,
  pcb_fabrication_note_path,
  pcb_fabrication_note_text,
  pcb_fabrication_note_rect,
  pcb_fabrication_note_dimension,
  pcb_note_text,
  pcb_note_rect,
  pcb_note_path,
  pcb_note_line,
  pcb_note_dimension,
  pcb_autorouting_error,
  pcb_footprint_overlap_error,
  pcb_courtyard_overlap_error,
  pcb_breakout_point,
  pcb_cutout,
  pcb_ground_plane,
  pcb_ground_plane_region,
  pcb_thermal_spoke,
  pcb_copper_pour,
  pcb_component_outside_board_error,
  pcb_component_not_on_board_edge_error,
  pcb_component_invalid_layer_error,
  pcb_courtyard_rect,
  pcb_courtyard_outline,
  pcb_courtyard_polygon,
  pcb_courtyard_circle,
  pcb_courtyard_pill,
  schematic_box,
  schematic_text,
  schematic_line,
  schematic_rect,
  schematic_circle,
  schematic_arc,
  schematic_component,
  schematic_symbol,
  schematic_port,
  schematic_trace,
  schematic_path,
  schematic_error,
  schematic_layout_error,
  schematic_net_label,
  schematic_debug_object,
  schematic_voltage_probe,
  schematic_manual_edit_conflict_warning,
  schematic_group,
  schematic_sheet,
  schematic_table,
  schematic_table_cell,
  cad_component,
  simulation_voltage_source,
  simulation_current_source,
  simulation_experiment,
  simulation_transient_voltage_graph,
  simulation_transient_current_graph,
  simulation_switch,
  simulation_voltage_probe,
  simulation_current_probe,
  simulation_oscilloscope_trace,
  simulation_unknown_experiment_error,
  simulation_op_amp,
  simulation_spice_subcircuit
]);
var any_soup_element = any_circuit_element;
expectTypesMatch(true);
expectStringUnionsMatch(true);
// ../../work/placement-analysis/node_modules/transformation-matrix/src/fromTransformAttribute.autogenerated.js
function peg$subclass(child, parent) {
  function C() {
    this.constructor = child;
  }
  C.prototype = parent.prototype;
  child.prototype = new C;
}
function peg$SyntaxError(message, expected, found, location) {
  var self2 = Error.call(this, message);
  if (Object.setPrototypeOf) {
    Object.setPrototypeOf(self2, peg$SyntaxError.prototype);
  }
  self2.expected = expected;
  self2.found = found;
  self2.location = location;
  self2.name = "SyntaxError";
  return self2;
}
peg$subclass(peg$SyntaxError, Error);
function peg$padEnd(str, targetLength, padString) {
  padString = padString || " ";
  if (str.length > targetLength) {
    return str;
  }
  targetLength -= str.length;
  padString += padString.repeat(targetLength);
  return str + padString.slice(0, targetLength);
}
peg$SyntaxError.prototype.format = function(sources) {
  var str = "Error: " + this.message;
  if (this.location) {
    var src = null;
    var k;
    for (k = 0;k < sources.length; k++) {
      if (sources[k].source === this.location.source) {
        src = sources[k].text.split(/\r\n|\n|\r/g);
        break;
      }
    }
    var s = this.location.start;
    var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
    var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
    if (src) {
      var e = this.location.end;
      var filler = peg$padEnd("", offset_s.line.toString().length, " ");
      var line = src[s.line - 1];
      var last = s.line === e.line ? e.column : line.length + 1;
      var hatLen = last - s.column || 1;
      str += `
 --> ` + loc + `
` + filler + ` |
` + offset_s.line + " | " + line + `
` + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
    } else {
      str += `
 at ` + loc;
    }
  }
  return str;
};
peg$SyntaxError.buildMessage = function(expected, found) {
  var DESCRIBE_EXPECTATION_FNS = {
    literal: function(expectation) {
      return '"' + literalEscape(expectation.text) + '"';
    },
    class: function(expectation) {
      var escapedParts = expectation.parts.map(function(part) {
        return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
      });
      return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
    },
    any: function() {
      return "any character";
    },
    end: function() {
      return "end of input";
    },
    other: function(expectation) {
      return expectation.description;
    }
  };
  function hex(ch) {
    return ch.charCodeAt(0).toString(16).toUpperCase();
  }
  function literalEscape(s) {
    return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
      return "\\x0" + hex(ch);
    }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
      return "\\x" + hex(ch);
    });
  }
  function classEscape(s) {
    return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
      return "\\x0" + hex(ch);
    }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
      return "\\x" + hex(ch);
    });
  }
  function describeExpectation(expectation) {
    return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
  }
  function describeExpected(expected2) {
    var descriptions = expected2.map(describeExpectation);
    var i, j;
    descriptions.sort();
    if (descriptions.length > 0) {
      for (i = 1, j = 1;i < descriptions.length; i++) {
        if (descriptions[i - 1] !== descriptions[i]) {
          descriptions[j] = descriptions[i];
          j++;
        }
      }
      descriptions.length = j;
    }
    switch (descriptions.length) {
      case 1:
        return descriptions[0];
      case 2:
        return descriptions[0] + " or " + descriptions[1];
      default:
        return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
    }
  }
  function describeFound(found2) {
    return found2 ? '"' + literalEscape(found2) + '"' : "end of input";
  }
  return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
};
// ../../work/placement-analysis/node_modules/parsel-js/dist/parsel.js
var TRIM_TOKENS = new Set(["combinator", "comma"]);
var RECURSIVE_PSEUDO_CLASSES = new Set([
  "not",
  "is",
  "where",
  "has",
  "matches",
  "-moz-any",
  "-webkit-any",
  "nth-child",
  "nth-last-child"
]);

// ../../work/placement-analysis/node_modules/@tscircuit/circuit-json-util/dist/index.js
function connect(map, a, b) {
  if (!a || !b)
    return;
  let setA = map.get(a);
  if (!setA) {
    setA = /* @__PURE__ */ new Set;
    map.set(a, setA);
  }
  setA.add(b);
  let setB = map.get(b);
  if (!setB) {
    setB = /* @__PURE__ */ new Set;
    map.set(b, setB);
  }
  setB.add(a);
}
function buildSubtree(soup, opts) {
  if (!opts.subcircuit_id && !opts.source_group_id)
    return [...soup];
  let effectiveOpts = opts;
  if (opts.subcircuit_id) {
    const subcircuitIds = /* @__PURE__ */ new Set([opts.subcircuit_id]);
    const groupChildren = /* @__PURE__ */ new Map;
    const groupSubcircuit = /* @__PURE__ */ new Map;
    for (const elm of soup) {
      if (elm.type === "source_group") {
        const groupId = elm.source_group_id;
        const subcircuitId = elm.subcircuit_id;
        if (subcircuitId) {
          groupSubcircuit.set(groupId, subcircuitId);
        }
        const parentId = elm.parent_source_group_id;
        if (parentId) {
          if (!groupChildren.has(parentId)) {
            groupChildren.set(parentId, []);
          }
          groupChildren.get(parentId).push(groupId);
        }
      }
    }
    let rootGroupId;
    for (const [groupId, subcircuitId] of groupSubcircuit) {
      if (subcircuitId === opts.subcircuit_id) {
        rootGroupId = groupId;
        break;
      }
    }
    if (rootGroupId) {
      const collectChildSubcircuits = (groupId) => {
        const children = groupChildren.get(groupId) || [];
        for (const childId of children) {
          const childSubcircuit = groupSubcircuit.get(childId);
          if (childSubcircuit) {
            subcircuitIds.add(childSubcircuit);
          }
          collectChildSubcircuits(childId);
        }
      };
      collectChildSubcircuits(rootGroupId);
      effectiveOpts = { ...opts, subcircuit_ids: Array.from(subcircuitIds) };
    }
  }
  const idMap = /* @__PURE__ */ new Map;
  for (const elm of soup) {
    const idKey = `${elm.type}_id`;
    const idVal = elm[idKey];
    if (typeof idVal === "string") {
      idMap.set(idVal, elm);
    }
  }
  const adj = /* @__PURE__ */ new Map;
  for (const elm of soup) {
    const entries = Object.entries(elm);
    for (const [key, val] of entries) {
      if (key === "parent_source_group_id")
        continue;
      if (key.endsWith("_id") && typeof val === "string") {
        const other = idMap.get(val);
        connect(adj, elm, other);
      } else if (key.endsWith("_ids") && Array.isArray(val)) {
        for (const v of val) {
          if (typeof v === "string") {
            const other = idMap.get(v);
            connect(adj, elm, other);
          }
        }
      }
    }
  }
  const queue = [];
  const included = /* @__PURE__ */ new Set;
  for (const elm of soup) {
    let shouldInclude = false;
    if (effectiveOpts.subcircuit_id && "subcircuit_id" in elm && elm.subcircuit_id === effectiveOpts.subcircuit_id) {
      shouldInclude = true;
    } else if (effectiveOpts.subcircuit_ids && "subcircuit_id" in elm && elm.subcircuit_id && effectiveOpts.subcircuit_ids.includes(elm.subcircuit_id)) {
      shouldInclude = true;
    } else if (effectiveOpts.source_group_id && "source_group_id" in elm && elm.source_group_id === effectiveOpts.source_group_id) {
      shouldInclude = true;
    } else if (effectiveOpts.source_group_id && "member_source_group_ids" in elm && Array.isArray(elm.member_source_group_ids) && elm.member_source_group_ids.includes(effectiveOpts.source_group_id)) {
      shouldInclude = true;
    }
    if (shouldInclude) {
      queue.push(elm);
      included.add(elm);
    }
  }
  while (queue.length > 0) {
    const elm = queue.shift();
    const neighbors = adj.get(elm);
    if (!neighbors)
      continue;
    for (const n of neighbors) {
      if (!included.has(n)) {
        included.add(n);
        queue.push(n);
      }
    }
  }
  return soup.filter((e) => included.has(e));
}
var cju = (circuitJsonInput, options = {}) => {
  const circuitJson = circuitJsonInput;
  let internalStore = circuitJson._internal_store;
  if (!internalStore) {
    internalStore = {
      counts: {},
      editCount: 0
    };
    circuitJson._internal_store = internalStore;
    for (const elm of circuitJson) {
      const type = elm.type;
      const idVal = elm[`${type}_id`];
      if (!idVal)
        continue;
      const idNum = Number.parseInt(idVal.split("_").pop());
      if (!Number.isNaN(idNum)) {
        internalStore.counts[type] = Math.max(internalStore.counts[type] ?? 0, idNum);
      }
    }
  }
  const su2 = new Proxy({}, {
    get: (proxy_target, prop) => {
      if (prop === "toArray") {
        return () => {
          circuitJson.editCount = internalStore.editCount;
          return circuitJson;
        };
      }
      if (prop === "editCount") {
        return internalStore.editCount;
      }
      if (prop === "subtree") {
        return (opts) => cju(buildSubtree(circuitJson, opts), options);
      }
      if (prop === "insert") {
        return (elm) => {
          const component_type2 = elm.type;
          if (!component_type2) {
            throw new Error("insert requires an element with a type");
          }
          internalStore.counts[component_type2] ??= -1;
          internalStore.counts[component_type2]++;
          const index = internalStore.counts[component_type2];
          const newElm = {
            ...elm,
            type: component_type2,
            [`${component_type2}_id`]: `${component_type2}_${index}`
          };
          if (options.validateInserts) {
            const parser = exports_dist[component_type2] ?? any_soup_element;
            parser.parse(newElm);
          }
          circuitJson.push(newElm);
          internalStore.editCount++;
          return newElm;
        };
      }
      if (prop === "insertAll") {
        return (elms) => {
          return elms.map((elm) => su2.insert(elm));
        };
      }
      const component_type = prop;
      return {
        get: (id) => circuitJson.find((e) => e.type === component_type && e[`${component_type}_id`] === id),
        getUsing: (using) => {
          const keys = Object.keys(using);
          if (keys.length !== 1) {
            throw new Error("getUsing requires exactly one key, e.g. { pcb_component_id }");
          }
          const join_key = keys[0];
          const join_type = join_key.replace("_id", "");
          const joiner = circuitJson.find((e) => e.type === join_type && e[join_key] === using[join_key]);
          if (!joiner)
            return null;
          return circuitJson.find((e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]);
        },
        getWhere: (where) => {
          const keys = Object.keys(where);
          return circuitJson.find((e) => e.type === component_type && keys.every((key) => e[key] === where[key]));
        },
        list: (where) => {
          const keys = !where ? [] : Object.keys(where);
          return circuitJson.filter((e) => e.type === component_type && keys.every((key) => e[key] === where[key]));
        },
        insert: (elm) => {
          internalStore.counts[component_type] ??= -1;
          internalStore.counts[component_type]++;
          const index = internalStore.counts[component_type];
          const newElm = {
            type: component_type,
            [`${component_type}_id`]: `${component_type}_${index}`,
            ...elm
          };
          if (options.validateInserts) {
            const parser = exports_dist[component_type] ?? any_soup_element;
            parser.parse(newElm);
          }
          circuitJson.push(newElm);
          internalStore.editCount++;
          return newElm;
        },
        delete: (id) => {
          const elm = circuitJson.find((e) => e[`${component_type}_id`] === id);
          if (!elm)
            return;
          circuitJson.splice(circuitJson.indexOf(elm), 1);
          internalStore.editCount++;
        },
        update: (id, newProps) => {
          const elm = circuitJson.find((e) => e.type === component_type && e[`${component_type}_id`] === id);
          if (!elm)
            return null;
          Object.assign(elm, newProps);
          internalStore.editCount++;
          return elm;
        },
        select: (selector) => {
          if (component_type === "source_component") {
            return circuitJson.find((e) => e.type === "source_component" && e.name === selector.replace(/\./g, ""));
          } else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
            const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
            const source_component = circuitJson.find((e) => e.type === "source_component" && e.name === component_name);
            if (!source_component)
              return null;
            const source_port2 = circuitJson.find((e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector)));
            if (!source_port2)
              return null;
            if (component_type === "source_port")
              return source_port2;
            if (component_type === "pcb_port") {
              return circuitJson.find((e) => e.type === "pcb_port" && e.source_port_id === source_port2.source_port_id);
            } else if (component_type === "schematic_port") {
              return circuitJson.find((e) => e.type === "schematic_port" && e.source_port_id === source_port2.source_port_id);
            }
          }
        }
      };
    }
  });
  return su2;
};
cju.unparsed = cju;
var cju_default = cju;
function createIdKey(element) {
  const type = element.type;
  return `${type}:${element[`${type}_id`]}`;
}
var cjuIndexed = (soup, options = {}) => {
  let internalStore = soup._internal_store_indexed;
  if (!internalStore) {
    internalStore = {
      counts: {},
      editCount: 0,
      indexes: {}
    };
    for (const elm of soup) {
      const type = elm.type;
      const idVal = elm[`${type}_id`];
      if (!idVal)
        continue;
      const idNum = Number.parseInt(idVal.split("_").pop() || "");
      if (!Number.isNaN(idNum)) {
        internalStore.counts[type] = Math.max(internalStore.counts[type] ?? 0, idNum);
      }
    }
    const indexConfig = options.indexConfig || {};
    const indexes = internalStore.indexes;
    if (indexConfig.byId) {
      indexes.byId = /* @__PURE__ */ new Map;
    }
    if (indexConfig.byType) {
      indexes.byType = /* @__PURE__ */ new Map;
    }
    if (indexConfig.byRelation) {
      indexes.byRelation = /* @__PURE__ */ new Map;
    }
    if (indexConfig.bySubcircuit) {
      indexes.bySubcircuit = /* @__PURE__ */ new Map;
    }
    if (indexConfig.byCustomField && indexConfig.byCustomField.length > 0) {
      indexes.byCustomField = /* @__PURE__ */ new Map;
      for (const field of indexConfig.byCustomField) {
        indexes.byCustomField.set(field, /* @__PURE__ */ new Map);
      }
    }
    for (const element of soup) {
      if (indexConfig.byId) {
        const idKey = createIdKey(element);
        indexes.byId.set(idKey, element);
      }
      if (indexConfig.byType) {
        const elementsOfType = indexes.byType.get(element.type) || [];
        elementsOfType.push(element);
        indexes.byType.set(element.type, elementsOfType);
      }
      if (indexConfig.byRelation) {
        const elementEntries = Object.entries(element);
        for (const [key, value] of elementEntries) {
          if (key.endsWith("_id") && key !== `${element.type}_id` && typeof value === "string") {
            const relationTypeMap = indexes.byRelation.get(key) || /* @__PURE__ */ new Map;
            const relatedElements = relationTypeMap.get(value) || [];
            relatedElements.push(element);
            relationTypeMap.set(value, relatedElements);
            indexes.byRelation.set(key, relationTypeMap);
          }
        }
      }
      if (indexConfig.bySubcircuit && "subcircuit_id" in element) {
        const subcircuitId = element.subcircuit_id;
        if (subcircuitId && typeof subcircuitId === "string") {
          const subcircuitElements = indexes.bySubcircuit.get(subcircuitId) || [];
          subcircuitElements.push(element);
          indexes.bySubcircuit.set(subcircuitId, subcircuitElements);
        }
      }
      if (indexConfig.byCustomField && indexes.byCustomField) {
        for (const field of indexConfig.byCustomField) {
          if (field in element) {
            const fieldValue = element[field];
            if (fieldValue !== undefined && (typeof fieldValue === "string" || typeof fieldValue === "number")) {
              const fieldValueStr = String(fieldValue);
              const fieldMap = indexes.byCustomField.get(field);
              const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];
              elementsWithFieldValue.push(element);
              fieldMap.set(fieldValueStr, elementsWithFieldValue);
            }
          }
        }
      }
    }
    soup._internal_store_indexed = internalStore;
  }
  const suIndexed = new Proxy({}, {
    get: (proxy_target, prop) => {
      if (prop === "toArray") {
        return () => {
          soup.editCount = internalStore.editCount;
          return soup;
        };
      }
      if (prop === "editCount") {
        return internalStore.editCount;
      }
      const component_type = prop;
      return {
        get: (id) => {
          const indexConfig = options.indexConfig || {};
          if (indexConfig.byId && internalStore.indexes.byId) {
            return internalStore.indexes.byId.get(`${component_type}:${id}`) || null;
          }
          if (indexConfig.byType && internalStore.indexes.byType) {
            const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
            return elementsOfType.find((e) => e[`${component_type}_id`] === id) || null;
          }
          return soup.find((e) => e.type === component_type && e[`${component_type}_id`] === id) || null;
        },
        getUsing: (using) => {
          const indexConfig = options.indexConfig || {};
          const keys = Object.keys(using);
          if (keys.length !== 1) {
            throw new Error("getUsing requires exactly one key, e.g. { pcb_component_id }");
          }
          const join_key = keys[0];
          const join_type = join_key.replace("_id", "");
          if (indexConfig.byRelation && internalStore.indexes.byRelation) {
            const relationMap = internalStore.indexes.byRelation.get(join_key);
            if (relationMap) {
              const relatedElements = relationMap.get(using[join_key]) || [];
              const joiner2 = relatedElements.find((e) => e.type === join_type);
              if (!joiner2)
                return null;
              const joinerId = joiner2[`${component_type}_id`];
              if (indexConfig.byId && internalStore.indexes.byId) {
                return internalStore.indexes.byId.get(`${component_type}:${joinerId}`) || null;
              }
              if (indexConfig.byType && internalStore.indexes.byType) {
                const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
                return elementsOfType.find((e) => e[`${component_type}_id`] === joinerId) || null;
              }
              return soup.find((e) => e.type === component_type && e[`${component_type}_id`] === joinerId) || null;
            }
          }
          const joiner = soup.find((e) => e.type === join_type && e[join_key] === using[join_key]);
          if (!joiner)
            return null;
          return soup.find((e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]) || null;
        },
        getWhere: (where) => {
          const indexConfig = options.indexConfig || {};
          const keys = Object.keys(where);
          if (keys.length === 1 && indexConfig.byCustomField && internalStore.indexes.byCustomField) {
            const field = keys[0];
            const fieldMap = internalStore.indexes.byCustomField.get(field);
            if (fieldMap) {
              const fieldValue = String(where[field]);
              const elementsWithFieldValue = fieldMap.get(fieldValue) || [];
              return elementsWithFieldValue.find((e) => e.type === component_type) || null;
            }
          }
          if ("subcircuit_id" in where && indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit) {
            const subcircuitId = where.subcircuit_id;
            const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
            return subcircuitElements.find((e) => e.type === component_type && keys.every((key) => e[key] === where[key])) || null;
          }
          if (indexConfig.byType && internalStore.indexes.byType) {
            const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
            return elementsOfType.find((e) => keys.every((key) => e[key] === where[key])) || null;
          }
          return soup.find((e) => e.type === component_type && keys.every((key) => e[key] === where[key])) || null;
        },
        list: (where) => {
          const indexConfig = options.indexConfig || {};
          const keys = !where ? [] : Object.keys(where);
          if (keys.length === 0 && indexConfig.byType && internalStore.indexes.byType) {
            return internalStore.indexes.byType.get(component_type) || [];
          }
          if (keys.length === 1 && keys[0] === "subcircuit_id" && indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit) {
            const subcircuitId = where.subcircuit_id;
            const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
            return subcircuitElements.filter((e) => e.type === component_type);
          }
          let elementsToFilter;
          if (indexConfig.byType && internalStore.indexes.byType) {
            elementsToFilter = internalStore.indexes.byType.get(component_type) || [];
          } else {
            elementsToFilter = soup.filter((e) => e.type === component_type);
          }
          if (keys.length > 0) {
            return elementsToFilter.filter((e) => keys.every((key) => e[key] === where[key]));
          }
          return elementsToFilter;
        },
        insert: (elm) => {
          internalStore.counts[component_type] ??= -1;
          internalStore.counts[component_type]++;
          const index = internalStore.counts[component_type];
          const newElm = {
            type: component_type,
            [`${component_type}_id`]: `${component_type}_${index}`,
            ...elm
          };
          if (options.validateInserts) {
            const parser = exports_dist[component_type] ?? any_soup_element;
            parser.parse(newElm);
          }
          soup.push(newElm);
          internalStore.editCount++;
          const indexConfig = options.indexConfig || {};
          if (indexConfig.byId && internalStore.indexes.byId) {
            const idKey = createIdKey(newElm);
            internalStore.indexes.byId.set(idKey, newElm);
          }
          if (indexConfig.byType && internalStore.indexes.byType) {
            const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
            elementsOfType.push(newElm);
            internalStore.indexes.byType.set(component_type, elementsOfType);
          }
          if (indexConfig.byRelation && internalStore.indexes.byRelation) {
            const elementEntries = Object.entries(newElm);
            for (const [key, value] of elementEntries) {
              if (key.endsWith("_id") && key !== `${newElm.type}_id` && typeof value === "string") {
                const relationTypeMap = internalStore.indexes.byRelation.get(key) || /* @__PURE__ */ new Map;
                const relatedElements = relationTypeMap.get(value) || [];
                relatedElements.push(newElm);
                relationTypeMap.set(value, relatedElements);
                internalStore.indexes.byRelation.set(key, relationTypeMap);
              }
            }
          }
          if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in newElm) {
            const subcircuitId = newElm.subcircuit_id;
            if (subcircuitId && typeof subcircuitId === "string") {
              const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
              subcircuitElements.push(newElm);
              internalStore.indexes.bySubcircuit.set(subcircuitId, subcircuitElements);
            }
          }
          if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
            for (const field of indexConfig.byCustomField) {
              if (field in newElm) {
                const fieldValue = newElm[field];
                if (fieldValue !== undefined && (typeof fieldValue === "string" || typeof fieldValue === "number")) {
                  const fieldValueStr = String(fieldValue);
                  const fieldMap = internalStore.indexes.byCustomField.get(field);
                  const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];
                  elementsWithFieldValue.push(newElm);
                  fieldMap.set(fieldValueStr, elementsWithFieldValue);
                }
              }
            }
          }
          return newElm;
        },
        delete: (id) => {
          const indexConfig = options.indexConfig || {};
          let elm;
          if (indexConfig.byId && internalStore.indexes.byId) {
            elm = internalStore.indexes.byId.get(`${component_type}:${id}`);
          } else if (indexConfig.byType && internalStore.indexes.byType) {
            const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
            elm = elementsOfType.find((e) => e[`${component_type}_id`] === id);
          } else {
            elm = soup.find((e) => e[`${component_type}_id`] === id);
          }
          if (!elm)
            return;
          const elmIndex = soup.indexOf(elm);
          if (elmIndex >= 0) {
            soup.splice(elmIndex, 1);
            internalStore.editCount++;
          }
          if (indexConfig.byId && internalStore.indexes.byId) {
            const idKey = createIdKey(elm);
            internalStore.indexes.byId.delete(idKey);
          }
          if (indexConfig.byType && internalStore.indexes.byType) {
            const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
            const filteredElements = elementsOfType.filter((e) => e[`${component_type}_id`] !== id);
            internalStore.indexes.byType.set(component_type, filteredElements);
          }
          if (indexConfig.byRelation && internalStore.indexes.byRelation) {
            for (const [
              relationKey,
              relationMap
            ] of internalStore.indexes.byRelation.entries()) {
              for (const [relationValue, elements] of relationMap.entries()) {
                const updatedElements = elements.filter((e) => e !== elm);
                if (updatedElements.length === 0) {
                  relationMap.delete(relationValue);
                } else {
                  relationMap.set(relationValue, updatedElements);
                }
              }
            }
          }
          if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in elm) {
            const subcircuitId = elm.subcircuit_id;
            if (subcircuitId) {
              const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
              const updatedElements = subcircuitElements.filter((e) => e !== elm);
              if (updatedElements.length === 0) {
                internalStore.indexes.bySubcircuit.delete(subcircuitId);
              } else {
                internalStore.indexes.bySubcircuit.set(subcircuitId, updatedElements);
              }
            }
          }
          if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
            for (const fieldMap of internalStore.indexes.byCustomField.values()) {
              for (const [fieldValue, elements] of fieldMap.entries()) {
                const updatedElements = elements.filter((e) => e !== elm);
                if (updatedElements.length === 0) {
                  fieldMap.delete(fieldValue);
                } else {
                  fieldMap.set(fieldValue, updatedElements);
                }
              }
            }
          }
        },
        update: (id, newProps) => {
          const indexConfig = options.indexConfig || {};
          let elm;
          if (indexConfig.byId && internalStore.indexes.byId) {
            elm = internalStore.indexes.byId.get(`${component_type}:${id}`);
          } else if (indexConfig.byType && internalStore.indexes.byType) {
            const elementsOfType = internalStore.indexes.byType.get(component_type) || [];
            elm = elementsOfType.find((e) => e[`${component_type}_id`] === id);
          } else {
            elm = soup.find((e) => e.type === component_type && e[`${component_type}_id`] === id);
          }
          if (!elm)
            return null;
          if (indexConfig.byRelation && internalStore.indexes.byRelation) {
            const elementEntries = Object.entries(elm);
            for (const [key, value] of elementEntries) {
              if (key.endsWith("_id") && key !== `${elm.type}_id` && typeof value === "string") {
                if (key in newProps && newProps[key] !== value) {
                  const relationTypeMap = internalStore.indexes.byRelation.get(key);
                  if (relationTypeMap) {
                    const relatedElements = relationTypeMap.get(value) || [];
                    const updatedElements = relatedElements.filter((e) => e !== elm);
                    if (updatedElements.length === 0) {
                      relationTypeMap.delete(value);
                    } else {
                      relationTypeMap.set(value, updatedElements);
                    }
                  }
                }
              }
            }
          }
          if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in elm && "subcircuit_id" in newProps) {
            const oldSubcircuitId = elm.subcircuit_id;
            const newSubcircuitId = newProps.subcircuit_id;
            if (oldSubcircuitId !== newSubcircuitId) {
              const subcircuitElements = internalStore.indexes.bySubcircuit.get(oldSubcircuitId) || [];
              const updatedElements = subcircuitElements.filter((e) => e !== elm);
              if (updatedElements.length === 0) {
                internalStore.indexes.bySubcircuit.delete(oldSubcircuitId);
              } else {
                internalStore.indexes.bySubcircuit.set(oldSubcircuitId, updatedElements);
              }
            }
          }
          if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
            for (const field of indexConfig.byCustomField) {
              if (field in elm && field in newProps && elm[field] !== newProps[field]) {
                const fieldMap = internalStore.indexes.byCustomField.get(field);
                if (fieldMap) {
                  const oldValue = String(elm[field]);
                  const elements = fieldMap.get(oldValue) || [];
                  const updatedElements = elements.filter((e) => e !== elm);
                  if (updatedElements.length === 0) {
                    fieldMap.delete(oldValue);
                  } else {
                    fieldMap.set(oldValue, updatedElements);
                  }
                }
              }
            }
          }
          Object.assign(elm, newProps);
          internalStore.editCount++;
          if (indexConfig.byRelation && internalStore.indexes.byRelation) {
            const elementEntries = Object.entries(elm);
            for (const [key, value] of elementEntries) {
              if (key.endsWith("_id") && key !== `${elm.type}_id` && typeof value === "string") {
                if (key in newProps) {
                  const relationTypeMap = internalStore.indexes.byRelation.get(key) || /* @__PURE__ */ new Map;
                  const relatedElements = relationTypeMap.get(value) || [];
                  if (!relatedElements.includes(elm)) {
                    relatedElements.push(elm);
                    relationTypeMap.set(value, relatedElements);
                    internalStore.indexes.byRelation.set(key, relationTypeMap);
                  }
                }
              }
            }
          }
          if (indexConfig.bySubcircuit && internalStore.indexes.bySubcircuit && "subcircuit_id" in elm && "subcircuit_id" in newProps) {
            const subcircuitId = elm.subcircuit_id;
            if (subcircuitId && typeof subcircuitId === "string") {
              const subcircuitElements = internalStore.indexes.bySubcircuit.get(subcircuitId) || [];
              if (!subcircuitElements.includes(elm)) {
                subcircuitElements.push(elm);
                internalStore.indexes.bySubcircuit.set(subcircuitId, subcircuitElements);
              }
            }
          }
          if (indexConfig.byCustomField && internalStore.indexes.byCustomField) {
            for (const field of indexConfig.byCustomField) {
              if (field in elm && field in newProps) {
                const fieldValue = elm[field];
                if (fieldValue !== undefined && (typeof fieldValue === "string" || typeof fieldValue === "number")) {
                  const fieldValueStr = String(fieldValue);
                  const fieldMap = internalStore.indexes.byCustomField.get(field);
                  const elementsWithFieldValue = fieldMap.get(fieldValueStr) || [];
                  if (!elementsWithFieldValue.includes(elm)) {
                    elementsWithFieldValue.push(elm);
                    fieldMap.set(fieldValueStr, elementsWithFieldValue);
                  }
                }
              }
            }
          }
          return elm;
        },
        select: (selector) => {
          if (component_type === "source_component") {
            return soup.find((e) => e.type === "source_component" && e.name === selector.replace(/\./g, "")) || null;
          } else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
            const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
            const source_component = soup.find((e) => e.type === "source_component" && e.name === component_name);
            if (!source_component)
              return null;
            const source_port2 = soup.find((e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector)));
            if (!source_port2)
              return null;
            if (component_type === "source_port")
              return source_port2;
            if (component_type === "pcb_port") {
              return soup.find((e) => e.type === "pcb_port" && e.source_port_id === source_port2.source_port_id) || null;
            } else if (component_type === "schematic_port") {
              return soup.find((e) => e.type === "schematic_port" && e.source_port_id === source_port2.source_port_id) || null;
            }
          }
          return null;
        }
      };
    }
  });
  return suIndexed;
};
cjuIndexed.unparsed = cjuIndexed;

// ../../work/placement-analysis/lib/utils/schematic-sheets.ts
var getSchematicSheetNamesById = (circuitJson) => {
  const map = new Map;
  for (const element of circuitJson) {
    if (element.type === "schematic_sheet" && element.name) {
      map.set(element.schematic_sheet_id, element.name);
    }
  }
  return map;
};

// ../../work/placement-analysis/lib/utils/placements.ts
var isSchematicBox = (el) => el.type === "schematic_box";
var isSchematicComponent = (el) => el.type === "schematic_component";
var getSchematicSheetId = (el) => el.schematic_sheet_id;
var getSourceComponentName = (circuitJson, sourceComponentId) => {
  if (!sourceComponentId)
    return;
  return cju_default(circuitJson).source_component.get(sourceComponentId)?.name;
};
var getSourceComponentMetadata = (schematicBox, circuitJson) => {
  if (!schematicBox.schematic_component_id)
    return {};
  const util3 = cju_default(circuitJson);
  const sc = util3.schematic_component.get(schematicBox.schematic_component_id);
  if (!sc?.source_component_id)
    return {};
  const sourceComponent = util3.source_component.get(sc.source_component_id);
  return {
    sourceComponentId: sc.source_component_id,
    sourceComponentName: sourceComponent?.name
  };
};
var schematicComponentToPlacement = (schematicComponent, circuitJson, schematicSheetNameById, schematicBox) => {
  let schematicSheetId = getSchematicSheetId(schematicComponent);
  if (schematicSheetId === undefined && schematicBox) {
    schematicSheetId = getSchematicSheetId(schematicBox);
  }
  let schematicSheetName;
  if (schematicSheetId) {
    schematicSheetName = schematicSheetNameById.get(schematicSheetId);
  }
  const placement = {
    lineItemType: "SchematicBoxPlacement",
    positionAnchor: "center",
    schX: schematicComponent.center.x,
    schY: schematicComponent.center.y,
    width: schematicBox?.width ?? schematicComponent.size.width,
    height: schematicBox?.height ?? schematicComponent.size.height,
    sourceComponentId: schematicComponent.source_component_id,
    sourceComponentName: getSourceComponentName(circuitJson, schematicComponent.source_component_id),
    schematicComponentId: schematicComponent.schematic_component_id,
    schematicSymbolId: schematicBox?.schematic_symbol_id ?? schematicComponent.schematic_symbol_id,
    subcircuitId: schematicComponent.subcircuit_id ?? schematicBox?.subcircuit_id
  };
  if (schematicSheetId) {
    placement.schematicSheetId = schematicSheetId;
  }
  if (schematicSheetName) {
    placement.schematicSheetName = schematicSheetName;
  }
  return placement;
};
var schematicBoxToPlacement = (schematicBox, circuitJson, schematicSheetNameById) => {
  const schematicSheetId = getSchematicSheetId(schematicBox);
  let schematicSheetName;
  if (schematicSheetId) {
    schematicSheetName = schematicSheetNameById.get(schematicSheetId);
  }
  const placement = {
    lineItemType: "SchematicBoxPlacement",
    positionAnchor: "center",
    schX: schematicBox.x,
    schY: schematicBox.y,
    width: schematicBox.width,
    height: schematicBox.height,
    ...getSourceComponentMetadata(schematicBox, circuitJson),
    schematicComponentId: schematicBox.schematic_component_id,
    schematicSymbolId: schematicBox.schematic_symbol_id,
    subcircuitId: schematicBox.subcircuit_id
  };
  if (schematicSheetId) {
    placement.schematicSheetId = schematicSheetId;
  }
  if (schematicSheetName) {
    placement.schematicSheetName = schematicSheetName;
  }
  return placement;
};
var buildSolverContext = (circuitJson) => {
  const schematicBoxes = circuitJson.filter(isSchematicBox);
  const schematicSheetNameById = getSchematicSheetNamesById(circuitJson);
  const schematicComponentIds = new Set(circuitJson.filter(isSchematicComponent).map((sc) => sc.schematic_component_id));
  const componentPlacements = [
    ...circuitJson.filter(isSchematicComponent).map((sc) => schematicComponentToPlacement(sc, circuitJson, schematicSheetNameById, schematicBoxes.find((sb) => sb.schematic_component_id === sc.schematic_component_id))),
    ...schematicBoxes.filter((sb) => !sb.schematic_component_id || !schematicComponentIds.has(sb.schematic_component_id)).map((sb) => schematicBoxToPlacement(sb, circuitJson, schematicSheetNameById))
  ];
  return { circuitJson, componentPlacements };
};

// ../../work/placement-analysis/lib/solvers/SwitchPullResistorPlacementSolver/SwitchPullResistorPlacementSolver.ts
class SwitchPullResistorPlacementSolver extends BaseSolver {
  params;
  constructor(params) {
    super();
    this.params = params;
  }
  _step() {
    const index = new PlacementNetworkIndex(this.params.ctx);
    for (const pair of getSwitchPullResistorPairs(index)) {
      const { resistor, switchBox, signalPort, signalSchY, pullDirection } = pair;
      if (pair.horizontalPushbutton)
        continue;
      const signal = index.connected(signalPort.source_port_id);
      if (index.portsByNet.get(signal)?.length !== 2)
        continue;
      if (signalPort.needs_external_pullup || signalPort.needs_external_pulldown)
        continue;
      const wrongSideGap = pullDirection === "up" ? signalSchY - (resistor.schY + resistor.height / 2) : resistor.schY - resistor.height / 2 - signalSchY;
      if (wrongSideGap <= 1.5)
        continue;
      const preferredSide = pullDirection === "up" ? "above" : "below";
      this.params.issues.push({
        lineItemType: "PullResistorOnWrongSide",
        resistorSchematicBox: resistor,
        hostSchematicBox: switchBox,
        signalSourcePortId: signalPort.source_port_id,
        signalPinName: signalPort.name,
        signalSchY,
        pullDirection,
        preferredSide,
        wrongSideGap,
        maxRecommendedWrongSideGap: 1.5,
        message: `place ${resistor.sourceComponentName} ${preferredSide} ${switchBox.sourceComponentName} so the pull-${pullDirection} branch reads toward ${pullDirection === "up" ? "power" : "ground"}`
      });
    }
    this.solved = true;
  }
}

// ../../work/placement-analysis/lib/utils/trace-name.ts
function getTraceName(circuitJson, trace) {
  const sourceTrace = circuitJson.find((e) => e.type === "source_trace" && e.source_trace_id === trace.source_trace_id);
  if (sourceTrace?.type === "source_trace" && sourceTrace.name)
    return sourceTrace.name;
  const first = trace.edges[0];
  const last = trace.edges.at(-1);
  const endpointName = (point2, id) => {
    const ports = circuitJson.filter((e) => e.type === "schematic_port" && e.schematic_sheet_id === trace.schematic_sheet_id && (id ? e.schematic_port_id === id : Math.hypot(e.center.x - point2.x, e.center.y - point2.y) <= 0.01));
    if (ports.length !== 1 || ports[0]?.type !== "schematic_port")
      return;
    const port = ports[0];
    const sourcePort = circuitJson.find((e) => e.type === "source_port" && e.source_port_id === port.source_port_id);
    const component = circuitJson.find((e) => e.type === "schematic_component" && e.schematic_component_id === port.schematic_component_id);
    const sourceComponentId = sourcePort?.type === "source_port" ? sourcePort.source_component_id : component?.type === "schematic_component" ? component.source_component_id : undefined;
    const sourceComponent = circuitJson.find((e) => e.type === "source_component" && e.source_component_id === sourceComponentId);
    if (sourceComponent?.type !== "source_component" || !sourceComponent.name)
      return;
    const pin = sourcePort?.type === "source_port" && sourcePort.name ? sourcePort.name : port.pin_number !== undefined ? `pin${port.pin_number}` : port.display_pin_label;
    return pin ? `${sourceComponent.name}.${pin}` : sourceComponent.name;
  };
  const from = first && endpointName(first.from, first.from_schematic_port_id);
  const to = last && endpointName(last.to, last.to_schematic_port_id);
  if (from && to)
    return `${from} to ${to}`;
  return sourceTrace?.type === "source_trace" && sourceTrace.display_name || from || to || "trace";
}

// ../../work/placement-analysis/node_modules/calculate-elbow/lib/calculateElbowBends.ts
var calculateElbowBends = (p1, p2, overshootAmount) => {
  const result = [{ x: p1.x, y: p1.y }];
  const midX = (p1.x + p2.x) / 2;
  const midY = (p1.y + p2.y) / 2;
  const p2Target = { x: p2.x, y: p2.y };
  switch (p2.facingDirection) {
    case "x+":
      p2Target.x += overshootAmount;
      break;
    case "x-":
      p2Target.x -= overshootAmount;
      break;
    case "y+":
      p2Target.y += overshootAmount;
      break;
    case "y-":
      p2Target.y -= overshootAmount;
      break;
  }
  const startDir = p1.facingDirection ?? "none";
  const endDir = p2.facingDirection ?? "none";
  const push = (pt) => {
    const last = result[result.length - 1];
    if (last.x !== pt.x || last.y !== pt.y)
      result.push(pt);
  };
  const yAligned = Math.abs(p1.y - p2.y) <= Math.max(0.000001, overshootAmount * 0.1);
  const xAligned = Math.abs(p1.x - p2.x) <= Math.max(0.000001, overshootAmount * 0.1);
  if (startDir === "none" && endDir === "none") {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 1;
    push({ x: midX, y: p1.y });
    push({ x: midX, y: p2.y });
  } else if (startDir === "x+" && endDir === "y+") {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2;
    if (p1.x > p2.x && p1.y < p2.y) {
      globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.1;
      push({ x: p1.x + overshootAmount, y: p1.y });
      push({ x: p1.x + overshootAmount, y: p2.y + overshootAmount });
      push({ x: p2.x, y: p2.y + overshootAmount });
    } else if (!xAligned && !yAligned && p1.x < p2.x && p1.y > p2.y) {
      globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.2;
      push({ x: p2.x, y: p1.y });
    } else if (xAligned) {
      globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.3;
      push({ x: p1.x + overshootAmount, y: p1.y });
      push({ x: p1.x + overshootAmount, y: p2.y + overshootAmount });
      push({ x: p2.x, y: p2.y + overshootAmount });
    } else {
      if (p1.x < p2.x) {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.4;
        push({ x: midX, y: p1.y });
        push({ x: midX, y: p2Target.y });
        push({ x: p2.x, y: p2Target.y });
      } else if (p1.y <= p2.y + overshootAmount) {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.5;
        push({ x: p1.x + overshootAmount, y: p1.y });
        push({ x: p1.x + overshootAmount, y: p1.y + overshootAmount });
        push({ x: p2.x, y: p1.y + overshootAmount });
        push({ x: p2.x, y: p2.y });
      } else {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 2.6;
        push({ x: p1.x + overshootAmount, y: p1.y });
        push({ x: p1.x + overshootAmount, y: (p1.y + p2.y) / 2 });
        push({ x: p2.x, y: (p1.y + p2.y) / 2 });
      }
    }
  } else if (startDir === "x+" && endDir === "x+" && !yAligned) {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 3;
    const commonX = Math.max(p1.x + overshootAmount, p2Target.x);
    push({ x: commonX, y: p1.y });
    push({ x: commonX, y: p2.y });
  } else if (startDir === "x+" && endDir === "x+" && yAligned) {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 3.1;
    push({ x: p1.x + overshootAmount, y: p1.y });
    push({ x: p1.x + overshootAmount, y: p1.y + overshootAmount });
    push({ x: p2.x + overshootAmount, y: p1.y + overshootAmount });
    push({ x: p2.x + overshootAmount, y: p2.y });
  } else if (startDir === "x+" && endDir === "y-") {
    if (xAligned && p1.y <= p2.y) {
      globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.11;
      push({ x: p1.x + overshootAmount, y: p1.y });
      push({ x: p1.x + overshootAmount, y: midY });
      push({ x: p2.x, y: midY });
    } else if (xAligned && p1.y > p2.y) {
      globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.12;
      push({ x: p1.x + overshootAmount, y: p1.y });
      push({ x: p1.x + overshootAmount, y: p2.y - overshootAmount });
      push({ x: p2.x, y: p2.y - overshootAmount });
    } else if (p1.x < p2.x && p1.y < p2.y) {
      globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.2;
      push({ x: p2.x, y: p1.y });
    } else {
      if (p1.x > p2.x && p1.y < p2.y) {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.3;
        const p1OvershootX = p1.x + overshootAmount;
        push({ x: p1OvershootX, y: p1.y });
        push({ x: p1OvershootX, y: midY });
        push({ x: p2.x, y: midY });
      } else if (p1.x > p2.x && p1.y > p2.y) {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.4;
        const p1OvershootX = p1.x + overshootAmount;
        push({ x: p1OvershootX, y: p1.y });
        push({ x: p1OvershootX, y: p2Target.y });
        push({ x: p2.x, y: p2Target.y });
      } else if (p1.y === p2.y) {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.5;
        push({ x: p1.x + overshootAmount, y: p1.y });
        push({ x: p1.x + overshootAmount, y: p1.y - overshootAmount });
        push({ x: p2.x, y: p1.y - overshootAmount });
      } else {
        globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 4.6;
        push({ x: midX, y: p1.y });
        push({ x: midX, y: p2Target.y });
        push({ x: p2.x, y: p2Target.y });
      }
    }
  } else if (startDir === "x+" && endDir === "x-" && p1.x + overshootAmount >= p2.x - overshootAmount && !yAligned) {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 5;
    const p1OvershootX = p1.x + overshootAmount;
    push({ x: p1OvershootX, y: p1.y });
    push({ x: p1OvershootX, y: midY });
    push({ x: p2Target.x, y: midY });
    push({ x: p2Target.x, y: p2Target.y });
  } else if (startDir === "x+" && endDir === "x-" && yAligned && p2.x > p1.x) {} else if (startDir === "x+" && endDir === "x-" && yAligned) {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 7;
    push({ x: p1.x + overshootAmount, y: p1.y });
    push({ x: p1.x + overshootAmount, y: p1.y + overshootAmount });
    push({ x: p2.x - overshootAmount, y: p1.y + overshootAmount });
    push({ x: p2.x - overshootAmount, y: p1.y });
  } else {
    globalThis.__DEBUG_CALCULATE_ELBOW_CASE = 8;
    if (startDir === "x+") {
      push({ x: p1.x + overshootAmount, y: p1.y });
    }
    push({ x: midX, y: result[result.length - 1].y });
    push({ x: midX, y: p2Target.y });
    push({ x: p2Target.x, y: p2Target.y });
  }
  push({ x: p2.x, y: p2.y });
  return result;
};

// ../../work/placement-analysis/node_modules/calculate-elbow/lib/index.ts
var calculateElbow = (point1, point2, options = {}) => {
  let p1 = point1;
  let p2 = point2;
  let orderFlipped = false;
  if (p1.x > p2.x || p1.x === p2.x && p1.y > p2.y) {
    orderFlipped = true;
    [p1, p2] = [p2, p1];
  }
  const mirrorX = p1.facingDirection === "x-";
  const mirrorY = p1.facingDirection === "y-";
  const mirrorPoint = (pt) => {
    const x = mirrorX ? p1.x - (pt.x - p1.x) : pt.x;
    const y = mirrorY ? p1.y - (pt.y - p1.y) : pt.y;
    let facing = pt.facingDirection;
    if (mirrorX) {
      if (facing === "x+")
        facing = "x-";
      else if (facing === "x-")
        facing = "x+";
    }
    if (mirrorY) {
      if (facing === "y+")
        facing = "y-";
      else if (facing === "y-")
        facing = "y+";
    }
    return { x, y, facingDirection: facing };
  };
  const rotateCW = (pt, centre) => {
    const dx = pt.x - centre.x;
    const dy = pt.y - centre.y;
    const x = centre.x + dy;
    const y = centre.y - dx;
    let facing = pt.facingDirection;
    switch (facing) {
      case "x+":
        facing = "y-";
        break;
      case "y-":
        facing = "x-";
        break;
      case "x-":
        facing = "y+";
        break;
      case "y+":
        facing = "x+";
        break;
    }
    return { x, y, facingDirection: facing };
  };
  const rotateCCW = (pt, centre) => {
    const dx = pt.x - centre.x;
    const dy = pt.y - centre.y;
    return { x: centre.x - dy, y: centre.y + dx };
  };
  const mp1 = mirrorX || mirrorY ? mirrorPoint(p1) : p1;
  const mp2 = mirrorX || mirrorY ? mirrorPoint(p2) : p2;
  let rp1 = mp1;
  let rp2 = mp2;
  let rotated = false;
  if (mp1.facingDirection === "y+") {
    rotated = true;
    rp1 = { ...mp1, facingDirection: "x+" };
    rp2 = rotateCW(mp2, mp1);
  }
  const overshootAmount = options?.overshoot ?? 0.1 * Math.max(Math.abs(rp1.x - rp2.x), Math.abs(rp1.y - rp2.y));
  let result = calculateElbowBends(rp1, rp2, overshootAmount);
  if (rotated) {
    result = result.map((pt) => rotateCCW(pt, rp1));
  }
  if (mirrorX || mirrorY) {
    result = result.map(({ x, y }) => ({
      x: mirrorX ? p1.x - (x - p1.x) : x,
      y: mirrorY ? p1.y - (y - p1.y) : y
    }));
  }
  return orderFlipped ? result.reverse() : result;
};

// ../../work/placement-analysis/lib/utils/schematic-text-geometry.ts
var rectPolygon = (bounds) => [
  { x: bounds.left, y: bounds.bottom },
  { x: bounds.right, y: bounds.bottom },
  { x: bounds.right, y: bounds.top },
  { x: bounds.left, y: bounds.top }
];
var advance = (character) => {
  if (/\s/.test(character))
    return 0.28;
  if (/[ilI.,:;!'|]/.test(character))
    return 0.25;
  if (/[MW@%]/.test(character))
    return 0.9;
  if (/[mw]/.test(character))
    return 0.8;
  if (/[A-Z]/.test(character))
    return 0.67;
  return 0.56;
};
var widthInEm = (text) => Array.from(text).reduce((width, character) => width + advance(character), 0);
function getSchematicTextPolygons(text) {
  const size2 = text.font_size;
  if (!Number.isFinite(size2) || size2 <= 0 || !Number.isFinite(text.rotation) || !Number.isFinite(text.position.x) || !Number.isFinite(text.position.y))
    return [];
  const anchor = text.anchor;
  const horizontal = anchor.includes("left") ? 0 : anchor.includes("right") ? 1 : 0.5;
  const top = anchor.includes("top") ? 0 : anchor.includes("bottom") ? size2 : size2 / 2;
  const radians = -text.rotation * Math.PI / 180;
  const cos = Math.cos(radians);
  const sin = Math.sin(radians);
  return text.text.split(`
`).flatMap((line, index) => {
    const visible = line.trim();
    if (!visible)
      return [];
    const leading = line.length - line.trimStart().length;
    const left = (widthInEm(line.slice(0, leading)) - widthInEm(line) * horizontal) * size2;
    const polygon = rectPolygon({
      left,
      right: left + widthInEm(visible) * size2,
      top: top - index * size2 - size2 * 0.05,
      bottom: top - (index + 1) * size2 + size2 * 0.05
    });
    return [
      polygon.map(({ x, y }) => ({
        x: text.position.x + x * cos - y * sin,
        y: text.position.y + x * sin + y * cos
      }))
    ];
  });
}
function polygonsOverlap(a, b) {
  for (const polygon of [a, b]) {
    for (let i = 0;i < polygon.length; i++) {
      const p = polygon[i];
      const q = polygon[(i + 1) % polygon.length];
      const length2 = Math.hypot(q.x - p.x, q.y - p.y);
      if (length2 < 0.000000001)
        continue;
      const nx = -(q.y - p.y) / length2;
      const ny = (q.x - p.x) / length2;
      const project = (points) => points.map(({ x, y }) => x * nx + y * ny);
      const pa = project(a);
      const pb = project(b);
      if (Math.min(Math.max(...pa), Math.max(...pb)) - Math.max(Math.min(...pa), Math.min(...pb)) <= 0.000001)
        return false;
    }
  }
  return true;
}
function traceSegmentPolygon(from, to) {
  const length2 = Math.hypot(to.x - from.x, to.y - from.y);
  if (length2 < 0.000000001)
    return;
  const dx = -(to.y - from.y) / length2 * 0.01;
  const dy = (to.x - from.x) / length2 * 0.01;
  return [
    { x: from.x + dx, y: from.y + dy },
    { x: to.x + dx, y: to.y + dy },
    { x: to.x - dx, y: to.y - dy },
    { x: from.x - dx, y: from.y - dy }
  ];
}
function segmentCrossesPolygon(from, to, polygon) {
  if (Math.hypot(to.x - from.x, to.y - from.y) < 0.000000001)
    return false;
  let low = 0;
  let high = 1;
  for (let i = 0;i < polygon.length; i++) {
    const p = polygon[i];
    const q = polygon[(i + 1) % polygon.length];
    const length2 = Math.hypot(q.x - p.x, q.y - p.y);
    if (length2 < 0.000000001)
      continue;
    const nx = -(q.y - p.y) / length2;
    const ny = (q.x - p.x) / length2;
    const start = (from.x - p.x) * nx + (from.y - p.y) * ny - 0.000001;
    const end = (to.x - p.x) * nx + (to.y - p.y) * ny - 0.000001;
    if (start <= 0 && end <= 0)
      return false;
    if (start <= 0)
      low = Math.max(low, -start / (end - start));
    if (end <= 0)
      high = Math.min(high, -start / (end - start));
    if (high <= low)
      return false;
  }
  return high > low;
}
var polygonBounds = (polygons) => {
  const points = polygons.flat();
  return {
    left: Math.min(...points.map((p) => p.x)),
    right: Math.max(...points.map((p) => p.x)),
    top: Math.max(...points.map((p) => p.y)),
    bottom: Math.min(...points.map((p) => p.y))
  };
};

// ../../work/placement-analysis/lib/solvers/TraceSimplificationSolver/TraceSimplificationSolver.ts
class TraceSimplificationSolver extends BaseSolver {
  static EPSILON = 0.01;
  ctx;
  out;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.ctx = ctx;
    this.out = issues;
  }
  _step() {
    const ports = this.ctx.circuitJson.filter((element) => element.type === "schematic_port");
    const portsById = new Map(ports.map((port) => [port.schematic_port_id, port]));
    const placementsByComponentId = new Map(this.ctx.componentPlacements.flatMap((placement) => placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));
    const emittedMoves = new Set;
    for (const trace of this.ctx.circuitJson.filter((element) => element.type === "schematic_trace")) {
      const points = this.getTracePoints(trace);
      const currentTurnCount = this.countTurns(points);
      if (currentTurnCount !== 3)
        continue;
      const candidates = [
        this.getCandidate({
          trace,
          points,
          atStart: true,
          currentTurnCount,
          ports,
          portsById,
          placementsByComponentId
        }),
        this.getCandidate({
          trace,
          points,
          atStart: false,
          currentTurnCount,
          ports,
          portsById,
          placementsByComponentId
        })
      ].filter((candidate) => Boolean(candidate));
      for (const candidate of [...candidates]) {
        if (!candidate.target.sourceComponentName?.startsWith("U"))
          continue;
        for (const point2 of [points[0], points.at(-1)]) {
          const port = this.findPortAtPoint(ports, point2, trace.schematic_sheet_id);
          const target = port?.schematic_component_id ? placementsByComponentId.get(port.schematic_component_id) : undefined;
          if (!target || !/^[CR]/.test(target.sourceComponentName ?? ""))
            continue;
          candidates.push({
            target,
            deltaSchX: -candidate.deltaSchX,
            deltaSchY: -candidate.deltaSchY,
            currentTurnCount,
            suggestedTurnCount: candidate.suggestedTurnCount
          });
        }
      }
      const priority = (candidate) => /^[CR]/.test(candidate.target.sourceComponentName ?? "") ? 0 : candidate.target.sourceComponentName?.startsWith("U") ? 2 : 1;
      candidates.sort((a, b) => priority(a) - priority(b));
      for (const candidate of candidates) {
        if (this.wouldOverlapAnotherComponent(candidate))
          continue;
        if (!this.validateMove(trace, candidate, ports))
          continue;
        const moveKey = [
          candidate.target.schematicComponentId,
          candidate.deltaSchX.toFixed(3),
          candidate.deltaSchY.toFixed(3)
        ].join("\x00");
        if (emittedMoves.has(moveKey))
          break;
        emittedMoves.add(moveKey);
        this.out.push(this.makeIssue(trace, candidate));
        break;
      }
    }
    this.solved = true;
  }
  getCandidate({
    trace,
    points,
    atStart,
    currentTurnCount,
    ports,
    portsById,
    placementsByComponentId
  }) {
    if (points.length < 4)
      return;
    const terminalIndex = atStart ? 0 : points.length - 1;
    const leadIndex = atStart ? 1 : points.length - 2;
    const acrossIndex = atStart ? 2 : points.length - 3;
    const retainedIndex = atStart ? 3 : points.length - 4;
    const terminalPoint = points[terminalIndex];
    const leadPoint = points[leadIndex];
    const acrossPoint = points[acrossIndex];
    const retainedPoint = points[retainedIndex];
    const terminalEdge = atStart ? trace.edges[0] : trace.edges.at(-1);
    if (!terminalEdge)
      return;
    const portId = atStart ? terminalEdge.from_schematic_port_id : terminalEdge.to_schematic_port_id;
    const port = portId ? portsById.get(portId) : this.findPortAtPoint(ports, terminalPoint, trace.schematic_sheet_id);
    if (!port?.schematic_component_id || !port.facing_direction)
      return;
    const leadAxis = this.getAxis(terminalPoint, leadPoint);
    const shiftAxis = this.getAxis(leadPoint, acrossPoint);
    const retainedAxis = this.getAxis(acrossPoint, retainedPoint);
    const portAxis = port.facing_direction === "left" || port.facing_direction === "right" ? "horizontal" : "vertical";
    if (!leadAxis || !shiftAxis || !retainedAxis)
      return;
    if (leadAxis !== portAxis || shiftAxis === portAxis || retainedAxis !== portAxis) {
      return;
    }
    if (!this.isPointInFacingDirection(terminalPoint, leadPoint, port.facing_direction) || !this.isPointInFacingDirection(acrossPoint, retainedPoint, port.facing_direction)) {
      return;
    }
    const target = placementsByComponentId.get(port.schematic_component_id);
    if (!target)
      return;
    const deltaSchX = acrossPoint.x - leadPoint.x;
    const deltaSchY = acrossPoint.y - leadPoint.y;
    if (Math.abs(deltaSchX) <= TraceSimplificationSolver.EPSILON && Math.abs(deltaSchY) <= TraceSimplificationSolver.EPSILON) {
      return;
    }
    const movedTerminalPoint = {
      x: terminalPoint.x + deltaSchX,
      y: terminalPoint.y + deltaSchY
    };
    const suggestedPoints = atStart ? [movedTerminalPoint, ...points.slice(2)] : [...points.slice(0, -2), movedTerminalPoint];
    const suggestedTurnCount = this.countTurns(suggestedPoints);
    if (suggestedTurnCount === undefined || suggestedTurnCount !== 1 || suggestedTurnCount >= currentTurnCount) {
      return;
    }
    return {
      target,
      deltaSchX,
      deltaSchY,
      currentTurnCount,
      suggestedTurnCount
    };
  }
  validateMove(targetTrace, candidate, ports) {
    const componentId = candidate.target.schematicComponentId;
    const sheetId = candidate.target.schematicSheetId;
    const sheetPorts = ports.filter((p) => p.schematic_sheet_id === sheetId);
    const movingPorts = sheetPorts.filter((p) => p.schematic_component_id === componentId);
    const traces = this.ctx.circuitJson.filter((e) => e.type === "schematic_trace" && e.schematic_sheet_id === sheetId);
    const touchesPort = (trace, port) => trace.edges.some((edge) => edge.from_schematic_port_id === port.schematic_port_id || edge.to_schematic_port_id === port.schematic_port_id || this.pointsEqual(edge.from, port.center) || this.pointsEqual(edge.to, port.center));
    const affected = traces.filter((trace) => movingPorts.some((port) => touchesPort(trace, port)));
    if (!affected.includes(targetTrace))
      return false;
    if (this.ctx.circuitJson.some((e) => e.type === "schematic_net_label" && e.schematic_sheet_id === sheetId && movingPorts.some((p) => this.pointsEqual(e.anchor_position ?? e.center, p.center))))
      return false;
    const shift = (point2) => ({
      x: point2.x + candidate.deltaSchX,
      y: point2.y + candidate.deltaSchY
    });
    const directions2 = {
      left: "x-",
      right: "x+",
      up: "y+",
      down: "y-"
    };
    const endpoint = (port, moved) => ({
      ...moved && port.schematic_component_id === componentId ? shift(port.center) : port.center,
      facingDirection: directions2[port.facing_direction]
    });
    const length2 = (points) => points.slice(1).reduce((sum, p, i) => sum + Math.abs(p.x - points[i].x) + Math.abs(p.y - points[i].y), 0);
    const segments = (points) => points.slice(1).map((to, i) => ({ from: points[i], to }));
    const movedBounds = centeredRect(candidate.target.schX + candidate.deltaSchX, candidate.target.schY + candidate.deltaSchY, candidate.target.width, candidate.target.height);
    const unaffected = traces.filter((trace) => !affected.includes(trace));
    if (unaffected.some((trace) => trace.edges.some((edge) => segmentCrossesPolygon(edge.from, edge.to, rectPolygon(movedBounds)))))
      return false;
    const textPolygons = this.ctx.circuitJson.flatMap((e) => {
      if (e.type === "schematic_net_label" && e.schematic_sheet_id === sheetId)
        return [rectPolygon(getNetLabelBounds(e))];
      if (e.type !== "schematic_text" || e.schematic_sheet_id !== sheetId)
        return [];
      return getSchematicTextPolygons(e.schematic_component_id === componentId ? { ...e, position: shift(e.position) } : e);
    });
    if (textPolygons.some((polygon) => polygonsOverlap(polygon, rectPolygon(movedBounds))))
      return false;
    const proposed = [];
    for (const trace of affected) {
      const oldPoints = this.getTracePoints(trace);
      if (oldPoints.length < 2 || trace.junctions?.length)
        return false;
      const resolve = (point2, id) => {
        const matches = sheetPorts.filter((p) => id ? p.schematic_port_id === id : this.pointsEqual(p.center, point2));
        return matches.length === 1 && this.pointsEqual(matches[0].center, point2) ? matches[0] : undefined;
      };
      const start = resolve(oldPoints[0], trace.edges[0].from_schematic_port_id);
      const end = resolve(oldPoints.at(-1), trace.edges.at(-1).to_schematic_port_id);
      if (!start?.facing_direction || !end?.facing_direction)
        return false;
      if (movingPorts.some((p) => touchesPort(trace, p) && p !== start && p !== end))
        return false;
      const isInteriorConnection = (point2) => !this.pointsEqual(point2, start.center) && !this.pointsEqual(point2, end.center) && segments(oldPoints).some(({ from, to }) => Math.abs(Math.hypot(point2.x - from.x, point2.y - from.y) + Math.hypot(point2.x - to.x, point2.y - to.y) - Math.hypot(to.x - from.x, to.y - from.y)) < 0.000001);
      if (traces.some((other) => other !== trace && other.edges.some((edge) => isInteriorConnection(edge.from) || isInteriorConnection(edge.to))))
        return false;
      if (this.ctx.circuitJson.some((e) => e.type === "schematic_net_label" && e.schematic_sheet_id === sheetId && isInteriorConnection(e.anchor_position ?? e.center)))
        return false;
      const points = calculateElbow(endpoint(start, true), endpoint(end, true)).filter((point2, i, all) => i === 0 || !this.pointsEqual(point2, all[i - 1]));
      const turns = this.countTurns(points);
      const oldTurns = this.countTurns(oldPoints);
      if (points.length < 2 || turns === undefined || oldTurns === undefined || turns > oldTurns || length2(points) > length2(oldPoints) + 0.000001)
        return false;
      if (!this.isPointInFacingDirection(points[0], points[1], start.facing_direction) || !this.isPointInFacingDirection(points.at(-1), points.at(-2), end.facing_direction))
        return false;
      if (trace === targetTrace) {
        const baselineTurns = this.countTurns(calculateElbow(endpoint(start, false), endpoint(end, false)));
        if (turns >= oldTurns || baselineTurns === undefined || turns >= baselineTurns)
          return false;
        candidate.suggestedTurnCount = turns;
      }
      for (const segment of segments(points)) {
        if (textPolygons.some((polygon2) => segmentCrossesPolygon(segment.from, segment.to, polygon2)))
          return false;
        if (this.ctx.componentPlacements.some((p) => {
          if (p.schematicSheetId !== sheetId)
            return false;
          const bounds = p.schematicComponentId === componentId ? movedBounds : centeredRect(p.schX, p.schY, p.width, p.height);
          return segmentCrossesPolygon(segment.from, segment.to, rectPolygon(bounds));
        }))
          return false;
        const polygon = traceSegmentPolygon(segment.from, segment.to);
        if (!polygon)
          continue;
        const otherSegments = [
          ...unaffected.flatMap((t) => t.edges),
          ...proposed.flatMap((t) => segments(t.points))
        ];
        if (otherSegments.some((edge) => {
          if ([start, end].some((port) => port.schematic_component_id !== componentId && [segment.from, segment.to].some((p) => this.pointsEqual(p, port.center)) && [edge.from, edge.to].some((p) => this.pointsEqual(p, port.center))) && this.getAxis(segment.from, segment.to) !== this.getAxis(edge.from, edge.to))
            return false;
          const other = traceSegmentPolygon(edge.from, edge.to);
          return other && polygonsOverlap(polygon, other);
        }))
          return false;
      }
      proposed.push({ schematicTraceId: trace.schematic_trace_id, points });
    }
    candidate.suggestedTraces = proposed;
    return true;
  }
  getTracePoints(trace) {
    const firstEdge = trace.edges[0];
    if (!firstEdge)
      return [];
    const points = [firstEdge.from];
    for (const edge of trace.edges) {
      const previousPoint = points.at(-1);
      if (!this.pointsEqual(previousPoint, edge.from))
        return [];
      points.push(edge.to);
    }
    return points;
  }
  countTurns(points) {
    const axes = [];
    for (const [index, point2] of points.slice(1).entries()) {
      const previousPoint = points[index];
      if (this.pointsEqual(previousPoint, point2))
        continue;
      const axis = this.getAxis(previousPoint, point2);
      if (!axis)
        return;
      axes.push(axis);
    }
    return axes.slice(1).filter((axis, index) => axis !== axes[index]).length;
  }
  pointsEqual(a, b) {
    const { EPSILON: EPSILON3 } = TraceSimplificationSolver;
    return Math.abs(a.x - b.x) <= EPSILON3 && Math.abs(a.y - b.y) <= EPSILON3;
  }
  getAxis(a, b) {
    const dx = Math.abs(b.x - a.x);
    const dy = Math.abs(b.y - a.y);
    const { EPSILON: EPSILON3 } = TraceSimplificationSolver;
    if (dx <= EPSILON3 && dy > EPSILON3)
      return "vertical";
    if (dy <= EPSILON3 && dx > EPSILON3)
      return "horizontal";
    return;
  }
  isPointInFacingDirection(origin, point2, facingDirection) {
    const { EPSILON: EPSILON3 } = TraceSimplificationSolver;
    switch (facingDirection) {
      case "left":
        return point2.x < origin.x - EPSILON3;
      case "right":
        return point2.x > origin.x + EPSILON3;
      case "up":
        return point2.y > origin.y + EPSILON3;
      case "down":
        return point2.y < origin.y - EPSILON3;
    }
  }
  findPortAtPoint(ports, point2, schematicSheetId) {
    const { EPSILON: EPSILON3 } = TraceSimplificationSolver;
    return ports.find((port) => port.schematic_sheet_id === schematicSheetId && Math.abs(port.center.x - point2.x) <= EPSILON3 && Math.abs(port.center.y - point2.y) <= EPSILON3);
  }
  wouldOverlapAnotherComponent(candidate) {
    const movedBounds = centeredRect(candidate.target.schX + candidate.deltaSchX, candidate.target.schY + candidate.deltaSchY, candidate.target.width, candidate.target.height);
    return this.ctx.componentPlacements.some((placement) => {
      if (placement === candidate.target)
        return false;
      if (placement.schematicSheetId !== candidate.target.schematicSheetId) {
        return false;
      }
      return Boolean(rectOverlap(movedBounds, centeredRect(placement.schX, placement.schY, placement.width, placement.height)));
    });
  }
  makeIssue(trace, candidate) {
    const targetName = candidate.target.sourceComponentName ?? candidate.target.schematicComponentId ?? "component";
    const direction = this.getMoveDirection(candidate.deltaSchX, candidate.deltaSchY);
    const distance5 = Math.abs(candidate.deltaSchX || candidate.deltaSchY);
    const newSchX = candidate.target.schX + candidate.deltaSchX;
    const newSchY = candidate.target.schY + candidate.deltaSchY;
    return {
      lineItemType: "TraceCanBeSimplifiedByMovingComponent",
      schematicTraceId: trace.schematic_trace_id,
      traceName: getTraceName(this.ctx.circuitJson, trace),
      targetComponent: candidate.target,
      deltaSchX: candidate.deltaSchX,
      deltaSchY: candidate.deltaSchY,
      newSchX,
      newSchY,
      currentTurnCount: candidate.currentTurnCount,
      suggestedTurnCount: candidate.suggestedTurnCount,
      suggestedTraces: candidate.suggestedTraces,
      message: `move ${targetName} ${direction} by ${fmtNumber(distance5)} (to schX=${fmtNumber(newSchX)}, schY=${fmtNumber(newSchY)}) to reduce this trace from ${candidate.currentTurnCount} turns to ${candidate.suggestedTurnCount}`
    };
  }
  getMoveDirection(deltaSchX, deltaSchY) {
    if (Math.abs(deltaSchX) > TraceSimplificationSolver.EPSILON) {
      return deltaSchX > 0 ? "right" : "left";
    }
    return deltaSchY > 0 ? "up" : "down";
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "traceName", issue.traceName);
    addAttr(attrs, "targetComponentName", issue.targetComponent.sourceComponentName);
    addAttr(attrs, "deltaSchX", issue.deltaSchX, { formatDelta: true });
    addAttr(attrs, "deltaSchY", issue.deltaSchY, { formatDelta: true });
    addAttr(attrs, "newSchX", issue.newSchX);
    addAttr(attrs, "newSchY", issue.newSchY);
    addAttr(attrs, "currentTurnCount", issue.currentTurnCount);
    addAttr(attrs, "suggestedTurnCount", issue.suggestedTurnCount);
    addAttr(attrs, "message", issue.message);
    return `<TraceCanBeSimplifiedByMovingComponent ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/getPowerOrGroundConnectionIds.ts
function getPowerOrGroundConnectionIds(circuitJson) {
  const powerOrGroundIds = new Set;
  const idsByConnectivityKey = new Map;
  for (const element of circuitJson) {
    if (element.type !== "source_net" && element.type !== "source_port")
      continue;
    const id = element.type === "source_net" ? element.source_net_id : element.source_port_id;
    const isPowerOrGround = element.type === "source_net" ? element.is_power || element.is_ground || element.is_positive_voltage_source : element.provides_power || element.requires_power || element.provides_ground || element.requires_ground;
    if (isPowerOrGround)
      powerOrGroundIds.add(id);
    const key = element.subcircuit_connectivity_map_key;
    if (key !== undefined) {
      const ids = idsByConnectivityKey.get(key) ?? [];
      ids.push(id);
      idsByConnectivityKey.set(key, ids);
    }
  }
  const sourceConnectivity = getSourcePortConnectivityMapFromCircuitJson(circuitJson);
  const networks = findConnectedNetworks([
    ...Object.values(sourceConnectivity.netMap),
    ...idsByConnectivityKey.values()
  ]);
  for (const ids of Object.values(networks)) {
    if (ids.some((id) => powerOrGroundIds.has(id))) {
      for (const id of ids)
        powerOrGroundIds.add(id);
    }
  }
  return powerOrGroundIds;
}

// ../../work/placement-analysis/lib/solvers/TwoPinComponentOrientationSolver/TwoPinComponentOrientationSolver.ts
class TwoPinComponentOrientationSolver extends BaseSolver {
  static EPSILON = 0.01;
  ctx;
  out;
  powerOrGroundConnectionIds;
  constructor({
    ctx,
    issues
  }) {
    super();
    this.ctx = ctx;
    this.out = issues;
    this.powerOrGroundConnectionIds = getPowerOrGroundConnectionIds(ctx.circuitJson);
  }
  _step() {
    const ports = this.ctx.circuitJson.filter((element) => element.type === "schematic_port");
    const portsById = new Map(ports.map((port) => [port.schematic_port_id, port]));
    const portsByComponentId = new Map;
    for (const port of ports) {
      if (!port.schematic_component_id)
        continue;
      const componentPorts = portsByComponentId.get(port.schematic_component_id) ?? [];
      componentPorts.push(port);
      portsByComponentId.set(port.schematic_component_id, componentPorts);
    }
    const placementsByComponentId = new Map(this.ctx.componentPlacements.flatMap((placement) => placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));
    const bestCandidateByComponentId = new Map;
    for (const trace of this.ctx.circuitJson.filter((element) => element.type === "schematic_trace")) {
      const points = this.getTracePoints(trace);
      const currentTurnCount = this.countTurns(points);
      if (currentTurnCount === undefined || currentTurnCount < 2)
        continue;
      const endpoints = this.getTraceEndpoints(trace, points, ports, portsById);
      if (!endpoints)
        continue;
      for (const [targetEndpoint, connectedEndpoint] of [
        endpoints,
        [endpoints[1], endpoints[0]]
      ]) {
        const candidate = this.getFlipCandidate({
          trace,
          targetEndpoint,
          connectedEndpoint,
          currentTurnCount,
          portsByComponentId,
          placementsByComponentId
        });
        if (!candidate)
          continue;
        const componentId = candidate.targetPort.schematic_component_id;
        const existing = bestCandidateByComponentId.get(componentId);
        if (!existing || this.isBetterCandidate(candidate, existing)) {
          bestCandidateByComponentId.set(componentId, candidate);
        }
      }
    }
    for (const candidate of bestCandidateByComponentId.values()) {
      this.out.push(this.makeIssue(candidate));
    }
    this.solved = true;
  }
  getFlipCandidate({
    trace,
    targetEndpoint,
    connectedEndpoint,
    currentTurnCount,
    portsByComponentId,
    placementsByComponentId
  }) {
    const targetPort = targetEndpoint.port;
    const connectedPort = connectedEndpoint.port;
    const targetComponentId = targetPort.schematic_component_id;
    const connectedComponentId = connectedPort.schematic_component_id;
    if (!targetComponentId || !connectedComponentId || targetComponentId === connectedComponentId || targetPort.schematic_sheet_id !== connectedPort.schematic_sheet_id) {
      return;
    }
    const componentPorts = portsByComponentId.get(targetComponentId);
    if (componentPorts?.length !== 2)
      return;
    if (componentPorts.some((port) => port.source_port_id && this.powerOrGroundConnectionIds.has(port.source_port_id))) {
      return;
    }
    const connectedComponentPorts = portsByComponentId.get(connectedComponentId) ?? [];
    if (connectedComponentPorts.length <= 2)
      return;
    const otherPort = componentPorts.find((port) => port.schematic_port_id !== targetPort.schematic_port_id);
    if (!otherPort || !this.areOppositePorts(targetPort, otherPort))
      return;
    const currentFacingDirection = targetPort.facing_direction;
    const suggestedFacingDirection = otherPort.facing_direction;
    if (!currentFacingDirection || !suggestedFacingDirection)
      return;
    if (!this.traceLeavesPortInFacingDirection(targetEndpoint))
      return;
    const connectedPoint = connectedPort.center;
    if (this.isPointInFacingDirection(targetPort.center, connectedPoint, currentFacingDirection) || !this.isPointInFacingDirection(otherPort.center, connectedPoint, suggestedFacingDirection) || !connectedPort.facing_direction || !this.isPointInFacingDirection(connectedPoint, otherPort.center, connectedPort.facing_direction)) {
      return;
    }
    const suggestedTurnCount = this.getMinimumTurnCount(otherPort.center, connectedPoint, suggestedFacingDirection);
    if (suggestedTurnCount >= currentTurnCount)
      return;
    const targetPlacement = placementsByComponentId.get(targetComponentId);
    const connectedPlacement = placementsByComponentId.get(connectedComponentId);
    if (!targetPlacement || !connectedPlacement)
      return;
    return {
      trace,
      targetPort,
      targetPlacement,
      connectedPlacement,
      suggestedFacingDirection,
      currentTurnCount,
      suggestedTurnCount,
      traceLength: this.getTraceLength(targetEndpoint.pointsFromEndpoint)
    };
  }
  getTraceEndpoints(trace, points, ports, portsById) {
    const firstEdge = trace.edges[0];
    const lastEdge = trace.edges.at(-1);
    if (!firstEdge || !lastEdge || points.length < 2)
      return;
    const startPort = firstEdge.from_schematic_port_id ? portsById.get(firstEdge.from_schematic_port_id) : this.findPortAtPoint(ports, points[0], trace.schematic_sheet_id);
    const endPort = lastEdge.to_schematic_port_id ? portsById.get(lastEdge.to_schematic_port_id) : this.findPortAtPoint(ports, points.at(-1), trace.schematic_sheet_id);
    if (!startPort || !endPort)
      return;
    return [
      { port: startPort, pointsFromEndpoint: points },
      { port: endPort, pointsFromEndpoint: [...points].reverse() }
    ];
  }
  getTracePoints(trace) {
    const firstEdge = trace.edges[0];
    if (!firstEdge)
      return [];
    const points = [firstEdge.from];
    for (const edge of trace.edges) {
      if (!this.pointsEqual(points.at(-1), edge.from))
        return [];
      points.push(edge.to);
    }
    return points;
  }
  countTurns(points) {
    const axes = [];
    for (const [index, point2] of points.slice(1).entries()) {
      const previousPoint = points[index];
      if (this.pointsEqual(previousPoint, point2))
        continue;
      const axis = this.getAxis(previousPoint, point2);
      if (!axis)
        return;
      if (axes.at(-1) !== axis)
        axes.push(axis);
    }
    return Math.max(0, axes.length - 1);
  }
  traceLeavesPortInFacingDirection(endpoint) {
    const nextPoint = endpoint.pointsFromEndpoint.find((point2) => !this.pointsEqual(point2, endpoint.port.center));
    return Boolean(nextPoint && endpoint.port.facing_direction && this.isPointInFacingDirection(endpoint.port.center, nextPoint, endpoint.port.facing_direction));
  }
  areOppositePorts(a, b) {
    const horizontal = (a.facing_direction === "left" && b.facing_direction === "right" || a.facing_direction === "right" && b.facing_direction === "left") && Math.abs(a.center.y - b.center.y) <= TwoPinComponentOrientationSolver.EPSILON;
    const vertical = (a.facing_direction === "up" && b.facing_direction === "down" || a.facing_direction === "down" && b.facing_direction === "up") && Math.abs(a.center.x - b.center.x) <= TwoPinComponentOrientationSolver.EPSILON;
    return horizontal || vertical;
  }
  getMinimumTurnCount(from, to, facingDirection) {
    const alignedWithFacingAxis = facingDirection === "left" || facingDirection === "right" ? Math.abs(from.y - to.y) <= TwoPinComponentOrientationSolver.EPSILON : Math.abs(from.x - to.x) <= TwoPinComponentOrientationSolver.EPSILON;
    return alignedWithFacingAxis ? 0 : 1;
  }
  isPointInFacingDirection(origin, point2, facingDirection) {
    const { EPSILON: EPSILON3 } = TwoPinComponentOrientationSolver;
    switch (facingDirection) {
      case "left":
        return point2.x < origin.x - EPSILON3;
      case "right":
        return point2.x > origin.x + EPSILON3;
      case "up":
        return point2.y > origin.y + EPSILON3;
      case "down":
        return point2.y < origin.y - EPSILON3;
    }
  }
  getAxis(a, b) {
    const dx = Math.abs(a.x - b.x);
    const dy = Math.abs(a.y - b.y);
    const { EPSILON: EPSILON3 } = TwoPinComponentOrientationSolver;
    if (dx <= EPSILON3 && dy > EPSILON3)
      return "vertical";
    if (dy <= EPSILON3 && dx > EPSILON3)
      return "horizontal";
    return;
  }
  pointsEqual(a, b) {
    const { EPSILON: EPSILON3 } = TwoPinComponentOrientationSolver;
    return Math.abs(a.x - b.x) <= EPSILON3 && Math.abs(a.y - b.y) <= EPSILON3;
  }
  findPortAtPoint(ports, point2, schematicSheetId) {
    return ports.find((port) => port.schematic_sheet_id === schematicSheetId && this.pointsEqual(port.center, point2));
  }
  getTraceLength(points) {
    return points.slice(1).reduce((length2, point2, index) => {
      const previousPoint = points[index];
      return length2 + Math.abs(point2.x - previousPoint.x) + Math.abs(point2.y - previousPoint.y);
    }, 0);
  }
  isBetterCandidate(candidate, existing) {
    const improvement = candidate.currentTurnCount - candidate.suggestedTurnCount;
    const existingImprovement = existing.currentTurnCount - existing.suggestedTurnCount;
    return improvement > existingImprovement || improvement === existingImprovement && candidate.traceLength > existing.traceLength;
  }
  makeIssue(candidate) {
    const targetName = candidate.targetPlacement.sourceComponentName ?? candidate.targetPlacement.schematicComponentId ?? "component";
    const connectedName = candidate.connectedPlacement.sourceComponentName ?? candidate.connectedPlacement.schematicComponentId ?? "connected component";
    const targetPin = candidate.targetPort.pin_number ? `pin${candidate.targetPort.pin_number}` : candidate.targetPort.display_pin_label;
    return {
      lineItemType: "TwoPinComponentCouldBeFlipped",
      schematicTraceId: candidate.trace.schematic_trace_id,
      traceName: getTraceName(this.ctx.circuitJson, candidate.trace),
      targetComponent: candidate.targetPlacement,
      connectedComponent: candidate.connectedPlacement,
      targetPin,
      currentFacingDirection: candidate.targetPort.facing_direction,
      suggestedFacingDirection: candidate.suggestedFacingDirection,
      deltaSchRotation: 180,
      currentTurnCount: candidate.currentTurnCount,
      suggestedTurnCount: candidate.suggestedTurnCount,
      message: `rotate ${targetName} by 180° so ${targetPin ?? "its connected pin"} faces ${connectedName} and reduce this trace from ${candidate.currentTurnCount} turns to ${candidate.suggestedTurnCount}`
    };
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "traceName", issue.traceName);
    addAttr(attrs, "targetComponentName", issue.targetComponent.sourceComponentName);
    addAttr(attrs, "connectedComponentName", issue.connectedComponent.sourceComponentName);
    addAttr(attrs, "targetPin", issue.targetPin);
    addAttr(attrs, "currentFacingDirection", issue.currentFacingDirection);
    addAttr(attrs, "suggestedFacingDirection", issue.suggestedFacingDirection);
    addAttr(attrs, "deltaSchRotation", issue.deltaSchRotation);
    addAttr(attrs, "currentTurnCount", issue.currentTurnCount);
    addAttr(attrs, "suggestedTurnCount", issue.suggestedTurnCount);
    addAttr(attrs, "message", issue.message);
    return `<TwoPinComponentCouldBeFlipped ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/VerboseNetLabelSolver/VerboseNetLabelSolver.ts
class VerboseNetLabelSolver extends BaseSolver {
  params;
  VERBOSE_NET_LABEL_MESSAGE = "Create trace with schDisplayLabel";
  netLabels;
  tokenToInvolvedPin;
  schematicSheetNameById;
  currentIndex = 0;
  seen = new Set;
  constructor(params) {
    super();
    this.params = params;
    const { circuitJson } = params.ctx;
    this.netLabels = circuitJson.filter((el) => this.isSchematicNetLabel(el));
    this.tokenToInvolvedPin = this.buildTokenToInvolvedPinMap(circuitJson);
    this.schematicSheetNameById = getSchematicSheetNamesById(circuitJson);
    this.solved = this.netLabels.length === 0;
  }
  _step() {
    const label = this.netLabels[this.currentIndex++];
    if (!label) {
      this.solved = true;
      return;
    }
    this.solved = this.currentIndex >= this.netLabels.length;
    const seenKey = `${label.schematic_sheet_id ?? ""}:${label.text}`;
    if (!label.text.includes("/") || this.seen.has(seenKey))
      return;
    this.seen.add(seenKey);
    let schematicSheetName;
    if (label.schematic_sheet_id) {
      schematicSheetName = this.schematicSheetNameById.get(label.schematic_sheet_id);
    }
    const issue = {
      lineItemType: "VerboseSchematicNetLabel",
      schematicNetLabelId: label.schematic_net_label_id,
      sourceNetId: label.source_net_id,
      schematicSheetId: label.schematic_sheet_id,
      schematicSheetName,
      text: label.text,
      involvedPins: this.getInvolvedPins(label.text, this.tokenToInvolvedPin),
      schX: label.center.x,
      schY: label.center.y,
      message: this.VERBOSE_NET_LABEL_MESSAGE
    };
    this.params.issues.push(issue);
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "message", issue.message);
    addAttr(attrs, "text", issue.text);
    addAttr(attrs, "involvedPins", issue.involvedPins.join(","));
    addAttr(attrs, "schSheetName", issue.schematicSheetName);
    addAttr(attrs, "schX", issue.schX);
    addAttr(attrs, "schY", issue.schY);
    return `<VerboseSchematicNetLabel ${attrs.join(" ")} />`;
  }
  isSchematicNetLabel(el) {
    return el.type === "schematic_net_label";
  }
  isSourcePort(el) {
    return el.type === "source_port";
  }
  getSourceComponentWithName(el) {
    if (el.type !== "source_component" || !("source_component_id" in el) || !("name" in el) || typeof el.source_component_id !== "string" || typeof el.name !== "string")
      return null;
    return { source_component_id: el.source_component_id, name: el.name };
  }
  getSourcePortNameCandidates(port) {
    return [
      port.most_frequently_referenced_by_name,
      port.name,
      ...port.port_hints ?? [],
      port.pin_number === undefined ? undefined : String(port.pin_number)
    ].filter((n) => Boolean(n));
  }
  getBestSourcePortName(port) {
    return port.most_frequently_referenced_by_name ?? port.name ?? (port.pin_number === undefined ? "" : `pin${port.pin_number}`);
  }
  buildTokenToInvolvedPinMap(circuitJson) {
    const sourceComponentById = new Map(circuitJson.flatMap((el) => {
      const sc = this.getSourceComponentWithName(el);
      return sc ? [sc] : [];
    }).map((sc) => [sc.source_component_id, sc]));
    const map = new Map;
    for (const port of circuitJson.filter((el) => this.isSourcePort(el))) {
      if (!port.source_component_id)
        continue;
      const sc = sourceComponentById.get(port.source_component_id);
      if (!sc?.name)
        continue;
      const involvedPin = `${sc.name}.${this.getBestSourcePortName(port)}`;
      for (const name of this.getSourcePortNameCandidates(port)) {
        map.set(`${sc.name}_${name}`, involvedPin);
      }
    }
    return map;
  }
  getInvolvedPins(text, tokenToInvolvedPin) {
    const pins = new Set;
    for (const token of text.split("/")) {
      const pin = tokenToInvolvedPin.get(token);
      if (pin)
        pins.add(pin);
    }
    return Array.from(pins);
  }
}

// ../../work/placement-analysis/lib/solvers/SchematicTextClearanceSolver/SchematicTextClearanceSolver.ts
class SchematicTextClearanceSolver extends BaseSolver {
  params;
  texts;
  obstacles;
  sheetNames;
  index = 0;
  constructor(params) {
    super();
    this.params = params;
    const { ctx } = params;
    this.sheetNames = getSchematicSheetNamesById(ctx.circuitJson);
    const customSymbolIds = new Set(ctx.circuitJson.flatMap((element) => element.type === "schematic_component" && element.is_box_with_pins === false && !element.symbol_name ? [element.schematic_component_id] : []));
    const seenText = new Set;
    this.texts = ctx.circuitJson.flatMap((element) => {
      if (element.type !== "schematic_text")
        return [];
      if (element.schematic_component_id || element.schematic_symbol_id || "source_trace_id" in element && element.source_trace_id)
        return [];
      const polygons = getSchematicTextPolygons(element);
      if (!polygons.length)
        return [];
      const sheetId = element.schematic_sheet_id;
      const fingerprint = JSON.stringify([
        sheetId,
        element.text,
        element.position.x,
        element.position.y,
        element.font_size,
        element.anchor,
        element.rotation,
        element.color
      ]);
      if (seenText.has(fingerprint))
        return [];
      seenText.add(fingerprint);
      return [
        {
          text: element,
          polygons,
          sheetId,
          object: {
            type: "text",
            id: element.schematic_text_id,
            text: element.text
          }
        }
      ];
    });
    this.obstacles = [
      ...ctx.componentPlacements.flatMap((p) => p.schematicComponentId && !customSymbolIds.has(p.schematicComponentId) ? [
        {
          object: {
            type: "component",
            id: p.schematicComponentId,
            componentName: p.sourceComponentName,
            schematicComponentId: p.schematicComponentId
          },
          polygons: [
            rectPolygon(centeredRect(p.schX, p.schY, p.width, p.height))
          ],
          sheetId: p.schematicSheetId
        }
      ] : []),
      ...ctx.circuitJson.flatMap((element) => element.type === "schematic_trace" ? [
        {
          object: {
            type: "trace",
            id: element.schematic_trace_id
          },
          sheetId: element.schematic_sheet_id,
          segments: element.edges,
          polygons: element.edges.flatMap((edge) => {
            const polygon = traceSegmentPolygon(edge.from, edge.to);
            return polygon ? [polygon] : [];
          })
        }
      ] : [])
    ];
    this.solved = this.texts.length === 0;
  }
  _step() {
    const text = this.texts[this.index];
    const targets = [...this.obstacles, ...this.texts.slice(this.index + 1)];
    const collisions = targets.filter((target) => this.collides(text, target));
    if (collisions.length) {
      const suggestedMove = this.findClearPosition(text);
      for (const target of collisions) {
        this.params.issues.push({
          lineItemType: "SchematicTextCollision",
          schematicSheetId: text.sheetId,
          schematicSheetName: text.sheetId ? this.sheetNames.get(text.sheetId) : undefined,
          schematicTextId: text.text.schematic_text_id,
          text: text.text.text,
          collidingObject: target.object,
          textBounds: polygonBounds(text.polygons),
          collidingObjectBounds: polygonBounds(target.polygons),
          suggestedMove,
          message: `Text "${text.text.text}" overlaps ${target.object.type} ${target.object.componentName ?? target.object.id}; reposition the text to leave its visible area clear.`
        });
      }
    }
    this.index++;
    this.solved = this.index >= this.texts.length;
  }
  collides(text, obstacle) {
    if (text.sheetId !== obstacle.sheetId)
      return false;
    return text.polygons.some((a) => obstacle.segments ? obstacle.segments.some((edge) => segmentCrossesPolygon(edge.from, edge.to, a)) : obstacle.polygons.some((b) => polygonsOverlap(a, b)));
  }
  findClearPosition(text) {
    const obstacles = [
      ...this.obstacles,
      ...this.texts.filter((t) => t !== text)
    ];
    const step = Math.max(0.1, text.text.font_size / 2);
    for (let distance5 = step;distance5 <= Math.max(4, text.text.font_size * 8); distance5 += step) {
      for (const [dx, dy] of [
        [0, distance5],
        [0, -distance5],
        [-distance5, 0],
        [distance5, 0]
      ]) {
        const newSchX = Math.round((text.text.position.x + dx) * 1000) / 1000;
        const newSchY = Math.round((text.text.position.y + dy) * 1000) / 1000;
        const moved = {
          ...text,
          polygons: getSchematicTextPolygons({
            ...text.text,
            position: { x: newSchX, y: newSchY }
          })
        };
        if (obstacles.every((obstacle) => !this.collides(moved, obstacle)))
          return { newSchX, newSchY };
      }
    }
    return;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "schematicTextId", issue.schematicTextId);
    addAttr(attrs, "text", issue.text);
    addAttr(attrs, "collidingObjectType", issue.collidingObject.type);
    addAttr(attrs, "collidingObjectId", issue.collidingObject.id);
    addAttr(attrs, "newSchX", issue.suggestedMove?.newSchX);
    addAttr(attrs, "newSchY", issue.suggestedMove?.newSchY);
    addAttr(attrs, "message", issue.message);
    return `<SchematicTextCollision ${attrs.join(" ")} />`;
  }
}

// ../../work/placement-analysis/lib/solvers/ResetNetworkGroupingSolver/ResetNetworkGroupingSolver.ts
class ResetNetworkGroupingSolver extends BaseSolver {
  params;
  static MIN_DISTANCE = 6;
  networks;
  index = 0;
  constructor(params) {
    super();
    this.params = params;
    this.networks = this.findNetworks(params.ctx);
    this.solved = this.networks.length === 0;
  }
  _step() {
    const network = this.networks[this.index];
    const rcMembers = network.members.slice(0, 2);
    const threshold = Math.max(ResetNetworkGroupingSolver.MIN_DISTANCE, ...rcMembers.map((p) => 3 * Math.max(p.width, p.height)));
    const distances = rcMembers.map((p) => Math.hypot(Math.max(0, Math.abs(p.schX - network.pinPosition.x) - p.width / 2), Math.max(0, Math.abs(p.schY - network.pinPosition.y) - p.height / 2)));
    if (distances.some((distance5) => distance5 > threshold)) {
      const hostName = network.host.sourceComponentName ?? network.host.schematicComponentId;
      const resetPin = resetPinName(network.pin);
      const memberNames = rcMembers.map((p) => p.sourceComponentName ?? p.schematicComponentId).join(", ");
      this.params.issues.push({
        lineItemType: "ResetNetworkNotGrouped",
        hostSchematicBox: network.host,
        resetSourcePortId: network.pin.source_port_id,
        resetPinName: resetPin,
        supportNetworkComponents: network.members,
        maxDistanceFromResetPin: Math.round(Math.max(...distances) * 100) / 100,
        maxRecommendedDistance: threshold,
        message: `Group ${memberNames} near ${hostName}.${resetPin} so the reset pull-up and capacitor can be read together. Preserve all net connections; associated test points may remain in a debug area.`
      });
    }
    this.index++;
    this.solved = this.index >= this.networks.length;
  }
  findNetworks(ctx) {
    const root = getSourceConnectivity(ctx.circuitJson);
    const sources = ctx.circuitJson.filter((e) => e.type === "source_component");
    const sourceById = new Map(sources.map((e) => [e.source_component_id, e]));
    const ports = ctx.circuitJson.filter((e) => e.type === "source_port");
    const portsByComponent = new Map;
    const portsByNet = new Map;
    const power = new Set;
    const ground = new Set;
    for (const port of ports) {
      if (!port.source_component_id)
        continue;
      const componentPorts = portsByComponent.get(port.source_component_id) ?? [];
      componentPorts.push(port);
      portsByComponent.set(port.source_component_id, componentPorts);
      const net = root(port.source_port_id);
      const netPorts = portsByNet.get(net) ?? [];
      netPorts.push(port);
      portsByNet.set(net, netPorts);
      if (port.provides_power || port.requires_power)
        power.add(net);
      if (port.provides_ground || port.requires_ground)
        ground.add(net);
    }
    for (const element of ctx.circuitJson) {
      if (element.type !== "source_net")
        continue;
      if (element.is_power || element.is_positive_voltage_source)
        power.add(root(element.source_net_id));
      if (element.is_ground)
        ground.add(root(element.source_net_id));
    }
    const placementBySource = new Map(ctx.componentPlacements.flatMap((p) => p.sourceComponentId ? [[p.sourceComponentId, p]] : []));
    const schematicPorts = ctx.circuitJson.filter((e) => e.type === "schematic_port");
    const schematicComponents = new Map(ctx.circuitJson.filter((e) => e.type === "schematic_component").map((e) => [e.schematic_component_id, e]));
    const networks = [];
    const seen = new Set;
    for (const pin of ports) {
      if (!pin.source_component_id || !resetPinName(pin) || pin.do_not_connect)
        continue;
      if (sourceById.get(pin.source_component_id)?.ftype !== "simple_chip")
        continue;
      const net = root(pin.source_port_id);
      if (seen.has(net) || power.has(net) || ground.has(net))
        continue;
      seen.add(net);
      const peers = portsByNet.get(net) ?? [];
      const chips = new Set(peers.filter((p) => p.source_component_id && sourceById.get(p.source_component_id)?.ftype === "simple_chip").map((p) => p.source_component_id));
      if (chips.size !== 1)
        continue;
      const host = placementBySource.get(pin.source_component_id);
      const schematicPin = schematicPorts.find((p) => p.source_port_id === pin.source_port_id && p.schematic_component_id === host?.schematicComponentId);
      if (!host || !schematicPin || schematicPin.schematic_sheet_id !== host.schematicSheetId)
        continue;
      const pullups = [];
      const capacitors = [];
      const testpoints = [];
      let unsupported = false;
      for (const id of new Set(peers.map((p) => p.source_component_id))) {
        if (!id || id === pin.source_component_id)
          continue;
        const type = sourceById.get(id)?.ftype;
        const componentPorts = portsByComponent.get(id) ?? [];
        const placement = placementBySource.get(id);
        if (type === "simple_connector" || type === "simple_pin_header")
          continue;
        if (!placement) {
          unsupported = true;
          break;
        }
        if (type === "simple_test_point" && componentPorts.length === 1) {
          testpoints.push(placement);
          continue;
        }
        if (componentPorts.length !== 2) {
          unsupported = true;
          break;
        }
        const other = componentPorts.find((p) => root(p.source_port_id) !== net);
        if (!other) {
          unsupported = true;
          break;
        }
        const otherNet = root(other.source_port_id);
        if (type === "simple_resistor" && power.has(otherNet) && !ground.has(otherNet))
          pullups.push(placement);
        else if (type === "simple_capacitor" && ground.has(otherNet) && !power.has(otherNet))
          capacitors.push(placement);
        else {
          unsupported = true;
          break;
        }
      }
      if (unsupported || pullups.length !== 1 || capacitors.length !== 1)
        continue;
      const members = [...pullups, ...capacitors, ...testpoints];
      const hostGroup = host.schematicComponentId ? schematicComponents.get(host.schematicComponentId)?.schematic_group_id : undefined;
      if (members.some((member) => {
        const group = member.schematicComponentId ? schematicComponents.get(member.schematicComponentId)?.schematic_group_id : undefined;
        return member.schematicSheetId !== host.schematicSheetId || member.subcircuitId !== host.subcircuitId || group !== hostGroup;
      }))
        continue;
      networks.push({ host, pin, pinPosition: schematicPin.center, members });
    }
    return networks;
  }
  static issueToString(issue) {
    const attrs = [];
    addAttr(attrs, "hostComponentName", issue.hostSchematicBox.sourceComponentName);
    addAttr(attrs, "resetPin", issue.resetPinName);
    addAttr(attrs, "supportNetworkComponents", issue.supportNetworkComponents.map((p) => p.sourceComponentName ?? p.schematicComponentId).join(","));
    addAttr(attrs, "maxDistanceFromResetPin", issue.maxDistanceFromResetPin);
    addAttr(attrs, "maxRecommendedDistance", issue.maxRecommendedDistance);
    addAttr(attrs, "message", issue.message);
    return `<ResetNetworkNotGrouped ${attrs.join(" ")} />`;
  }
}
var resetPinName = (port) => [port.name, ...port.port_hints ?? []].find((name) => /^N?(RESET|RST)(N|B)?$/.test(name.toUpperCase().replace(/[_\-!~#/]/g, "")));

// ../../work/placement-analysis/lib/solvers/SchematicPlacementPipeline/SchematicPlacementPipeline.ts
var solversByIssueType = {
  CapacitorSeparatedFromChipPins: [ChipPinPairCapacitorPlacementSolver],
  PiFilterComponentsNotGrouped: [PiFilterPlacementSolver],
  MosfetGateNetworkNotGrouped: [MosfetGateNetworkPlacementSolver],
  FlybackDiodeSeparatedFromRelayCoil: [RelayFlybackDiodePlacementSolver],
  ComponentOverlap: [SchematicBoxOverlapSolver],
  SchematicBoxHasALotOfSurroundingWhitespace: [],
  CapacitorSymbolHorizontal: [
    CapacitorOrientationSolver,
    TwoPinComponentRailOrientationSolver
  ],
  VerboseSchematicNetLabel: [VerboseNetLabelSolver],
  PinHeaderSchematicBoxTooWide: [SchematicBoxTooWideSolver],
  GenericSchematicBoxTooWide: [SchematicBoxTooWideSolver],
  SchematicBoxInnerLabelCollision: [SchematicBoxInnerLabelCollisionSolver],
  SchematicPinPaddingToEdgeTooLarge: [SchematicPinPaddingToEdgeSolver],
  DiodeResistorNotAligned: [DiodeResistorAlignmentSolver],
  ComponentPinsWouldAlignWithVerticalShift: [ComponentPinAlignmentSolver],
  TraceCanBeSimplifiedByMovingComponent: [TraceSimplificationSolver],
  FourPinCrystalPatternMismatch: [FourPinCrystalPatternSolver],
  CrystalNotCenteredOverLoadCapacitors: [CrystalLoadCapacitorPlacementSolver],
  ComponentNetLabelCollision: [ComponentNetLabelCollisionSolver],
  ComponentBoxNetLabelCollision: [ComponentNetLabelCollisionSolver],
  NetLabelCollision: [ComponentNetLabelCollisionSolver],
  FeedbackNetworkNotCompact: [FeedbackNetworkPlacementSolver],
  PullResistorOnWrongSide: [
    PullResistorPlacementSolver,
    SwitchPullResistorPlacementSolver
  ],
  SchematicTextCollision: [SchematicTextClearanceSolver],
  ResetNetworkNotGrouped: [ResetNetworkGroupingSolver],
  TwoPinComponentCouldBeFlipped: [TwoPinComponentOrientationSolver],
  TwoPinComponentShouldBeVertical: [TwoPinComponentRailOrientationSolver],
  TwoPinComponentHasInvertedRails: [TwoPinComponentRailOrientationSolver],
  DecouplingCapacitorsNotCloseTogether: [DecouplingCapacitorGroupingSolver],
  ConnectorPositionCausesTraceDetours: [ConnectorPlacementSolver],
  LowSideTransistorNotAlignedWithLoad: [LowSideTransistorPlacementSolver],
  UsbSeriesResistorsNotAligned: [UsbSeriesResistorPlacementSolver],
  CurrentSenseShuntSeparatedFromInputs: [CurrentSenseShuntPlacementSolver],
  VoltageDividerSupplyResistorBelowGroundResistor: [
    VoltageDividerPlacementSolver
  ],
  RegulatorCapacitorsOnWrongSides: [
    RegulatorInputOutputCapacitorPlacementSolver
  ]
};

class SchematicPlacementPipeline extends BasePipelineSolver {
  ctx;
  issues = [];
  pipelineDef = [
    definePipelineStep("SchematicTextClearanceSolver", SchematicTextClearanceSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("ResetNetworkGroupingSolver", ResetNetworkGroupingSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("SchematicBoxOverlapSolver", SchematicBoxOverlapSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("CapacitorOrientationSolver", CapacitorOrientationSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("VerboseNetLabelSolver", VerboseNetLabelSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("SchematicBoxTooWideSolver", SchematicBoxTooWideSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("SchematicPinPaddingToEdgeSolver", SchematicPinPaddingToEdgeSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("SchematicBoxInnerLabelCollisionSolver", SchematicBoxInnerLabelCollisionSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("DiodeResistorAlignmentSolver", DiodeResistorAlignmentSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("ComponentPinAlignmentSolver", ComponentPinAlignmentSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("TraceSimplificationSolver", TraceSimplificationSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("FourPinCrystalPatternSolver", FourPinCrystalPatternSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("CrystalLoadCapacitorPlacementSolver", CrystalLoadCapacitorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("TwoPinComponentOrientationSolver", TwoPinComponentOrientationSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("FeedbackNetworkPlacementSolver", FeedbackNetworkPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("TwoPinComponentRailOrientationSolver", TwoPinComponentRailOrientationSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("PullResistorPlacementSolver", PullResistorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("SwitchPullResistorPlacementSolver", SwitchPullResistorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("ComponentNetLabelCollisionSolver", ComponentNetLabelCollisionSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("DecouplingCapacitorGroupingSolver", DecouplingCapacitorGroupingSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("ConnectorPlacementSolver", ConnectorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("LowSideTransistorPlacementSolver", LowSideTransistorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("UsbSeriesResistorPlacementSolver", UsbSeriesResistorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("RegulatorInputOutputCapacitorPlacementSolver", RegulatorInputOutputCapacitorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("VoltageDividerPlacementSolver", VoltageDividerPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("CurrentSenseShuntPlacementSolver", CurrentSenseShuntPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("RelayFlybackDiodePlacementSolver", RelayFlybackDiodePlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("PiFilterPlacementSolver", PiFilterPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("MosfetGateNetworkPlacementSolver", MosfetGateNetworkPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ]),
    definePipelineStep("ChipPinPairCapacitorPlacementSolver", ChipPinPairCapacitorPlacementSolver, (p) => [
      { ctx: p.ctx, issues: p.issues }
    ])
  ];
  selectedIssueTypes;
  constructor(circuitJson, options = {}) {
    super(circuitJson);
    if (options.issueTypes !== undefined) {
      this.selectedIssueTypes = new Set(options.issueTypes);
      const selectedSolvers = new Set(options.issueTypes.flatMap((type) => solversByIssueType[type]));
      this.pipelineDef = this.pipelineDef.filter((step) => selectedSolvers.has(step.solverClass));
    }
  }
  _setup() {
    this.ctx = buildSolverContext(this.inputProblem);
  }
  getOutput() {
    const railOrientationComponentIds = new Set(this.issues.flatMap((issue) => issue.lineItemType === "TwoPinComponentShouldBeVertical" && issue.schematicBox.schematicComponentId ? [issue.schematicBox.schematicComponentId] : []));
    return {
      issues: this.issues.filter((issue) => issue.lineItemType !== "CapacitorSymbolHorizontal" || !railOrientationComponentIds.has(issue.schematicBox.schematicComponentId ?? "")).filter((issue) => this.selectedIssueTypes === undefined || this.selectedIssueTypes.has(issue.lineItemType)),
      componentPlacements: this.ctx.componentPlacements
    };
  }
}

// ../../work/placement-analysis/lib/utils/issue-context.ts
var POSITION_EPSILON = 0.01;
var getRelevantPlacementsForIssues = ({
  issues,
  componentPlacements,
  circuitJson
}) => {
  const relevantPlacements = new Set;
  const placementByComponentId = new Map(componentPlacements.flatMap((placement) => placement.schematicComponentId ? [[placement.schematicComponentId, placement]] : []));
  const placementsByName = new Map;
  for (const placement of componentPlacements) {
    if (!placement.sourceComponentName)
      continue;
    const namedPlacements = placementsByName.get(placement.sourceComponentName);
    if (namedPlacements)
      namedPlacements.push(placement);
    else
      placementsByName.set(placement.sourceComponentName, [placement]);
  }
  const addPlacement = (placement) => {
    if (!placement)
      return;
    const canonicalPlacement = placement.schematicComponentId ? placementByComponentId.get(placement.schematicComponentId) : componentPlacements.find((candidate) => candidate.sourceComponentId === placement.sourceComponentId && candidate.schX === placement.schX && candidate.schY === placement.schY);
    if (canonicalPlacement)
      relevantPlacements.add(canonicalPlacement);
  };
  const addComponentName = (componentName, schematicSheetId) => {
    if (!componentName)
      return;
    for (const placement of placementsByName.get(componentName) ?? []) {
      if (schematicSheetId === undefined || placement.schematicSheetId === schematicSheetId) {
        relevantPlacements.add(placement);
      }
    }
  };
  for (const issue of issues) {
    switch (issue.lineItemType) {
      case "CapacitorSeparatedFromChipPins":
        addPlacement(issue.hostSchematicBox);
        addPlacement(issue.capacitorSchematicBox);
        break;
      case "PiFilterComponentsNotGrouped":
        addPlacement(issue.inductorSchematicBox);
        addPlacement(issue.firstCapacitorSchematicBox);
        addPlacement(issue.secondCapacitorSchematicBox);
        break;
      case "MosfetGateNetworkNotGrouped":
        addPlacement(issue.mosfetSchematicBox);
        addPlacement(issue.seriesGateResistorSchematicBox);
        addPlacement(issue.gateSourceResistorSchematicBox);
        break;
      case "FlybackDiodeSeparatedFromRelayCoil":
        addPlacement(issue.relaySchematicBox);
        addPlacement(issue.diodeSchematicBox);
        break;
      case "CurrentSenseShuntSeparatedFromInputs":
        addPlacement(issue.amplifierSchematicBox);
        addPlacement(issue.shuntSchematicBox);
        break;
      case "VoltageDividerSupplyResistorBelowGroundResistor":
        addPlacement(issue.supplyResistorSchematicBox);
        addPlacement(issue.groundResistorSchematicBox);
        break;
      case "RegulatorCapacitorsOnWrongSides":
        addPlacement(issue.regulatorSchematicBox);
        addPlacement(issue.inputCapacitorSchematicBox);
        addPlacement(issue.outputCapacitorSchematicBox);
        break;
      case "UsbSeriesResistorsNotAligned":
        addPlacement(issue.positiveResistorSchematicBox);
        addPlacement(issue.negativeResistorSchematicBox);
        break;
      case "LowSideTransistorNotAlignedWithLoad":
        addPlacement(issue.transistorSchematicBox);
        addPlacement(issue.loadSchematicBox);
        addPlacement(issue.baseResistorSchematicBox);
        addPlacement(issue.clampDiodeSchematicBox);
        break;
      case "DecouplingCapacitorsNotCloseTogether":
        for (const placement of issue.capacitorSchematicBoxes)
          addPlacement(placement);
        break;
      case "ConnectorPositionCausesTraceDetours":
        addPlacement(issue.connectorSchematicBox);
        for (const placement of issue.connectedComponents)
          addPlacement(placement);
        break;
      case "ResetNetworkNotGrouped":
        addPlacement(issue.hostSchematicBox);
        for (const placement of issue.supportNetworkComponents)
          addPlacement(placement);
        break;
      case "SchematicTextCollision":
        if (issue.collidingObject.schematicComponentId)
          addPlacement(placementByComponentId.get(issue.collidingObject.schematicComponentId));
        if (issue.collidingObject.type === "trace") {
          for (const placement of getTraceEndpointPlacements({
            schematicTraceId: issue.collidingObject.id,
            circuitJson,
            placementByComponentId
          }))
            addPlacement(placement);
        }
        break;
      case "ComponentOverlap":
        addPlacement(issue.firstComponent);
        addPlacement(issue.secondComponent);
        break;
      case "SchematicBoxHasALotOfSurroundingWhitespace":
      case "CapacitorSymbolHorizontal":
      case "PinHeaderSchematicBoxTooWide":
      case "GenericSchematicBoxTooWide":
      case "SchematicBoxInnerLabelCollision":
      case "SchematicPinPaddingToEdgeTooLarge":
        addPlacement(issue.schematicBox);
        break;
      case "VerboseSchematicNetLabel":
        for (const pin of issue.involvedPins) {
          addComponentName(getComponentNameFromPin(pin), issue.schematicSheetId);
        }
        break;
      case "DiodeResistorNotAligned":
        addPlacement(issue.diodeSchematicBox);
        addPlacement(issue.resistorSchematicBox);
        break;
      case "ComponentPinsWouldAlignWithVerticalShift":
        addPlacement(issue.firstComponent);
        addPlacement(issue.secondComponent);
        addPlacement(issue.targetComponent);
        break;
      case "TraceCanBeSimplifiedByMovingComponent":
        addPlacement(issue.targetComponent);
        for (const placement of getTraceEndpointPlacements({
          schematicTraceId: issue.schematicTraceId,
          circuitJson,
          placementByComponentId
        })) {
          relevantPlacements.add(placement);
        }
        break;
      case "FourPinCrystalPatternMismatch":
        for (const target of issue.suggestedPlacements)
          addPlacement(target.schematicBox);
        break;
      case "CrystalNotCenteredOverLoadCapacitors":
        addPlacement(issue.crystalSchematicBox);
        addPlacement(issue.firstLoadCapacitorSchematicBox);
        addPlacement(issue.secondLoadCapacitorSchematicBox);
        break;
      case "TwoPinComponentCouldBeFlipped":
        addPlacement(issue.targetComponent);
        addPlacement(issue.connectedComponent);
        break;
      case "FeedbackNetworkNotCompact":
        addPlacement(issue.amplifierSchematicBox);
        for (const component of issue.feedbackComponents)
          addPlacement(component);
        break;
      case "TwoPinComponentShouldBeVertical":
      case "TwoPinComponentHasInvertedRails":
        addPlacement(issue.schematicBox);
        break;
      case "PullResistorOnWrongSide":
        addPlacement(issue.resistorSchematicBox);
        addPlacement(issue.hostSchematicBox);
        break;
      case "ComponentNetLabelCollision":
        addPlacement(issue.firstComponent);
        addPlacement(issue.secondComponent);
        break;
      case "ComponentBoxNetLabelCollision":
        addPlacement(issue.boxComponent);
        addPlacement(issue.labelComponent);
        break;
      case "NetLabelCollision":
        for (const pair of issue.pairs) {
          addComponentName(pair.comp1Name, issue.schematicSheetId);
          addComponentName(pair.comp2Name, issue.schematicSheetId);
        }
        for (const move of issue.moves) {
          addComponentName(move.componentName, issue.schematicSheetId);
        }
        break;
    }
  }
  return componentPlacements.filter((placement) => relevantPlacements.has(placement));
};
var getIssueSchematicSheetContext = (issue) => {
  if ("schematicSheetId" in issue || "schematicSheetName" in issue) {
    const schematicSheetId = "schematicSheetId" in issue && typeof issue.schematicSheetId === "string" ? issue.schematicSheetId : undefined;
    const schematicSheetName = "schematicSheetName" in issue && typeof issue.schematicSheetName === "string" ? issue.schematicSheetName : undefined;
    if (schematicSheetId || schematicSheetName) {
      return { schematicSheetId, schematicSheetName };
    }
  }
  for (const value of Object.values(issue).flat()) {
    if (isSchematicBoxPlacement(value)) {
      return {
        schematicSheetId: value.schematicSheetId,
        schematicSheetName: value.schematicSheetName
      };
    }
  }
  return {};
};
var getComponentNameFromPin = (pin) => {
  const separatorIndex = pin.lastIndexOf(".");
  return separatorIndex === -1 ? pin : pin.slice(0, separatorIndex);
};
var isSchematicBoxPlacement = (value) => Boolean(value && typeof value === "object" && "positionAnchor" in value && value.positionAnchor === "center" && "schX" in value && "schY" in value && "width" in value && "height" in value);
var getTraceEndpointPlacements = ({
  schematicTraceId,
  circuitJson,
  placementByComponentId
}) => {
  const trace = circuitJson.find((element) => element.type === "schematic_trace" && element.schematic_trace_id === schematicTraceId);
  const firstEdge = trace?.edges[0];
  const lastEdge = trace?.edges.at(-1);
  if (!trace || !firstEdge || !lastEdge)
    return [];
  const ports = circuitJson.filter((element) => element.type === "schematic_port");
  const portsById = new Map(ports.map((port) => [port.schematic_port_id, port]));
  const endpointPorts = [
    firstEdge.from_schematic_port_id ? portsById.get(firstEdge.from_schematic_port_id) : findPortAtPoint(ports, firstEdge.from, trace.schematic_sheet_id),
    lastEdge.to_schematic_port_id ? portsById.get(lastEdge.to_schematic_port_id) : findPortAtPoint(ports, lastEdge.to, trace.schematic_sheet_id)
  ];
  return endpointPorts.flatMap((port) => {
    const placement = port?.schematic_component_id ? placementByComponentId.get(port.schematic_component_id) : undefined;
    return placement ? [placement] : [];
  });
};
var findPortAtPoint = (ports, point2, schematicSheetId) => ports.find((port) => port.schematic_sheet_id === schematicSheetId && Math.abs(port.center.x - point2.x) <= POSITION_EPSILON && Math.abs(port.center.y - point2.y) <= POSITION_EPSILON);

// ../../work/placement-analysis/lib/analyze-schematic-placement.ts
class SchematicPlacementAnalysis {
  lineItems;
  groupBySchematicSheet;
  constructor(lineItems, groupBySchematicSheet = false) {
    this.lineItems = lineItems;
    this.groupBySchematicSheet = groupBySchematicSheet;
  }
  getLineItems() {
    return this.lineItems;
  }
  getIssues(filter = {}) {
    return this.lineItems.flatMap((item) => item.lineItemType === "SchematicPlacementIssues" ? item.issues : []).filter((issue) => (filter.issueTypes === undefined || filter.issueTypes.includes(issue.lineItemType)) && (filter.schematicSheetId === undefined || (getIssueSchematicSheetContext(issue).schematicSheetId ?? "") === filter.schematicSheetId));
  }
  getIssueCounts(filter = {}) {
    const counts = {
      FlybackDiodeSeparatedFromRelayCoil: 0,
      ComponentOverlap: 0,
      SchematicBoxHasALotOfSurroundingWhitespace: 0,
      CapacitorSymbolHorizontal: 0,
      VerboseSchematicNetLabel: 0,
      PinHeaderSchematicBoxTooWide: 0,
      GenericSchematicBoxTooWide: 0,
      SchematicBoxInnerLabelCollision: 0,
      SchematicPinPaddingToEdgeTooLarge: 0,
      DiodeResistorNotAligned: 0,
      ComponentPinsWouldAlignWithVerticalShift: 0,
      TraceCanBeSimplifiedByMovingComponent: 0,
      FourPinCrystalPatternMismatch: 0,
      CrystalNotCenteredOverLoadCapacitors: 0,
      ComponentNetLabelCollision: 0,
      ComponentBoxNetLabelCollision: 0,
      NetLabelCollision: 0,
      FeedbackNetworkNotCompact: 0,
      PullResistorOnWrongSide: 0,
      SchematicTextCollision: 0,
      ResetNetworkNotGrouped: 0,
      TwoPinComponentCouldBeFlipped: 0,
      TwoPinComponentShouldBeVertical: 0,
      TwoPinComponentHasInvertedRails: 0,
      DecouplingCapacitorsNotCloseTogether: 0,
      ConnectorPositionCausesTraceDetours: 0,
      LowSideTransistorNotAlignedWithLoad: 0,
      UsbSeriesResistorsNotAligned: 0,
      RegulatorCapacitorsOnWrongSides: 0,
      VoltageDividerSupplyResistorBelowGroundResistor: 0,
      CurrentSenseShuntSeparatedFromInputs: 0,
      PiFilterComponentsNotGrouped: 0,
      MosfetGateNetworkNotGrouped: 0,
      CapacitorSeparatedFromChipPins: 0
    };
    for (const issue of this.getIssues(filter))
      counts[issue.lineItemType]++;
    return counts;
  }
  getString() {
    return this.toString();
  }
  schematicBoxPlacementsToString(lineItem) {
    const attrs = [];
    addAttr(attrs, "componentName", lineItem.sourceComponentName);
    addAttr(attrs, "positionAnchor", lineItem.positionAnchor);
    addAttr(attrs, "schX", lineItem.schX);
    addAttr(attrs, "schY", lineItem.schY);
    addAttr(attrs, "width", lineItem.width);
    addAttr(attrs, "height", lineItem.height);
    return `<SchematicBoxPlacement ${attrs.join(" ")} />`;
  }
  schematicIssuesToString(issue) {
    switch (issue.lineItemType) {
      case "CapacitorSeparatedFromChipPins":
        return ChipPinPairCapacitorPlacementSolver.issueToString(issue);
      case "PiFilterComponentsNotGrouped":
        return PiFilterPlacementSolver.issueToString(issue);
      case "MosfetGateNetworkNotGrouped":
        return MosfetGateNetworkPlacementSolver.issueToString(issue);
      case "CurrentSenseShuntSeparatedFromInputs":
        return CurrentSenseShuntPlacementSolver.issueToString(issue);
      case "ComponentOverlap":
        return SchematicBoxOverlapSolver.issueToString(issue);
      case "CapacitorSymbolHorizontal":
        return CapacitorOrientationSolver.issueToString(issue);
      case "DecouplingCapacitorsNotCloseTogether":
        return DecouplingCapacitorGroupingSolver.issueToString(issue);
      case "VerboseSchematicNetLabel":
        return VerboseNetLabelSolver.issueToString(issue);
      case "PinHeaderSchematicBoxTooWide":
      case "GenericSchematicBoxTooWide":
        return SchematicBoxTooWideSolver.issueToString(issue);
      case "SchematicBoxInnerLabelCollision":
        return SchematicBoxInnerLabelCollisionSolver.issueToString(issue);
      case "SchematicPinPaddingToEdgeTooLarge":
        return SchematicPinPaddingToEdgeSolver.issueToString(issue);
      case "DiodeResistorNotAligned":
        return DiodeResistorAlignmentSolver.issueToString(issue);
      case "ComponentPinsWouldAlignWithVerticalShift":
        return ComponentPinAlignmentSolver.issueToString(issue);
      case "TraceCanBeSimplifiedByMovingComponent":
        return TraceSimplificationSolver.issueToString(issue);
      case "FourPinCrystalPatternMismatch":
        return FourPinCrystalPatternSolver.issueToString(issue);
      case "CrystalNotCenteredOverLoadCapacitors":
        return CrystalLoadCapacitorPlacementSolver.issueToString(issue);
      case "TwoPinComponentCouldBeFlipped":
        return TwoPinComponentOrientationSolver.issueToString(issue);
      case "FeedbackNetworkNotCompact":
        return FeedbackNetworkPlacementSolver.issueToString(issue);
      case "TwoPinComponentShouldBeVertical":
      case "TwoPinComponentHasInvertedRails":
        return TwoPinComponentRailOrientationSolver.issueToString(issue);
      case "PullResistorOnWrongSide":
        return PullResistorPlacementSolver.issueToString(issue);
      case "NetLabelCollision":
        return ComponentNetLabelCollisionSolver.netLabelCollisionToString(issue);
      case "SchematicTextCollision":
        return SchematicTextClearanceSolver.issueToString(issue);
      case "ResetNetworkNotGrouped":
        return ResetNetworkGroupingSolver.issueToString(issue);
      case "ConnectorPositionCausesTraceDetours":
        return ConnectorPlacementSolver.issueToString(issue);
      case "LowSideTransistorNotAlignedWithLoad":
        return LowSideTransistorPlacementSolver.issueToString(issue);
      case "FlybackDiodeSeparatedFromRelayCoil":
        return RelayFlybackDiodePlacementSolver.issueToString(issue);
      case "VoltageDividerSupplyResistorBelowGroundResistor":
        return VoltageDividerPlacementSolver.issueToString(issue);
      case "RegulatorCapacitorsOnWrongSides":
        return RegulatorInputOutputCapacitorPlacementSolver.issueToString(issue);
      case "UsbSeriesResistorsNotAligned":
        return UsbSeriesResistorPlacementSolver.issueToString(issue);
      default:
        return "";
    }
  }
  toString() {
    const schematicBoxPlacements = this.lineItems.filter((lineItem) => lineItem.lineItemType === "SchematicBoxPlacement");
    const issues = this.lineItems.flatMap((lineItem) => lineItem.lineItemType === "SchematicPlacementIssues" ? lineItem.issues : []);
    if (issues.length === 0)
      return "";
    if (!this.groupBySchematicSheet) {
      return this.issueContextToLines(schematicBoxPlacements, issues).join(`
`);
    }
    const groups = new Map;
    const getOrCreateGroup = (context) => {
      const key = context.schematicSheetId ?? context.schematicSheetName ?? "__default__";
      const existingGroup = groups.get(key);
      if (existingGroup)
        return existingGroup;
      const group = { ...context, placements: [], issues: [] };
      groups.set(key, group);
      return group;
    };
    for (const issue of issues) {
      getOrCreateGroup(getIssueSchematicSheetContext(issue)).issues.push(issue);
    }
    for (const placement of schematicBoxPlacements) {
      getOrCreateGroup({
        schematicSheetId: placement.schematicSheetId,
        schematicSheetName: placement.schematicSheetName
      }).placements.push(placement);
    }
    return [...groups.values()].flatMap((group) => {
      const sheetAttrs = [];
      addAttr(sheetAttrs, "name", group.schematicSheetName);
      addAttr(sheetAttrs, "id", group.schematicSheetId);
      return [
        `<SchematicSheet${sheetAttrs.length > 0 ? ` ${sheetAttrs.join(" ")}` : ""}>`,
        ...this.issueContextToLines(group.placements, group.issues),
        "</SchematicSheet>"
      ];
    }).join(`
`);
  }
  issueContextToLines(placements, issues) {
    return [
      ...placements.length > 0 ? [
        "<SchematicBoxPositions>",
        ...placements.map(this.schematicBoxPlacementsToString),
        "</SchematicBoxPositions>"
      ] : [],
      "<SchematicPlacementIssues>",
      ...issues.map(this.schematicIssuesToString),
      "</SchematicPlacementIssues>"
    ];
  }
}
var analyzeSchematicPlacement = (circuitJson, options = {}) => {
  const pipeline = new SchematicPlacementPipeline(circuitJson, options);
  pipeline.solve();
  const { issues, componentPlacements } = pipeline.getOutput();
  const relevantPlacements = getRelevantPlacementsForIssues({
    issues,
    componentPlacements,
    circuitJson
  });
  const lineItems = [
    ...relevantPlacements,
    ...issues.length > 0 ? [{ lineItemType: "SchematicPlacementIssues", issues }] : []
  ];
  const schematicSheetIds = new Set(circuitJson.flatMap((element) => ("schematic_sheet_id" in element) && typeof element.schematic_sheet_id === "string" ? [element.schematic_sheet_id] : []));
  return new SchematicPlacementAnalysis(lineItems, schematicSheetIds.size > 1);
};
export {
  analyzeSchematicPlacement,
  SchematicPlacementAnalysis
};