altium-to-circuit-json 0.0.21 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/index.js +54 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,10 @@ bun run test:update-svg
|
|
|
94
94
|
|
|
95
95
|
Every imported reference used by the test suite has a side-by-side SVG snapshot. The committed fixtures are generated from pinned upstream URLs and are not stored in this repository.
|
|
96
96
|
|
|
97
|
+
The real-world PCB corpus covers NodeMCU ESP-12, EBAZ4205, HERON Payload SSM,
|
|
98
|
+
SimpleFOC Mini, and SimpleFOC Shield V3. The schematic corpus covers NodeMCU,
|
|
99
|
+
HERON PAY-SSM and Systems PCB, SimpleFOC Mini, and SimpleFOC Shield V3.
|
|
100
|
+
|
|
97
101
|
The TI SPRCAL9 / TMDS62LEVM Rev. B regression corpus includes all 57
|
|
98
102
|
schematic sheets and a top-copper PCB comparison. Its large downloaded source
|
|
99
103
|
files are checksum-verified and cached in CI. To also write the complete
|
package/dist/index.js
CHANGED
|
@@ -1130,35 +1130,56 @@ function createSourceComponent(params) {
|
|
|
1130
1130
|
source_component_id: sourceComponentId
|
|
1131
1131
|
};
|
|
1132
1132
|
if (classification === "resistor") {
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
ftype: "simple_resistor",
|
|
1137
|
-
resistance: primaryValue || 0
|
|
1133
|
+
const resistance = parseFiniteComponentValue({
|
|
1134
|
+
componentUnit: "\u03A9",
|
|
1135
|
+
componentValue: primaryValue
|
|
1138
1136
|
});
|
|
1139
|
-
if (
|
|
1137
|
+
if (resistance !== void 0) {
|
|
1138
|
+
const parsed = source_simple_resistor.safeParse({
|
|
1139
|
+
...common,
|
|
1140
|
+
display_resistance: value || void 0,
|
|
1141
|
+
ftype: "simple_resistor",
|
|
1142
|
+
resistance
|
|
1143
|
+
});
|
|
1144
|
+
if (parsed.success) return parsed.data;
|
|
1145
|
+
}
|
|
1140
1146
|
}
|
|
1141
1147
|
if (classification === "capacitor") {
|
|
1142
|
-
const
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
ftype: "simple_capacitor",
|
|
1146
|
-
capacitance: primaryValue || 0
|
|
1148
|
+
const capacitance = parseFiniteComponentValue({
|
|
1149
|
+
componentUnit: "F",
|
|
1150
|
+
componentValue: primaryValue
|
|
1147
1151
|
});
|
|
1148
|
-
if (
|
|
1152
|
+
if (capacitance !== void 0) {
|
|
1153
|
+
const parsed = source_simple_capacitor.safeParse({
|
|
1154
|
+
...common,
|
|
1155
|
+
display_capacitance: value || void 0,
|
|
1156
|
+
ftype: "simple_capacitor",
|
|
1157
|
+
capacitance
|
|
1158
|
+
});
|
|
1159
|
+
if (parsed.success) return parsed.data;
|
|
1160
|
+
}
|
|
1149
1161
|
}
|
|
1150
1162
|
if (classification === "inductor") {
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
ftype: "simple_inductor",
|
|
1155
|
-
inductance: primaryValue || 0
|
|
1163
|
+
const inductance = parseFiniteComponentValue({
|
|
1164
|
+
componentUnit: "H",
|
|
1165
|
+
componentValue: primaryValue
|
|
1156
1166
|
});
|
|
1157
|
-
if (
|
|
1167
|
+
if (inductance !== void 0) {
|
|
1168
|
+
const parsed = source_simple_inductor.safeParse({
|
|
1169
|
+
...common,
|
|
1170
|
+
display_inductance: value || void 0,
|
|
1171
|
+
ftype: "simple_inductor",
|
|
1172
|
+
inductance
|
|
1173
|
+
});
|
|
1174
|
+
if (parsed.success) return parsed.data;
|
|
1175
|
+
}
|
|
1158
1176
|
}
|
|
1159
1177
|
if (classification === "crystal" && (pinCount === 2 || pinCount === 4)) {
|
|
1160
|
-
const frequency =
|
|
1161
|
-
|
|
1178
|
+
const frequency = parseFiniteComponentValue({
|
|
1179
|
+
componentUnit: "Hz",
|
|
1180
|
+
componentValue: value
|
|
1181
|
+
});
|
|
1182
|
+
if (frequency !== void 0) {
|
|
1162
1183
|
const parsed = source_simple_crystal.safeParse({
|
|
1163
1184
|
...common,
|
|
1164
1185
|
frequency,
|
|
@@ -1182,6 +1203,19 @@ function createSourceComponent(params) {
|
|
|
1182
1203
|
ftype
|
|
1183
1204
|
};
|
|
1184
1205
|
}
|
|
1206
|
+
function parseFiniteComponentValue({
|
|
1207
|
+
componentUnit,
|
|
1208
|
+
componentValue
|
|
1209
|
+
}) {
|
|
1210
|
+
const parsedComponentValue = parseAndConvertSiUnit(
|
|
1211
|
+
componentValue,
|
|
1212
|
+
componentUnit
|
|
1213
|
+
).value;
|
|
1214
|
+
if (typeof parsedComponentValue !== "number" || !Number.isFinite(parsedComponentValue)) {
|
|
1215
|
+
return void 0;
|
|
1216
|
+
}
|
|
1217
|
+
return parsedComponentValue;
|
|
1218
|
+
}
|
|
1185
1219
|
function createComponentText(params) {
|
|
1186
1220
|
const { anchor, component, id, position, text } = params;
|
|
1187
1221
|
return {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/convert-altium-pcb-doc-to-circuit-json.ts","../lib/schematic/convert-semantic-schematic.ts","../lib/schematic/geometry.ts","../lib/schematic/ids.ts","../lib/schematic/symbols.ts","../lib/schematic/coordinates.ts","../lib/schematic/render-primitives.ts","../lib/schematic/sheet-layout.ts","../lib/schematic/render-text.ts","../lib/schematic/render-symbols.ts","../lib/schematic/render-record.ts","../lib/convert-altium-sch-doc-to-circuit-json.ts","../lib/convert-altium-to-circuit-json.ts"],"sourcesContent":["import {\n AltiumArcRecord,\n AltiumFillRecord,\n AltiumPadRecord,\n type AltiumPcbDocument,\n type AltiumPoint,\n type AltiumRecord,\n AltiumRegionRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n getPcbRegionGeometry,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCourtyardOutline,\n PcbCutout,\n PcbHole,\n PcbPlatedHole,\n PcbSilkscreenLine,\n PcbSilkscreenPath,\n PcbSilkscreenRect,\n PcbSilkscreenText,\n PcbSmtPad,\n PcbTrace,\n PcbVia,\n} from \"circuit-json\"\n\nconst MILS_TO_MILLIMETERS = 0.0254\nconst BOARD_ID = \"pcb_board_altium\"\nconst BOARD_GRAPHICS_COMPONENT_ID = \"pcb_component_altium_board_graphics\"\n\nexport interface ConvertAltiumPcbDocOptions {\n includeBoardOutline?: boolean\n includeComponents?: boolean\n includeCourtyards?: boolean\n includePads?: boolean\n includeSilkscreen?: boolean\n includeTraces?: boolean\n includeVias?: boolean\n}\n\nexport function convertAltiumPcbDocToCircuitJson(\n document: AltiumPcbDocument,\n options: ConvertAltiumPcbDocOptions = {},\n): AnyCircuitElement[] {\n const elements: AnyCircuitElement[] = []\n\n if (options.includeBoardOutline !== false) {\n elements.push(createBoard(document))\n for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {\n if (cutout.outline.points.length < 3) continue\n elements.push({\n type: \"pcb_cutout\",\n pcb_cutout_id: `pcb_cutout_altium_${index}`,\n pcb_board_id: BOARD_ID,\n shape: \"polygon\",\n points: cutout.outline.points.map(toMillimeterPoint),\n } satisfies PcbCutout)\n }\n }\n\n if (options.includeComponents !== false) {\n for (const [index, component] of document.components.entries()) {\n const position = component.position\n if (!position) continue\n const bounds = document.getComponentBounds(component)\n elements.push({\n type: \"pcb_component\",\n pcb_component_id: componentId(index),\n source_component_id: `source_component_altium_${index}`,\n center: toMillimeterPoint(position),\n width: milsToMillimeters(\n bounds ? bounds.maxX - bounds.minX : (component.heightMils ?? 20),\n ),\n height: milsToMillimeters(\n bounds ? bounds.maxY - bounds.minY : (component.heightMils ?? 20),\n ),\n layer: component.side === \"bottom\" ? \"bottom\" : \"top\",\n rotation: component.rotation,\n position_mode: \"none\",\n obstructs_within_bounds: false,\n } satisfies PcbComponent)\n }\n }\n\n if (\n options.includeCourtyards !== false &&\n options.includeComponents !== false\n ) {\n elements.push(...convertCourtyards(document))\n }\n\n for (const [index, record] of document.records.entries()) {\n if (record instanceof AltiumPadRecord && options.includePads !== false) {\n const pad = convertPad(record, index)\n if (pad) elements.push(pad)\n continue\n }\n\n if (record instanceof AltiumTrackRecord) {\n if (isCourtyardLayer(record.layer)) continue\n if (isOverlayLayer(record.layer)) {\n if (options.includeSilkscreen === false) continue\n const line = convertSilkscreenLine(record, index)\n if (line) elements.push(line)\n } else if (options.includeTraces !== false) {\n const trace = convertTrack(record, index)\n if (trace) elements.push(trace)\n }\n continue\n }\n\n if (record instanceof AltiumViaRecord && options.includeVias !== false) {\n const via = convertVia(record, index)\n if (via) elements.push(via)\n continue\n }\n\n if (\n options.includeSilkscreen === false ||\n !isOverlayLayer(getLayer(record))\n ) {\n continue\n }\n\n if (record instanceof AltiumArcRecord) {\n const path = convertSilkscreenArc(record, index)\n if (path) elements.push(path)\n } else if (record instanceof AltiumFillRecord) {\n const rect = convertSilkscreenFill(record, index)\n if (rect) elements.push(rect)\n } else if (record instanceof AltiumTextRecord) {\n const text = convertSilkscreenText(record, index)\n if (text) elements.push(text)\n }\n }\n\n return elements\n}\n\ninterface CourtyardPath {\n componentId: string\n layer: \"top\" | \"bottom\"\n points: AltiumPoint[]\n strokeWidthMils: number\n}\n\nfunction convertCourtyards(document: AltiumPcbDocument): PcbCourtyardOutline[] {\n const componentIds = new Map(\n document.components.flatMap((component, index) =>\n component.position ? [[component, componentId(index)] as const] : [],\n ),\n )\n const paths: CourtyardPath[] = []\n\n for (const record of document.records) {\n const layer = getLayer(record)\n if (!isCourtyardLayer(layer)) continue\n const component = document.getComponentForRecord(record)\n const ownedComponentId = component ? componentIds.get(component) : undefined\n if (!ownedComponentId) continue\n const points = getCourtyardRecordPoints(record)\n if (points.length < 2) continue\n paths.push({\n componentId: ownedComponentId,\n layer: mapCourtyardLayer(layer),\n points,\n strokeWidthMils:\n record instanceof AltiumTrackRecord || record instanceof AltiumArcRecord\n ? (record.widthMils ?? 4)\n : 0,\n })\n }\n\n const courtyards: PcbCourtyardOutline[] = []\n for (const path of stitchCourtyardPaths(paths)) {\n if (!isClosedAltiumPath(path.points)) continue\n const outline = removeClosingPoint(path.points).map(toMillimeterPoint)\n if (outline.length < 3) continue\n courtyards.push({\n type: \"pcb_courtyard_outline\",\n pcb_courtyard_outline_id: `pcb_courtyard_outline_altium_${courtyards.length}`,\n pcb_component_id: path.componentId,\n layer: path.layer,\n outline,\n })\n }\n return courtyards\n}\n\nfunction getCourtyardRecordPoints(record: AltiumRecord): AltiumPoint[] {\n if (record instanceof AltiumTrackRecord) {\n return record.start && record.end ? [record.start, record.end] : []\n }\n if (record instanceof AltiumArcRecord) {\n return record.center && record.radiusMils\n ? approximateArc({\n center: record.center,\n radius: record.radiusMils,\n startAngle: record.startAngle,\n endAngle: record.endAngle,\n })\n : []\n }\n if (record instanceof AltiumRegionRecord) {\n return getPcbRegionGeometry(record).outline.points\n }\n return []\n}\n\nfunction stitchCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const groups = new Map<string, CourtyardPath[]>()\n for (const path of deduplicateCourtyardPaths(paths)) {\n const key = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n ].join(\"|\")\n const group = groups.get(key) ?? []\n group.push(path)\n groups.set(key, group)\n }\n return [...groups.values()].flatMap(stitchCourtyardPathGroup)\n}\n\nfunction stitchCourtyardPathGroup(group: CourtyardPath[]): CourtyardPath[] {\n const remaining = [...group]\n const stitched: CourtyardPath[] = []\n while (remaining.length > 0) {\n const first = remaining.shift()\n if (!first) break\n const path = { ...first, points: [...first.points] }\n while (appendConnectedCourtyardPath(path, remaining)) {\n // Continue until no segment can extend either end of this path.\n }\n stitched.push(path)\n }\n return stitched\n}\n\nfunction appendConnectedCourtyardPath(\n stitched: CourtyardPath,\n remaining: CourtyardPath[],\n): boolean {\n const stitchedStart = stitched.points[0]\n const stitchedEnd = stitched.points.at(-1)\n if (!stitchedStart || !stitchedEnd) return false\n\n for (const [index, candidate] of remaining.entries()) {\n const candidateStart = candidate.points[0]\n const candidateEnd = candidate.points.at(-1)\n if (!candidateStart || !candidateEnd) continue\n if (altiumPointsApproximatelyEqual(stitchedEnd, candidateStart)) {\n stitched.points.push(...candidate.points.slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedEnd, candidateEnd)) {\n stitched.points.push(...candidate.points.toReversed().slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateEnd)) {\n stitched.points.unshift(...candidate.points.slice(0, -1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateStart)) {\n stitched.points.unshift(...candidate.points.toReversed().slice(0, -1))\n } else {\n continue\n }\n remaining.splice(index, 1)\n return true\n }\n return false\n}\n\nfunction deduplicateCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const signatures = new Set<string>()\n return paths.filter((path) => {\n const forwardPoints = path.points.map(formatAltiumPoint).join(\"|\")\n const reversePoints = path.points\n .toReversed()\n .map(formatAltiumPoint)\n .join(\"|\")\n const pointsSignature =\n forwardPoints < reversePoints ? forwardPoints : reversePoints\n const signature = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n pointsSignature,\n ].join(\"|\")\n if (signatures.has(signature)) return false\n signatures.add(signature)\n return true\n })\n}\n\nfunction formatAltiumPoint(point: AltiumPoint): string {\n return `${point.x.toFixed(4)},${point.y.toFixed(4)}`\n}\n\nfunction isClosedAltiumPath(points: AltiumPoint[]): boolean {\n const first = points[0]\n const last = points.at(-1)\n return Boolean(first && last && altiumPointsApproximatelyEqual(first, last))\n}\n\nfunction removeClosingPoint(points: AltiumPoint[]): AltiumPoint[] {\n const first = points[0]\n const last = points.at(-1)\n return first && last && altiumPointsApproximatelyEqual(first, last)\n ? points.slice(0, -1)\n : points\n}\n\nfunction altiumPointsApproximatelyEqual(\n left: AltiumPoint,\n right: AltiumPoint,\n): boolean {\n return (\n Math.abs(left.x - right.x) <= 0.01 && Math.abs(left.y - right.y) <= 0.01\n )\n}\n\nfunction createBoard(document: AltiumPcbDocument): PcbBoard {\n const outline = document.boardGeometry.outline.points.map(toMillimeterPoint)\n const bounds =\n getAltiumBounds(document.boardGeometry.outline.points) ??\n getFallbackPcbBounds(document.records)\n const width = Math.max(milsToMillimeters(bounds.maxX - bounds.minX), 0.1)\n const height = Math.max(milsToMillimeters(bounds.maxY - bounds.minY), 0.1)\n const numLayers = document.board\n ? Math.max(\n getPcbLayerStack(document.board).entries.filter((entry) =>\n Boolean(mapCopperLayer(entry.name ?? entry.layerId)),\n ).length,\n 2,\n )\n : 2\n\n return {\n type: \"pcb_board\",\n pcb_board_id: BOARD_ID,\n center: {\n x: milsToMillimeters((bounds.minX + bounds.maxX) / 2),\n y: milsToMillimeters((bounds.minY + bounds.maxY) / 2),\n },\n width,\n height,\n ...(outline.length >= 3 ? { shape: \"polygon\" as const, outline } : {}),\n thickness: 1.6,\n num_layers: numLayers,\n material: \"fr4\",\n }\n}\n\nfunction getFallbackPcbBounds(records: AltiumRecord[]): {\n maxX: number\n maxY: number\n minX: number\n minY: number\n} {\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (\n record instanceof AltiumPadRecord ||\n record instanceof AltiumViaRecord\n ) {\n if (record.position) points.push(record.position)\n } else if (record instanceof AltiumTrackRecord) {\n if (record.start) points.push(record.start)\n if (record.end) points.push(record.end)\n }\n }\n return getAltiumBounds(points) ?? { minX: 0, minY: 0, maxX: 1000, maxY: 800 }\n}\n\nfunction convertTrack(\n record: AltiumTrackRecord,\n index: number,\n): PcbTrace | undefined {\n const start = record.start\n const end = record.end\n const layer = mapCopperLayer(record.layer)\n if (!start || !end || !layer) return undefined\n const width = milsToMillimeters(record.widthMils ?? 4)\n return {\n type: \"pcb_trace\",\n pcb_trace_id: `pcb_trace_altium_${index}`,\n should_round_corners: true,\n route: [\n { route_type: \"wire\", ...toMillimeterPoint(start), width, layer },\n { route_type: \"wire\", ...toMillimeterPoint(end), width, layer },\n ],\n }\n}\n\nfunction convertVia(\n record: AltiumViaRecord,\n index: number,\n): PcbVia | undefined {\n if (!record.position) return undefined\n const startLayer = mapCopperLayer(record.startLayer) ?? \"top\"\n const endLayer = mapCopperLayer(record.endLayer) ?? \"bottom\"\n const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer]\n const outerDiameter = milsToMillimeters(record.diameterMils ?? 20)\n return {\n type: \"pcb_via\",\n pcb_via_id: `pcb_via_altium_${index}`,\n ...toMillimeterPoint(record.position),\n outer_diameter: outerDiameter,\n hole_diameter: milsToMillimeters(\n record.holeSizeMils ?? (record.diameterMils ?? 20) * 0.45,\n ),\n layers,\n is_tented: record.tentedTop === true && record.tentedBottom === true,\n }\n}\n\nfunction convertPad(\n record: AltiumPadRecord,\n index: number,\n): PcbSmtPad | PcbPlatedHole | PcbHole | undefined {\n const position = record.position\n const size = record.size\n if (!position || !size) return undefined\n const x = milsToMillimeters(position.x)\n const y = milsToMillimeters(position.y)\n const width = milsToMillimeters(size.width)\n const height = milsToMillimeters(size.height)\n const holeDiameter = milsToMillimeters(record.holeSizeMils ?? 0)\n const shape = normalizeShape(record.shape)\n const id = `altium_${index}`\n\n if (record.plated === false && holeDiameter > 0) {\n return {\n type: \"pcb_hole\",\n pcb_hole_id: `pcb_hole_${id}`,\n hole_shape: \"circle\",\n hole_diameter: holeDiameter,\n x,\n y,\n }\n }\n\n if (record.behavior === \"through-hole\" || holeDiameter > 0) {\n const slotLengthMils = getMeasurement(record, \"SLOTLENGTH\")\n const holeWidthMils = record.holeWidthMils ?? record.holeSizeMils\n const isSlot =\n normalizeShape(record.holeType).includes(\"SLOT\") ||\n (slotLengthMils ?? 0) > (record.holeSizeMils ?? 0) ||\n (holeWidthMils ?? 0) > (record.holeSizeMils ?? 0)\n const layers: LayerRef[] = [\"top\", \"bottom\"]\n\n if (isSlot) {\n const holeWidth = milsToMillimeters(\n Math.max(\n slotLengthMils ?? holeWidthMils ?? record.holeSizeMils ?? 1,\n 1,\n ),\n )\n const holeHeight = Math.max(holeDiameter, MILS_TO_MILLIMETERS)\n if (isRectangularShape(shape)) {\n const rotated = record.holeRotation !== 0 || record.rotation !== 0\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: rotated\n ? \"rotated_pill_hole_with_rect_pad\"\n : \"pill_hole_with_rect_pad\",\n hole_shape: rotated ? \"rotated_pill\" : \"pill\",\n pad_shape: \"rect\",\n hole_width: holeWidth,\n hole_height: holeHeight,\n ...(rotated ? { hole_ccw_rotation: record.holeRotation } : {}),\n rect_pad_width: width,\n rect_pad_height: height,\n ...(rotated ? { rect_ccw_rotation: record.rotation } : {}),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n } as PcbPlatedHole\n }\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: holeWidth,\n hole_height: holeHeight,\n ccw_rotation: record.holeRotation || record.rotation,\n x,\n y,\n layers,\n }\n }\n\n if (isRectangularShape(shape)) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circular_hole_with_rect_pad\",\n hole_shape: \"circle\",\n pad_shape: \"rect\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n rect_pad_width: width,\n rect_pad_height: height,\n rect_border_radius: shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : 0,\n rect_ccw_rotation: record.rotation,\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"hole_with_polygon_pad\",\n hole_shape: \"circle\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n pad_outline: createOctagonPoints({\n x,\n y,\n width,\n height,\n rotation: record.rotation,\n }),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) >= 0.0001) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n hole_height: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n ccw_rotation: record.rotation,\n x,\n y,\n layers,\n }\n }\n }\n\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circle\",\n outer_diameter: Math.max(width, height),\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n x,\n y,\n layers,\n }\n }\n\n const layer = mapCopperLayer(record.layer)\n if (!layer) return undefined\n const base = {\n type: \"pcb_smtpad\" as const,\n pcb_smtpad_id: `pcb_smtpad_${id}`,\n x,\n y,\n layer,\n soldermask_margin:\n record.solderMaskExpansionMils === undefined\n ? undefined\n : milsToMillimeters(record.solderMaskExpansionMils),\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n ...base,\n shape: \"polygon\",\n points: createOctagonPoints({\n x,\n y,\n width,\n height,\n rotation: record.rotation,\n }),\n }\n }\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) < 0.0001) {\n return { ...base, shape: \"circle\", radius: width / 2 }\n }\n return record.rotation === 0\n ? {\n ...base,\n shape: \"pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n }\n : {\n ...base,\n shape: \"rotated_pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n ccw_rotation: record.rotation,\n }\n }\n\n const cornerRadius = shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : undefined\n return record.rotation === 0\n ? { ...base, shape: \"rect\", width, height, corner_radius: cornerRadius }\n : {\n ...base,\n shape: \"rotated_rect\",\n width,\n height,\n corner_radius: cornerRadius,\n ccw_rotation: record.rotation,\n }\n}\n\nfunction convertSilkscreenLine(\n record: AltiumTrackRecord,\n index: number,\n): PcbSilkscreenLine | undefined {\n if (!record.start || !record.end) return undefined\n return {\n type: \"pcb_silkscreen_line\",\n pcb_silkscreen_line_id: `pcb_silkscreen_line_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n ...withNumberedPoints(record.start, record.end),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenArc(\n record: AltiumArcRecord,\n index: number,\n): PcbSilkscreenPath | undefined {\n if (!record.center || !record.radiusMils) return undefined\n const points = approximateArc({\n center: record.center,\n radius: record.radiusMils,\n startAngle: record.startAngle,\n endAngle: record.endAngle,\n })\n return {\n type: \"pcb_silkscreen_path\",\n pcb_silkscreen_path_id: `pcb_silkscreen_path_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n route: points.map(toMillimeterPoint),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenFill(\n record: AltiumFillRecord,\n index: number,\n): PcbSilkscreenRect | undefined {\n if (!record.bounds) return undefined\n const width = milsToMillimeters(record.bounds.maxX - record.bounds.minX)\n const height = milsToMillimeters(record.bounds.maxY - record.bounds.minY)\n return {\n type: \"pcb_silkscreen_rect\",\n pcb_silkscreen_rect_id: `pcb_silkscreen_rect_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n center: {\n x: milsToMillimeters((record.bounds.minX + record.bounds.maxX) / 2),\n y: milsToMillimeters((record.bounds.minY + record.bounds.maxY) / 2),\n },\n width,\n height,\n stroke_width: Math.min(width, height),\n is_filled: true,\n has_stroke: false,\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenText(\n record: AltiumTextRecord,\n index: number,\n): PcbSilkscreenText | undefined {\n const text =\n decodeAltiumWideString(record.getDecoded(\"WIDESTRING\")) ||\n record.getDecoded(\"TEXT\") ||\n record.text\n if (!record.position || !text) return undefined\n return {\n type: \"pcb_silkscreen_text\",\n pcb_silkscreen_text_id: `pcb_silkscreen_text_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n text,\n font: \"tscircuit2024\",\n font_size: milsToMillimeters(record.heightMils ?? 30),\n anchor_position: toMillimeterPoint(record.position),\n anchor_alignment: mapTextAnchor(record.justification),\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n is_mirrored: record.mirrored,\n }\n}\n\nfunction decodeAltiumWideString(raw: string | undefined): string {\n if (!raw) return \"\"\n if (!/^\\d+(?:,\\d+)*$/u.test(raw)) return raw\n try {\n return String.fromCodePoint(...raw.split(\",\").map(Number))\n } catch {\n return raw\n }\n}\n\nfunction pcbComponentIdForRecord(record: AltiumRecord): string {\n const index = record.getNumber(\"COMPONENT\")\n return index === undefined || index < 0\n ? BOARD_GRAPHICS_COMPONENT_ID\n : componentId(index)\n}\n\nfunction componentId(index: number): string {\n return `pcb_component_altium_${index}`\n}\n\nfunction mapTextAnchor(\n justification: string | undefined,\n): \"bottom_left\" | \"bottom_center\" | \"bottom_right\" | \"center\" {\n const normalized = justification?.replace(/[\\s_-]+/gu, \"\").toUpperCase()\n if (normalized?.includes(\"CENTER\")) return \"bottom_center\"\n if (normalized?.includes(\"RIGHT\")) return \"bottom_right\"\n if (normalized?.includes(\"LEFT\")) return \"bottom_left\"\n return \"center\"\n}\n\nfunction mapCopperLayer(layer: string | undefined): LayerRef | undefined {\n const normalized = normalizeLayer(layer)\n if (normalized === \"TOP\" || normalized === \"TOPLAYER\") return \"top\"\n if (normalized === \"BOTTOM\" || normalized === \"BOTTOMLAYER\") return \"bottom\"\n const innerMatch = /^(?:MID|MIDLAYER|INTERNALPLANE)(\\d+)$/u.exec(normalized)\n if (!innerMatch?.[1]) return undefined\n const innerNumber = Math.min(Math.max(Number(innerMatch[1]), 1), 8)\n return `inner${innerNumber}` as LayerRef\n}\n\nfunction isOverlayLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"TOPOVERLAY\" || normalized === \"BOTTOMOVERLAY\"\n}\n\nfunction isCourtyardLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"MECHANICAL15\" || normalized === \"MECHANICAL16\"\n}\n\nfunction mapCourtyardLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"MECHANICAL16\" ? \"bottom\" : \"top\"\n}\n\nfunction mapOverlayLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"BOTTOMOVERLAY\" ? \"bottom\" : \"top\"\n}\n\nfunction getLayer(record: AltiumRecord): string | undefined {\n return record.getDecoded(\"LAYER\")\n}\n\nfunction normalizeLayer(layer: string | undefined): string {\n return (layer ?? \"\").replace(/[\\s_.-]+/gu, \"\").toUpperCase()\n}\n\nfunction normalizeShape(shape: string | undefined): string {\n return (shape ?? \"ROUND\").replace(/[\\s_-]+/gu, \"\").toUpperCase()\n}\n\nfunction isRectangularShape(shape: string): boolean {\n return shape.includes(\"RECT\") || shape === \"SQUARE\"\n}\n\nfunction getMeasurement(record: AltiumRecord, key: string): number | undefined {\n return parseAltiumMeasurementToMils(record.getCaseInsensitive(key))\n}\n\nfunction milsToMillimeters(value: number): number {\n return value * MILS_TO_MILLIMETERS\n}\n\nfunction toMillimeterPoint(point: AltiumPoint): { x: number; y: number } {\n return { x: milsToMillimeters(point.x), y: milsToMillimeters(point.y) }\n}\n\nfunction withNumberedPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n): { x1: number; x2: number; y1: number; y2: number } {\n return {\n x1: milsToMillimeters(start.x),\n y1: milsToMillimeters(start.y),\n x2: milsToMillimeters(end.x),\n y2: milsToMillimeters(end.y),\n }\n}\n\nfunction approximateArc({\n center,\n radius,\n startAngle,\n endAngle,\n}: {\n center: AltiumPoint\n radius: number\n startAngle: number\n endAngle: number\n}): AltiumPoint[] {\n const sweep = endAngle - startAngle || 360\n const segments = Math.max(8, Math.ceil(Math.abs(sweep) / 7.5))\n return Array.from({ length: segments + 1 }, (_, index) => {\n const angle = startAngle + (sweep * index) / segments\n const radians = (angle * Math.PI) / 180\n return {\n x: center.x + Math.cos(radians) * radius,\n y: center.y + Math.sin(radians) * radius,\n }\n })\n}\n\nfunction createOctagonPoints({\n x,\n y,\n width,\n height,\n rotation,\n}: {\n x: number\n y: number\n width: number\n height: number\n rotation: number\n}): Array<{ x: number; y: number }> {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const chamfer = Math.min(width, height) / 4\n const points = [\n { x: -halfWidth + chamfer, y: -halfHeight },\n { x: halfWidth - chamfer, y: -halfHeight },\n { x: halfWidth, y: -halfHeight + chamfer },\n { x: halfWidth, y: halfHeight - chamfer },\n { x: halfWidth - chamfer, y: halfHeight },\n { x: -halfWidth + chamfer, y: halfHeight },\n { x: -halfWidth, y: halfHeight - chamfer },\n { x: -halfWidth, y: -halfHeight + chamfer },\n ]\n const radians = (rotation * Math.PI) / 180\n return points.map((point) => ({\n x: x + point.x * Math.cos(radians) - point.y * Math.sin(radians),\n y: y + point.x * Math.sin(radians) + point.y * Math.cos(radians),\n }))\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicDocumentIndex,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport {\n type AnyCircuitElement,\n type SchematicComponent,\n type SchematicNetLabel,\n type SchematicPort,\n type SchematicText,\n type SchematicTrace,\n type SourceComponentBase,\n type SourceNet,\n type SourcePort,\n type SourceTrace,\n source_simple_capacitor,\n source_simple_crystal,\n source_simple_inductor,\n source_simple_mosfet,\n source_simple_resistor,\n} from \"circuit-json\"\nimport { parseAndConvertSiUnit } from \"format-si-unit\"\nimport { type SchSymbol, symbols } from \"schematic-symbols\"\nimport {\n type Bounds,\n type CardinalDirection,\n getAveragePoint,\n getBoundsCenter,\n getBoundsForPoints,\n getCorner,\n getDirectionForVector,\n getLocation,\n getPointDistance,\n getRectangle,\n getVectorDifference,\n mergeBounds,\n pointKey,\n pointsEqual,\n scalePoint,\n subtractPoints,\n} from \"./geometry\"\nimport {\n isGroundNet,\n isPowerNet,\n sanitizeId,\n segmentKey,\n uniqueStrings,\n} from \"./ids\"\nimport {\n classifyComponent,\n getMosfetVariant,\n getPrimaryComponentValue,\n isPolarizedCapacitor,\n} from \"./symbols\"\n\nexport interface SemanticSchematicOptions {\n includeHidden?: boolean\n includeText?: boolean\n scale: number\n schematicSheetId: string\n}\n\nexport interface SemanticSchematicConversion {\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n}\n\ninterface ConvertedPort {\n isSchematicVisible: boolean\n point: AltiumPoint\n record: AltiumRecord\n schematicPort: SchematicPort\n sourcePort: SourcePort\n}\n\ninterface SymbolPortAssignment {\n convertedPort: ConvertedPort\n symbolPort: SchSymbol[\"ports\"][number]\n}\n\ninterface SymbolSelection {\n assignments: SymbolPortAssignment[]\n name: string\n symbol: SchSymbol\n}\n\ninterface SemanticNet {\n id: string\n names: string[]\n points: AltiumPoint[]\n records: AltiumRecord[]\n}\n\ninterface SemanticNetGraph {\n getConnectedWiresForRecord(record: AltiumRecord): AltiumRecord[]\n nets: SemanticNet[]\n}\n\ninterface SchematicSegment {\n end: AltiumPoint\n start: AltiumPoint\n}\n\nconst DIRECTION_BY_ORIENTATION: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst VECTOR_BY_DIRECTION: Readonly<Record<CardinalDirection, AltiumPoint>> = {\n down: { x: 0, y: -1 },\n left: { x: -1, y: 0 },\n right: { x: 1, y: 0 },\n up: { x: 0, y: 1 },\n}\n\nconst CARDINAL_DIRECTIONS: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst SYMBOL_CATALOG = symbols as Record<string, SchSymbol | undefined>\nconst SYMBOL_NAMES = Object.keys(SYMBOL_CATALOG)\nconst INLINE_NET_LABEL_COLOR = \"rgb(132, 0, 0)\"\nconst DEFAULT_INLINE_NET_LABEL_FONT_SIZE = 0.18\nconst MIN_INLINE_NET_LABEL_FONT_SIZE = 0.1\nconst INLINE_NET_LABEL_CHARACTER_WIDTH = 0.12\nconst INLINE_NET_LABEL_HORIZONTAL_PADDING = 0.12\n\n/**\n * Converts records that have native Circuit JSON semantics before the\n * primitive fallback runs. This deliberately favors Circuit JSON's component,\n * port, trace, net, and symbol model over reproducing Altium's drawing style.\n */\nexport function convertSemanticSchematic(\n document: AltiumSchDoc,\n options: SemanticSchematicOptions,\n): SemanticSchematicConversion {\n const handledRecords = new Set<AltiumRecord>()\n const elements: AnyCircuitElement[] = []\n const convertedPorts: ConvertedPort[] = []\n\n convertComponents({\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n })\n\n const semanticNetGraph = buildSemanticNetGraph(document, convertedPorts)\n\n const connectivity = convertConnectivity({\n convertedPorts,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n convertNetLabels({\n connectivity,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n return { elements, handledRecords }\n}\n\nfunction convertComponents(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n}): void {\n const { convertedPorts, document, elements, handledRecords, options } = params\n const documentIndex = getSchematicDocumentIndex(document)\n const sourceComponentIdByDesignator = new Map<string, string>()\n\n for (const [componentIndex, componentRecord] of document.records.entries()) {\n if (componentRecord.recordKind !== \"1\") continue\n handledRecords.add(componentRecord)\n\n const ownedRecords = documentIndex.getOwnedRecords(componentRecord)\n for (const ownedRecord of ownedRecords) handledRecords.add(ownedRecord)\n\n const currentPartId = componentRecord.getNumber(\"CURRENTPARTID\") ?? 1\n const visibleOwnedRecords = ownedRecords.filter((record) =>\n isOwnedRecordVisible(record, currentPartId),\n )\n const pins = visibleOwnedRecords.filter(\n (record) =>\n record.recordKind === \"2\" &&\n (!isPinHidden(record) || options.includeHidden === true),\n )\n if (pins.length === 0) continue\n const visibleSymbolLabels = new Set(\n visibleOwnedRecords\n .filter((record) => record.recordKind === \"4\")\n .flatMap((record) => {\n const text = record.getDecoded(\"TEXT\")?.trim().toUpperCase()\n return text ? [text] : []\n }),\n )\n\n const designator =\n findOwnedText(ownedRecords, \"34\", \"Designator\") ??\n componentRecord.getDecoded(\"DESIGNATOR\") ??\n `U${componentIndex}`\n // Altium libraries commonly store the human-readable component value in\n // the named `Value` parameter, while `Comment` may contain a manufacturer\n // part number (or another library-specific description). Prefer the\n // explicit value field and retain the older fallbacks for simpler files.\n const value =\n findOwnedText(ownedRecords, \"41\", \"Value\")?.trim() ||\n findOwnedText(ownedRecords, \"41\", \"Comment\")?.trim() ||\n componentRecord.getDecoded(\"COMMENT\")?.trim() ||\n componentRecord.getDecoded(\"DESIGNITEMID\")?.trim() ||\n componentRecord.getDecoded(\"LIBREFERENCE\")?.trim() ||\n \"\"\n const libraryReference =\n componentRecord.getDecoded(\"LIBREFERENCE\") ??\n componentRecord.getDecoded(\"DESIGNITEMID\") ??\n designator\n const manufacturerPartNumber = findOwnedText(\n ownedRecords,\n \"41\",\n \"Mfr_part_number\",\n )\n const normalizedDesignator = designator.trim().toUpperCase()\n const existingSourceComponentId =\n sourceComponentIdByDesignator.get(normalizedDesignator)\n const sourceComponentId =\n existingSourceComponentId ?? `source_component_altium_${componentIndex}`\n const schematicComponentId = `schematic_component_altium_${componentIndex}`\n if (!existingSourceComponentId) {\n sourceComponentIdByDesignator.set(normalizedDesignator, sourceComponentId)\n elements.push(\n createSourceComponent({\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount: pins.length,\n sourceComponentId,\n value,\n }),\n )\n }\n\n const componentPorts = pins.map((pin, pinIndex) =>\n convertComponentPin({\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n visibleSymbolLabels,\n }),\n )\n const bodyBounds = getComponentBodyBounds(\n visibleOwnedRecords,\n componentPorts.map(({ point }) => point),\n )\n const symbolSelection = selectCircuitJsonSymbol({\n designator,\n libraryReference,\n ports: componentPorts,\n })\n const center = scalePoint(getBoundsCenter(bodyBounds), options.scale)\n const size = symbolSelection\n ? { ...symbolSelection.symbol.size }\n : {\n height: Math.max(\n (bodyBounds.maxY - bodyBounds.minY) * options.scale,\n 0.4,\n ),\n width: Math.max(\n (bodyBounds.maxX - bodyBounds.minX) * options.scale,\n 0.4,\n ),\n }\n if (symbolSelection) {\n applyNativeSymbolPortGeometry({\n center,\n selection: symbolSelection,\n })\n }\n convertedPorts.push(...componentPorts)\n elements.push(\n ...componentPorts.flatMap(\n ({ isSchematicVisible, sourcePort, schematicPort }) => [\n sourcePort,\n ...(isSchematicVisible ? [schematicPort] : []),\n ],\n ),\n )\n const schematicComponent: SchematicComponent = {\n type: \"schematic_component\",\n center,\n // circuit-to-svg uses this flag as the renderable component gate for\n // both generated boxes and components selected by symbol_name.\n is_box_with_pins: true,\n schematic_component_id: schematicComponentId,\n schematic_sheet_id: options.schematicSheetId,\n size,\n source_component_id: sourceComponentId,\n symbol_display_value: value,\n ...(symbolSelection ? { symbol_name: symbolSelection.name } : {}),\n }\n elements.push(schematicComponent)\n\n if (!symbolSelection && options.includeText !== false) {\n elements.push(\n createComponentText({\n anchor: \"bottom_left\",\n component: schematicComponent,\n id: `schematic_component_designator_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y + size.height / 2 + 0.13,\n },\n text: designator,\n }),\n )\n if (value) {\n elements.push(\n createComponentText({\n anchor: \"top_left\",\n component: schematicComponent,\n id: `schematic_component_value_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y - size.height / 2 - 0.13,\n },\n text: value,\n }),\n )\n }\n }\n }\n}\n\nfunction convertComponentPin(params: {\n document: AltiumSchDoc\n options: SemanticSchematicOptions\n pin: AltiumRecord\n pinIndex: number\n schematicComponentId: string\n sourceComponentId: string\n visibleSymbolLabels: Set<string>\n}): ConvertedPort {\n const {\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n visibleSymbolLabels,\n } = params\n const recordIndex = document.records.indexOf(pin)\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n const orientation = (pinConglomerate ?? pin.getNumber(\"ORIENTATION\") ?? 0) & 3\n const direction = DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n const directionVector = VECTOR_BY_DIRECTION[direction]\n const location = getLocation(pin) ?? { x: 0, y: 0 }\n const pinLength = Math.max(pin.getNumber(\"PINLENGTH\") ?? 10, 0)\n const terminalPoint = {\n x: location.x + directionVector.x * pinLength,\n y: location.y + directionVector.y * pinLength,\n }\n const designator = pin.getDecoded(\"DESIGNATOR\") ?? `${pinIndex + 1}`\n const pinNumber = parsePinNumber(designator)\n const name = pin.getDecoded(\"NAME\") ?? designator\n const sourcePortId = `source_port_altium_${recordIndex}`\n const schematicPortId = `schematic_port_altium_${recordIndex}`\n const sourcePort: SourcePort = {\n type: \"source_port\",\n name,\n port_hints: uniqueStrings([\n designator,\n name,\n pinNumber === undefined ? undefined : `pin${pinNumber}`,\n ]),\n source_component_id: sourceComponentId,\n source_port_id: sourcePortId,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n }\n const electricalType = pin.getNumber(\"ELECTRICAL\")\n const normalizedName = name.trim().toUpperCase()\n const functionalName = normalizedName.replace(/\\d+$/u, \"\")\n const showName =\n pinConglomerate === undefined ||\n (pinConglomerate & 0x08) !== 0 ||\n visibleSymbolLabels.has(normalizedName) ||\n visibleSymbolLabels.has(functionalName)\n const schematicPort: SchematicPort = {\n type: \"schematic_port\",\n center: scalePoint(terminalPoint, options.scale),\n ...(showName && name ? { display_pin_label: name } : {}),\n distance_from_component_edge: pinLength * options.scale,\n facing_direction: direction,\n is_connected: false,\n schematic_component_id: schematicComponentId,\n schematic_port_id: schematicPortId,\n schematic_sheet_id: options.schematicSheetId,\n side_of_component: directionToSide(direction),\n source_port_id: sourcePortId,\n true_ccw_index: pinIndex,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n ...(electricalType === 0 || electricalType === 1\n ? { has_input_arrow: true }\n : {}),\n ...(electricalType === 1 || electricalType === 2\n ? { has_output_arrow: true }\n : {}),\n }\n return {\n isSchematicVisible: true,\n point: terminalPoint,\n record: pin,\n schematicPort,\n sourcePort,\n }\n}\n\nfunction createSourceComponent(params: {\n designator: string\n libraryReference: string\n manufacturerPartNumber?: string\n pinCount: number\n sourceComponentId: string\n value: string\n}): AnyCircuitElement {\n const {\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount,\n sourceComponentId,\n value,\n } = params\n const classification = classifyComponent({ designator, libraryReference })\n const primaryValue = getPrimaryComponentValue(value)\n const common = {\n type: \"source_component\" as const,\n display_name: designator,\n display_value: value || undefined,\n manufacturer_part_number: manufacturerPartNumber,\n name: designator,\n source_component_id: sourceComponentId,\n }\n\n if (classification === \"resistor\") {\n const parsed = source_simple_resistor.safeParse({\n ...common,\n display_resistance: value || undefined,\n ftype: \"simple_resistor\",\n resistance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"capacitor\") {\n const parsed = source_simple_capacitor.safeParse({\n ...common,\n display_capacitance: value || undefined,\n ftype: \"simple_capacitor\",\n capacitance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"inductor\") {\n const parsed = source_simple_inductor.safeParse({\n ...common,\n display_inductance: value || undefined,\n ftype: \"simple_inductor\",\n inductance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"crystal\" && (pinCount === 2 || pinCount === 4)) {\n const frequency = parseAndConvertSiUnit(value, \"Hz\").value\n if (typeof frequency === \"number\" && Number.isFinite(frequency)) {\n const parsed = source_simple_crystal.safeParse({\n ...common,\n frequency,\n ftype: \"simple_crystal\",\n pin_variant: pinCount === 4 ? \"four_pin\" : \"two_pin\",\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"mosfet\" && pinCount >= 3) {\n const parsed = source_simple_mosfet.safeParse({\n ...common,\n ...getMosfetVariant(libraryReference),\n ftype: \"simple_mosfet\",\n })\n if (parsed.success) return parsed.data\n }\n\n const ftype:\n | \"simple_chip\"\n | \"simple_diode\"\n | \"simple_led\"\n | \"simple_test_point\" =\n classification === \"diode\"\n ? \"simple_diode\"\n : classification === \"led\"\n ? \"simple_led\"\n : classification === \"testpoint\"\n ? \"simple_test_point\"\n : \"simple_chip\"\n return {\n ...common,\n ftype,\n } satisfies SourceComponentBase\n}\n\nfunction createComponentText(params: {\n anchor: SchematicText[\"anchor\"]\n component: SchematicComponent\n id: string\n position: AltiumPoint\n text: string\n}): SchematicText {\n const { anchor, component, id, position, text } = params\n return {\n type: \"schematic_text\",\n anchor,\n color: \"#006464\",\n font_size: 0.18,\n position,\n rotation: 0,\n schematic_component_id: component.schematic_component_id,\n schematic_sheet_id: component.schematic_sheet_id,\n schematic_text_id: id,\n text,\n }\n}\n\n/**\n * Altium permits labels and pin hot spots to land anywhere on a wire segment,\n * not only on declared polyline vertices. Build the electrical graph with\n * those geometric joins so Circuit JSON source traces carry the real ports and\n * net names. Mid-segment crossings remain disconnected unless one wire has a\n * vertex there or Altium emits an explicit junction record.\n */\nfunction buildSemanticNetGraph(\n document: AltiumSchDoc,\n convertedPorts: ConvertedPort[],\n): SemanticNetGraph {\n const disjointSet = new PointDisjointSet()\n const pointValues = new Map<string, AltiumPoint>()\n const wireRecords = document.records.filter(\n (record) => record.recordKind === \"27\",\n )\n const segments: SchematicSegment[] = []\n\n for (const wire of wireRecords) {\n const points = getSchematicRecordPoints(wire)\n for (const point of points) {\n addGraphPoint(disjointSet, pointValues, point)\n }\n for (let index = 1; index < points.length; index++) {\n const start = points[index - 1]\n const end = points[index]\n if (!start || !end) continue\n disjointSet.union(pointKey(start), pointKey(end))\n segments.push({ end, start })\n }\n }\n\n const positionedRecords = document.records.flatMap((record) => {\n if (![\"4\", \"17\", \"18\", \"25\", \"29\"].includes(record.recordKind ?? \"\")) {\n return []\n }\n const point =\n record.recordKind === \"18\"\n ? getPortConnectionGeometry(record, segments)?.anchor\n : getLocation(record)\n return point ? [{ point, record }] : []\n })\n const positionedPins = convertedPorts.map(({ point, record }) => ({\n point,\n record,\n }))\n const joinPoints = [\n ...new Map(\n wireRecords\n .flatMap((wire) => getSchematicRecordPoints(wire))\n .map((point) => [pointKey(point), point]),\n ).values(),\n ...positionedRecords.map(({ point }) => point),\n ...positionedPins.map(({ point }) => point),\n ]\n\n for (const point of joinPoints) {\n addGraphPoint(disjointSet, pointValues, point)\n for (const segment of segments) {\n if (isPointOnSegment(point, segment.start, segment.end)) {\n disjointSet.union(pointKey(point), pointKey(segment.start))\n }\n }\n }\n\n interface MutableSemanticNet {\n id: string\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n }\n const groupedByRoot = new Map<string, MutableSemanticNet>()\n const getGroup = (point: AltiumPoint): MutableSemanticNet => {\n const root = disjointSet.find(pointKey(point))\n const existing = groupedByRoot.get(root)\n if (existing) return existing\n const created: MutableSemanticNet = {\n id: root,\n names: new Set(),\n points: new Map(),\n records: new Set(),\n }\n groupedByRoot.set(root, created)\n return created\n }\n\n for (const point of pointValues.values()) {\n getGroup(point).points.set(pointKey(point), point)\n }\n for (const wire of wireRecords) {\n const firstPoint = getSchematicRecordPoints(wire)[0]\n if (firstPoint) getGroup(firstPoint).records.add(wire)\n }\n for (const { point, record } of [...positionedRecords, ...positionedPins]) {\n const group = getGroup(point)\n group.records.add(record)\n const name = getElectricalRecordName(record)\n if (name) group.names.add(name)\n }\n\n const connectedWiresByRecord = new Map<AltiumRecord, AltiumRecord[]>()\n for (const group of groupedByRoot.values()) {\n const wires = [...group.records].filter(\n (record) => record.recordKind === \"27\",\n )\n for (const record of group.records) {\n connectedWiresByRecord.set(record, wires)\n }\n }\n\n const mergedGroups: MutableSemanticNet[] = []\n for (const group of groupedByRoot.values()) {\n if (group.records.size === 0) continue\n const normalizedNames = new Set(\n [...group.names].map((name) => name.trim().toUpperCase()),\n )\n const matches = mergedGroups.filter((candidate) =>\n [...candidate.names].some((name) =>\n normalizedNames.has(name.trim().toUpperCase()),\n ),\n )\n if (matches.length === 0 || normalizedNames.size === 0) {\n mergedGroups.push(group)\n continue\n }\n const target = matches[0]\n if (!target) continue\n mergeSemanticNetGroup(target, group)\n for (const duplicate of matches.slice(1)) {\n mergeSemanticNetGroup(target, duplicate)\n const duplicateIndex = mergedGroups.indexOf(duplicate)\n if (duplicateIndex >= 0) mergedGroups.splice(duplicateIndex, 1)\n }\n }\n\n const nets: SemanticNet[] = mergedGroups.map((group) => ({\n id: group.id,\n names: [...group.names],\n points: [...group.points.values()],\n records: [...group.records],\n }))\n return {\n getConnectedWiresForRecord: (record) =>\n connectedWiresByRecord.get(record) ?? [],\n nets,\n }\n}\n\nfunction addGraphPoint(\n disjointSet: PointDisjointSet,\n pointValues: Map<string, AltiumPoint>,\n point: AltiumPoint,\n): void {\n const key = pointKey(point)\n disjointSet.add(key)\n pointValues.set(key, point)\n}\n\nfunction getElectricalRecordName(record: AltiumRecord): string | undefined {\n if (record.recordKind === \"18\") return record.getDecoded(\"NAME\")\n if ([\"4\", \"17\", \"25\"].includes(record.recordKind ?? \"\")) {\n return record.getDecoded(\"TEXT\")\n }\n return undefined\n}\n\nfunction mergeSemanticNetGroup(\n target: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n source: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n): void {\n for (const name of source.names) target.names.add(name)\n for (const [key, point] of source.points) target.points.set(key, point)\n for (const record of source.records) target.records.add(record)\n}\n\nfunction isPointOnSegment(\n point: AltiumPoint,\n start: AltiumPoint,\n end: AltiumPoint,\n): boolean {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const cross = (point.x - start.x) * dy - (point.y - start.y) * dx\n const tolerance = 0.000001 * Math.max(Math.abs(dx), Math.abs(dy), 1)\n if (Math.abs(cross) > tolerance) return false\n const dot = (point.x - start.x) * dx + (point.y - start.y) * dy\n if (dot < -tolerance) return false\n const lengthSquared = dx * dx + dy * dy\n return dot <= lengthSquared + tolerance\n}\n\nfunction splitSegmentAtPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n candidates: AltiumPoint[],\n): AltiumPoint[] {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const lengthSquared = dx * dx + dy * dy\n if (lengthSquared === 0) return [start]\n\n const pointsByKey = new Map<string, AltiumPoint>([\n [pointKey(start), start],\n [pointKey(end), end],\n ])\n for (const candidate of candidates) {\n if (isPointOnSegment(candidate, start, end)) {\n pointsByKey.set(pointKey(candidate), candidate)\n }\n }\n return [...pointsByKey.values()].sort((left, right) => {\n const leftDistance = (left.x - start.x) * dx + (left.y - start.y) * dy\n const rightDistance = (right.x - start.x) * dx + (right.y - start.y) * dy\n return leftDistance - rightDistance\n })\n}\n\nclass PointDisjointSet {\n private readonly parent = new Map<string, string>()\n\n add(value: string): void {\n if (!this.parent.has(value)) this.parent.set(value, value)\n }\n\n find(value: string): string {\n this.add(value)\n const parent = this.parent.get(value) ?? value\n if (parent === value) return value\n const root = this.find(parent)\n this.parent.set(value, root)\n return root\n }\n\n union(left: string, right: string): void {\n const leftRoot = this.find(left)\n const rightRoot = this.find(right)\n if (leftRoot !== rightRoot) this.parent.set(rightRoot, leftRoot)\n }\n}\n\ninterface ConnectivityConversion {\n sourceNetIdByRecord: Map<AltiumRecord, string>\n sourceNetIdByName: Map<string, string>\n sourcePortCountByRecord: Map<AltiumRecord, number>\n sourceTraceIdByRecord: Map<AltiumRecord, string>\n schematicTraceIdByRecord: Map<AltiumRecord, string>\n}\n\nfunction convertConnectivity(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): ConnectivityConversion {\n const {\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n const sourceNetIdByName = new Map<string, string>()\n const sourceNetIdByRecord = new Map<AltiumRecord, string>()\n const sourcePortCountByRecord = new Map<AltiumRecord, number>()\n const sourceTraceIdByRecord = new Map<AltiumRecord, string>()\n const schematicTraceIdByRecord = new Map<AltiumRecord, string>()\n const portsByPoint = groupByPoint(convertedPorts)\n\n for (const [netIndex, net] of graph.nets.entries()) {\n const wires = net.records.filter((record) => record.recordKind === \"27\")\n const connectedConvertedPorts = uniqueConvertedPorts(\n net.points.flatMap((point) => portsByPoint.get(pointKey(point)) ?? []),\n )\n const connectedPorts = connectedConvertedPorts.map(\n ({ sourcePort }) => sourcePort.source_port_id,\n )\n if (\n wires.length === 0 &&\n !(\n (net.names.length > 0 && connectedPorts.length > 0) ||\n connectedPorts.length > 1\n )\n ) {\n continue\n }\n const sourceNetIds = net.names.map((name) =>\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName,\n }),\n )\n for (const record of net.records) {\n const firstSourceNetId = sourceNetIds[0]\n if (firstSourceNetId) sourceNetIdByRecord.set(record, firstSourceNetId)\n }\n\n const sourceTraceId = `source_trace_altium_${netIndex}`\n for (const record of net.records) {\n sourcePortCountByRecord.set(record, connectedPorts.length)\n sourceTraceIdByRecord.set(record, sourceTraceId)\n }\n const sourceTrace: SourceTrace = {\n type: \"source_trace\",\n connected_source_net_ids: sourceNetIds,\n connected_source_port_ids: connectedPorts,\n display_name: net.names[0],\n name: net.names[0],\n source_trace_id: sourceTraceId,\n }\n elements.push(sourceTrace)\n\n const netJunctions = document.records\n .filter(\n (record) =>\n record.recordKind === \"29\" &&\n net.points.some((point) => pointsEqual(point, getLocation(record))),\n )\n .flatMap((record) => {\n handledRecords.add(record)\n const location = getLocation(record)\n return location ? [scalePoint(location, options.scale)] : []\n })\n\n for (const wire of wires) handledRecords.add(wire)\n const prunedSegmentKeys = getEquivalentPortPrunedSegmentKeys({\n convertedPorts: connectedConvertedPorts,\n net,\n wires,\n })\n let renderedWireIndex = 0\n for (const wire of wires) {\n const wireRecordIndex = document.records.indexOf(wire)\n const schematicTraceId = `schematic_trace_altium_${wireRecordIndex}`\n const points = getSchematicRecordPoints(wire)\n const edges: SchematicTrace[\"edges\"] = []\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const from = points[pointIndex - 1]\n const to = points[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let segmentPointIndex = 1;\n segmentPointIndex < segmentPoints.length;\n segmentPointIndex++\n ) {\n const segmentFrom = segmentPoints[segmentPointIndex - 1]\n const segmentTo = segmentPoints[segmentPointIndex]\n if (!segmentFrom || !segmentTo) continue\n if (prunedSegmentKeys.has(segmentKey(segmentFrom, segmentTo))) {\n continue\n }\n const fromPort = portsByPoint\n .get(pointKey(segmentFrom))\n ?.find((port) => port.isSchematicVisible)\n const toPort = portsByPoint\n .get(pointKey(segmentTo))\n ?.find((port) => port.isSchematicVisible)\n const fromPortId = getPortIdAtElectricalPoint(\n fromPort,\n segmentFrom,\n options.scale,\n )\n const toPortId = getPortIdAtElectricalPoint(\n toPort,\n segmentTo,\n options.scale,\n )\n edges.push({\n from: scalePoint(segmentFrom, options.scale),\n to: scalePoint(segmentTo, options.scale),\n ...(fromPortId ? { from_schematic_port_id: fromPortId } : {}),\n ...(toPortId ? { to_schematic_port_id: toPortId } : {}),\n })\n }\n }\n if (edges.length === 0) continue\n schematicTraceIdByRecord.set(wire, schematicTraceId)\n elements.push({\n type: \"schematic_trace\",\n edges,\n junctions: renderedWireIndex === 0 ? netJunctions : [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: schematicTraceId,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n renderedWireIndex++\n }\n\n for (const convertedPort of connectedConvertedPorts) {\n if (!convertedPort.isSchematicVisible) continue\n const electricalTerminal = scalePoint(convertedPort.point, options.scale)\n if (pointsEqual(convertedPort.schematicPort.center, electricalTerminal)) {\n continue\n }\n const portRecordIndex = document.records.indexOf(convertedPort.record)\n elements.push({\n type: \"schematic_trace\",\n edges: createPortLeadEdges(convertedPort, electricalTerminal),\n junctions: [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: `schematic_trace_altium_port_lead_${portRecordIndex}`,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n }\n\n const connectedPortIds = new Set(connectedPorts)\n for (const convertedPort of convertedPorts) {\n if (\n convertedPort.isSchematicVisible &&\n connectedPortIds.has(convertedPort.sourcePort.source_port_id)\n ) {\n convertedPort.schematicPort.is_connected = true\n }\n }\n }\n\n return {\n schematicTraceIdByRecord,\n sourceNetIdByName,\n sourceNetIdByRecord,\n sourcePortCountByRecord,\n sourceTraceIdByRecord,\n }\n}\n\nfunction getEquivalentPortPrunedSegmentKeys(params: {\n convertedPorts: ConvertedPort[]\n net: SemanticNet\n wires: AltiumRecord[]\n}): Set<string> {\n const { convertedPorts, net, wires } = params\n const hiddenPortPoints = convertedPorts\n .filter((port) => !port.isSchematicVisible)\n .map((port) => port.point)\n if (hiddenPortPoints.length === 0) return new Set()\n\n const wireSegments = getWireSegments(wires)\n const protectedPointKeys = new Set(\n convertedPorts\n .filter((port) => port.isSchematicVisible)\n .map((port) => pointKey(port.point)),\n )\n for (const record of net.records) {\n if (![\"4\", \"17\", \"18\", \"25\"].includes(record.recordKind ?? \"\")) continue\n const location =\n record.recordKind === \"18\"\n ? getPortConnectionGeometry(record, wireSegments)?.anchor\n : getLocation(record)\n if (location) protectedPointKeys.add(pointKey(location))\n }\n\n interface PrunableSegment {\n endKey: string\n key: string\n startKey: string\n }\n const segments = new Map<string, PrunableSegment>()\n const segmentKeysByPoint = new Map<string, Set<string>>()\n const addIncidentSegment = (point: AltiumPoint, key: string): void => {\n const pointSegments = segmentKeysByPoint.get(pointKey(point))\n if (pointSegments) pointSegments.add(key)\n else segmentKeysByPoint.set(pointKey(point), new Set([key]))\n }\n\n for (const wire of wires) {\n const wirePoints = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < wirePoints.length; pointIndex++) {\n const from = wirePoints[pointIndex - 1]\n const to = wirePoints[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let splitIndex = 1;\n splitIndex < segmentPoints.length;\n splitIndex++\n ) {\n const segmentFrom = segmentPoints[splitIndex - 1]\n const segmentTo = segmentPoints[splitIndex]\n if (!segmentFrom || !segmentTo) continue\n const key = segmentKey(segmentFrom, segmentTo)\n segments.set(key, {\n endKey: pointKey(segmentTo),\n key,\n startKey: pointKey(segmentFrom),\n })\n addIncidentSegment(segmentFrom, key)\n addIncidentSegment(segmentTo, key)\n }\n }\n }\n\n const removedSegmentKeys = new Set<string>()\n const pendingPointKeys = hiddenPortPoints.map((point) => pointKey(point))\n while (pendingPointKeys.length > 0) {\n const currentPointKey = pendingPointKeys.shift()\n if (!currentPointKey || protectedPointKeys.has(currentPointKey)) continue\n const activeSegmentKeys = [\n ...(segmentKeysByPoint.get(currentPointKey) ?? []),\n ].filter((key) => !removedSegmentKeys.has(key))\n if (activeSegmentKeys.length !== 1) continue\n const segment = segments.get(activeSegmentKeys[0] ?? \"\")\n if (!segment) continue\n removedSegmentKeys.add(segment.key)\n pendingPointKeys.push(\n segment.startKey === currentPointKey ? segment.endKey : segment.startKey,\n )\n }\n return removedSegmentKeys\n}\n\nfunction createPortLeadEdges(\n convertedPort: ConvertedPort,\n electricalTerminal: AltiumPoint,\n): SchematicTrace[\"edges\"] {\n const portCenter = convertedPort.schematicPort.center\n const facingDirection =\n convertedPort.schematicPort.facing_direction ?? \"right\"\n const elbow =\n facingDirection === \"left\" || facingDirection === \"right\"\n ? { x: electricalTerminal.x, y: portCenter.y }\n : { x: portCenter.x, y: electricalTerminal.y }\n const points = [portCenter, elbow, electricalTerminal].filter(\n (point, index, allPoints) =>\n index === 0 || !pointsEqual(point, allPoints[index - 1]),\n )\n\n return points.slice(1).flatMap((to, index) => {\n const from = points[index]\n if (!from) return []\n return [\n {\n from,\n ...(index === 0\n ? {\n from_schematic_port_id:\n convertedPort.schematicPort.schematic_port_id,\n }\n : {}),\n to,\n },\n ]\n })\n}\n\nfunction convertNetLabels(params: {\n connectivity: ConnectivityConversion\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): void {\n const {\n connectivity,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n const allWireSegments = getWireSegments(\n document.records.filter((record) => record.recordKind === \"27\"),\n )\n\n for (const [recordIndex, record] of document.records.entries()) {\n const recordKind = record.recordKind\n if (!recordKind || ![\"4\", \"17\", \"18\", \"25\"].includes(recordKind)) {\n continue\n }\n if (record.getBoolean(\"ISHIDDEN\") && options.includeHidden !== true) {\n handledRecords.add(record)\n continue\n }\n const name =\n record.recordKind === \"18\"\n ? record.getDecoded(\"NAME\")\n : record.getDecoded(\"TEXT\")\n const portConnection =\n recordKind === \"18\"\n ? getPortConnectionGeometry(record, allWireSegments)\n : undefined\n const location = portConnection?.anchor ?? getLocation(record)\n if (!name || !location) continue\n const connectedWires = graph.getConnectedWiresForRecord(record)\n const wire = connectedWires[0]\n // Altium's generic label record is also used for page titles and notes.\n // It is only an electrical net label when it touches a wire.\n if (recordKind === \"4\" && !wire) continue\n const sourceTraceId = connectivity.sourceTraceIdByRecord.get(record)\n const shouldRenderInline =\n Boolean(sourceTraceId) &&\n (recordKind === \"25\" ||\n (recordKind === \"18\" &&\n (record.getNumber(\"IOTYPE\") ?? 0) === 0 &&\n connectivity.sourcePortCountByRecord.get(record) === 2 &&\n !isPowerNet(name)))\n if (shouldRenderInline && sourceTraceId) {\n handledRecords.add(record)\n elements.push(\n createInlineNetLabelText({\n connectedWires,\n document,\n location,\n name,\n options,\n record,\n recordIndex,\n sourceTraceId,\n }),\n )\n continue\n }\n handledRecords.add(record)\n\n const sourceNetId =\n connectivity.sourceNetIdByRecord.get(record) ??\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName: connectivity.sourceNetIdByName,\n })\n const schematicTraceId = wire\n ? connectivity.schematicTraceIdByRecord.get(wire)\n : undefined\n const direction = getRecordDirection(record)\n const symbolName =\n record.recordKind === \"17\"\n ? getPowerPortSymbolName(record, direction)\n : undefined\n const schematicNetLabel: SchematicNetLabel = {\n type: \"schematic_net_label\",\n anchor_position: scalePoint(location, options.scale),\n anchor_side: directionToOppositeSide(\n portConnection?.bodyDirection ?? direction,\n ),\n center: scalePoint(location, options.scale),\n schematic_net_label_id: `schematic_net_label_altium_${recordIndex}`,\n schematic_sheet_id: options.schematicSheetId,\n source_net_id: sourceNetId,\n text: name,\n ...(schematicTraceId ? { schematic_trace_id: schematicTraceId } : {}),\n ...(symbolName ? { symbol_name: symbolName } : {}),\n }\n elements.push(schematicNetLabel)\n }\n}\n\nfunction createInlineNetLabelText(params: {\n connectedWires: AltiumRecord[]\n document: AltiumSchDoc\n location: AltiumPoint\n name: string\n options: SemanticSchematicOptions\n record: AltiumRecord\n recordIndex: number\n sourceTraceId: string\n}): SchematicText {\n const {\n connectedWires,\n document,\n location,\n name,\n options,\n record,\n recordIndex,\n sourceTraceId,\n } = params\n const direction = getInlineNetLabelDirection(record, location, connectedWires)\n const scaledLocation = scalePoint(location, options.scale)\n const fontSize = getInlineNetLabelFontSize(record, document, options.scale)\n const fontScale = fontSize / DEFAULT_INLINE_NET_LABEL_FONT_SIZE\n const textWidth =\n (name.length * INLINE_NET_LABEL_CHARACTER_WIDTH +\n INLINE_NET_LABEL_HORIZONTAL_PADDING) *\n fontScale\n const isVertical = direction === \"up\" || direction === \"down\"\n const directionSign = direction === \"left\" || direction === \"down\" ? -1 : 1\n const isTerminalPort = record.recordKind === \"18\"\n const anchor: SchematicText[\"anchor\"] = isTerminalPort\n ? directionSign > 0\n ? \"left\"\n : \"right\"\n : \"center\"\n const position = isTerminalPort\n ? isVertical\n ? {\n x: scaledLocation.x - fontSize / 2,\n y: scaledLocation.y,\n }\n : {\n x: scaledLocation.x,\n y: scaledLocation.y + fontSize / 2,\n }\n : isVertical\n ? {\n x: scaledLocation.x - fontSize / 2,\n y: scaledLocation.y + (directionSign * textWidth) / 2,\n }\n : {\n x: scaledLocation.x + (directionSign * textWidth) / 2,\n y: scaledLocation.y + fontSize / 2,\n }\n\n return {\n type: \"schematic_text\",\n anchor,\n color: INLINE_NET_LABEL_COLOR,\n font_size: fontSize,\n position,\n rotation: isVertical ? -90 : 0,\n schematic_sheet_id: options.schematicSheetId,\n schematic_text_id: `schematic_inline_net_label_altium_${recordIndex}`,\n source_trace_id: sourceTraceId,\n text: name,\n }\n}\n\nfunction getInlineNetLabelFontSize(\n record: AltiumRecord,\n document: AltiumSchDoc,\n scale: number,\n): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n const sheetRecord = document.records.find(\n (candidate) => candidate.recordKind === \"31\",\n )\n const sourceFontSize = Number(\n sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ??\n DEFAULT_INLINE_NET_LABEL_FONT_SIZE / scale,\n )\n return Math.min(\n DEFAULT_INLINE_NET_LABEL_FONT_SIZE,\n Math.max(MIN_INLINE_NET_LABEL_FONT_SIZE, sourceFontSize * scale),\n )\n}\n\nfunction getInlineNetLabelDirection(\n record: AltiumRecord,\n location: AltiumPoint,\n connectedWires: AltiumRecord[],\n): CardinalDirection {\n if (record.recordKind !== \"18\") return getRecordDirection(record)\n\n for (const wire of connectedWires) {\n const points = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const start = points[pointIndex - 1]\n const end = points[pointIndex]\n if (!start || !end || !isPointOnSegment(location, start, end)) continue\n const other = pointsEqual(location, start)\n ? end\n : pointsEqual(location, end)\n ? start\n : undefined\n if (!other) continue\n // Place the inline text away from the wire interior, matching the side\n // on which Altium drew the port body instead of covering the circuit.\n const dx = location.x - other.x\n const dy = location.y - other.y\n if (Math.abs(dx) >= Math.abs(dy)) return dx < 0 ? \"left\" : \"right\"\n return dy < 0 ? \"down\" : \"up\"\n }\n }\n\n return getRecordDirection(record)\n}\n\nfunction getWireSegments(wires: AltiumRecord[]): SchematicSegment[] {\n return wires.flatMap((wire) => {\n const points = getSchematicRecordPoints(wire)\n const segments: SchematicSegment[] = []\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const start = points[pointIndex - 1]\n const end = points[pointIndex]\n if (start && end) segments.push({ end, start })\n }\n return segments\n })\n}\n\nfunction getPortConnectionGeometry(\n record: AltiumRecord,\n wireSegments: SchematicSegment[],\n): { anchor: AltiumPoint; bodyDirection: CardinalDirection } | undefined {\n const origin = getLocation(record)\n if (!origin) return undefined\n\n const originToExtremity = getRecordDirection(record)\n const directionVector = VECTOR_BY_DIRECTION[originToExtremity]\n const width = Math.max(record.getNumber(\"WIDTH\") ?? 16, 0)\n const extremity = {\n x: origin.x + directionVector.x * width,\n y: origin.y + directionVector.y * width,\n }\n const touchesWireEndpoint = (point: AltiumPoint): boolean =>\n wireSegments.some((segment) =>\n isPointNearSegmentEndpoint(point, segment.start, segment.end),\n )\n const originConnected = touchesWireEndpoint(origin)\n const extremityConnected = touchesWireEndpoint(extremity)\n const connectedEnd = record.getNumber(\"CONNECTEDEND\")\n const connectsAtExtremity =\n connectedEnd === 2 ||\n (connectedEnd !== 1 &&\n connectedEnd !== 3 &&\n !originConnected &&\n extremityConnected)\n\n return connectsAtExtremity\n ? {\n anchor: extremity,\n bodyDirection: getOppositeDirection(originToExtremity),\n }\n : { anchor: origin, bodyDirection: originToExtremity }\n}\n\nfunction isPointNearSegmentEndpoint(\n point: AltiumPoint,\n start: AltiumPoint,\n end: AltiumPoint,\n): boolean {\n return isPointNear(point, start) || isPointNear(point, end)\n}\n\nfunction isPointNear(point: AltiumPoint, other: AltiumPoint): boolean {\n const tolerance = 1.1\n return (point.x - other.x) ** 2 + (point.y - other.y) ** 2 <= tolerance ** 2\n}\n\nfunction getOppositeDirection(direction: CardinalDirection): CardinalDirection {\n if (direction === \"up\") return \"down\"\n if (direction === \"down\") return \"up\"\n return direction === \"left\" ? \"right\" : \"left\"\n}\n\nfunction getOrCreateSourceNet(params: {\n elements: AnyCircuitElement[]\n name: string\n sourceNetIdByName: Map<string, string>\n}): string {\n const { elements, name, sourceNetIdByName } = params\n const normalizedName = name.trim().toUpperCase()\n const existing = sourceNetIdByName.get(normalizedName)\n if (existing) return existing\n\n const sourceNetIdBase = `source_net_altium_${sanitizeId(name)}`\n const existingIds = new Set(\n elements.flatMap((element) =>\n element.type === \"source_net\" ? [element.source_net_id] : [],\n ),\n )\n let sourceNetId = sourceNetIdBase\n let suffix = 2\n while (existingIds.has(sourceNetId)) {\n sourceNetId = `${sourceNetIdBase}_${suffix}`\n suffix++\n }\n const sourceNet: SourceNet = {\n type: \"source_net\",\n is_ground: isGroundNet(name),\n is_power: isPowerNet(name),\n member_source_group_ids: [],\n name,\n source_net_id: sourceNetId,\n }\n elements.push(sourceNet)\n sourceNetIdByName.set(normalizedName, sourceNetId)\n return sourceNetId\n}\n\nfunction selectCircuitJsonSymbol(params: {\n designator: string\n libraryReference: string\n ports: ConvertedPort[]\n}): SymbolSelection | undefined {\n const { designator, libraryReference, ports } = params\n const classification = classifyComponent({ designator, libraryReference })\n let baseName: string | undefined\n let candidateNames: string[] = []\n if (classification === \"testpoint\" && ports.length === 1) {\n baseName = \"testpoint\"\n } else if (classification === \"crystal\" && ports.length === 2) {\n baseName = \"crystal\"\n } else if (classification === \"crystal\" && ports.length === 4) {\n baseName = \"crystal_4pin\"\n } else if (\n classification === \"mosfet\" &&\n ports.length >= 3 &&\n hasCompleteMosfetFunctionalGroups(ports)\n ) {\n const { channel_type, mosfet_mode } = getMosfetVariant(libraryReference)\n const channel = channel_type === \"p\" ? \"p\" : \"n\"\n const mode = mosfet_mode === \"depletion\" ? \"d\" : \"e\"\n const prefix = `${channel}_channel_${mode}_mosfet_transistor_gate_`\n candidateNames = SYMBOL_NAMES.filter((name) => name.startsWith(prefix))\n } else if (ports.length !== 2) {\n return undefined\n } else if (classification === \"resistor\") {\n baseName = \"boxresistor\"\n } else if (classification === \"capacitor\") {\n baseName = isPolarizedCapacitor(libraryReference)\n ? \"capacitor_polarized\"\n : \"capacitor\"\n } else if (classification === \"ferrite_bead\") {\n baseName = \"ferrite_bead\"\n } else if (classification === \"inductor\") {\n baseName = \"inductor\"\n } else if (classification === \"led\") {\n baseName = \"led\"\n }\n if (classification === \"diode\") {\n const lower = libraryReference.toLowerCase()\n baseName = lower.includes(\"schottky\") ? \"schottky_diode\" : \"diode\"\n }\n if (baseName) {\n candidateNames = CARDINAL_DIRECTIONS.map(\n (direction) => `${baseName}_${direction}`,\n )\n }\n if (candidateNames.length === 0) return undefined\n\n const selections = candidateNames.flatMap((name) => {\n const symbol = SYMBOL_CATALOG[name]\n const supportsEquivalentMosfetPads =\n classification === \"mosfet\" && symbol?.ports.length === 3\n if (\n !symbol ||\n (!supportsEquivalentMosfetPads && symbol.ports.length !== ports.length)\n ) {\n return []\n }\n const assignments = assignConvertedPortsToSymbolPorts(ports, symbol, {\n allowFunctionalPortReuse: classification === \"mosfet\",\n geometryInterchangeableLabels:\n classification === \"crystal\" && ports.length === 4\n ? new Set([\"2\", \"4\"])\n : undefined,\n })\n return assignments.length === ports.length\n ? [{ assignments, name, symbol } satisfies SymbolSelection]\n : []\n })\n return selections.sort(\n (left, right) =>\n getSymbolDirectionScore(left) - getSymbolDirectionScore(right),\n )[0]\n}\n\nfunction hasCompleteMosfetFunctionalGroups(ports: ConvertedPort[]): boolean {\n const groups = ports.map((port) =>\n normalizeFunctionalPortLabel(port.sourcePort.name),\n )\n return (\n groups.every((group) => group !== undefined) && new Set(groups).size === 3\n )\n}\n\nfunction assignConvertedPortsToSymbolPorts(\n ports: ConvertedPort[],\n symbol: SchSymbol,\n options: {\n allowFunctionalPortReuse?: boolean\n geometryInterchangeableLabels?: Set<string>\n } = {},\n): SymbolPortAssignment[] {\n const unusedSymbolPorts = new Set(symbol.ports)\n const orderedPorts = [...ports].sort(compareConvertedPorts)\n const assignments: SymbolPortAssignment[] = []\n const convertedCenter = getAveragePoint(ports.map(({ point }) => point))\n\n for (const [portIndex, convertedPort] of orderedPorts.entries()) {\n const rawHints = [\n convertedPort.schematicPort.pin_number?.toString(),\n convertedPort.sourcePort.name,\n ...(convertedPort.sourcePort.port_hints ?? []),\n ].filter((hint): hint is string => Boolean(hint))\n const functionalHints = new Set(\n rawHints.flatMap((hint) => {\n const normalized = normalizeFunctionalPortLabel(hint)\n return normalized ? [normalized] : []\n }),\n )\n const functionalPortCandidates = options.allowFunctionalPortReuse\n ? symbol.ports\n : [...unusedSymbolPorts]\n const functionalSymbolPort = functionalPortCandidates.find((symbolPort) =>\n symbolPort.labels.some((label) => {\n const normalized = normalizeFunctionalPortLabel(label)\n return normalized ? functionalHints.has(normalized) : false\n }),\n )\n const exactHints = new Set(rawHints.map((hint) => hint.toLowerCase()))\n const exactSymbolPort = [...unusedSymbolPorts].find((symbolPort) =>\n symbolPort.labels.some((label) => exactHints.has(label.toLowerCase())),\n )\n const interchangeableLabels = options.geometryInterchangeableLabels\n const isGeometryInterchangeable = rawHints.some((hint) =>\n interchangeableLabels?.has(hint.toLowerCase()),\n )\n const geometrySymbolPort = isGeometryInterchangeable\n ? [...unusedSymbolPorts]\n .filter((symbolPort) =>\n symbolPort.labels.some((label) =>\n interchangeableLabels?.has(label.toLowerCase()),\n ),\n )\n .sort(\n (left, right) =>\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(left, symbol.center),\n ) -\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(right, symbol.center),\n ),\n )[0]\n : undefined\n const symbolPort =\n functionalSymbolPort ??\n geometrySymbolPort ??\n exactSymbolPort ??\n symbol.ports[portIndex] ??\n [...unusedSymbolPorts][0]\n if (!symbolPort) continue\n if (!functionalSymbolPort || !options.allowFunctionalPortReuse) {\n unusedSymbolPorts.delete(symbolPort)\n }\n assignments.push({ convertedPort, symbolPort })\n }\n return assignments\n}\n\nfunction compareConvertedPorts(\n left: ConvertedPort,\n right: ConvertedPort,\n): number {\n const leftPinNumber = left.schematicPort.pin_number\n const rightPinNumber = right.schematicPort.pin_number\n if (leftPinNumber !== undefined && rightPinNumber !== undefined) {\n return leftPinNumber - rightPinNumber\n }\n return (\n (left.schematicPort.true_ccw_index ?? 0) -\n (right.schematicPort.true_ccw_index ?? 0)\n )\n}\n\nfunction getSymbolDirectionScore(selection: SymbolSelection): number {\n const [first, second] = selection.assignments\n if (!first) return Number.POSITIVE_INFINITY\n if (!second) {\n const expectedDirection =\n VECTOR_BY_DIRECTION[\n first.convertedPort.schematicPort.facing_direction ?? \"right\"\n ]\n return getVectorDifference(\n expectedDirection,\n subtractPoints(first.symbolPort, selection.symbol.center),\n )\n }\n let difference = 0\n let comparisonCount = 0\n for (\n let firstIndex = 0;\n firstIndex < selection.assignments.length;\n firstIndex++\n ) {\n for (\n let secondIndex = firstIndex + 1;\n secondIndex < selection.assignments.length;\n secondIndex++\n ) {\n const firstAssignment = selection.assignments[firstIndex]\n const secondAssignment = selection.assignments[secondIndex]\n if (!firstAssignment || !secondAssignment) continue\n const pairDifference = getVectorDifference(\n subtractPoints(\n secondAssignment.convertedPort.point,\n firstAssignment.convertedPort.point,\n ),\n subtractPoints(secondAssignment.symbolPort, firstAssignment.symbolPort),\n )\n if (!Number.isFinite(pairDifference)) continue\n difference += pairDifference\n comparisonCount++\n }\n }\n return comparisonCount > 0\n ? difference / comparisonCount\n : Number.POSITIVE_INFINITY\n}\n\nfunction normalizeFunctionalPortLabel(value: string): string | undefined {\n const normalized = value.toLowerCase().replace(/[^a-z]/gu, \"\")\n if (normalized === \"g\" || normalized === \"gate\") return \"gate\"\n if (normalized === \"d\" || normalized === \"drain\") return \"drain\"\n if (normalized === \"s\" || normalized === \"source\") return \"source\"\n return undefined\n}\n\nfunction applyNativeSymbolPortGeometry(params: {\n center: AltiumPoint\n selection: SymbolSelection\n}): void {\n const { center, selection } = params\n const assignmentsBySymbolPort = new Map<\n SchSymbol[\"ports\"][number],\n SymbolPortAssignment[]\n >()\n for (const assignment of selection.assignments) {\n const assignments = assignmentsBySymbolPort.get(assignment.symbolPort)\n if (assignments) assignments.push(assignment)\n else assignmentsBySymbolPort.set(assignment.symbolPort, [assignment])\n }\n\n for (const [symbolPort, assignments] of assignmentsBySymbolPort) {\n const offset = subtractPoints(symbolPort, selection.symbol.center)\n const direction = getDirectionForVector(offset)\n const symbolPortCenter = {\n x: center.x + offset.x,\n y: center.y + offset.y,\n }\n const representative = assignments.sort(\n (left, right) =>\n getPointDistance(\n left.convertedPort.schematicPort.center,\n symbolPortCenter,\n ) -\n getPointDistance(\n right.convertedPort.schematicPort.center,\n symbolPortCenter,\n ),\n )[0]\n for (const { convertedPort } of assignments) {\n convertedPort.isSchematicVisible =\n convertedPort === representative?.convertedPort\n convertedPort.schematicPort.center = symbolPortCenter\n convertedPort.schematicPort.distance_from_component_edge = Math.hypot(\n offset.x,\n offset.y,\n )\n convertedPort.schematicPort.facing_direction = direction\n convertedPort.schematicPort.side_of_component = directionToSide(direction)\n }\n }\n}\n\nfunction getPowerPortSymbolName(\n record: AltiumRecord,\n direction: CardinalDirection,\n): string {\n const style = Math.round(record.getNumber(\"STYLE\") ?? 2)\n if (style === 4) return `ground_${direction}`\n if (style === 5) return `ground_${direction}`\n if (style === 6) return `tilted_ground_${direction}`\n return `vcc_${direction}`\n}\n\nfunction getComponentBodyBounds(\n records: AltiumRecord[],\n portPoints: AltiumPoint[],\n): Bounds {\n const rectangles = records\n .filter((record) => record.recordKind === \"14\")\n .flatMap((record) => {\n const rectangle = getRectangle(record)\n return rectangle ? [rectangle] : []\n })\n if (rectangles.length > 0) return mergeBounds(rectangles)\n\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (record.recordKind === \"2\") continue\n const location = getLocation(record)\n const corner = getCorner(record)\n if (location && corner) points.push(location, corner)\n points.push(...getSchematicRecordPoints(record))\n if (record.recordKind === \"8\" && location) {\n const radiusX = Math.abs(record.getNumber(\"RADIUS\") ?? 0)\n const radiusY = Math.abs(record.getNumber(\"SECONDARYRADIUS\") ?? radiusX)\n points.push(\n { x: location.x - radiusX, y: location.y - radiusY },\n { x: location.x + radiusX, y: location.y + radiusY },\n )\n }\n }\n if (points.length > 0) return getBoundsForPoints(points)\n const bounds = getBoundsForPoints(portPoints)\n if (bounds.minX === bounds.maxX) {\n bounds.minX -= 2\n bounds.maxX += 2\n }\n if (bounds.minY === bounds.maxY) {\n bounds.minY -= 2\n bounds.maxY += 2\n }\n return bounds\n}\n\nfunction findOwnedText(\n records: AltiumRecord[],\n recordKind: string,\n name: string,\n): string | undefined {\n return records\n .find(\n (record) =>\n record.recordKind === recordKind &&\n record.getDecoded(\"NAME\")?.toLowerCase() === name.toLowerCase(),\n )\n ?.getDecoded(\"TEXT\")\n}\n\nfunction isOwnedRecordVisible(\n record: AltiumRecord,\n currentPartId: number,\n): boolean {\n const ownerPartId = record.getNumber(\"OWNERPARTID\")\n const ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n}\n\nfunction isPinHidden(pin: AltiumRecord): boolean {\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n return (\n pin.getBoolean(\"ISHIDDEN\") === true ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n )\n}\n\nfunction getRecordDirection(record: AltiumRecord): CardinalDirection {\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n return DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n}\n\nfunction directionToSide(\n direction: CardinalDirection,\n): NonNullable<SchematicPort[\"side_of_component\"]> {\n if (direction === \"up\") return \"top\"\n if (direction === \"down\") return \"bottom\"\n return direction\n}\n\nfunction directionToOppositeSide(\n direction: CardinalDirection,\n): SchematicNetLabel[\"anchor_side\"] {\n if (direction === \"up\") return \"bottom\"\n if (direction === \"down\") return \"top\"\n return direction === \"left\" ? \"right\" : \"left\"\n}\n\nfunction groupByPoint(ports: ConvertedPort[]): Map<string, ConvertedPort[]> {\n const grouped = new Map<string, ConvertedPort[]>()\n for (const port of ports) {\n const key = pointKey(port.point)\n const existing = grouped.get(key)\n if (existing) existing.push(port)\n else grouped.set(key, [port])\n }\n return grouped\n}\n\nfunction uniqueConvertedPorts(ports: ConvertedPort[]): ConvertedPort[] {\n const seenSourcePortIds = new Set<string>()\n return ports.filter((port) => {\n const sourcePortId = port.sourcePort.source_port_id\n if (seenSourcePortIds.has(sourcePortId)) return false\n seenSourcePortIds.add(sourcePortId)\n return true\n })\n}\n\nfunction getPortIdAtElectricalPoint(\n port: ConvertedPort | undefined,\n electricalPoint: AltiumPoint,\n scale: number,\n): string | undefined {\n if (!port?.isSchematicVisible) return undefined\n return pointsEqual(\n port.schematicPort.center,\n scalePoint(electricalPoint, scale),\n )\n ? port.schematicPort.schematic_port_id\n : undefined\n}\n\nfunction parsePinNumber(value: string): number | undefined {\n const parsed = Number(value)\n return Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined\n}\n","import type { AltiumPoint, AltiumRecord } from \"altiumts\"\n\nexport interface Bounds {\n maxX: number\n maxY: number\n minX: number\n minY: number\n}\n\nexport type CardinalDirection = \"up\" | \"down\" | \"left\" | \"right\"\n\nexport function getAveragePoint(points: AltiumPoint[]): AltiumPoint {\n if (points.length === 0) return { x: 0, y: 0 }\n return {\n x: points.reduce((sum, point) => sum + point.x, 0) / points.length,\n y: points.reduce((sum, point) => sum + point.y, 0) / points.length,\n }\n}\n\nexport function getVectorDifference(\n left: AltiumPoint,\n right: AltiumPoint,\n): number {\n const leftLength = Math.hypot(left.x, left.y)\n const rightLength = Math.hypot(right.x, right.y)\n if (leftLength === 0 || rightLength === 0) {\n return Number.POSITIVE_INFINITY\n }\n const cosine =\n (left.x * right.x + left.y * right.y) / (leftLength * rightLength)\n return 1 - Math.max(-1, Math.min(1, cosine))\n}\n\nexport function getPointDistance(\n left: AltiumPoint,\n right: AltiumPoint,\n): number {\n return Math.hypot(left.x - right.x, left.y - right.y)\n}\n\nexport function subtractPoints(\n left: AltiumPoint,\n right: AltiumPoint,\n): AltiumPoint {\n return { x: left.x - right.x, y: left.y - right.y }\n}\n\nexport function getDirectionForVector(vector: AltiumPoint): CardinalDirection {\n if (Math.abs(vector.x) >= Math.abs(vector.y)) {\n return vector.x >= 0 ? \"right\" : \"left\"\n }\n return vector.y >= 0 ? \"up\" : \"down\"\n}\n\nexport function getBoundsForPoints(points: AltiumPoint[]): Bounds {\n if (points.length === 0) return { maxX: 1, maxY: 1, minX: -1, minY: -1 }\n return {\n maxX: Math.max(...points.map((point) => point.x)),\n maxY: Math.max(...points.map((point) => point.y)),\n minX: Math.min(...points.map((point) => point.x)),\n minY: Math.min(...points.map((point) => point.y)),\n }\n}\n\nexport function mergeBounds(bounds: Bounds[]): Bounds {\n return {\n maxX: Math.max(...bounds.map((bound) => bound.maxX)),\n maxY: Math.max(...bounds.map((bound) => bound.maxY)),\n minX: Math.min(...bounds.map((bound) => bound.minX)),\n minY: Math.min(...bounds.map((bound) => bound.minY)),\n }\n}\n\nexport function getBoundsCenter(bounds: Bounds): AltiumPoint {\n return {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n}\n\nexport function getRectangle(record: AltiumRecord): Bounds | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n }\n}\n\nexport function getLocation(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"LOCATION.X\")\n const y = getCoordinate(record, \"LOCATION.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nexport function getCorner(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"CORNER.X\")\n const y = getCoordinate(record, \"CORNER.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nfunction getCoordinate(record: AltiumRecord, key: string): number | undefined {\n const raw = record.getCaseInsensitive(key)\n if (raw === undefined) return undefined\n const integer = Number(raw)\n if (!Number.isFinite(integer)) return undefined\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (fractionRaw === undefined) return integer\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integer\n return integer < 0 ? integer - fraction : integer + fraction\n}\n\nexport function scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nexport function pointKey(point: AltiumPoint): string {\n return `${point.x.toFixed(6)},${point.y.toFixed(6)}`\n}\n\nexport function pointsEqual(\n left: AltiumPoint,\n right: AltiumPoint | undefined,\n): boolean {\n return (\n right !== undefined &&\n Math.abs(left.x - right.x) < 0.000001 &&\n Math.abs(left.y - right.y) < 0.000001\n )\n}\n","export function uniqueStrings(values: Array<string | undefined>): string[] {\n return [...new Set(values.filter((value): value is string => Boolean(value)))]\n}\n\nexport function sanitizeId(value: string): string {\n const sanitized = value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, \"_\")\n .replace(/^_+|_+$/gu, \"\")\n return sanitized || \"unnamed\"\n}\n\nexport function segmentKey(\n start: { x: number; y: number },\n end: { x: number; y: number },\n): string {\n const startKey = `${start.x.toFixed(6)},${start.y.toFixed(6)}`\n const endKey = `${end.x.toFixed(6)},${end.y.toFixed(6)}`\n return startKey < endKey ? `${startKey}|${endKey}` : `${endKey}|${startKey}`\n}\n\nexport function isGroundNet(name: string): boolean {\n return /(?:^|[_+-])(?:[adp]?gnd|ground)(?:$|[_+\\d-])/iu.test(name)\n}\n\nexport function isPowerNet(name: string): boolean {\n return (\n isGroundNet(name) ||\n /(?:^|[_+-])(?:vcc|vdd|vss)(?:$|[a-z0-9_+-])/iu.test(name) ||\n /(?:^|[_+-])(?:vin|vout|pwr|power)(?:$|[_+\\d-])/iu.test(name)\n )\n}\n","export type ComponentClassification =\n | \"capacitor\"\n | \"crystal\"\n | \"diode\"\n | \"ferrite_bead\"\n | \"inductor\"\n | \"led\"\n | \"mosfet\"\n | \"resistor\"\n | \"testpoint\"\n | \"unknown\"\n\nexport function classifyComponent(params: {\n designator: string\n libraryReference: string\n}): ComponentClassification {\n const { designator, libraryReference } = params\n const prefix = designator.match(/^[A-Z]+/iu)?.[0]?.toUpperCase() ?? \"\"\n const lowerReference = libraryReference.toLowerCase()\n if (prefix === \"TP\" || lowerReference.includes(\"testpoint\")) {\n return \"testpoint\"\n }\n if (\n prefix === \"Y\" ||\n lowerReference.includes(\"crystal\") ||\n /(?:^|[_-])cry(?:\\d|[_-]|$)/iu.test(libraryReference)\n ) {\n return \"crystal\"\n }\n if (lowerReference.includes(\"mosfet\")) return \"mosfet\"\n if (\n prefix === \"FB\" ||\n prefix === \"FL\" ||\n lowerReference.includes(\"ferrite\") ||\n lowerReference.includes(\"emifilter_ind\")\n ) {\n return \"ferrite_bead\"\n }\n if (prefix === \"LED\" || lowerReference.includes(\"led\")) return \"led\"\n if (prefix === \"R\" || lowerReference.includes(\"resistor\")) return \"resistor\"\n if (prefix === \"C\" || /(?:^|[_-])cap(?:[_-]|$)/iu.test(libraryReference)) {\n return \"capacitor\"\n }\n if (prefix === \"L\" || lowerReference.includes(\"inductor\")) return \"inductor\"\n if (prefix === \"D\" || lowerReference.includes(\"diode\")) return \"diode\"\n return \"unknown\"\n}\n\nexport function getMosfetVariant(libraryReference: string): {\n channel_type: \"n\" | \"p\"\n mosfet_mode: \"depletion\" | \"enhancement\"\n} {\n const lowerReference = libraryReference.toLowerCase()\n const isPChannel =\n /(?:^|[_-])p(?:channel)?(?:[_-]|$)/iu.test(libraryReference) ||\n lowerReference.includes(\"pmos\") ||\n lowerReference.includes(\"csd25\")\n return {\n channel_type: isPChannel ? \"p\" : \"n\",\n mosfet_mode: lowerReference.includes(\"depletion\")\n ? \"depletion\"\n : \"enhancement\",\n }\n}\n\nexport function isPolarizedCapacitor(libraryReference: string): boolean {\n return /(?:^|[_-])cap(?:acitor)?[_-]?pol(?:arized)?(?:[_-]|$)/iu.test(\n libraryReference,\n )\n}\n\nexport function getPrimaryComponentValue(componentValue: string): string {\n return componentValue.split(/[_/\\s]+/u).find(Boolean) ?? componentValue\n}\n","import type { AltiumPoint, AltiumRecord } from \"altiumts\"\n\nexport interface Rectangle {\n maxX: number\n maxY: number\n minX: number\n minY: number\n}\n\nexport function getLocation(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"LOCATION.X\") === undefined ||\n record.getCaseInsensitive(\"LOCATION.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"LOCATION.X\"),\n y: getCoordinate(record, \"LOCATION.Y\"),\n }\n}\n\nexport function getCorner(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"CORNER.X\") === undefined ||\n record.getCaseInsensitive(\"CORNER.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"CORNER.X\"),\n y: getCoordinate(record, \"CORNER.Y\"),\n }\n}\n\nexport function getRectangle(record: AltiumRecord): Rectangle | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n }\n}\n\nexport function getCoordinate(\n record: AltiumRecord,\n key: string,\n fallback = 0,\n): number {\n const integerPart = Number(record.getCaseInsensitive(key) ?? fallback)\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (!Number.isFinite(integerPart) || fractionRaw === undefined) {\n return Number.isFinite(integerPart) ? integerPart : fallback\n }\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integerPart\n return integerPart < 0 ? integerPart - fraction : integerPart + fraction\n}\n\nexport function scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n","import { type AltiumRecord, getSchematicRecordPoints } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicArc,\n SchematicCircle,\n SchematicPath,\n SchematicRect,\n SchematicTrace,\n} from \"circuit-json\"\nimport {\n getCoordinate,\n getCorner,\n getLocation,\n getRectangle,\n scalePoint,\n} from \"./coordinates\"\nimport { altiumColorToCss, createLine } from \"./render-text\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\n\nexport function renderPrimitiveRecord({\n record,\n index,\n context,\n color,\n strokeWidth,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n color: string\n strokeWidth: number\n}): AnyCircuitElement[] | undefined {\n const kind = record.recordKind\n const scale = context.scale\n if (kind === \"27\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_trace\",\n schematic_trace_id: `schematic_trace_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n junctions: [],\n edges: points.slice(1).map((point, pointIndex) => ({\n from: points[pointIndex] ?? point,\n to: point,\n })),\n } satisfies SchematicTrace,\n ]\n }\n\n if (kind === \"6\" || kind === \"7\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_path_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points,\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color:\n kind === \"7\"\n ? altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"transparent\",\n )\n : undefined,\n is_filled: kind === \"7\",\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"13\") {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return []\n return [\n createLine({\n index,\n start: location,\n end: corner,\n color,\n strokeWidth,\n scale,\n }),\n ]\n }\n\n if (kind === \"10\" || kind === \"14\") {\n const rectangle = getRectangle(record)\n if (!rectangle) return []\n return [\n {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_rect_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect,\n ]\n }\n\n if (kind === \"8\") {\n const center = getLocation(record)\n if (!center) return []\n const radiusX = getCoordinate(record, \"RADIUS\", 1)\n const radiusY = getCoordinate(record, \"SECONDARYRADIUS\", radiusX)\n if (Math.abs(radiusX - radiusY) < 0.0001) {\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_circle_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: radiusX * scale,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_ellipse_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: approximateEllipse({ center, radiusX, radiusY }).map((point) =>\n scalePoint(point, scale),\n ),\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"11\" || kind === \"12\") {\n const center = getLocation(record)\n if (!center) return []\n return [\n {\n type: \"schematic_arc\",\n schematic_arc_id: `schematic_arc_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: getCoordinate(record, \"RADIUS\", 1) * scale,\n start_angle_degrees: Number(\n record.getCaseInsensitive(\"STARTANGLE\") ?? 0,\n ),\n end_angle_degrees: Number(record.getCaseInsensitive(\"ENDANGLE\") ?? 360),\n direction: \"counterclockwise\",\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n } satisfies SchematicArc,\n ]\n }\n\n return undefined\n}\n\n/** Approximate an Altium ellipse with a closed Circuit JSON path. */\nexport function approximateEllipse({\n center,\n radiusX,\n radiusY,\n}: {\n center: { x: number; y: number }\n radiusX: number\n radiusY: number\n}): Array<{ x: number; y: number }> {\n return Array.from({ length: 49 }, (_, index) => {\n const radians = (index / 48) * Math.PI * 2\n return {\n x: center.x + Math.cos(radians) * radiusX,\n y: center.y + Math.sin(radians) * radiusY,\n }\n })\n}\n","import type { AltiumRecord, AltiumSchDoc } from \"altiumts\"\nimport type { AnyCircuitElement, Point, SchematicRect } from \"circuit-json\"\n\nexport const SCHEMATIC_SHEET_ID = \"schematic_sheet_altium\"\n\nconst SCHEMATIC_UNIT_TO_MILLIMETERS = 10.16 / 1.1\nconst SCHEMATIC_SHEET_INSET = 5 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_WIDTH = 297 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_HEIGHT = 210 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_INNER_WIDTH =\n SCHEMATIC_SHEET_WIDTH - SCHEMATIC_SHEET_INSET * 2\nconst SCHEMATIC_SHEET_INNER_HEIGHT =\n SCHEMATIC_SHEET_HEIGHT - SCHEMATIC_SHEET_INSET * 2\n\nexport interface SheetDimensions {\n height: number\n width: number\n}\n\nexport interface SchematicContext {\n document: AltiumSchDoc\n records: AltiumRecord[]\n scale: number\n sheetRecord?: AltiumRecord\n}\n\nexport function getAltiumSheetDimensions(\n sheetRecord: AltiumRecord | undefined,\n): SheetDimensions {\n return {\n width: getPositiveNumber(sheetRecord?.getCaseInsensitive(\"CUSTOMX\"), 1000),\n height: getPositiveNumber(sheetRecord?.getCaseInsensitive(\"CUSTOMY\"), 800),\n }\n}\n\nexport function getPageFitScale(sheetDimensions: SheetDimensions): number {\n return Math.min(\n SCHEMATIC_SHEET_INNER_WIDTH / sheetDimensions.width,\n SCHEMATIC_SHEET_INNER_HEIGHT / sheetDimensions.height,\n )\n}\n\nexport function createSheetBorder(\n sheetRecord: AltiumRecord | undefined,\n scale: number,\n): SchematicRect {\n const { height, width } = getAltiumSheetDimensions(sheetRecord)\n return {\n type: \"schematic_rect\",\n schematic_rect_id: \"schematic_rect_altium_sheet_border\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: { x: (width * scale) / 2, y: (height * scale) / 2 },\n width: width * scale,\n height: height * scale,\n rotation: 0,\n stroke_width: 0.1,\n color: \"#334155\",\n is_filled: false,\n is_dashed: false,\n }\n}\n\nexport function translateSchematicElement(\n element: AnyCircuitElement,\n offset: Point,\n): AnyCircuitElement {\n const translatePoint = (point: Point): Point => ({\n x: point.x + offset.x,\n y: point.y + offset.y,\n })\n switch (element.type) {\n case \"schematic_component\":\n case \"schematic_port\":\n case \"schematic_rect\":\n case \"schematic_circle\":\n case \"schematic_arc\":\n return { ...element, center: translatePoint(element.center) }\n case \"schematic_net_label\":\n return {\n ...element,\n center: translatePoint(element.center),\n ...(element.anchor_position\n ? { anchor_position: translatePoint(element.anchor_position) }\n : {}),\n }\n case \"schematic_text\":\n return { ...element, position: translatePoint(element.position) }\n case \"schematic_path\":\n return {\n ...element,\n points: element.points.map(translatePoint),\n }\n case \"schematic_line\":\n return {\n ...element,\n x1: element.x1 + offset.x,\n x2: element.x2 + offset.x,\n y1: element.y1 + offset.y,\n y2: element.y2 + offset.y,\n }\n case \"schematic_trace\":\n return {\n ...element,\n edges: element.edges.map((edge) => ({\n ...edge,\n from: translatePoint(edge.from),\n to: translatePoint(edge.to),\n })),\n junctions: element.junctions.map(translatePoint),\n }\n default:\n return element\n }\n}\n\nexport function shouldRenderSchematicRecord(\n record: AltiumRecord,\n context: SchematicContext,\n): boolean {\n let ownerPartId = record.getNumber(\"OWNERPARTID\")\n let ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n let current: AltiumRecord | undefined = record\n const visited = new Set<AltiumRecord>()\n\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = context.document.getParent(current)\n if (!parent) return true\n\n if (ownerPartId === undefined || ownerPartId <= 0) {\n ownerPartId = current.getNumber(\"OWNERPARTID\")\n }\n if (ownerPartDisplayMode === undefined) {\n ownerPartDisplayMode = current.getNumber(\"OWNERPARTDISPLAYMODE\")\n }\n\n if (parent.recordKind === \"1\") {\n const currentPartId = parent.getNumber(\"CURRENTPARTID\") ?? 1\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n }\n current = parent\n }\n return true\n}\n\nfunction getPositiveNumber(value: unknown, fallback: number): number {\n const parsed = Number(value)\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback\n}\n","import type { AltiumPoint, AltiumRecord } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicLine,\n SchematicRect,\n SchematicText,\n} from \"circuit-json\"\nimport type { ConvertAltiumSchDocOptions } from \"../convert-altium-sch-doc-to-circuit-json\"\nimport {\n getCoordinate,\n getLocation,\n getRectangle,\n scalePoint,\n} from \"./coordinates\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\n\nexport function renderTextRecord({\n record,\n index,\n context,\n options,\n color,\n strokeWidth,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: ConvertAltiumSchDocOptions\n color: string\n strokeWidth: number\n}): AnyCircuitElement[] | undefined {\n const kind = record.recordKind\n const scale = context.scale\n if (kind === \"4\" || kind === \"25\" || kind === \"34\" || kind === \"41\") {\n if (options.includeText === false) return []\n if (record.getBoolean(\"ISHIDDEN\") && !options.includeHidden) return []\n const text =\n record.getDecoded(\"TEXT\") ??\n record.getDecoded(\"NAME\") ??\n record.getDecoded(\"DESIGNATOR\")\n const location = getLocation(record)\n if (!text || !location) return []\n return [createText({ record, index, text, location, color, context })]\n }\n\n if (kind === \"28\") {\n const rectangle = getRectangle(record)\n const text = decodeMultilineText(record.getDecoded(\"TEXT\") ?? \"\")\n if (!rectangle || !text || options.includeText === false) return []\n const fontSize = getFontSize(record, context)\n const fontFamily = getFontFamily(record, context)\n const margin = Math.max(getCoordinate(record, \"TEXTMARGIN\", 0), 0)\n const frameWidth = rectangle.maxX - rectangle.minX\n const frameHeight = rectangle.maxY - rectangle.minY\n const availableWidth = Math.max(frameWidth - margin * 2, fontSize)\n const availableHeight = Math.max(frameHeight - margin * 2, fontSize)\n const wrappedLines =\n record.getBoolean(\"WORDWRAP\") === false\n ? text.split(\"\\n\")\n : wrapSchematicText(text, availableWidth, fontSize, fontFamily)\n const lineHeight = fontSize\n const visibleLines =\n record.getBoolean(\"CLIPTORECT\") === false\n ? wrappedLines\n : wrappedLines.slice(\n 0,\n Math.max(Math.ceil(availableHeight / lineHeight), 1),\n )\n const alignment = Number(record.getCaseInsensitive(\"ALIGNMENT\") ?? 1)\n const horizontalAnchor =\n alignment === 2 ? \"center\" : alignment === 3 ? \"right\" : \"left\"\n const textX =\n horizontalAnchor === \"center\"\n ? (rectangle.minX + rectangle.maxX) / 2\n : horizontalAnchor === \"right\"\n ? rectangle.maxX - margin\n : rectangle.minX + margin\n const textColor = altiumColorToCss(\n record.getCaseInsensitive(\"TEXTCOLOR\") ??\n record.getCaseInsensitive(\"COLOR\"),\n \"#1f2937\",\n )\n const elements: AnyCircuitElement[] = visibleLines.map((line, lineIndex) =>\n createDirectText({\n id: `schematic_text_frame_line_altium_${index}_${lineIndex}`,\n text: line,\n location: {\n x: textX,\n y: rectangle.maxY - margin - lineIndex * lineHeight,\n },\n fontSize,\n color: textColor,\n scale,\n rotation: 0,\n anchor: `top_${horizontalAnchor}` as SchematicText[\"anchor\"],\n }),\n )\n\n const isSolid = record.getBoolean(\"ISSOLID\") === true\n const showBorder = record.getBoolean(\"SHOWBORDER\") === true\n if (isSolid || showBorder) {\n elements.unshift({\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_text_frame_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: frameWidth * scale,\n height: frameHeight * scale,\n rotation: 0,\n stroke_width: showBorder ? strokeWidth : 0,\n color: showBorder ? color : \"transparent\",\n is_filled: isSolid,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect)\n }\n\n return elements\n }\n\n return undefined\n}\n\nexport function createLine({\n index,\n start,\n end,\n color,\n strokeWidth,\n scale,\n suffix = \"line\",\n}: {\n index: number\n start: AltiumPoint\n end: AltiumPoint\n color: string\n strokeWidth: number\n scale: number\n suffix?: string\n}): SchematicLine {\n return {\n type: \"schematic_line\",\n schematic_line_id: `schematic_line_altium_${index}_${suffix}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n x1: start.x * scale,\n y1: start.y * scale,\n x2: end.x * scale,\n y2: end.y * scale,\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n }\n}\n\nexport function createText({\n record,\n index,\n text,\n location,\n color,\n context,\n}: {\n record: AltiumRecord\n index: number\n text: string\n location: AltiumPoint\n color: string\n context: SchematicContext\n}): SchematicText {\n const positioning = getTextPositioning(record)\n return createDirectText({\n id: `schematic_text_altium_${index}`,\n text,\n location,\n fontSize: getFontSize(record, context),\n color,\n scale: context.scale,\n rotation: positioning.rotation,\n anchor: positioning.anchor,\n })\n}\n\nexport function createDirectText({\n id,\n text,\n location,\n fontSize,\n color,\n scale,\n rotation,\n anchor,\n}: {\n id: string\n text: string\n location: AltiumPoint\n fontSize: number\n color: string\n scale: number\n rotation: number\n anchor: SchematicText[\"anchor\"]\n}): SchematicText {\n return {\n type: \"schematic_text\",\n schematic_text_id: id,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n text,\n font_size: Math.max(fontSize * scale, 0.2),\n position: scalePoint(location, scale),\n rotation,\n anchor,\n color,\n }\n}\n\nexport function getFontSize(\n record: AltiumRecord,\n context: SchematicContext,\n): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return Math.max(\n Number(context.sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? 9),\n 1,\n )\n}\n\nexport function getFontFamily(\n record: AltiumRecord,\n context: SchematicContext,\n): string {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return context.sheetRecord?.getDecoded(`FONTNAME${fontId}`) ?? \"Arial\"\n}\n\nfunction getTextPositioning(record: AltiumRecord): {\n anchor: SchematicText[\"anchor\"]\n rotation: number\n} {\n const justification = Math.min(\n Math.max(Math.round(record.getNumber(\"JUSTIFICATION\") ?? 0), 0),\n 8,\n )\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n let column = justification % 3\n const row = Math.floor(justification / 3)\n if (orientation === 2 || orientation === 3) column = 2 - column\n const horizontal = [\"left\", \"center\", \"right\"][column] ?? \"left\"\n const vertical = [\"bottom\", \"center\", \"top\"][row] ?? \"bottom\"\n const anchor =\n horizontal === \"center\" && vertical === \"center\"\n ? \"center\"\n : (`${vertical}_${horizontal}` as SchematicText[\"anchor\"])\n return { anchor, rotation: orientation === 1 || orientation === 3 ? 90 : 0 }\n}\n\nexport function decodeMultilineText(text: string): string {\n return text.replaceAll(\"~1\", \"\\n\").replaceAll(\"\\\\n\", \"\\n\")\n}\n\nexport function wrapSchematicText(\n text: string,\n maximumWidth: number,\n fontSize: number,\n fontFamily: string,\n): string[] {\n return text.split(\"\\n\").flatMap((paragraph) => {\n if (\n estimateSchematicTextWidth(paragraph, fontSize, fontFamily) <=\n maximumWidth\n ) {\n return [paragraph]\n }\n const lines: string[] = []\n let line = \"\"\n for (const word of paragraph.split(/\\s+/u)) {\n if (!line) line = word\n else if (\n estimateSchematicTextWidth(`${line} ${word}`, fontSize, fontFamily) <=\n maximumWidth\n ) {\n line = `${line} ${word}`\n } else {\n lines.push(line)\n line = word\n }\n }\n if (line) lines.push(line)\n return lines.length > 0 ? lines : [paragraph]\n })\n}\n\nfunction estimateSchematicTextWidth(\n text: string,\n fontSize: number,\n fontFamily: string,\n): number {\n if (/courier|mono/iu.test(fontFamily)) return text.length * fontSize * 0.6\n if (!/times|cambria|serif/iu.test(fontFamily)) {\n return text.length * fontSize * 0.52\n }\n return [...text].reduce((width, character) => {\n const emWidth =\n character === \" \"\n ? 0.23\n : /[ilI1.,:;!'`|]/u.test(character)\n ? 0.2\n : /[mwMW@%]/u.test(character)\n ? 0.7\n : /[A-Z0-9]/u.test(character)\n ? 0.5\n : 0.4\n return width + emWidth * fontSize\n }, 0)\n}\n\nexport function altiumColorToCss(\n raw: string | undefined,\n fallback: string,\n): string {\n if (raw === undefined) return fallback\n const colorValue = Number(raw)\n if (!Number.isInteger(colorValue) || colorValue < 0) return fallback\n const red = colorValue & 0xff\n const green = (colorValue >>> 8) & 0xff\n const blue = (colorValue >>> 16) & 0xff\n return `#${toHex(red)}${toHex(green)}${toHex(blue)}`\n}\n\nfunction toHex(value: number): string {\n return value.toString(16).padStart(2, \"0\")\n}\n","import type { AltiumRecord } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicPath,\n SchematicText,\n} from \"circuit-json\"\nimport { getLocation, scalePoint } from \"./coordinates\"\nimport {\n altiumColorToCss,\n createDirectText,\n createLine,\n getFontSize,\n} from \"./render-text\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\n\nexport interface SymbolRenderOptions {\n includeHidden?: boolean\n includeText?: boolean\n}\n\nexport function renderHierarchicalPort({\n record,\n index,\n context,\n options,\n color,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: SymbolRenderOptions\n color: string\n}): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const width = Math.max(Number(record.getCaseInsensitive(\"WIDTH\") ?? 16), 10)\n const height = Math.max(Number(record.getCaseInsensitive(\"HEIGHT\") ?? 10), 4)\n const halfHeight = height / 2\n const pointDepth = Math.min(width * 0.22, height)\n const ioType = Number(record.getCaseInsensitive(\"IOTYPE\") ?? 0)\n const points =\n ioType === 1\n ? [\n { x: location.x, y: location.y },\n { x: location.x + pointDepth, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x + pointDepth, y: location.y - halfHeight },\n ]\n : ioType === 2\n ? [\n { x: location.x, y: location.y + halfHeight },\n {\n x: location.x + width - pointDepth,\n y: location.y + halfHeight,\n },\n { x: location.x + width, y: location.y },\n {\n x: location.x + width - pointDepth,\n y: location.y - halfHeight,\n },\n { x: location.x, y: location.y - halfHeight },\n ]\n : [\n { x: location.x, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x, y: location.y - halfHeight },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const name = record.getDecoded(\"NAME\")\n if (name && options.includeText !== false) {\n elements.push(\n createDirectText({\n id: `schematic_port_text_altium_${index}`,\n text: name,\n location: { x: location.x + width / 2, y: location.y },\n fontSize: getFontSize(record, context),\n color: altiumColorToCss(record.getCaseInsensitive(\"TEXTCOLOR\"), color),\n scale: context.scale,\n rotation: 0,\n anchor: \"center\",\n }),\n )\n }\n return elements\n}\n\nexport function renderPin({\n record,\n index,\n context,\n options,\n color,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: SymbolRenderOptions\n color: string\n}): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const pinConglomerate = record.getNumber(\"PINCONGLOMERATE\")\n const hidden =\n record.getBoolean(\"ISHIDDEN\") ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n if (hidden && !options.includeHidden) return []\n const orientation =\n (pinConglomerate ?? Number(record.getCaseInsensitive(\"ORIENTATION\") ?? 0)) &\n 3\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const length = Math.max(\n Number(record.getCaseInsensitive(\"PINLENGTH\") ?? 10),\n 1,\n )\n const end = {\n x: location.x + direction.x * length,\n y: location.y + direction.y * length,\n }\n const elements: AnyCircuitElement[] = [\n createLine({\n index,\n start: location,\n end,\n color,\n strokeWidth: 0.1,\n scale: context.scale,\n suffix: \"pin\",\n }),\n ]\n if (options.includeText === false) return elements\n const name = record.getDecoded(\"NAME\") ?? \"\"\n const designator = record.getDecoded(\"DESIGNATOR\") ?? \"\"\n const showName =\n pinConglomerate === undefined || (pinConglomerate & 0x08) !== 0\n const showDesignator =\n pinConglomerate === undefined || (pinConglomerate & 0x10) !== 0\n const rotation = orientation === 1 || orientation === 3 ? 90 : 0\n const directionMatchesText = orientation === 0 || orientation === 1\n const textOffset = 2\n if (showName && name) {\n elements.push(\n createDirectText({\n id: `schematic_pin_name_altium_${index}`,\n text: name,\n location: {\n x: location.x - direction.x * textOffset,\n y: location.y - direction.y * textOffset,\n },\n fontSize: 6,\n color,\n scale: context.scale,\n rotation,\n anchor: directionMatchesText ? \"right\" : \"left\",\n }),\n )\n }\n if (showDesignator && designator) {\n elements.push(\n createDirectText({\n id: `schematic_pin_designator_altium_${index}`,\n text: designator,\n location: {\n x: location.x + direction.x * textOffset,\n y: location.y + direction.y * textOffset,\n },\n fontSize: 6,\n color,\n scale: context.scale,\n rotation,\n anchor: directionMatchesText ? \"left\" : \"right\",\n }),\n )\n }\n return elements\n}\n\nexport function renderPowerPort({\n record,\n index,\n context,\n options,\n color,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: SymbolRenderOptions\n color: string\n}): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const perpendicular = { x: -direction.y, y: direction.x }\n const point = (along: number, across = 0) => ({\n x: location.x + direction.x * along + perpendicular.x * across,\n y: location.y + direction.y * along + perpendicular.y * across,\n })\n const line = (\n start: { x: number; y: number },\n end: { x: number; y: number },\n suffix: string,\n ) =>\n createLine({\n index,\n start,\n end,\n color,\n strokeWidth: 0.1,\n scale: context.scale,\n suffix,\n })\n const style = Math.round(Number(record.getCaseInsensitive(\"STYLE\") ?? 2))\n const elements: AnyCircuitElement[] = []\n let labelDistance: number\n if (style === 2) {\n elements.push(\n line(location, point(8), \"power_port_stem\"),\n line(point(8, -5), point(8, 5), \"power_port_bar\"),\n )\n labelDistance = 12\n } else if (style === 5) {\n elements.push(line(location, point(4), \"power_port_stem\"), {\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [point(4, -7), point(4, 7), point(12)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n is_filled: false,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 16\n } else if (style === 4) {\n elements.push(\n line(location, point(4), \"power_port_stem\"),\n ...[\n { along: 4, halfWidth: 7 },\n { along: 8, halfWidth: 4.5 },\n { along: 12, halfWidth: 2 },\n ].map(({ along, halfWidth }, lineIndex) =>\n line(\n point(along, -halfWidth),\n point(along, halfWidth),\n `power_port_ground_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 16\n } else if (style === 6) {\n elements.push(\n line(location, point(4), \"power_port_stem\"),\n line(point(4, -7), point(4, 7), \"power_port_chassis_bar\"),\n ...[\n { from: -7, to: -9 },\n { from: 0, to: -2 },\n { from: 7, to: 5 },\n ].map(({ from, to }, lineIndex) =>\n line(point(4, from), point(9, to), `power_port_chassis_${lineIndex}`),\n ),\n )\n labelDistance = 14\n } else {\n elements.push({\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [location, point(10, -5), point(10, 5)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: color,\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 14\n }\n const text = record.getDecoded(\"TEXT\") ?? record.getDecoded(\"NAME\")\n if (\n text &&\n options.includeText !== false &&\n record.getBoolean(\"SHOWNETNAME\") !== false\n ) {\n const vertical = direction.y !== 0\n const anchor: SchematicText[\"anchor\"] = vertical\n ? direction.y > 0\n ? \"bottom_center\"\n : \"top_center\"\n : direction.x > 0\n ? \"center_left\"\n : \"center_right\"\n elements.push(\n createDirectText({\n id: `schematic_power_port_text_altium_${index}`,\n text,\n location: point(labelDistance),\n fontSize: getFontSize(record, context),\n color,\n scale: context.scale,\n rotation: 0,\n anchor,\n }),\n )\n }\n return elements\n}\n","import type { AltiumRecord } from \"altiumts\"\nimport type { AnyCircuitElement, SchematicCircle } from \"circuit-json\"\nimport type { ConvertAltiumSchDocOptions } from \"../convert-altium-sch-doc-to-circuit-json\"\nimport { getLocation, scalePoint } from \"./coordinates\"\nimport { renderPrimitiveRecord } from \"./render-primitives\"\nimport {\n renderHierarchicalPort,\n renderPin,\n renderPowerPort,\n} from \"./render-symbols\"\nimport { altiumColorToCss, createLine, renderTextRecord } from \"./render-text\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\nexport function convertSchematicRecord(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n): AnyCircuitElement[] {\n const kind = record.recordKind\n const scale = context.scale\n const color = altiumColorToCss(record.getCaseInsensitive(\"COLOR\"), \"#1f2937\")\n const strokeWidth = Math.max(\n Number(record.getCaseInsensitive(\"LINEWIDTH\") ?? 1) * scale,\n 0.05,\n )\n\n const primitive = renderPrimitiveRecord({\n record,\n index,\n context,\n color,\n strokeWidth,\n })\n if (primitive) return primitive\n\n if (kind === \"2\") {\n return renderPin({ record, index, context, options, color })\n }\n\n if (kind === \"29\") {\n const location = getLocation(record)\n if (!location) return []\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_junction_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(location, scale),\n radius: Math.max(\n Number(record.getCaseInsensitive(\"SIZE\") ?? 1) * 0.18,\n 0.15,\n ),\n color,\n is_filled: true,\n fill_color: color,\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n\n if (kind === \"22\") {\n const location = getLocation(record)\n if (!location) return []\n // altiumts renders the \"Small Cross\" no-ERC symbol with four Altium\n // coordinate units on either side of its anchor.\n const radius = 4\n const noErcStrokeWidth = Math.max(scale, 0.02)\n return [\n createLine({\n index,\n start: { x: location.x - radius, y: location.y - radius },\n end: { x: location.x + radius, y: location.y + radius },\n color,\n strokeWidth: noErcStrokeWidth,\n scale,\n suffix: \"a\",\n }),\n createLine({\n index,\n start: { x: location.x + radius, y: location.y - radius },\n end: { x: location.x - radius, y: location.y + radius },\n color,\n strokeWidth: noErcStrokeWidth,\n scale,\n suffix: \"b\",\n }),\n ]\n }\n\n if (kind === \"17\") {\n return renderPowerPort({ record, index, context, options, color })\n }\n\n if (kind === \"18\") {\n return renderHierarchicalPort({ record, index, context, options, color })\n }\n\n const textElement = renderTextRecord({\n record,\n index,\n context,\n options,\n color,\n strokeWidth,\n })\n if (textElement) return textElement\n\n return []\n}\n","import type { AltiumSchDoc } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicGroup,\n SchematicSheet,\n} from \"circuit-json\"\nimport { convertSemanticSchematic } from \"./schematic/convert-semantic-schematic\"\nimport { convertSchematicRecord as renderSchematicRecord } from \"./schematic/render-record\"\nimport {\n createSheetBorder,\n getAltiumSheetDimensions,\n getPageFitScale,\n SCHEMATIC_SHEET_ID,\n type SchematicContext,\n shouldRenderSchematicRecord,\n translateSchematicElement,\n} from \"./schematic/sheet-layout\"\nexport interface ConvertAltiumSchDocOptions {\n centerOnSchematicSheet?: boolean\n includeHidden?: boolean\n includeSheetBorder?: boolean\n includeText?: boolean\n schematicUnitScale?: number\n sheetName?: string\n}\n\nexport function convertAltiumSchDocToCircuitJson(\n document: AltiumSchDoc,\n options: ConvertAltiumSchDocOptions = {},\n): AnyCircuitElement[] {\n const records = document.records\n const sheetRecord = records.find((record) => record.recordKind === \"31\")\n const sheetDimensions = getAltiumSheetDimensions(sheetRecord)\n const scale = options.schematicUnitScale ?? getPageFitScale(sheetDimensions)\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(\"schematicUnitScale must be a positive finite number\")\n }\n\n const context: SchematicContext = { document, records, scale, sheetRecord }\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_sheet\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n name: options.sheetName ?? \"Altium schematic\",\n outline_color: \"#334155\",\n sheet_index: 0,\n } satisfies SchematicSheet,\n ]\n\n if (options.includeSheetBorder === true) {\n elements.push(createSheetBorder(sheetRecord, scale))\n }\n\n const semanticConversion = convertSemanticSchematic(document, {\n includeHidden: options.includeHidden,\n includeText: options.includeText,\n scale,\n schematicSheetId: SCHEMATIC_SHEET_ID,\n })\n elements.push(...semanticConversion.elements)\n\n for (const [index, record] of records.entries()) {\n if (semanticConversion.handledRecords.has(record)) continue\n if (!shouldRenderSchematicRecord(record, context)) continue\n const converted = renderSchematicRecord(record, index, context, options)\n elements.push(...converted)\n }\n\n const schematicComponentIds = elements\n .filter(\n (\n element,\n ): element is Extract<\n AnyCircuitElement,\n { type: \"schematic_component\" }\n > => element.type === \"schematic_component\",\n )\n .map((element) => element.schematic_component_id)\n if (schematicComponentIds.length > 0) {\n elements.push({\n type: \"schematic_group\",\n schematic_group_id: \"schematic_group_altium\",\n source_group_id: \"source_group_altium\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: {\n x: (sheetDimensions.width * scale) / 2,\n y: (sheetDimensions.height * scale) / 2,\n },\n width: sheetDimensions.width * scale,\n height: sheetDimensions.height * scale,\n schematic_component_ids: schematicComponentIds,\n name: options.sheetName ?? \"Altium schematic\",\n } satisfies SchematicGroup)\n }\n\n if (options.centerOnSchematicSheet === false) return elements\n\n const offset = {\n x: (-sheetDimensions.width * scale) / 2,\n y: (-sheetDimensions.height * scale) / 2,\n }\n return elements.map((element) => translateSchematicElement(element, offset))\n}\n","import {\n AltiumBinaryPcbDoc,\n AltiumPcbDoc,\n type AltiumPcbDocument,\n AltiumSchDoc,\n parseAltiumFile,\n parseAltiumPcbDoc,\n parseAltiumSchDoc,\n} from \"altiumts\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport {\n type ConvertAltiumPcbDocOptions,\n convertAltiumPcbDocToCircuitJson,\n} from \"./convert-altium-pcb-doc-to-circuit-json\"\nimport {\n type ConvertAltiumSchDocOptions,\n convertAltiumSchDocToCircuitJson,\n} from \"./convert-altium-sch-doc-to-circuit-json\"\n\nexport type AltiumSourceType = \"auto\" | \"pcb\" | \"schematic\"\n\nexport interface ConvertAltiumToCircuitJsonOptions {\n pcb?: ConvertAltiumPcbDocOptions\n schematic?: ConvertAltiumSchDocOptions\n sourceType?: AltiumSourceType\n}\n\nexport type SupportedAltiumDocument = AltiumPcbDocument | AltiumSchDoc\n\nexport function convertAltiumToCircuitJson(\n source: ArrayBuffer | Uint8Array | string,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n const sourceType = options.sourceType ?? \"auto\"\n\n if (sourceType === \"pcb\") {\n if (typeof source === \"string\") {\n return convertAltiumPcbDocToCircuitJson(\n parseAltiumPcbDoc(source),\n options.pcb,\n )\n }\n const { document } = parseAltiumFile(toUint8Array(source))\n if (\n !(document instanceof AltiumPcbDoc) &&\n !(document instanceof AltiumBinaryPcbDoc)\n ) {\n throw new TypeError(\n `Expected an Altium PCB document, got ${document.type}`,\n )\n }\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n if (sourceType === \"schematic\") {\n return convertAltiumSchDocToCircuitJson(\n parseAltiumSchDoc(normalizeSchematicSource(source)),\n options.schematic,\n )\n }\n\n const bytes = toUint8Array(source)\n const { document } = parseAltiumFile(bytes)\n return convertAltiumDocumentToCircuitJson(document, options)\n}\n\nexport function convertAltiumDocumentToCircuitJson(\n document: unknown,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n if (document instanceof AltiumSchDoc) {\n return convertAltiumSchDocToCircuitJson(document, options.schematic)\n }\n if (\n document instanceof AltiumPcbDoc ||\n document instanceof AltiumBinaryPcbDoc\n ) {\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n const type =\n typeof document === \"object\" && document !== null && \"type\" in document\n ? String(document.type)\n : typeof document\n throw new TypeError(`Unsupported Altium document type: ${type}`)\n}\n\nfunction toUint8Array(source: ArrayBuffer | Uint8Array | string): Uint8Array {\n if (typeof source === \"string\") return new TextEncoder().encode(source)\n if (source instanceof Uint8Array) return source\n return new Uint8Array(source)\n}\n\nfunction normalizeSchematicSource(\n source: ArrayBuffer | Uint8Array | string,\n): Uint8Array | string {\n return source instanceof ArrayBuffer ? new Uint8Array(source) : source\n}\n"],"mappings":"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","names":["symbolPort","getLocation","getCoordinate","getCorner","getRectangle","scalePoint","getSchematicRecordPoints","getLocation","getRectangle","getCoordinate","scalePoint","getSchematicRecordPoints","scalePoint","getLocation","getCorner","getRectangle","getCoordinate","getLocation","scalePoint","getLocation","scalePoint","document"]}
|
|
1
|
+
{"version":3,"sources":["../lib/convert-altium-pcb-doc-to-circuit-json.ts","../lib/schematic/convert-semantic-schematic.ts","../lib/schematic/geometry.ts","../lib/schematic/ids.ts","../lib/schematic/symbols.ts","../lib/schematic/coordinates.ts","../lib/schematic/render-primitives.ts","../lib/schematic/sheet-layout.ts","../lib/schematic/render-text.ts","../lib/schematic/render-symbols.ts","../lib/schematic/render-record.ts","../lib/convert-altium-sch-doc-to-circuit-json.ts","../lib/convert-altium-to-circuit-json.ts"],"sourcesContent":["import {\n AltiumArcRecord,\n AltiumFillRecord,\n AltiumPadRecord,\n type AltiumPcbDocument,\n type AltiumPoint,\n type AltiumRecord,\n AltiumRegionRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n getPcbRegionGeometry,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCourtyardOutline,\n PcbCutout,\n PcbHole,\n PcbPlatedHole,\n PcbSilkscreenLine,\n PcbSilkscreenPath,\n PcbSilkscreenRect,\n PcbSilkscreenText,\n PcbSmtPad,\n PcbTrace,\n PcbVia,\n} from \"circuit-json\"\n\nconst MILS_TO_MILLIMETERS = 0.0254\nconst BOARD_ID = \"pcb_board_altium\"\nconst BOARD_GRAPHICS_COMPONENT_ID = \"pcb_component_altium_board_graphics\"\n\nexport interface ConvertAltiumPcbDocOptions {\n includeBoardOutline?: boolean\n includeComponents?: boolean\n includeCourtyards?: boolean\n includePads?: boolean\n includeSilkscreen?: boolean\n includeTraces?: boolean\n includeVias?: boolean\n}\n\nexport function convertAltiumPcbDocToCircuitJson(\n document: AltiumPcbDocument,\n options: ConvertAltiumPcbDocOptions = {},\n): AnyCircuitElement[] {\n const elements: AnyCircuitElement[] = []\n\n if (options.includeBoardOutline !== false) {\n elements.push(createBoard(document))\n for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {\n if (cutout.outline.points.length < 3) continue\n elements.push({\n type: \"pcb_cutout\",\n pcb_cutout_id: `pcb_cutout_altium_${index}`,\n pcb_board_id: BOARD_ID,\n shape: \"polygon\",\n points: cutout.outline.points.map(toMillimeterPoint),\n } satisfies PcbCutout)\n }\n }\n\n if (options.includeComponents !== false) {\n for (const [index, component] of document.components.entries()) {\n const position = component.position\n if (!position) continue\n const bounds = document.getComponentBounds(component)\n elements.push({\n type: \"pcb_component\",\n pcb_component_id: componentId(index),\n source_component_id: `source_component_altium_${index}`,\n center: toMillimeterPoint(position),\n width: milsToMillimeters(\n bounds ? bounds.maxX - bounds.minX : (component.heightMils ?? 20),\n ),\n height: milsToMillimeters(\n bounds ? bounds.maxY - bounds.minY : (component.heightMils ?? 20),\n ),\n layer: component.side === \"bottom\" ? \"bottom\" : \"top\",\n rotation: component.rotation,\n position_mode: \"none\",\n obstructs_within_bounds: false,\n } satisfies PcbComponent)\n }\n }\n\n if (\n options.includeCourtyards !== false &&\n options.includeComponents !== false\n ) {\n elements.push(...convertCourtyards(document))\n }\n\n for (const [index, record] of document.records.entries()) {\n if (record instanceof AltiumPadRecord && options.includePads !== false) {\n const pad = convertPad(record, index)\n if (pad) elements.push(pad)\n continue\n }\n\n if (record instanceof AltiumTrackRecord) {\n if (isCourtyardLayer(record.layer)) continue\n if (isOverlayLayer(record.layer)) {\n if (options.includeSilkscreen === false) continue\n const line = convertSilkscreenLine(record, index)\n if (line) elements.push(line)\n } else if (options.includeTraces !== false) {\n const trace = convertTrack(record, index)\n if (trace) elements.push(trace)\n }\n continue\n }\n\n if (record instanceof AltiumViaRecord && options.includeVias !== false) {\n const via = convertVia(record, index)\n if (via) elements.push(via)\n continue\n }\n\n if (\n options.includeSilkscreen === false ||\n !isOverlayLayer(getLayer(record))\n ) {\n continue\n }\n\n if (record instanceof AltiumArcRecord) {\n const path = convertSilkscreenArc(record, index)\n if (path) elements.push(path)\n } else if (record instanceof AltiumFillRecord) {\n const rect = convertSilkscreenFill(record, index)\n if (rect) elements.push(rect)\n } else if (record instanceof AltiumTextRecord) {\n const text = convertSilkscreenText(record, index)\n if (text) elements.push(text)\n }\n }\n\n return elements\n}\n\ninterface CourtyardPath {\n componentId: string\n layer: \"top\" | \"bottom\"\n points: AltiumPoint[]\n strokeWidthMils: number\n}\n\nfunction convertCourtyards(document: AltiumPcbDocument): PcbCourtyardOutline[] {\n const componentIds = new Map(\n document.components.flatMap((component, index) =>\n component.position ? [[component, componentId(index)] as const] : [],\n ),\n )\n const paths: CourtyardPath[] = []\n\n for (const record of document.records) {\n const layer = getLayer(record)\n if (!isCourtyardLayer(layer)) continue\n const component = document.getComponentForRecord(record)\n const ownedComponentId = component ? componentIds.get(component) : undefined\n if (!ownedComponentId) continue\n const points = getCourtyardRecordPoints(record)\n if (points.length < 2) continue\n paths.push({\n componentId: ownedComponentId,\n layer: mapCourtyardLayer(layer),\n points,\n strokeWidthMils:\n record instanceof AltiumTrackRecord || record instanceof AltiumArcRecord\n ? (record.widthMils ?? 4)\n : 0,\n })\n }\n\n const courtyards: PcbCourtyardOutline[] = []\n for (const path of stitchCourtyardPaths(paths)) {\n if (!isClosedAltiumPath(path.points)) continue\n const outline = removeClosingPoint(path.points).map(toMillimeterPoint)\n if (outline.length < 3) continue\n courtyards.push({\n type: \"pcb_courtyard_outline\",\n pcb_courtyard_outline_id: `pcb_courtyard_outline_altium_${courtyards.length}`,\n pcb_component_id: path.componentId,\n layer: path.layer,\n outline,\n })\n }\n return courtyards\n}\n\nfunction getCourtyardRecordPoints(record: AltiumRecord): AltiumPoint[] {\n if (record instanceof AltiumTrackRecord) {\n return record.start && record.end ? [record.start, record.end] : []\n }\n if (record instanceof AltiumArcRecord) {\n return record.center && record.radiusMils\n ? approximateArc({\n center: record.center,\n radius: record.radiusMils,\n startAngle: record.startAngle,\n endAngle: record.endAngle,\n })\n : []\n }\n if (record instanceof AltiumRegionRecord) {\n return getPcbRegionGeometry(record).outline.points\n }\n return []\n}\n\nfunction stitchCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const groups = new Map<string, CourtyardPath[]>()\n for (const path of deduplicateCourtyardPaths(paths)) {\n const key = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n ].join(\"|\")\n const group = groups.get(key) ?? []\n group.push(path)\n groups.set(key, group)\n }\n return [...groups.values()].flatMap(stitchCourtyardPathGroup)\n}\n\nfunction stitchCourtyardPathGroup(group: CourtyardPath[]): CourtyardPath[] {\n const remaining = [...group]\n const stitched: CourtyardPath[] = []\n while (remaining.length > 0) {\n const first = remaining.shift()\n if (!first) break\n const path = { ...first, points: [...first.points] }\n while (appendConnectedCourtyardPath(path, remaining)) {\n // Continue until no segment can extend either end of this path.\n }\n stitched.push(path)\n }\n return stitched\n}\n\nfunction appendConnectedCourtyardPath(\n stitched: CourtyardPath,\n remaining: CourtyardPath[],\n): boolean {\n const stitchedStart = stitched.points[0]\n const stitchedEnd = stitched.points.at(-1)\n if (!stitchedStart || !stitchedEnd) return false\n\n for (const [index, candidate] of remaining.entries()) {\n const candidateStart = candidate.points[0]\n const candidateEnd = candidate.points.at(-1)\n if (!candidateStart || !candidateEnd) continue\n if (altiumPointsApproximatelyEqual(stitchedEnd, candidateStart)) {\n stitched.points.push(...candidate.points.slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedEnd, candidateEnd)) {\n stitched.points.push(...candidate.points.toReversed().slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateEnd)) {\n stitched.points.unshift(...candidate.points.slice(0, -1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateStart)) {\n stitched.points.unshift(...candidate.points.toReversed().slice(0, -1))\n } else {\n continue\n }\n remaining.splice(index, 1)\n return true\n }\n return false\n}\n\nfunction deduplicateCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const signatures = new Set<string>()\n return paths.filter((path) => {\n const forwardPoints = path.points.map(formatAltiumPoint).join(\"|\")\n const reversePoints = path.points\n .toReversed()\n .map(formatAltiumPoint)\n .join(\"|\")\n const pointsSignature =\n forwardPoints < reversePoints ? forwardPoints : reversePoints\n const signature = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n pointsSignature,\n ].join(\"|\")\n if (signatures.has(signature)) return false\n signatures.add(signature)\n return true\n })\n}\n\nfunction formatAltiumPoint(point: AltiumPoint): string {\n return `${point.x.toFixed(4)},${point.y.toFixed(4)}`\n}\n\nfunction isClosedAltiumPath(points: AltiumPoint[]): boolean {\n const first = points[0]\n const last = points.at(-1)\n return Boolean(first && last && altiumPointsApproximatelyEqual(first, last))\n}\n\nfunction removeClosingPoint(points: AltiumPoint[]): AltiumPoint[] {\n const first = points[0]\n const last = points.at(-1)\n return first && last && altiumPointsApproximatelyEqual(first, last)\n ? points.slice(0, -1)\n : points\n}\n\nfunction altiumPointsApproximatelyEqual(\n left: AltiumPoint,\n right: AltiumPoint,\n): boolean {\n return (\n Math.abs(left.x - right.x) <= 0.01 && Math.abs(left.y - right.y) <= 0.01\n )\n}\n\nfunction createBoard(document: AltiumPcbDocument): PcbBoard {\n const outline = document.boardGeometry.outline.points.map(toMillimeterPoint)\n const bounds =\n getAltiumBounds(document.boardGeometry.outline.points) ??\n getFallbackPcbBounds(document.records)\n const width = Math.max(milsToMillimeters(bounds.maxX - bounds.minX), 0.1)\n const height = Math.max(milsToMillimeters(bounds.maxY - bounds.minY), 0.1)\n const numLayers = document.board\n ? Math.max(\n getPcbLayerStack(document.board).entries.filter((entry) =>\n Boolean(mapCopperLayer(entry.name ?? entry.layerId)),\n ).length,\n 2,\n )\n : 2\n\n return {\n type: \"pcb_board\",\n pcb_board_id: BOARD_ID,\n center: {\n x: milsToMillimeters((bounds.minX + bounds.maxX) / 2),\n y: milsToMillimeters((bounds.minY + bounds.maxY) / 2),\n },\n width,\n height,\n ...(outline.length >= 3 ? { shape: \"polygon\" as const, outline } : {}),\n thickness: 1.6,\n num_layers: numLayers,\n material: \"fr4\",\n }\n}\n\nfunction getFallbackPcbBounds(records: AltiumRecord[]): {\n maxX: number\n maxY: number\n minX: number\n minY: number\n} {\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (\n record instanceof AltiumPadRecord ||\n record instanceof AltiumViaRecord\n ) {\n if (record.position) points.push(record.position)\n } else if (record instanceof AltiumTrackRecord) {\n if (record.start) points.push(record.start)\n if (record.end) points.push(record.end)\n }\n }\n return getAltiumBounds(points) ?? { minX: 0, minY: 0, maxX: 1000, maxY: 800 }\n}\n\nfunction convertTrack(\n record: AltiumTrackRecord,\n index: number,\n): PcbTrace | undefined {\n const start = record.start\n const end = record.end\n const layer = mapCopperLayer(record.layer)\n if (!start || !end || !layer) return undefined\n const width = milsToMillimeters(record.widthMils ?? 4)\n return {\n type: \"pcb_trace\",\n pcb_trace_id: `pcb_trace_altium_${index}`,\n should_round_corners: true,\n route: [\n { route_type: \"wire\", ...toMillimeterPoint(start), width, layer },\n { route_type: \"wire\", ...toMillimeterPoint(end), width, layer },\n ],\n }\n}\n\nfunction convertVia(\n record: AltiumViaRecord,\n index: number,\n): PcbVia | undefined {\n if (!record.position) return undefined\n const startLayer = mapCopperLayer(record.startLayer) ?? \"top\"\n const endLayer = mapCopperLayer(record.endLayer) ?? \"bottom\"\n const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer]\n const outerDiameter = milsToMillimeters(record.diameterMils ?? 20)\n return {\n type: \"pcb_via\",\n pcb_via_id: `pcb_via_altium_${index}`,\n ...toMillimeterPoint(record.position),\n outer_diameter: outerDiameter,\n hole_diameter: milsToMillimeters(\n record.holeSizeMils ?? (record.diameterMils ?? 20) * 0.45,\n ),\n layers,\n is_tented: record.tentedTop === true && record.tentedBottom === true,\n }\n}\n\nfunction convertPad(\n record: AltiumPadRecord,\n index: number,\n): PcbSmtPad | PcbPlatedHole | PcbHole | undefined {\n const position = record.position\n const size = record.size\n if (!position || !size) return undefined\n const x = milsToMillimeters(position.x)\n const y = milsToMillimeters(position.y)\n const width = milsToMillimeters(size.width)\n const height = milsToMillimeters(size.height)\n const holeDiameter = milsToMillimeters(record.holeSizeMils ?? 0)\n const shape = normalizeShape(record.shape)\n const id = `altium_${index}`\n\n if (record.plated === false && holeDiameter > 0) {\n return {\n type: \"pcb_hole\",\n pcb_hole_id: `pcb_hole_${id}`,\n hole_shape: \"circle\",\n hole_diameter: holeDiameter,\n x,\n y,\n }\n }\n\n if (record.behavior === \"through-hole\" || holeDiameter > 0) {\n const slotLengthMils = getMeasurement(record, \"SLOTLENGTH\")\n const holeWidthMils = record.holeWidthMils ?? record.holeSizeMils\n const isSlot =\n normalizeShape(record.holeType).includes(\"SLOT\") ||\n (slotLengthMils ?? 0) > (record.holeSizeMils ?? 0) ||\n (holeWidthMils ?? 0) > (record.holeSizeMils ?? 0)\n const layers: LayerRef[] = [\"top\", \"bottom\"]\n\n if (isSlot) {\n const holeWidth = milsToMillimeters(\n Math.max(\n slotLengthMils ?? holeWidthMils ?? record.holeSizeMils ?? 1,\n 1,\n ),\n )\n const holeHeight = Math.max(holeDiameter, MILS_TO_MILLIMETERS)\n if (isRectangularShape(shape)) {\n const rotated = record.holeRotation !== 0 || record.rotation !== 0\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: rotated\n ? \"rotated_pill_hole_with_rect_pad\"\n : \"pill_hole_with_rect_pad\",\n hole_shape: rotated ? \"rotated_pill\" : \"pill\",\n pad_shape: \"rect\",\n hole_width: holeWidth,\n hole_height: holeHeight,\n ...(rotated ? { hole_ccw_rotation: record.holeRotation } : {}),\n rect_pad_width: width,\n rect_pad_height: height,\n ...(rotated ? { rect_ccw_rotation: record.rotation } : {}),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n } as PcbPlatedHole\n }\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: holeWidth,\n hole_height: holeHeight,\n ccw_rotation: record.holeRotation || record.rotation,\n x,\n y,\n layers,\n }\n }\n\n if (isRectangularShape(shape)) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circular_hole_with_rect_pad\",\n hole_shape: \"circle\",\n pad_shape: \"rect\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n rect_pad_width: width,\n rect_pad_height: height,\n rect_border_radius: shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : 0,\n rect_ccw_rotation: record.rotation,\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"hole_with_polygon_pad\",\n hole_shape: \"circle\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n pad_outline: createOctagonPoints({\n x,\n y,\n width,\n height,\n rotation: record.rotation,\n }),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) >= 0.0001) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n hole_height: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n ccw_rotation: record.rotation,\n x,\n y,\n layers,\n }\n }\n }\n\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circle\",\n outer_diameter: Math.max(width, height),\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n x,\n y,\n layers,\n }\n }\n\n const layer = mapCopperLayer(record.layer)\n if (!layer) return undefined\n const base = {\n type: \"pcb_smtpad\" as const,\n pcb_smtpad_id: `pcb_smtpad_${id}`,\n x,\n y,\n layer,\n soldermask_margin:\n record.solderMaskExpansionMils === undefined\n ? undefined\n : milsToMillimeters(record.solderMaskExpansionMils),\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n ...base,\n shape: \"polygon\",\n points: createOctagonPoints({\n x,\n y,\n width,\n height,\n rotation: record.rotation,\n }),\n }\n }\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) < 0.0001) {\n return { ...base, shape: \"circle\", radius: width / 2 }\n }\n return record.rotation === 0\n ? {\n ...base,\n shape: \"pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n }\n : {\n ...base,\n shape: \"rotated_pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n ccw_rotation: record.rotation,\n }\n }\n\n const cornerRadius = shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : undefined\n return record.rotation === 0\n ? { ...base, shape: \"rect\", width, height, corner_radius: cornerRadius }\n : {\n ...base,\n shape: \"rotated_rect\",\n width,\n height,\n corner_radius: cornerRadius,\n ccw_rotation: record.rotation,\n }\n}\n\nfunction convertSilkscreenLine(\n record: AltiumTrackRecord,\n index: number,\n): PcbSilkscreenLine | undefined {\n if (!record.start || !record.end) return undefined\n return {\n type: \"pcb_silkscreen_line\",\n pcb_silkscreen_line_id: `pcb_silkscreen_line_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n ...withNumberedPoints(record.start, record.end),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenArc(\n record: AltiumArcRecord,\n index: number,\n): PcbSilkscreenPath | undefined {\n if (!record.center || !record.radiusMils) return undefined\n const points = approximateArc({\n center: record.center,\n radius: record.radiusMils,\n startAngle: record.startAngle,\n endAngle: record.endAngle,\n })\n return {\n type: \"pcb_silkscreen_path\",\n pcb_silkscreen_path_id: `pcb_silkscreen_path_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n route: points.map(toMillimeterPoint),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenFill(\n record: AltiumFillRecord,\n index: number,\n): PcbSilkscreenRect | undefined {\n if (!record.bounds) return undefined\n const width = milsToMillimeters(record.bounds.maxX - record.bounds.minX)\n const height = milsToMillimeters(record.bounds.maxY - record.bounds.minY)\n return {\n type: \"pcb_silkscreen_rect\",\n pcb_silkscreen_rect_id: `pcb_silkscreen_rect_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n center: {\n x: milsToMillimeters((record.bounds.minX + record.bounds.maxX) / 2),\n y: milsToMillimeters((record.bounds.minY + record.bounds.maxY) / 2),\n },\n width,\n height,\n stroke_width: Math.min(width, height),\n is_filled: true,\n has_stroke: false,\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenText(\n record: AltiumTextRecord,\n index: number,\n): PcbSilkscreenText | undefined {\n const text =\n decodeAltiumWideString(record.getDecoded(\"WIDESTRING\")) ||\n record.getDecoded(\"TEXT\") ||\n record.text\n if (!record.position || !text) return undefined\n return {\n type: \"pcb_silkscreen_text\",\n pcb_silkscreen_text_id: `pcb_silkscreen_text_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n text,\n font: \"tscircuit2024\",\n font_size: milsToMillimeters(record.heightMils ?? 30),\n anchor_position: toMillimeterPoint(record.position),\n anchor_alignment: mapTextAnchor(record.justification),\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n is_mirrored: record.mirrored,\n }\n}\n\nfunction decodeAltiumWideString(raw: string | undefined): string {\n if (!raw) return \"\"\n if (!/^\\d+(?:,\\d+)*$/u.test(raw)) return raw\n try {\n return String.fromCodePoint(...raw.split(\",\").map(Number))\n } catch {\n return raw\n }\n}\n\nfunction pcbComponentIdForRecord(record: AltiumRecord): string {\n const index = record.getNumber(\"COMPONENT\")\n return index === undefined || index < 0\n ? BOARD_GRAPHICS_COMPONENT_ID\n : componentId(index)\n}\n\nfunction componentId(index: number): string {\n return `pcb_component_altium_${index}`\n}\n\nfunction mapTextAnchor(\n justification: string | undefined,\n): \"bottom_left\" | \"bottom_center\" | \"bottom_right\" | \"center\" {\n const normalized = justification?.replace(/[\\s_-]+/gu, \"\").toUpperCase()\n if (normalized?.includes(\"CENTER\")) return \"bottom_center\"\n if (normalized?.includes(\"RIGHT\")) return \"bottom_right\"\n if (normalized?.includes(\"LEFT\")) return \"bottom_left\"\n return \"center\"\n}\n\nfunction mapCopperLayer(layer: string | undefined): LayerRef | undefined {\n const normalized = normalizeLayer(layer)\n if (normalized === \"TOP\" || normalized === \"TOPLAYER\") return \"top\"\n if (normalized === \"BOTTOM\" || normalized === \"BOTTOMLAYER\") return \"bottom\"\n const innerMatch = /^(?:MID|MIDLAYER|INTERNALPLANE)(\\d+)$/u.exec(normalized)\n if (!innerMatch?.[1]) return undefined\n const innerNumber = Math.min(Math.max(Number(innerMatch[1]), 1), 8)\n return `inner${innerNumber}` as LayerRef\n}\n\nfunction isOverlayLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"TOPOVERLAY\" || normalized === \"BOTTOMOVERLAY\"\n}\n\nfunction isCourtyardLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"MECHANICAL15\" || normalized === \"MECHANICAL16\"\n}\n\nfunction mapCourtyardLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"MECHANICAL16\" ? \"bottom\" : \"top\"\n}\n\nfunction mapOverlayLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"BOTTOMOVERLAY\" ? \"bottom\" : \"top\"\n}\n\nfunction getLayer(record: AltiumRecord): string | undefined {\n return record.getDecoded(\"LAYER\")\n}\n\nfunction normalizeLayer(layer: string | undefined): string {\n return (layer ?? \"\").replace(/[\\s_.-]+/gu, \"\").toUpperCase()\n}\n\nfunction normalizeShape(shape: string | undefined): string {\n return (shape ?? \"ROUND\").replace(/[\\s_-]+/gu, \"\").toUpperCase()\n}\n\nfunction isRectangularShape(shape: string): boolean {\n return shape.includes(\"RECT\") || shape === \"SQUARE\"\n}\n\nfunction getMeasurement(record: AltiumRecord, key: string): number | undefined {\n return parseAltiumMeasurementToMils(record.getCaseInsensitive(key))\n}\n\nfunction milsToMillimeters(value: number): number {\n return value * MILS_TO_MILLIMETERS\n}\n\nfunction toMillimeterPoint(point: AltiumPoint): { x: number; y: number } {\n return { x: milsToMillimeters(point.x), y: milsToMillimeters(point.y) }\n}\n\nfunction withNumberedPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n): { x1: number; x2: number; y1: number; y2: number } {\n return {\n x1: milsToMillimeters(start.x),\n y1: milsToMillimeters(start.y),\n x2: milsToMillimeters(end.x),\n y2: milsToMillimeters(end.y),\n }\n}\n\nfunction approximateArc({\n center,\n radius,\n startAngle,\n endAngle,\n}: {\n center: AltiumPoint\n radius: number\n startAngle: number\n endAngle: number\n}): AltiumPoint[] {\n const sweep = endAngle - startAngle || 360\n const segments = Math.max(8, Math.ceil(Math.abs(sweep) / 7.5))\n return Array.from({ length: segments + 1 }, (_, index) => {\n const angle = startAngle + (sweep * index) / segments\n const radians = (angle * Math.PI) / 180\n return {\n x: center.x + Math.cos(radians) * radius,\n y: center.y + Math.sin(radians) * radius,\n }\n })\n}\n\nfunction createOctagonPoints({\n x,\n y,\n width,\n height,\n rotation,\n}: {\n x: number\n y: number\n width: number\n height: number\n rotation: number\n}): Array<{ x: number; y: number }> {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const chamfer = Math.min(width, height) / 4\n const points = [\n { x: -halfWidth + chamfer, y: -halfHeight },\n { x: halfWidth - chamfer, y: -halfHeight },\n { x: halfWidth, y: -halfHeight + chamfer },\n { x: halfWidth, y: halfHeight - chamfer },\n { x: halfWidth - chamfer, y: halfHeight },\n { x: -halfWidth + chamfer, y: halfHeight },\n { x: -halfWidth, y: halfHeight - chamfer },\n { x: -halfWidth, y: -halfHeight + chamfer },\n ]\n const radians = (rotation * Math.PI) / 180\n return points.map((point) => ({\n x: x + point.x * Math.cos(radians) - point.y * Math.sin(radians),\n y: y + point.x * Math.sin(radians) + point.y * Math.cos(radians),\n }))\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicDocumentIndex,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport {\n type AnyCircuitElement,\n type SchematicComponent,\n type SchematicNetLabel,\n type SchematicPort,\n type SchematicText,\n type SchematicTrace,\n type SourceComponentBase,\n type SourceNet,\n type SourcePort,\n type SourceTrace,\n source_simple_capacitor,\n source_simple_crystal,\n source_simple_inductor,\n source_simple_mosfet,\n source_simple_resistor,\n} from \"circuit-json\"\nimport { type BaseTscircuitUnit, parseAndConvertSiUnit } from \"format-si-unit\"\nimport { type SchSymbol, symbols } from \"schematic-symbols\"\nimport {\n type Bounds,\n type CardinalDirection,\n getAveragePoint,\n getBoundsCenter,\n getBoundsForPoints,\n getCorner,\n getDirectionForVector,\n getLocation,\n getPointDistance,\n getRectangle,\n getVectorDifference,\n mergeBounds,\n pointKey,\n pointsEqual,\n scalePoint,\n subtractPoints,\n} from \"./geometry\"\nimport {\n isGroundNet,\n isPowerNet,\n sanitizeId,\n segmentKey,\n uniqueStrings,\n} from \"./ids\"\nimport {\n classifyComponent,\n getMosfetVariant,\n getPrimaryComponentValue,\n isPolarizedCapacitor,\n} from \"./symbols\"\n\nexport interface SemanticSchematicOptions {\n includeHidden?: boolean\n includeText?: boolean\n scale: number\n schematicSheetId: string\n}\n\nexport interface SemanticSchematicConversion {\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n}\n\ninterface ConvertedPort {\n isSchematicVisible: boolean\n point: AltiumPoint\n record: AltiumRecord\n schematicPort: SchematicPort\n sourcePort: SourcePort\n}\n\ninterface SymbolPortAssignment {\n convertedPort: ConvertedPort\n symbolPort: SchSymbol[\"ports\"][number]\n}\n\ninterface SymbolSelection {\n assignments: SymbolPortAssignment[]\n name: string\n symbol: SchSymbol\n}\n\ninterface SemanticNet {\n id: string\n names: string[]\n points: AltiumPoint[]\n records: AltiumRecord[]\n}\n\ninterface SemanticNetGraph {\n getConnectedWiresForRecord(record: AltiumRecord): AltiumRecord[]\n nets: SemanticNet[]\n}\n\ninterface SchematicSegment {\n end: AltiumPoint\n start: AltiumPoint\n}\n\nconst DIRECTION_BY_ORIENTATION: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst VECTOR_BY_DIRECTION: Readonly<Record<CardinalDirection, AltiumPoint>> = {\n down: { x: 0, y: -1 },\n left: { x: -1, y: 0 },\n right: { x: 1, y: 0 },\n up: { x: 0, y: 1 },\n}\n\nconst CARDINAL_DIRECTIONS: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst SYMBOL_CATALOG = symbols as Record<string, SchSymbol | undefined>\nconst SYMBOL_NAMES = Object.keys(SYMBOL_CATALOG)\nconst INLINE_NET_LABEL_COLOR = \"rgb(132, 0, 0)\"\nconst DEFAULT_INLINE_NET_LABEL_FONT_SIZE = 0.18\nconst MIN_INLINE_NET_LABEL_FONT_SIZE = 0.1\nconst INLINE_NET_LABEL_CHARACTER_WIDTH = 0.12\nconst INLINE_NET_LABEL_HORIZONTAL_PADDING = 0.12\n\n/**\n * Converts records that have native Circuit JSON semantics before the\n * primitive fallback runs. This deliberately favors Circuit JSON's component,\n * port, trace, net, and symbol model over reproducing Altium's drawing style.\n */\nexport function convertSemanticSchematic(\n document: AltiumSchDoc,\n options: SemanticSchematicOptions,\n): SemanticSchematicConversion {\n const handledRecords = new Set<AltiumRecord>()\n const elements: AnyCircuitElement[] = []\n const convertedPorts: ConvertedPort[] = []\n\n convertComponents({\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n })\n\n const semanticNetGraph = buildSemanticNetGraph(document, convertedPorts)\n\n const connectivity = convertConnectivity({\n convertedPorts,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n convertNetLabels({\n connectivity,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n return { elements, handledRecords }\n}\n\nfunction convertComponents(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n}): void {\n const { convertedPorts, document, elements, handledRecords, options } = params\n const documentIndex = getSchematicDocumentIndex(document)\n const sourceComponentIdByDesignator = new Map<string, string>()\n\n for (const [componentIndex, componentRecord] of document.records.entries()) {\n if (componentRecord.recordKind !== \"1\") continue\n handledRecords.add(componentRecord)\n\n const ownedRecords = documentIndex.getOwnedRecords(componentRecord)\n for (const ownedRecord of ownedRecords) handledRecords.add(ownedRecord)\n\n const currentPartId = componentRecord.getNumber(\"CURRENTPARTID\") ?? 1\n const visibleOwnedRecords = ownedRecords.filter((record) =>\n isOwnedRecordVisible(record, currentPartId),\n )\n const pins = visibleOwnedRecords.filter(\n (record) =>\n record.recordKind === \"2\" &&\n (!isPinHidden(record) || options.includeHidden === true),\n )\n if (pins.length === 0) continue\n const visibleSymbolLabels = new Set(\n visibleOwnedRecords\n .filter((record) => record.recordKind === \"4\")\n .flatMap((record) => {\n const text = record.getDecoded(\"TEXT\")?.trim().toUpperCase()\n return text ? [text] : []\n }),\n )\n\n const designator =\n findOwnedText(ownedRecords, \"34\", \"Designator\") ??\n componentRecord.getDecoded(\"DESIGNATOR\") ??\n `U${componentIndex}`\n // Altium libraries commonly store the human-readable component value in\n // the named `Value` parameter, while `Comment` may contain a manufacturer\n // part number (or another library-specific description). Prefer the\n // explicit value field and retain the older fallbacks for simpler files.\n const value =\n findOwnedText(ownedRecords, \"41\", \"Value\")?.trim() ||\n findOwnedText(ownedRecords, \"41\", \"Comment\")?.trim() ||\n componentRecord.getDecoded(\"COMMENT\")?.trim() ||\n componentRecord.getDecoded(\"DESIGNITEMID\")?.trim() ||\n componentRecord.getDecoded(\"LIBREFERENCE\")?.trim() ||\n \"\"\n const libraryReference =\n componentRecord.getDecoded(\"LIBREFERENCE\") ??\n componentRecord.getDecoded(\"DESIGNITEMID\") ??\n designator\n const manufacturerPartNumber = findOwnedText(\n ownedRecords,\n \"41\",\n \"Mfr_part_number\",\n )\n const normalizedDesignator = designator.trim().toUpperCase()\n const existingSourceComponentId =\n sourceComponentIdByDesignator.get(normalizedDesignator)\n const sourceComponentId =\n existingSourceComponentId ?? `source_component_altium_${componentIndex}`\n const schematicComponentId = `schematic_component_altium_${componentIndex}`\n if (!existingSourceComponentId) {\n sourceComponentIdByDesignator.set(normalizedDesignator, sourceComponentId)\n elements.push(\n createSourceComponent({\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount: pins.length,\n sourceComponentId,\n value,\n }),\n )\n }\n\n const componentPorts = pins.map((pin, pinIndex) =>\n convertComponentPin({\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n visibleSymbolLabels,\n }),\n )\n const bodyBounds = getComponentBodyBounds(\n visibleOwnedRecords,\n componentPorts.map(({ point }) => point),\n )\n const symbolSelection = selectCircuitJsonSymbol({\n designator,\n libraryReference,\n ports: componentPorts,\n })\n const center = scalePoint(getBoundsCenter(bodyBounds), options.scale)\n const size = symbolSelection\n ? { ...symbolSelection.symbol.size }\n : {\n height: Math.max(\n (bodyBounds.maxY - bodyBounds.minY) * options.scale,\n 0.4,\n ),\n width: Math.max(\n (bodyBounds.maxX - bodyBounds.minX) * options.scale,\n 0.4,\n ),\n }\n if (symbolSelection) {\n applyNativeSymbolPortGeometry({\n center,\n selection: symbolSelection,\n })\n }\n convertedPorts.push(...componentPorts)\n elements.push(\n ...componentPorts.flatMap(\n ({ isSchematicVisible, sourcePort, schematicPort }) => [\n sourcePort,\n ...(isSchematicVisible ? [schematicPort] : []),\n ],\n ),\n )\n const schematicComponent: SchematicComponent = {\n type: \"schematic_component\",\n center,\n // circuit-to-svg uses this flag as the renderable component gate for\n // both generated boxes and components selected by symbol_name.\n is_box_with_pins: true,\n schematic_component_id: schematicComponentId,\n schematic_sheet_id: options.schematicSheetId,\n size,\n source_component_id: sourceComponentId,\n symbol_display_value: value,\n ...(symbolSelection ? { symbol_name: symbolSelection.name } : {}),\n }\n elements.push(schematicComponent)\n\n if (!symbolSelection && options.includeText !== false) {\n elements.push(\n createComponentText({\n anchor: \"bottom_left\",\n component: schematicComponent,\n id: `schematic_component_designator_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y + size.height / 2 + 0.13,\n },\n text: designator,\n }),\n )\n if (value) {\n elements.push(\n createComponentText({\n anchor: \"top_left\",\n component: schematicComponent,\n id: `schematic_component_value_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y - size.height / 2 - 0.13,\n },\n text: value,\n }),\n )\n }\n }\n }\n}\n\nfunction convertComponentPin(params: {\n document: AltiumSchDoc\n options: SemanticSchematicOptions\n pin: AltiumRecord\n pinIndex: number\n schematicComponentId: string\n sourceComponentId: string\n visibleSymbolLabels: Set<string>\n}): ConvertedPort {\n const {\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n visibleSymbolLabels,\n } = params\n const recordIndex = document.records.indexOf(pin)\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n const orientation = (pinConglomerate ?? pin.getNumber(\"ORIENTATION\") ?? 0) & 3\n const direction = DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n const directionVector = VECTOR_BY_DIRECTION[direction]\n const location = getLocation(pin) ?? { x: 0, y: 0 }\n const pinLength = Math.max(pin.getNumber(\"PINLENGTH\") ?? 10, 0)\n const terminalPoint = {\n x: location.x + directionVector.x * pinLength,\n y: location.y + directionVector.y * pinLength,\n }\n const designator = pin.getDecoded(\"DESIGNATOR\") ?? `${pinIndex + 1}`\n const pinNumber = parsePinNumber(designator)\n const name = pin.getDecoded(\"NAME\") ?? designator\n const sourcePortId = `source_port_altium_${recordIndex}`\n const schematicPortId = `schematic_port_altium_${recordIndex}`\n const sourcePort: SourcePort = {\n type: \"source_port\",\n name,\n port_hints: uniqueStrings([\n designator,\n name,\n pinNumber === undefined ? undefined : `pin${pinNumber}`,\n ]),\n source_component_id: sourceComponentId,\n source_port_id: sourcePortId,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n }\n const electricalType = pin.getNumber(\"ELECTRICAL\")\n const normalizedName = name.trim().toUpperCase()\n const functionalName = normalizedName.replace(/\\d+$/u, \"\")\n const showName =\n pinConglomerate === undefined ||\n (pinConglomerate & 0x08) !== 0 ||\n visibleSymbolLabels.has(normalizedName) ||\n visibleSymbolLabels.has(functionalName)\n const schematicPort: SchematicPort = {\n type: \"schematic_port\",\n center: scalePoint(terminalPoint, options.scale),\n ...(showName && name ? { display_pin_label: name } : {}),\n distance_from_component_edge: pinLength * options.scale,\n facing_direction: direction,\n is_connected: false,\n schematic_component_id: schematicComponentId,\n schematic_port_id: schematicPortId,\n schematic_sheet_id: options.schematicSheetId,\n side_of_component: directionToSide(direction),\n source_port_id: sourcePortId,\n true_ccw_index: pinIndex,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n ...(electricalType === 0 || electricalType === 1\n ? { has_input_arrow: true }\n : {}),\n ...(electricalType === 1 || electricalType === 2\n ? { has_output_arrow: true }\n : {}),\n }\n return {\n isSchematicVisible: true,\n point: terminalPoint,\n record: pin,\n schematicPort,\n sourcePort,\n }\n}\n\nfunction createSourceComponent(params: {\n designator: string\n libraryReference: string\n manufacturerPartNumber?: string\n pinCount: number\n sourceComponentId: string\n value: string\n}): AnyCircuitElement {\n const {\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount,\n sourceComponentId,\n value,\n } = params\n const classification = classifyComponent({ designator, libraryReference })\n const primaryValue = getPrimaryComponentValue(value)\n const common = {\n type: \"source_component\" as const,\n display_name: designator,\n display_value: value || undefined,\n manufacturer_part_number: manufacturerPartNumber,\n name: designator,\n source_component_id: sourceComponentId,\n }\n\n if (classification === \"resistor\") {\n const resistance = parseFiniteComponentValue({\n componentUnit: \"Ω\",\n componentValue: primaryValue,\n })\n if (resistance !== undefined) {\n const parsed = source_simple_resistor.safeParse({\n ...common,\n display_resistance: value || undefined,\n ftype: \"simple_resistor\",\n resistance,\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"capacitor\") {\n const capacitance = parseFiniteComponentValue({\n componentUnit: \"F\",\n componentValue: primaryValue,\n })\n if (capacitance !== undefined) {\n const parsed = source_simple_capacitor.safeParse({\n ...common,\n display_capacitance: value || undefined,\n ftype: \"simple_capacitor\",\n capacitance,\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"inductor\") {\n const inductance = parseFiniteComponentValue({\n componentUnit: \"H\",\n componentValue: primaryValue,\n })\n if (inductance !== undefined) {\n const parsed = source_simple_inductor.safeParse({\n ...common,\n display_inductance: value || undefined,\n ftype: \"simple_inductor\",\n inductance,\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"crystal\" && (pinCount === 2 || pinCount === 4)) {\n const frequency = parseFiniteComponentValue({\n componentUnit: \"Hz\",\n componentValue: value,\n })\n if (frequency !== undefined) {\n const parsed = source_simple_crystal.safeParse({\n ...common,\n frequency,\n ftype: \"simple_crystal\",\n pin_variant: pinCount === 4 ? \"four_pin\" : \"two_pin\",\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"mosfet\" && pinCount >= 3) {\n const parsed = source_simple_mosfet.safeParse({\n ...common,\n ...getMosfetVariant(libraryReference),\n ftype: \"simple_mosfet\",\n })\n if (parsed.success) return parsed.data\n }\n\n const ftype:\n | \"simple_chip\"\n | \"simple_diode\"\n | \"simple_led\"\n | \"simple_test_point\" =\n classification === \"diode\"\n ? \"simple_diode\"\n : classification === \"led\"\n ? \"simple_led\"\n : classification === \"testpoint\"\n ? \"simple_test_point\"\n : \"simple_chip\"\n return {\n ...common,\n ftype,\n } satisfies SourceComponentBase\n}\n\nfunction parseFiniteComponentValue({\n componentUnit,\n componentValue,\n}: {\n componentUnit: BaseTscircuitUnit\n componentValue: string\n}): number | undefined {\n const parsedComponentValue = parseAndConvertSiUnit(\n componentValue,\n componentUnit,\n ).value\n if (\n typeof parsedComponentValue !== \"number\" ||\n !Number.isFinite(parsedComponentValue)\n ) {\n return undefined\n }\n return parsedComponentValue\n}\n\nfunction createComponentText(params: {\n anchor: SchematicText[\"anchor\"]\n component: SchematicComponent\n id: string\n position: AltiumPoint\n text: string\n}): SchematicText {\n const { anchor, component, id, position, text } = params\n return {\n type: \"schematic_text\",\n anchor,\n color: \"#006464\",\n font_size: 0.18,\n position,\n rotation: 0,\n schematic_component_id: component.schematic_component_id,\n schematic_sheet_id: component.schematic_sheet_id,\n schematic_text_id: id,\n text,\n }\n}\n\n/**\n * Altium permits labels and pin hot spots to land anywhere on a wire segment,\n * not only on declared polyline vertices. Build the electrical graph with\n * those geometric joins so Circuit JSON source traces carry the real ports and\n * net names. Mid-segment crossings remain disconnected unless one wire has a\n * vertex there or Altium emits an explicit junction record.\n */\nfunction buildSemanticNetGraph(\n document: AltiumSchDoc,\n convertedPorts: ConvertedPort[],\n): SemanticNetGraph {\n const disjointSet = new PointDisjointSet()\n const pointValues = new Map<string, AltiumPoint>()\n const wireRecords = document.records.filter(\n (record) => record.recordKind === \"27\",\n )\n const segments: SchematicSegment[] = []\n\n for (const wire of wireRecords) {\n const points = getSchematicRecordPoints(wire)\n for (const point of points) {\n addGraphPoint(disjointSet, pointValues, point)\n }\n for (let index = 1; index < points.length; index++) {\n const start = points[index - 1]\n const end = points[index]\n if (!start || !end) continue\n disjointSet.union(pointKey(start), pointKey(end))\n segments.push({ end, start })\n }\n }\n\n const positionedRecords = document.records.flatMap((record) => {\n if (![\"4\", \"17\", \"18\", \"25\", \"29\"].includes(record.recordKind ?? \"\")) {\n return []\n }\n const point =\n record.recordKind === \"18\"\n ? getPortConnectionGeometry(record, segments)?.anchor\n : getLocation(record)\n return point ? [{ point, record }] : []\n })\n const positionedPins = convertedPorts.map(({ point, record }) => ({\n point,\n record,\n }))\n const joinPoints = [\n ...new Map(\n wireRecords\n .flatMap((wire) => getSchematicRecordPoints(wire))\n .map((point) => [pointKey(point), point]),\n ).values(),\n ...positionedRecords.map(({ point }) => point),\n ...positionedPins.map(({ point }) => point),\n ]\n\n for (const point of joinPoints) {\n addGraphPoint(disjointSet, pointValues, point)\n for (const segment of segments) {\n if (isPointOnSegment(point, segment.start, segment.end)) {\n disjointSet.union(pointKey(point), pointKey(segment.start))\n }\n }\n }\n\n interface MutableSemanticNet {\n id: string\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n }\n const groupedByRoot = new Map<string, MutableSemanticNet>()\n const getGroup = (point: AltiumPoint): MutableSemanticNet => {\n const root = disjointSet.find(pointKey(point))\n const existing = groupedByRoot.get(root)\n if (existing) return existing\n const created: MutableSemanticNet = {\n id: root,\n names: new Set(),\n points: new Map(),\n records: new Set(),\n }\n groupedByRoot.set(root, created)\n return created\n }\n\n for (const point of pointValues.values()) {\n getGroup(point).points.set(pointKey(point), point)\n }\n for (const wire of wireRecords) {\n const firstPoint = getSchematicRecordPoints(wire)[0]\n if (firstPoint) getGroup(firstPoint).records.add(wire)\n }\n for (const { point, record } of [...positionedRecords, ...positionedPins]) {\n const group = getGroup(point)\n group.records.add(record)\n const name = getElectricalRecordName(record)\n if (name) group.names.add(name)\n }\n\n const connectedWiresByRecord = new Map<AltiumRecord, AltiumRecord[]>()\n for (const group of groupedByRoot.values()) {\n const wires = [...group.records].filter(\n (record) => record.recordKind === \"27\",\n )\n for (const record of group.records) {\n connectedWiresByRecord.set(record, wires)\n }\n }\n\n const mergedGroups: MutableSemanticNet[] = []\n for (const group of groupedByRoot.values()) {\n if (group.records.size === 0) continue\n const normalizedNames = new Set(\n [...group.names].map((name) => name.trim().toUpperCase()),\n )\n const matches = mergedGroups.filter((candidate) =>\n [...candidate.names].some((name) =>\n normalizedNames.has(name.trim().toUpperCase()),\n ),\n )\n if (matches.length === 0 || normalizedNames.size === 0) {\n mergedGroups.push(group)\n continue\n }\n const target = matches[0]\n if (!target) continue\n mergeSemanticNetGroup(target, group)\n for (const duplicate of matches.slice(1)) {\n mergeSemanticNetGroup(target, duplicate)\n const duplicateIndex = mergedGroups.indexOf(duplicate)\n if (duplicateIndex >= 0) mergedGroups.splice(duplicateIndex, 1)\n }\n }\n\n const nets: SemanticNet[] = mergedGroups.map((group) => ({\n id: group.id,\n names: [...group.names],\n points: [...group.points.values()],\n records: [...group.records],\n }))\n return {\n getConnectedWiresForRecord: (record) =>\n connectedWiresByRecord.get(record) ?? [],\n nets,\n }\n}\n\nfunction addGraphPoint(\n disjointSet: PointDisjointSet,\n pointValues: Map<string, AltiumPoint>,\n point: AltiumPoint,\n): void {\n const key = pointKey(point)\n disjointSet.add(key)\n pointValues.set(key, point)\n}\n\nfunction getElectricalRecordName(record: AltiumRecord): string | undefined {\n if (record.recordKind === \"18\") return record.getDecoded(\"NAME\")\n if ([\"4\", \"17\", \"25\"].includes(record.recordKind ?? \"\")) {\n return record.getDecoded(\"TEXT\")\n }\n return undefined\n}\n\nfunction mergeSemanticNetGroup(\n target: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n source: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n): void {\n for (const name of source.names) target.names.add(name)\n for (const [key, point] of source.points) target.points.set(key, point)\n for (const record of source.records) target.records.add(record)\n}\n\nfunction isPointOnSegment(\n point: AltiumPoint,\n start: AltiumPoint,\n end: AltiumPoint,\n): boolean {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const cross = (point.x - start.x) * dy - (point.y - start.y) * dx\n const tolerance = 0.000001 * Math.max(Math.abs(dx), Math.abs(dy), 1)\n if (Math.abs(cross) > tolerance) return false\n const dot = (point.x - start.x) * dx + (point.y - start.y) * dy\n if (dot < -tolerance) return false\n const lengthSquared = dx * dx + dy * dy\n return dot <= lengthSquared + tolerance\n}\n\nfunction splitSegmentAtPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n candidates: AltiumPoint[],\n): AltiumPoint[] {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const lengthSquared = dx * dx + dy * dy\n if (lengthSquared === 0) return [start]\n\n const pointsByKey = new Map<string, AltiumPoint>([\n [pointKey(start), start],\n [pointKey(end), end],\n ])\n for (const candidate of candidates) {\n if (isPointOnSegment(candidate, start, end)) {\n pointsByKey.set(pointKey(candidate), candidate)\n }\n }\n return [...pointsByKey.values()].sort((left, right) => {\n const leftDistance = (left.x - start.x) * dx + (left.y - start.y) * dy\n const rightDistance = (right.x - start.x) * dx + (right.y - start.y) * dy\n return leftDistance - rightDistance\n })\n}\n\nclass PointDisjointSet {\n private readonly parent = new Map<string, string>()\n\n add(value: string): void {\n if (!this.parent.has(value)) this.parent.set(value, value)\n }\n\n find(value: string): string {\n this.add(value)\n const parent = this.parent.get(value) ?? value\n if (parent === value) return value\n const root = this.find(parent)\n this.parent.set(value, root)\n return root\n }\n\n union(left: string, right: string): void {\n const leftRoot = this.find(left)\n const rightRoot = this.find(right)\n if (leftRoot !== rightRoot) this.parent.set(rightRoot, leftRoot)\n }\n}\n\ninterface ConnectivityConversion {\n sourceNetIdByRecord: Map<AltiumRecord, string>\n sourceNetIdByName: Map<string, string>\n sourcePortCountByRecord: Map<AltiumRecord, number>\n sourceTraceIdByRecord: Map<AltiumRecord, string>\n schematicTraceIdByRecord: Map<AltiumRecord, string>\n}\n\nfunction convertConnectivity(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): ConnectivityConversion {\n const {\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n const sourceNetIdByName = new Map<string, string>()\n const sourceNetIdByRecord = new Map<AltiumRecord, string>()\n const sourcePortCountByRecord = new Map<AltiumRecord, number>()\n const sourceTraceIdByRecord = new Map<AltiumRecord, string>()\n const schematicTraceIdByRecord = new Map<AltiumRecord, string>()\n const portsByPoint = groupByPoint(convertedPorts)\n\n for (const [netIndex, net] of graph.nets.entries()) {\n const wires = net.records.filter((record) => record.recordKind === \"27\")\n const connectedConvertedPorts = uniqueConvertedPorts(\n net.points.flatMap((point) => portsByPoint.get(pointKey(point)) ?? []),\n )\n const connectedPorts = connectedConvertedPorts.map(\n ({ sourcePort }) => sourcePort.source_port_id,\n )\n if (\n wires.length === 0 &&\n !(\n (net.names.length > 0 && connectedPorts.length > 0) ||\n connectedPorts.length > 1\n )\n ) {\n continue\n }\n const sourceNetIds = net.names.map((name) =>\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName,\n }),\n )\n for (const record of net.records) {\n const firstSourceNetId = sourceNetIds[0]\n if (firstSourceNetId) sourceNetIdByRecord.set(record, firstSourceNetId)\n }\n\n const sourceTraceId = `source_trace_altium_${netIndex}`\n for (const record of net.records) {\n sourcePortCountByRecord.set(record, connectedPorts.length)\n sourceTraceIdByRecord.set(record, sourceTraceId)\n }\n const sourceTrace: SourceTrace = {\n type: \"source_trace\",\n connected_source_net_ids: sourceNetIds,\n connected_source_port_ids: connectedPorts,\n display_name: net.names[0],\n name: net.names[0],\n source_trace_id: sourceTraceId,\n }\n elements.push(sourceTrace)\n\n const netJunctions = document.records\n .filter(\n (record) =>\n record.recordKind === \"29\" &&\n net.points.some((point) => pointsEqual(point, getLocation(record))),\n )\n .flatMap((record) => {\n handledRecords.add(record)\n const location = getLocation(record)\n return location ? [scalePoint(location, options.scale)] : []\n })\n\n for (const wire of wires) handledRecords.add(wire)\n const prunedSegmentKeys = getEquivalentPortPrunedSegmentKeys({\n convertedPorts: connectedConvertedPorts,\n net,\n wires,\n })\n let renderedWireIndex = 0\n for (const wire of wires) {\n const wireRecordIndex = document.records.indexOf(wire)\n const schematicTraceId = `schematic_trace_altium_${wireRecordIndex}`\n const points = getSchematicRecordPoints(wire)\n const edges: SchematicTrace[\"edges\"] = []\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const from = points[pointIndex - 1]\n const to = points[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let segmentPointIndex = 1;\n segmentPointIndex < segmentPoints.length;\n segmentPointIndex++\n ) {\n const segmentFrom = segmentPoints[segmentPointIndex - 1]\n const segmentTo = segmentPoints[segmentPointIndex]\n if (!segmentFrom || !segmentTo) continue\n if (prunedSegmentKeys.has(segmentKey(segmentFrom, segmentTo))) {\n continue\n }\n const fromPort = portsByPoint\n .get(pointKey(segmentFrom))\n ?.find((port) => port.isSchematicVisible)\n const toPort = portsByPoint\n .get(pointKey(segmentTo))\n ?.find((port) => port.isSchematicVisible)\n const fromPortId = getPortIdAtElectricalPoint(\n fromPort,\n segmentFrom,\n options.scale,\n )\n const toPortId = getPortIdAtElectricalPoint(\n toPort,\n segmentTo,\n options.scale,\n )\n edges.push({\n from: scalePoint(segmentFrom, options.scale),\n to: scalePoint(segmentTo, options.scale),\n ...(fromPortId ? { from_schematic_port_id: fromPortId } : {}),\n ...(toPortId ? { to_schematic_port_id: toPortId } : {}),\n })\n }\n }\n if (edges.length === 0) continue\n schematicTraceIdByRecord.set(wire, schematicTraceId)\n elements.push({\n type: \"schematic_trace\",\n edges,\n junctions: renderedWireIndex === 0 ? netJunctions : [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: schematicTraceId,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n renderedWireIndex++\n }\n\n for (const convertedPort of connectedConvertedPorts) {\n if (!convertedPort.isSchematicVisible) continue\n const electricalTerminal = scalePoint(convertedPort.point, options.scale)\n if (pointsEqual(convertedPort.schematicPort.center, electricalTerminal)) {\n continue\n }\n const portRecordIndex = document.records.indexOf(convertedPort.record)\n elements.push({\n type: \"schematic_trace\",\n edges: createPortLeadEdges(convertedPort, electricalTerminal),\n junctions: [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: `schematic_trace_altium_port_lead_${portRecordIndex}`,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n }\n\n const connectedPortIds = new Set(connectedPorts)\n for (const convertedPort of convertedPorts) {\n if (\n convertedPort.isSchematicVisible &&\n connectedPortIds.has(convertedPort.sourcePort.source_port_id)\n ) {\n convertedPort.schematicPort.is_connected = true\n }\n }\n }\n\n return {\n schematicTraceIdByRecord,\n sourceNetIdByName,\n sourceNetIdByRecord,\n sourcePortCountByRecord,\n sourceTraceIdByRecord,\n }\n}\n\nfunction getEquivalentPortPrunedSegmentKeys(params: {\n convertedPorts: ConvertedPort[]\n net: SemanticNet\n wires: AltiumRecord[]\n}): Set<string> {\n const { convertedPorts, net, wires } = params\n const hiddenPortPoints = convertedPorts\n .filter((port) => !port.isSchematicVisible)\n .map((port) => port.point)\n if (hiddenPortPoints.length === 0) return new Set()\n\n const wireSegments = getWireSegments(wires)\n const protectedPointKeys = new Set(\n convertedPorts\n .filter((port) => port.isSchematicVisible)\n .map((port) => pointKey(port.point)),\n )\n for (const record of net.records) {\n if (![\"4\", \"17\", \"18\", \"25\"].includes(record.recordKind ?? \"\")) continue\n const location =\n record.recordKind === \"18\"\n ? getPortConnectionGeometry(record, wireSegments)?.anchor\n : getLocation(record)\n if (location) protectedPointKeys.add(pointKey(location))\n }\n\n interface PrunableSegment {\n endKey: string\n key: string\n startKey: string\n }\n const segments = new Map<string, PrunableSegment>()\n const segmentKeysByPoint = new Map<string, Set<string>>()\n const addIncidentSegment = (point: AltiumPoint, key: string): void => {\n const pointSegments = segmentKeysByPoint.get(pointKey(point))\n if (pointSegments) pointSegments.add(key)\n else segmentKeysByPoint.set(pointKey(point), new Set([key]))\n }\n\n for (const wire of wires) {\n const wirePoints = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < wirePoints.length; pointIndex++) {\n const from = wirePoints[pointIndex - 1]\n const to = wirePoints[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let splitIndex = 1;\n splitIndex < segmentPoints.length;\n splitIndex++\n ) {\n const segmentFrom = segmentPoints[splitIndex - 1]\n const segmentTo = segmentPoints[splitIndex]\n if (!segmentFrom || !segmentTo) continue\n const key = segmentKey(segmentFrom, segmentTo)\n segments.set(key, {\n endKey: pointKey(segmentTo),\n key,\n startKey: pointKey(segmentFrom),\n })\n addIncidentSegment(segmentFrom, key)\n addIncidentSegment(segmentTo, key)\n }\n }\n }\n\n const removedSegmentKeys = new Set<string>()\n const pendingPointKeys = hiddenPortPoints.map((point) => pointKey(point))\n while (pendingPointKeys.length > 0) {\n const currentPointKey = pendingPointKeys.shift()\n if (!currentPointKey || protectedPointKeys.has(currentPointKey)) continue\n const activeSegmentKeys = [\n ...(segmentKeysByPoint.get(currentPointKey) ?? []),\n ].filter((key) => !removedSegmentKeys.has(key))\n if (activeSegmentKeys.length !== 1) continue\n const segment = segments.get(activeSegmentKeys[0] ?? \"\")\n if (!segment) continue\n removedSegmentKeys.add(segment.key)\n pendingPointKeys.push(\n segment.startKey === currentPointKey ? segment.endKey : segment.startKey,\n )\n }\n return removedSegmentKeys\n}\n\nfunction createPortLeadEdges(\n convertedPort: ConvertedPort,\n electricalTerminal: AltiumPoint,\n): SchematicTrace[\"edges\"] {\n const portCenter = convertedPort.schematicPort.center\n const facingDirection =\n convertedPort.schematicPort.facing_direction ?? \"right\"\n const elbow =\n facingDirection === \"left\" || facingDirection === \"right\"\n ? { x: electricalTerminal.x, y: portCenter.y }\n : { x: portCenter.x, y: electricalTerminal.y }\n const points = [portCenter, elbow, electricalTerminal].filter(\n (point, index, allPoints) =>\n index === 0 || !pointsEqual(point, allPoints[index - 1]),\n )\n\n return points.slice(1).flatMap((to, index) => {\n const from = points[index]\n if (!from) return []\n return [\n {\n from,\n ...(index === 0\n ? {\n from_schematic_port_id:\n convertedPort.schematicPort.schematic_port_id,\n }\n : {}),\n to,\n },\n ]\n })\n}\n\nfunction convertNetLabels(params: {\n connectivity: ConnectivityConversion\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): void {\n const {\n connectivity,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n const allWireSegments = getWireSegments(\n document.records.filter((record) => record.recordKind === \"27\"),\n )\n\n for (const [recordIndex, record] of document.records.entries()) {\n const recordKind = record.recordKind\n if (!recordKind || ![\"4\", \"17\", \"18\", \"25\"].includes(recordKind)) {\n continue\n }\n if (record.getBoolean(\"ISHIDDEN\") && options.includeHidden !== true) {\n handledRecords.add(record)\n continue\n }\n const name =\n record.recordKind === \"18\"\n ? record.getDecoded(\"NAME\")\n : record.getDecoded(\"TEXT\")\n const portConnection =\n recordKind === \"18\"\n ? getPortConnectionGeometry(record, allWireSegments)\n : undefined\n const location = portConnection?.anchor ?? getLocation(record)\n if (!name || !location) continue\n const connectedWires = graph.getConnectedWiresForRecord(record)\n const wire = connectedWires[0]\n // Altium's generic label record is also used for page titles and notes.\n // It is only an electrical net label when it touches a wire.\n if (recordKind === \"4\" && !wire) continue\n const sourceTraceId = connectivity.sourceTraceIdByRecord.get(record)\n const shouldRenderInline =\n Boolean(sourceTraceId) &&\n (recordKind === \"25\" ||\n (recordKind === \"18\" &&\n (record.getNumber(\"IOTYPE\") ?? 0) === 0 &&\n connectivity.sourcePortCountByRecord.get(record) === 2 &&\n !isPowerNet(name)))\n if (shouldRenderInline && sourceTraceId) {\n handledRecords.add(record)\n elements.push(\n createInlineNetLabelText({\n connectedWires,\n document,\n location,\n name,\n options,\n record,\n recordIndex,\n sourceTraceId,\n }),\n )\n continue\n }\n handledRecords.add(record)\n\n const sourceNetId =\n connectivity.sourceNetIdByRecord.get(record) ??\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName: connectivity.sourceNetIdByName,\n })\n const schematicTraceId = wire\n ? connectivity.schematicTraceIdByRecord.get(wire)\n : undefined\n const direction = getRecordDirection(record)\n const symbolName =\n record.recordKind === \"17\"\n ? getPowerPortSymbolName(record, direction)\n : undefined\n const schematicNetLabel: SchematicNetLabel = {\n type: \"schematic_net_label\",\n anchor_position: scalePoint(location, options.scale),\n anchor_side: directionToOppositeSide(\n portConnection?.bodyDirection ?? direction,\n ),\n center: scalePoint(location, options.scale),\n schematic_net_label_id: `schematic_net_label_altium_${recordIndex}`,\n schematic_sheet_id: options.schematicSheetId,\n source_net_id: sourceNetId,\n text: name,\n ...(schematicTraceId ? { schematic_trace_id: schematicTraceId } : {}),\n ...(symbolName ? { symbol_name: symbolName } : {}),\n }\n elements.push(schematicNetLabel)\n }\n}\n\nfunction createInlineNetLabelText(params: {\n connectedWires: AltiumRecord[]\n document: AltiumSchDoc\n location: AltiumPoint\n name: string\n options: SemanticSchematicOptions\n record: AltiumRecord\n recordIndex: number\n sourceTraceId: string\n}): SchematicText {\n const {\n connectedWires,\n document,\n location,\n name,\n options,\n record,\n recordIndex,\n sourceTraceId,\n } = params\n const direction = getInlineNetLabelDirection(record, location, connectedWires)\n const scaledLocation = scalePoint(location, options.scale)\n const fontSize = getInlineNetLabelFontSize(record, document, options.scale)\n const fontScale = fontSize / DEFAULT_INLINE_NET_LABEL_FONT_SIZE\n const textWidth =\n (name.length * INLINE_NET_LABEL_CHARACTER_WIDTH +\n INLINE_NET_LABEL_HORIZONTAL_PADDING) *\n fontScale\n const isVertical = direction === \"up\" || direction === \"down\"\n const directionSign = direction === \"left\" || direction === \"down\" ? -1 : 1\n const isTerminalPort = record.recordKind === \"18\"\n const anchor: SchematicText[\"anchor\"] = isTerminalPort\n ? directionSign > 0\n ? \"left\"\n : \"right\"\n : \"center\"\n const position = isTerminalPort\n ? isVertical\n ? {\n x: scaledLocation.x - fontSize / 2,\n y: scaledLocation.y,\n }\n : {\n x: scaledLocation.x,\n y: scaledLocation.y + fontSize / 2,\n }\n : isVertical\n ? {\n x: scaledLocation.x - fontSize / 2,\n y: scaledLocation.y + (directionSign * textWidth) / 2,\n }\n : {\n x: scaledLocation.x + (directionSign * textWidth) / 2,\n y: scaledLocation.y + fontSize / 2,\n }\n\n return {\n type: \"schematic_text\",\n anchor,\n color: INLINE_NET_LABEL_COLOR,\n font_size: fontSize,\n position,\n rotation: isVertical ? -90 : 0,\n schematic_sheet_id: options.schematicSheetId,\n schematic_text_id: `schematic_inline_net_label_altium_${recordIndex}`,\n source_trace_id: sourceTraceId,\n text: name,\n }\n}\n\nfunction getInlineNetLabelFontSize(\n record: AltiumRecord,\n document: AltiumSchDoc,\n scale: number,\n): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n const sheetRecord = document.records.find(\n (candidate) => candidate.recordKind === \"31\",\n )\n const sourceFontSize = Number(\n sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ??\n DEFAULT_INLINE_NET_LABEL_FONT_SIZE / scale,\n )\n return Math.min(\n DEFAULT_INLINE_NET_LABEL_FONT_SIZE,\n Math.max(MIN_INLINE_NET_LABEL_FONT_SIZE, sourceFontSize * scale),\n )\n}\n\nfunction getInlineNetLabelDirection(\n record: AltiumRecord,\n location: AltiumPoint,\n connectedWires: AltiumRecord[],\n): CardinalDirection {\n if (record.recordKind !== \"18\") return getRecordDirection(record)\n\n for (const wire of connectedWires) {\n const points = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const start = points[pointIndex - 1]\n const end = points[pointIndex]\n if (!start || !end || !isPointOnSegment(location, start, end)) continue\n const other = pointsEqual(location, start)\n ? end\n : pointsEqual(location, end)\n ? start\n : undefined\n if (!other) continue\n // Place the inline text away from the wire interior, matching the side\n // on which Altium drew the port body instead of covering the circuit.\n const dx = location.x - other.x\n const dy = location.y - other.y\n if (Math.abs(dx) >= Math.abs(dy)) return dx < 0 ? \"left\" : \"right\"\n return dy < 0 ? \"down\" : \"up\"\n }\n }\n\n return getRecordDirection(record)\n}\n\nfunction getWireSegments(wires: AltiumRecord[]): SchematicSegment[] {\n return wires.flatMap((wire) => {\n const points = getSchematicRecordPoints(wire)\n const segments: SchematicSegment[] = []\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const start = points[pointIndex - 1]\n const end = points[pointIndex]\n if (start && end) segments.push({ end, start })\n }\n return segments\n })\n}\n\nfunction getPortConnectionGeometry(\n record: AltiumRecord,\n wireSegments: SchematicSegment[],\n): { anchor: AltiumPoint; bodyDirection: CardinalDirection } | undefined {\n const origin = getLocation(record)\n if (!origin) return undefined\n\n const originToExtremity = getRecordDirection(record)\n const directionVector = VECTOR_BY_DIRECTION[originToExtremity]\n const width = Math.max(record.getNumber(\"WIDTH\") ?? 16, 0)\n const extremity = {\n x: origin.x + directionVector.x * width,\n y: origin.y + directionVector.y * width,\n }\n const touchesWireEndpoint = (point: AltiumPoint): boolean =>\n wireSegments.some((segment) =>\n isPointNearSegmentEndpoint(point, segment.start, segment.end),\n )\n const originConnected = touchesWireEndpoint(origin)\n const extremityConnected = touchesWireEndpoint(extremity)\n const connectedEnd = record.getNumber(\"CONNECTEDEND\")\n const connectsAtExtremity =\n connectedEnd === 2 ||\n (connectedEnd !== 1 &&\n connectedEnd !== 3 &&\n !originConnected &&\n extremityConnected)\n\n return connectsAtExtremity\n ? {\n anchor: extremity,\n bodyDirection: getOppositeDirection(originToExtremity),\n }\n : { anchor: origin, bodyDirection: originToExtremity }\n}\n\nfunction isPointNearSegmentEndpoint(\n point: AltiumPoint,\n start: AltiumPoint,\n end: AltiumPoint,\n): boolean {\n return isPointNear(point, start) || isPointNear(point, end)\n}\n\nfunction isPointNear(point: AltiumPoint, other: AltiumPoint): boolean {\n const tolerance = 1.1\n return (point.x - other.x) ** 2 + (point.y - other.y) ** 2 <= tolerance ** 2\n}\n\nfunction getOppositeDirection(direction: CardinalDirection): CardinalDirection {\n if (direction === \"up\") return \"down\"\n if (direction === \"down\") return \"up\"\n return direction === \"left\" ? \"right\" : \"left\"\n}\n\nfunction getOrCreateSourceNet(params: {\n elements: AnyCircuitElement[]\n name: string\n sourceNetIdByName: Map<string, string>\n}): string {\n const { elements, name, sourceNetIdByName } = params\n const normalizedName = name.trim().toUpperCase()\n const existing = sourceNetIdByName.get(normalizedName)\n if (existing) return existing\n\n const sourceNetIdBase = `source_net_altium_${sanitizeId(name)}`\n const existingIds = new Set(\n elements.flatMap((element) =>\n element.type === \"source_net\" ? [element.source_net_id] : [],\n ),\n )\n let sourceNetId = sourceNetIdBase\n let suffix = 2\n while (existingIds.has(sourceNetId)) {\n sourceNetId = `${sourceNetIdBase}_${suffix}`\n suffix++\n }\n const sourceNet: SourceNet = {\n type: \"source_net\",\n is_ground: isGroundNet(name),\n is_power: isPowerNet(name),\n member_source_group_ids: [],\n name,\n source_net_id: sourceNetId,\n }\n elements.push(sourceNet)\n sourceNetIdByName.set(normalizedName, sourceNetId)\n return sourceNetId\n}\n\nfunction selectCircuitJsonSymbol(params: {\n designator: string\n libraryReference: string\n ports: ConvertedPort[]\n}): SymbolSelection | undefined {\n const { designator, libraryReference, ports } = params\n const classification = classifyComponent({ designator, libraryReference })\n let baseName: string | undefined\n let candidateNames: string[] = []\n if (classification === \"testpoint\" && ports.length === 1) {\n baseName = \"testpoint\"\n } else if (classification === \"crystal\" && ports.length === 2) {\n baseName = \"crystal\"\n } else if (classification === \"crystal\" && ports.length === 4) {\n baseName = \"crystal_4pin\"\n } else if (\n classification === \"mosfet\" &&\n ports.length >= 3 &&\n hasCompleteMosfetFunctionalGroups(ports)\n ) {\n const { channel_type, mosfet_mode } = getMosfetVariant(libraryReference)\n const channel = channel_type === \"p\" ? \"p\" : \"n\"\n const mode = mosfet_mode === \"depletion\" ? \"d\" : \"e\"\n const prefix = `${channel}_channel_${mode}_mosfet_transistor_gate_`\n candidateNames = SYMBOL_NAMES.filter((name) => name.startsWith(prefix))\n } else if (ports.length !== 2) {\n return undefined\n } else if (classification === \"resistor\") {\n baseName = \"boxresistor\"\n } else if (classification === \"capacitor\") {\n baseName = isPolarizedCapacitor(libraryReference)\n ? \"capacitor_polarized\"\n : \"capacitor\"\n } else if (classification === \"ferrite_bead\") {\n baseName = \"ferrite_bead\"\n } else if (classification === \"inductor\") {\n baseName = \"inductor\"\n } else if (classification === \"led\") {\n baseName = \"led\"\n }\n if (classification === \"diode\") {\n const lower = libraryReference.toLowerCase()\n baseName = lower.includes(\"schottky\") ? \"schottky_diode\" : \"diode\"\n }\n if (baseName) {\n candidateNames = CARDINAL_DIRECTIONS.map(\n (direction) => `${baseName}_${direction}`,\n )\n }\n if (candidateNames.length === 0) return undefined\n\n const selections = candidateNames.flatMap((name) => {\n const symbol = SYMBOL_CATALOG[name]\n const supportsEquivalentMosfetPads =\n classification === \"mosfet\" && symbol?.ports.length === 3\n if (\n !symbol ||\n (!supportsEquivalentMosfetPads && symbol.ports.length !== ports.length)\n ) {\n return []\n }\n const assignments = assignConvertedPortsToSymbolPorts(ports, symbol, {\n allowFunctionalPortReuse: classification === \"mosfet\",\n geometryInterchangeableLabels:\n classification === \"crystal\" && ports.length === 4\n ? new Set([\"2\", \"4\"])\n : undefined,\n })\n return assignments.length === ports.length\n ? [{ assignments, name, symbol } satisfies SymbolSelection]\n : []\n })\n return selections.sort(\n (left, right) =>\n getSymbolDirectionScore(left) - getSymbolDirectionScore(right),\n )[0]\n}\n\nfunction hasCompleteMosfetFunctionalGroups(ports: ConvertedPort[]): boolean {\n const groups = ports.map((port) =>\n normalizeFunctionalPortLabel(port.sourcePort.name),\n )\n return (\n groups.every((group) => group !== undefined) && new Set(groups).size === 3\n )\n}\n\nfunction assignConvertedPortsToSymbolPorts(\n ports: ConvertedPort[],\n symbol: SchSymbol,\n options: {\n allowFunctionalPortReuse?: boolean\n geometryInterchangeableLabels?: Set<string>\n } = {},\n): SymbolPortAssignment[] {\n const unusedSymbolPorts = new Set(symbol.ports)\n const orderedPorts = [...ports].sort(compareConvertedPorts)\n const assignments: SymbolPortAssignment[] = []\n const convertedCenter = getAveragePoint(ports.map(({ point }) => point))\n\n for (const [portIndex, convertedPort] of orderedPorts.entries()) {\n const rawHints = [\n convertedPort.schematicPort.pin_number?.toString(),\n convertedPort.sourcePort.name,\n ...(convertedPort.sourcePort.port_hints ?? []),\n ].filter((hint): hint is string => Boolean(hint))\n const functionalHints = new Set(\n rawHints.flatMap((hint) => {\n const normalized = normalizeFunctionalPortLabel(hint)\n return normalized ? [normalized] : []\n }),\n )\n const functionalPortCandidates = options.allowFunctionalPortReuse\n ? symbol.ports\n : [...unusedSymbolPorts]\n const functionalSymbolPort = functionalPortCandidates.find((symbolPort) =>\n symbolPort.labels.some((label) => {\n const normalized = normalizeFunctionalPortLabel(label)\n return normalized ? functionalHints.has(normalized) : false\n }),\n )\n const exactHints = new Set(rawHints.map((hint) => hint.toLowerCase()))\n const exactSymbolPort = [...unusedSymbolPorts].find((symbolPort) =>\n symbolPort.labels.some((label) => exactHints.has(label.toLowerCase())),\n )\n const interchangeableLabels = options.geometryInterchangeableLabels\n const isGeometryInterchangeable = rawHints.some((hint) =>\n interchangeableLabels?.has(hint.toLowerCase()),\n )\n const geometrySymbolPort = isGeometryInterchangeable\n ? [...unusedSymbolPorts]\n .filter((symbolPort) =>\n symbolPort.labels.some((label) =>\n interchangeableLabels?.has(label.toLowerCase()),\n ),\n )\n .sort(\n (left, right) =>\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(left, symbol.center),\n ) -\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(right, symbol.center),\n ),\n )[0]\n : undefined\n const symbolPort =\n functionalSymbolPort ??\n geometrySymbolPort ??\n exactSymbolPort ??\n symbol.ports[portIndex] ??\n [...unusedSymbolPorts][0]\n if (!symbolPort) continue\n if (!functionalSymbolPort || !options.allowFunctionalPortReuse) {\n unusedSymbolPorts.delete(symbolPort)\n }\n assignments.push({ convertedPort, symbolPort })\n }\n return assignments\n}\n\nfunction compareConvertedPorts(\n left: ConvertedPort,\n right: ConvertedPort,\n): number {\n const leftPinNumber = left.schematicPort.pin_number\n const rightPinNumber = right.schematicPort.pin_number\n if (leftPinNumber !== undefined && rightPinNumber !== undefined) {\n return leftPinNumber - rightPinNumber\n }\n return (\n (left.schematicPort.true_ccw_index ?? 0) -\n (right.schematicPort.true_ccw_index ?? 0)\n )\n}\n\nfunction getSymbolDirectionScore(selection: SymbolSelection): number {\n const [first, second] = selection.assignments\n if (!first) return Number.POSITIVE_INFINITY\n if (!second) {\n const expectedDirection =\n VECTOR_BY_DIRECTION[\n first.convertedPort.schematicPort.facing_direction ?? \"right\"\n ]\n return getVectorDifference(\n expectedDirection,\n subtractPoints(first.symbolPort, selection.symbol.center),\n )\n }\n let difference = 0\n let comparisonCount = 0\n for (\n let firstIndex = 0;\n firstIndex < selection.assignments.length;\n firstIndex++\n ) {\n for (\n let secondIndex = firstIndex + 1;\n secondIndex < selection.assignments.length;\n secondIndex++\n ) {\n const firstAssignment = selection.assignments[firstIndex]\n const secondAssignment = selection.assignments[secondIndex]\n if (!firstAssignment || !secondAssignment) continue\n const pairDifference = getVectorDifference(\n subtractPoints(\n secondAssignment.convertedPort.point,\n firstAssignment.convertedPort.point,\n ),\n subtractPoints(secondAssignment.symbolPort, firstAssignment.symbolPort),\n )\n if (!Number.isFinite(pairDifference)) continue\n difference += pairDifference\n comparisonCount++\n }\n }\n return comparisonCount > 0\n ? difference / comparisonCount\n : Number.POSITIVE_INFINITY\n}\n\nfunction normalizeFunctionalPortLabel(value: string): string | undefined {\n const normalized = value.toLowerCase().replace(/[^a-z]/gu, \"\")\n if (normalized === \"g\" || normalized === \"gate\") return \"gate\"\n if (normalized === \"d\" || normalized === \"drain\") return \"drain\"\n if (normalized === \"s\" || normalized === \"source\") return \"source\"\n return undefined\n}\n\nfunction applyNativeSymbolPortGeometry(params: {\n center: AltiumPoint\n selection: SymbolSelection\n}): void {\n const { center, selection } = params\n const assignmentsBySymbolPort = new Map<\n SchSymbol[\"ports\"][number],\n SymbolPortAssignment[]\n >()\n for (const assignment of selection.assignments) {\n const assignments = assignmentsBySymbolPort.get(assignment.symbolPort)\n if (assignments) assignments.push(assignment)\n else assignmentsBySymbolPort.set(assignment.symbolPort, [assignment])\n }\n\n for (const [symbolPort, assignments] of assignmentsBySymbolPort) {\n const offset = subtractPoints(symbolPort, selection.symbol.center)\n const direction = getDirectionForVector(offset)\n const symbolPortCenter = {\n x: center.x + offset.x,\n y: center.y + offset.y,\n }\n const representative = assignments.sort(\n (left, right) =>\n getPointDistance(\n left.convertedPort.schematicPort.center,\n symbolPortCenter,\n ) -\n getPointDistance(\n right.convertedPort.schematicPort.center,\n symbolPortCenter,\n ),\n )[0]\n for (const { convertedPort } of assignments) {\n convertedPort.isSchematicVisible =\n convertedPort === representative?.convertedPort\n convertedPort.schematicPort.center = symbolPortCenter\n convertedPort.schematicPort.distance_from_component_edge = Math.hypot(\n offset.x,\n offset.y,\n )\n convertedPort.schematicPort.facing_direction = direction\n convertedPort.schematicPort.side_of_component = directionToSide(direction)\n }\n }\n}\n\nfunction getPowerPortSymbolName(\n record: AltiumRecord,\n direction: CardinalDirection,\n): string {\n const style = Math.round(record.getNumber(\"STYLE\") ?? 2)\n if (style === 4) return `ground_${direction}`\n if (style === 5) return `ground_${direction}`\n if (style === 6) return `tilted_ground_${direction}`\n return `vcc_${direction}`\n}\n\nfunction getComponentBodyBounds(\n records: AltiumRecord[],\n portPoints: AltiumPoint[],\n): Bounds {\n const rectangles = records\n .filter((record) => record.recordKind === \"14\")\n .flatMap((record) => {\n const rectangle = getRectangle(record)\n return rectangle ? [rectangle] : []\n })\n if (rectangles.length > 0) return mergeBounds(rectangles)\n\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (record.recordKind === \"2\") continue\n const location = getLocation(record)\n const corner = getCorner(record)\n if (location && corner) points.push(location, corner)\n points.push(...getSchematicRecordPoints(record))\n if (record.recordKind === \"8\" && location) {\n const radiusX = Math.abs(record.getNumber(\"RADIUS\") ?? 0)\n const radiusY = Math.abs(record.getNumber(\"SECONDARYRADIUS\") ?? radiusX)\n points.push(\n { x: location.x - radiusX, y: location.y - radiusY },\n { x: location.x + radiusX, y: location.y + radiusY },\n )\n }\n }\n if (points.length > 0) return getBoundsForPoints(points)\n const bounds = getBoundsForPoints(portPoints)\n if (bounds.minX === bounds.maxX) {\n bounds.minX -= 2\n bounds.maxX += 2\n }\n if (bounds.minY === bounds.maxY) {\n bounds.minY -= 2\n bounds.maxY += 2\n }\n return bounds\n}\n\nfunction findOwnedText(\n records: AltiumRecord[],\n recordKind: string,\n name: string,\n): string | undefined {\n return records\n .find(\n (record) =>\n record.recordKind === recordKind &&\n record.getDecoded(\"NAME\")?.toLowerCase() === name.toLowerCase(),\n )\n ?.getDecoded(\"TEXT\")\n}\n\nfunction isOwnedRecordVisible(\n record: AltiumRecord,\n currentPartId: number,\n): boolean {\n const ownerPartId = record.getNumber(\"OWNERPARTID\")\n const ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n}\n\nfunction isPinHidden(pin: AltiumRecord): boolean {\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n return (\n pin.getBoolean(\"ISHIDDEN\") === true ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n )\n}\n\nfunction getRecordDirection(record: AltiumRecord): CardinalDirection {\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n return DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n}\n\nfunction directionToSide(\n direction: CardinalDirection,\n): NonNullable<SchematicPort[\"side_of_component\"]> {\n if (direction === \"up\") return \"top\"\n if (direction === \"down\") return \"bottom\"\n return direction\n}\n\nfunction directionToOppositeSide(\n direction: CardinalDirection,\n): SchematicNetLabel[\"anchor_side\"] {\n if (direction === \"up\") return \"bottom\"\n if (direction === \"down\") return \"top\"\n return direction === \"left\" ? \"right\" : \"left\"\n}\n\nfunction groupByPoint(ports: ConvertedPort[]): Map<string, ConvertedPort[]> {\n const grouped = new Map<string, ConvertedPort[]>()\n for (const port of ports) {\n const key = pointKey(port.point)\n const existing = grouped.get(key)\n if (existing) existing.push(port)\n else grouped.set(key, [port])\n }\n return grouped\n}\n\nfunction uniqueConvertedPorts(ports: ConvertedPort[]): ConvertedPort[] {\n const seenSourcePortIds = new Set<string>()\n return ports.filter((port) => {\n const sourcePortId = port.sourcePort.source_port_id\n if (seenSourcePortIds.has(sourcePortId)) return false\n seenSourcePortIds.add(sourcePortId)\n return true\n })\n}\n\nfunction getPortIdAtElectricalPoint(\n port: ConvertedPort | undefined,\n electricalPoint: AltiumPoint,\n scale: number,\n): string | undefined {\n if (!port?.isSchematicVisible) return undefined\n return pointsEqual(\n port.schematicPort.center,\n scalePoint(electricalPoint, scale),\n )\n ? port.schematicPort.schematic_port_id\n : undefined\n}\n\nfunction parsePinNumber(value: string): number | undefined {\n const parsed = Number(value)\n return Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined\n}\n","import type { AltiumPoint, AltiumRecord } from \"altiumts\"\n\nexport interface Bounds {\n maxX: number\n maxY: number\n minX: number\n minY: number\n}\n\nexport type CardinalDirection = \"up\" | \"down\" | \"left\" | \"right\"\n\nexport function getAveragePoint(points: AltiumPoint[]): AltiumPoint {\n if (points.length === 0) return { x: 0, y: 0 }\n return {\n x: points.reduce((sum, point) => sum + point.x, 0) / points.length,\n y: points.reduce((sum, point) => sum + point.y, 0) / points.length,\n }\n}\n\nexport function getVectorDifference(\n left: AltiumPoint,\n right: AltiumPoint,\n): number {\n const leftLength = Math.hypot(left.x, left.y)\n const rightLength = Math.hypot(right.x, right.y)\n if (leftLength === 0 || rightLength === 0) {\n return Number.POSITIVE_INFINITY\n }\n const cosine =\n (left.x * right.x + left.y * right.y) / (leftLength * rightLength)\n return 1 - Math.max(-1, Math.min(1, cosine))\n}\n\nexport function getPointDistance(\n left: AltiumPoint,\n right: AltiumPoint,\n): number {\n return Math.hypot(left.x - right.x, left.y - right.y)\n}\n\nexport function subtractPoints(\n left: AltiumPoint,\n right: AltiumPoint,\n): AltiumPoint {\n return { x: left.x - right.x, y: left.y - right.y }\n}\n\nexport function getDirectionForVector(vector: AltiumPoint): CardinalDirection {\n if (Math.abs(vector.x) >= Math.abs(vector.y)) {\n return vector.x >= 0 ? \"right\" : \"left\"\n }\n return vector.y >= 0 ? \"up\" : \"down\"\n}\n\nexport function getBoundsForPoints(points: AltiumPoint[]): Bounds {\n if (points.length === 0) return { maxX: 1, maxY: 1, minX: -1, minY: -1 }\n return {\n maxX: Math.max(...points.map((point) => point.x)),\n maxY: Math.max(...points.map((point) => point.y)),\n minX: Math.min(...points.map((point) => point.x)),\n minY: Math.min(...points.map((point) => point.y)),\n }\n}\n\nexport function mergeBounds(bounds: Bounds[]): Bounds {\n return {\n maxX: Math.max(...bounds.map((bound) => bound.maxX)),\n maxY: Math.max(...bounds.map((bound) => bound.maxY)),\n minX: Math.min(...bounds.map((bound) => bound.minX)),\n minY: Math.min(...bounds.map((bound) => bound.minY)),\n }\n}\n\nexport function getBoundsCenter(bounds: Bounds): AltiumPoint {\n return {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n}\n\nexport function getRectangle(record: AltiumRecord): Bounds | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n }\n}\n\nexport function getLocation(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"LOCATION.X\")\n const y = getCoordinate(record, \"LOCATION.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nexport function getCorner(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"CORNER.X\")\n const y = getCoordinate(record, \"CORNER.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nfunction getCoordinate(record: AltiumRecord, key: string): number | undefined {\n const raw = record.getCaseInsensitive(key)\n if (raw === undefined) return undefined\n const integer = Number(raw)\n if (!Number.isFinite(integer)) return undefined\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (fractionRaw === undefined) return integer\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integer\n return integer < 0 ? integer - fraction : integer + fraction\n}\n\nexport function scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nexport function pointKey(point: AltiumPoint): string {\n return `${point.x.toFixed(6)},${point.y.toFixed(6)}`\n}\n\nexport function pointsEqual(\n left: AltiumPoint,\n right: AltiumPoint | undefined,\n): boolean {\n return (\n right !== undefined &&\n Math.abs(left.x - right.x) < 0.000001 &&\n Math.abs(left.y - right.y) < 0.000001\n )\n}\n","export function uniqueStrings(values: Array<string | undefined>): string[] {\n return [...new Set(values.filter((value): value is string => Boolean(value)))]\n}\n\nexport function sanitizeId(value: string): string {\n const sanitized = value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, \"_\")\n .replace(/^_+|_+$/gu, \"\")\n return sanitized || \"unnamed\"\n}\n\nexport function segmentKey(\n start: { x: number; y: number },\n end: { x: number; y: number },\n): string {\n const startKey = `${start.x.toFixed(6)},${start.y.toFixed(6)}`\n const endKey = `${end.x.toFixed(6)},${end.y.toFixed(6)}`\n return startKey < endKey ? `${startKey}|${endKey}` : `${endKey}|${startKey}`\n}\n\nexport function isGroundNet(name: string): boolean {\n return /(?:^|[_+-])(?:[adp]?gnd|ground)(?:$|[_+\\d-])/iu.test(name)\n}\n\nexport function isPowerNet(name: string): boolean {\n return (\n isGroundNet(name) ||\n /(?:^|[_+-])(?:vcc|vdd|vss)(?:$|[a-z0-9_+-])/iu.test(name) ||\n /(?:^|[_+-])(?:vin|vout|pwr|power)(?:$|[_+\\d-])/iu.test(name)\n )\n}\n","export type ComponentClassification =\n | \"capacitor\"\n | \"crystal\"\n | \"diode\"\n | \"ferrite_bead\"\n | \"inductor\"\n | \"led\"\n | \"mosfet\"\n | \"resistor\"\n | \"testpoint\"\n | \"unknown\"\n\nexport function classifyComponent(params: {\n designator: string\n libraryReference: string\n}): ComponentClassification {\n const { designator, libraryReference } = params\n const prefix = designator.match(/^[A-Z]+/iu)?.[0]?.toUpperCase() ?? \"\"\n const lowerReference = libraryReference.toLowerCase()\n if (prefix === \"TP\" || lowerReference.includes(\"testpoint\")) {\n return \"testpoint\"\n }\n if (\n prefix === \"Y\" ||\n lowerReference.includes(\"crystal\") ||\n /(?:^|[_-])cry(?:\\d|[_-]|$)/iu.test(libraryReference)\n ) {\n return \"crystal\"\n }\n if (lowerReference.includes(\"mosfet\")) return \"mosfet\"\n if (\n prefix === \"FB\" ||\n prefix === \"FL\" ||\n lowerReference.includes(\"ferrite\") ||\n lowerReference.includes(\"emifilter_ind\")\n ) {\n return \"ferrite_bead\"\n }\n if (prefix === \"LED\" || lowerReference.includes(\"led\")) return \"led\"\n if (prefix === \"R\" || lowerReference.includes(\"resistor\")) return \"resistor\"\n if (prefix === \"C\" || /(?:^|[_-])cap(?:[_-]|$)/iu.test(libraryReference)) {\n return \"capacitor\"\n }\n if (prefix === \"L\" || lowerReference.includes(\"inductor\")) return \"inductor\"\n if (prefix === \"D\" || lowerReference.includes(\"diode\")) return \"diode\"\n return \"unknown\"\n}\n\nexport function getMosfetVariant(libraryReference: string): {\n channel_type: \"n\" | \"p\"\n mosfet_mode: \"depletion\" | \"enhancement\"\n} {\n const lowerReference = libraryReference.toLowerCase()\n const isPChannel =\n /(?:^|[_-])p(?:channel)?(?:[_-]|$)/iu.test(libraryReference) ||\n lowerReference.includes(\"pmos\") ||\n lowerReference.includes(\"csd25\")\n return {\n channel_type: isPChannel ? \"p\" : \"n\",\n mosfet_mode: lowerReference.includes(\"depletion\")\n ? \"depletion\"\n : \"enhancement\",\n }\n}\n\nexport function isPolarizedCapacitor(libraryReference: string): boolean {\n return /(?:^|[_-])cap(?:acitor)?[_-]?pol(?:arized)?(?:[_-]|$)/iu.test(\n libraryReference,\n )\n}\n\nexport function getPrimaryComponentValue(componentValue: string): string {\n return componentValue.split(/[_/\\s]+/u).find(Boolean) ?? componentValue\n}\n","import type { AltiumPoint, AltiumRecord } from \"altiumts\"\n\nexport interface Rectangle {\n maxX: number\n maxY: number\n minX: number\n minY: number\n}\n\nexport function getLocation(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"LOCATION.X\") === undefined ||\n record.getCaseInsensitive(\"LOCATION.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"LOCATION.X\"),\n y: getCoordinate(record, \"LOCATION.Y\"),\n }\n}\n\nexport function getCorner(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"CORNER.X\") === undefined ||\n record.getCaseInsensitive(\"CORNER.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"CORNER.X\"),\n y: getCoordinate(record, \"CORNER.Y\"),\n }\n}\n\nexport function getRectangle(record: AltiumRecord): Rectangle | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n }\n}\n\nexport function getCoordinate(\n record: AltiumRecord,\n key: string,\n fallback = 0,\n): number {\n const integerPart = Number(record.getCaseInsensitive(key) ?? fallback)\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (!Number.isFinite(integerPart) || fractionRaw === undefined) {\n return Number.isFinite(integerPart) ? integerPart : fallback\n }\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integerPart\n return integerPart < 0 ? integerPart - fraction : integerPart + fraction\n}\n\nexport function scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n","import { type AltiumRecord, getSchematicRecordPoints } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicArc,\n SchematicCircle,\n SchematicPath,\n SchematicRect,\n SchematicTrace,\n} from \"circuit-json\"\nimport {\n getCoordinate,\n getCorner,\n getLocation,\n getRectangle,\n scalePoint,\n} from \"./coordinates\"\nimport { altiumColorToCss, createLine } from \"./render-text\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\n\nexport function renderPrimitiveRecord({\n record,\n index,\n context,\n color,\n strokeWidth,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n color: string\n strokeWidth: number\n}): AnyCircuitElement[] | undefined {\n const kind = record.recordKind\n const scale = context.scale\n if (kind === \"27\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_trace\",\n schematic_trace_id: `schematic_trace_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n junctions: [],\n edges: points.slice(1).map((point, pointIndex) => ({\n from: points[pointIndex] ?? point,\n to: point,\n })),\n } satisfies SchematicTrace,\n ]\n }\n\n if (kind === \"6\" || kind === \"7\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_path_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points,\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color:\n kind === \"7\"\n ? altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"transparent\",\n )\n : undefined,\n is_filled: kind === \"7\",\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"13\") {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return []\n return [\n createLine({\n index,\n start: location,\n end: corner,\n color,\n strokeWidth,\n scale,\n }),\n ]\n }\n\n if (kind === \"10\" || kind === \"14\") {\n const rectangle = getRectangle(record)\n if (!rectangle) return []\n return [\n {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_rect_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect,\n ]\n }\n\n if (kind === \"8\") {\n const center = getLocation(record)\n if (!center) return []\n const radiusX = getCoordinate(record, \"RADIUS\", 1)\n const radiusY = getCoordinate(record, \"SECONDARYRADIUS\", radiusX)\n if (Math.abs(radiusX - radiusY) < 0.0001) {\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_circle_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: radiusX * scale,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_ellipse_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: approximateEllipse({ center, radiusX, radiusY }).map((point) =>\n scalePoint(point, scale),\n ),\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"11\" || kind === \"12\") {\n const center = getLocation(record)\n if (!center) return []\n return [\n {\n type: \"schematic_arc\",\n schematic_arc_id: `schematic_arc_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: getCoordinate(record, \"RADIUS\", 1) * scale,\n start_angle_degrees: Number(\n record.getCaseInsensitive(\"STARTANGLE\") ?? 0,\n ),\n end_angle_degrees: Number(record.getCaseInsensitive(\"ENDANGLE\") ?? 360),\n direction: \"counterclockwise\",\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n } satisfies SchematicArc,\n ]\n }\n\n return undefined\n}\n\n/** Approximate an Altium ellipse with a closed Circuit JSON path. */\nexport function approximateEllipse({\n center,\n radiusX,\n radiusY,\n}: {\n center: { x: number; y: number }\n radiusX: number\n radiusY: number\n}): Array<{ x: number; y: number }> {\n return Array.from({ length: 49 }, (_, index) => {\n const radians = (index / 48) * Math.PI * 2\n return {\n x: center.x + Math.cos(radians) * radiusX,\n y: center.y + Math.sin(radians) * radiusY,\n }\n })\n}\n","import type { AltiumRecord, AltiumSchDoc } from \"altiumts\"\nimport type { AnyCircuitElement, Point, SchematicRect } from \"circuit-json\"\n\nexport const SCHEMATIC_SHEET_ID = \"schematic_sheet_altium\"\n\nconst SCHEMATIC_UNIT_TO_MILLIMETERS = 10.16 / 1.1\nconst SCHEMATIC_SHEET_INSET = 5 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_WIDTH = 297 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_HEIGHT = 210 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_INNER_WIDTH =\n SCHEMATIC_SHEET_WIDTH - SCHEMATIC_SHEET_INSET * 2\nconst SCHEMATIC_SHEET_INNER_HEIGHT =\n SCHEMATIC_SHEET_HEIGHT - SCHEMATIC_SHEET_INSET * 2\n\nexport interface SheetDimensions {\n height: number\n width: number\n}\n\nexport interface SchematicContext {\n document: AltiumSchDoc\n records: AltiumRecord[]\n scale: number\n sheetRecord?: AltiumRecord\n}\n\nexport function getAltiumSheetDimensions(\n sheetRecord: AltiumRecord | undefined,\n): SheetDimensions {\n return {\n width: getPositiveNumber(sheetRecord?.getCaseInsensitive(\"CUSTOMX\"), 1000),\n height: getPositiveNumber(sheetRecord?.getCaseInsensitive(\"CUSTOMY\"), 800),\n }\n}\n\nexport function getPageFitScale(sheetDimensions: SheetDimensions): number {\n return Math.min(\n SCHEMATIC_SHEET_INNER_WIDTH / sheetDimensions.width,\n SCHEMATIC_SHEET_INNER_HEIGHT / sheetDimensions.height,\n )\n}\n\nexport function createSheetBorder(\n sheetRecord: AltiumRecord | undefined,\n scale: number,\n): SchematicRect {\n const { height, width } = getAltiumSheetDimensions(sheetRecord)\n return {\n type: \"schematic_rect\",\n schematic_rect_id: \"schematic_rect_altium_sheet_border\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: { x: (width * scale) / 2, y: (height * scale) / 2 },\n width: width * scale,\n height: height * scale,\n rotation: 0,\n stroke_width: 0.1,\n color: \"#334155\",\n is_filled: false,\n is_dashed: false,\n }\n}\n\nexport function translateSchematicElement(\n element: AnyCircuitElement,\n offset: Point,\n): AnyCircuitElement {\n const translatePoint = (point: Point): Point => ({\n x: point.x + offset.x,\n y: point.y + offset.y,\n })\n switch (element.type) {\n case \"schematic_component\":\n case \"schematic_port\":\n case \"schematic_rect\":\n case \"schematic_circle\":\n case \"schematic_arc\":\n return { ...element, center: translatePoint(element.center) }\n case \"schematic_net_label\":\n return {\n ...element,\n center: translatePoint(element.center),\n ...(element.anchor_position\n ? { anchor_position: translatePoint(element.anchor_position) }\n : {}),\n }\n case \"schematic_text\":\n return { ...element, position: translatePoint(element.position) }\n case \"schematic_path\":\n return {\n ...element,\n points: element.points.map(translatePoint),\n }\n case \"schematic_line\":\n return {\n ...element,\n x1: element.x1 + offset.x,\n x2: element.x2 + offset.x,\n y1: element.y1 + offset.y,\n y2: element.y2 + offset.y,\n }\n case \"schematic_trace\":\n return {\n ...element,\n edges: element.edges.map((edge) => ({\n ...edge,\n from: translatePoint(edge.from),\n to: translatePoint(edge.to),\n })),\n junctions: element.junctions.map(translatePoint),\n }\n default:\n return element\n }\n}\n\nexport function shouldRenderSchematicRecord(\n record: AltiumRecord,\n context: SchematicContext,\n): boolean {\n let ownerPartId = record.getNumber(\"OWNERPARTID\")\n let ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n let current: AltiumRecord | undefined = record\n const visited = new Set<AltiumRecord>()\n\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = context.document.getParent(current)\n if (!parent) return true\n\n if (ownerPartId === undefined || ownerPartId <= 0) {\n ownerPartId = current.getNumber(\"OWNERPARTID\")\n }\n if (ownerPartDisplayMode === undefined) {\n ownerPartDisplayMode = current.getNumber(\"OWNERPARTDISPLAYMODE\")\n }\n\n if (parent.recordKind === \"1\") {\n const currentPartId = parent.getNumber(\"CURRENTPARTID\") ?? 1\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n }\n current = parent\n }\n return true\n}\n\nfunction getPositiveNumber(value: unknown, fallback: number): number {\n const parsed = Number(value)\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback\n}\n","import type { AltiumPoint, AltiumRecord } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicLine,\n SchematicRect,\n SchematicText,\n} from \"circuit-json\"\nimport type { ConvertAltiumSchDocOptions } from \"../convert-altium-sch-doc-to-circuit-json\"\nimport {\n getCoordinate,\n getLocation,\n getRectangle,\n scalePoint,\n} from \"./coordinates\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\n\nexport function renderTextRecord({\n record,\n index,\n context,\n options,\n color,\n strokeWidth,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: ConvertAltiumSchDocOptions\n color: string\n strokeWidth: number\n}): AnyCircuitElement[] | undefined {\n const kind = record.recordKind\n const scale = context.scale\n if (kind === \"4\" || kind === \"25\" || kind === \"34\" || kind === \"41\") {\n if (options.includeText === false) return []\n if (record.getBoolean(\"ISHIDDEN\") && !options.includeHidden) return []\n const text =\n record.getDecoded(\"TEXT\") ??\n record.getDecoded(\"NAME\") ??\n record.getDecoded(\"DESIGNATOR\")\n const location = getLocation(record)\n if (!text || !location) return []\n return [createText({ record, index, text, location, color, context })]\n }\n\n if (kind === \"28\") {\n const rectangle = getRectangle(record)\n const text = decodeMultilineText(record.getDecoded(\"TEXT\") ?? \"\")\n if (!rectangle || !text || options.includeText === false) return []\n const fontSize = getFontSize(record, context)\n const fontFamily = getFontFamily(record, context)\n const margin = Math.max(getCoordinate(record, \"TEXTMARGIN\", 0), 0)\n const frameWidth = rectangle.maxX - rectangle.minX\n const frameHeight = rectangle.maxY - rectangle.minY\n const availableWidth = Math.max(frameWidth - margin * 2, fontSize)\n const availableHeight = Math.max(frameHeight - margin * 2, fontSize)\n const wrappedLines =\n record.getBoolean(\"WORDWRAP\") === false\n ? text.split(\"\\n\")\n : wrapSchematicText(text, availableWidth, fontSize, fontFamily)\n const lineHeight = fontSize\n const visibleLines =\n record.getBoolean(\"CLIPTORECT\") === false\n ? wrappedLines\n : wrappedLines.slice(\n 0,\n Math.max(Math.ceil(availableHeight / lineHeight), 1),\n )\n const alignment = Number(record.getCaseInsensitive(\"ALIGNMENT\") ?? 1)\n const horizontalAnchor =\n alignment === 2 ? \"center\" : alignment === 3 ? \"right\" : \"left\"\n const textX =\n horizontalAnchor === \"center\"\n ? (rectangle.minX + rectangle.maxX) / 2\n : horizontalAnchor === \"right\"\n ? rectangle.maxX - margin\n : rectangle.minX + margin\n const textColor = altiumColorToCss(\n record.getCaseInsensitive(\"TEXTCOLOR\") ??\n record.getCaseInsensitive(\"COLOR\"),\n \"#1f2937\",\n )\n const elements: AnyCircuitElement[] = visibleLines.map((line, lineIndex) =>\n createDirectText({\n id: `schematic_text_frame_line_altium_${index}_${lineIndex}`,\n text: line,\n location: {\n x: textX,\n y: rectangle.maxY - margin - lineIndex * lineHeight,\n },\n fontSize,\n color: textColor,\n scale,\n rotation: 0,\n anchor: `top_${horizontalAnchor}` as SchematicText[\"anchor\"],\n }),\n )\n\n const isSolid = record.getBoolean(\"ISSOLID\") === true\n const showBorder = record.getBoolean(\"SHOWBORDER\") === true\n if (isSolid || showBorder) {\n elements.unshift({\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_text_frame_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: frameWidth * scale,\n height: frameHeight * scale,\n rotation: 0,\n stroke_width: showBorder ? strokeWidth : 0,\n color: showBorder ? color : \"transparent\",\n is_filled: isSolid,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect)\n }\n\n return elements\n }\n\n return undefined\n}\n\nexport function createLine({\n index,\n start,\n end,\n color,\n strokeWidth,\n scale,\n suffix = \"line\",\n}: {\n index: number\n start: AltiumPoint\n end: AltiumPoint\n color: string\n strokeWidth: number\n scale: number\n suffix?: string\n}): SchematicLine {\n return {\n type: \"schematic_line\",\n schematic_line_id: `schematic_line_altium_${index}_${suffix}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n x1: start.x * scale,\n y1: start.y * scale,\n x2: end.x * scale,\n y2: end.y * scale,\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n }\n}\n\nexport function createText({\n record,\n index,\n text,\n location,\n color,\n context,\n}: {\n record: AltiumRecord\n index: number\n text: string\n location: AltiumPoint\n color: string\n context: SchematicContext\n}): SchematicText {\n const positioning = getTextPositioning(record)\n return createDirectText({\n id: `schematic_text_altium_${index}`,\n text,\n location,\n fontSize: getFontSize(record, context),\n color,\n scale: context.scale,\n rotation: positioning.rotation,\n anchor: positioning.anchor,\n })\n}\n\nexport function createDirectText({\n id,\n text,\n location,\n fontSize,\n color,\n scale,\n rotation,\n anchor,\n}: {\n id: string\n text: string\n location: AltiumPoint\n fontSize: number\n color: string\n scale: number\n rotation: number\n anchor: SchematicText[\"anchor\"]\n}): SchematicText {\n return {\n type: \"schematic_text\",\n schematic_text_id: id,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n text,\n font_size: Math.max(fontSize * scale, 0.2),\n position: scalePoint(location, scale),\n rotation,\n anchor,\n color,\n }\n}\n\nexport function getFontSize(\n record: AltiumRecord,\n context: SchematicContext,\n): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return Math.max(\n Number(context.sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? 9),\n 1,\n )\n}\n\nexport function getFontFamily(\n record: AltiumRecord,\n context: SchematicContext,\n): string {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return context.sheetRecord?.getDecoded(`FONTNAME${fontId}`) ?? \"Arial\"\n}\n\nfunction getTextPositioning(record: AltiumRecord): {\n anchor: SchematicText[\"anchor\"]\n rotation: number\n} {\n const justification = Math.min(\n Math.max(Math.round(record.getNumber(\"JUSTIFICATION\") ?? 0), 0),\n 8,\n )\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n let column = justification % 3\n const row = Math.floor(justification / 3)\n if (orientation === 2 || orientation === 3) column = 2 - column\n const horizontal = [\"left\", \"center\", \"right\"][column] ?? \"left\"\n const vertical = [\"bottom\", \"center\", \"top\"][row] ?? \"bottom\"\n const anchor =\n horizontal === \"center\" && vertical === \"center\"\n ? \"center\"\n : (`${vertical}_${horizontal}` as SchematicText[\"anchor\"])\n return { anchor, rotation: orientation === 1 || orientation === 3 ? 90 : 0 }\n}\n\nexport function decodeMultilineText(text: string): string {\n return text.replaceAll(\"~1\", \"\\n\").replaceAll(\"\\\\n\", \"\\n\")\n}\n\nexport function wrapSchematicText(\n text: string,\n maximumWidth: number,\n fontSize: number,\n fontFamily: string,\n): string[] {\n return text.split(\"\\n\").flatMap((paragraph) => {\n if (\n estimateSchematicTextWidth(paragraph, fontSize, fontFamily) <=\n maximumWidth\n ) {\n return [paragraph]\n }\n const lines: string[] = []\n let line = \"\"\n for (const word of paragraph.split(/\\s+/u)) {\n if (!line) line = word\n else if (\n estimateSchematicTextWidth(`${line} ${word}`, fontSize, fontFamily) <=\n maximumWidth\n ) {\n line = `${line} ${word}`\n } else {\n lines.push(line)\n line = word\n }\n }\n if (line) lines.push(line)\n return lines.length > 0 ? lines : [paragraph]\n })\n}\n\nfunction estimateSchematicTextWidth(\n text: string,\n fontSize: number,\n fontFamily: string,\n): number {\n if (/courier|mono/iu.test(fontFamily)) return text.length * fontSize * 0.6\n if (!/times|cambria|serif/iu.test(fontFamily)) {\n return text.length * fontSize * 0.52\n }\n return [...text].reduce((width, character) => {\n const emWidth =\n character === \" \"\n ? 0.23\n : /[ilI1.,:;!'`|]/u.test(character)\n ? 0.2\n : /[mwMW@%]/u.test(character)\n ? 0.7\n : /[A-Z0-9]/u.test(character)\n ? 0.5\n : 0.4\n return width + emWidth * fontSize\n }, 0)\n}\n\nexport function altiumColorToCss(\n raw: string | undefined,\n fallback: string,\n): string {\n if (raw === undefined) return fallback\n const colorValue = Number(raw)\n if (!Number.isInteger(colorValue) || colorValue < 0) return fallback\n const red = colorValue & 0xff\n const green = (colorValue >>> 8) & 0xff\n const blue = (colorValue >>> 16) & 0xff\n return `#${toHex(red)}${toHex(green)}${toHex(blue)}`\n}\n\nfunction toHex(value: number): string {\n return value.toString(16).padStart(2, \"0\")\n}\n","import type { AltiumRecord } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicPath,\n SchematicText,\n} from \"circuit-json\"\nimport { getLocation, scalePoint } from \"./coordinates\"\nimport {\n altiumColorToCss,\n createDirectText,\n createLine,\n getFontSize,\n} from \"./render-text\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\n\nexport interface SymbolRenderOptions {\n includeHidden?: boolean\n includeText?: boolean\n}\n\nexport function renderHierarchicalPort({\n record,\n index,\n context,\n options,\n color,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: SymbolRenderOptions\n color: string\n}): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const width = Math.max(Number(record.getCaseInsensitive(\"WIDTH\") ?? 16), 10)\n const height = Math.max(Number(record.getCaseInsensitive(\"HEIGHT\") ?? 10), 4)\n const halfHeight = height / 2\n const pointDepth = Math.min(width * 0.22, height)\n const ioType = Number(record.getCaseInsensitive(\"IOTYPE\") ?? 0)\n const points =\n ioType === 1\n ? [\n { x: location.x, y: location.y },\n { x: location.x + pointDepth, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x + pointDepth, y: location.y - halfHeight },\n ]\n : ioType === 2\n ? [\n { x: location.x, y: location.y + halfHeight },\n {\n x: location.x + width - pointDepth,\n y: location.y + halfHeight,\n },\n { x: location.x + width, y: location.y },\n {\n x: location.x + width - pointDepth,\n y: location.y - halfHeight,\n },\n { x: location.x, y: location.y - halfHeight },\n ]\n : [\n { x: location.x, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x, y: location.y - halfHeight },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const name = record.getDecoded(\"NAME\")\n if (name && options.includeText !== false) {\n elements.push(\n createDirectText({\n id: `schematic_port_text_altium_${index}`,\n text: name,\n location: { x: location.x + width / 2, y: location.y },\n fontSize: getFontSize(record, context),\n color: altiumColorToCss(record.getCaseInsensitive(\"TEXTCOLOR\"), color),\n scale: context.scale,\n rotation: 0,\n anchor: \"center\",\n }),\n )\n }\n return elements\n}\n\nexport function renderPin({\n record,\n index,\n context,\n options,\n color,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: SymbolRenderOptions\n color: string\n}): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const pinConglomerate = record.getNumber(\"PINCONGLOMERATE\")\n const hidden =\n record.getBoolean(\"ISHIDDEN\") ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n if (hidden && !options.includeHidden) return []\n const orientation =\n (pinConglomerate ?? Number(record.getCaseInsensitive(\"ORIENTATION\") ?? 0)) &\n 3\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const length = Math.max(\n Number(record.getCaseInsensitive(\"PINLENGTH\") ?? 10),\n 1,\n )\n const end = {\n x: location.x + direction.x * length,\n y: location.y + direction.y * length,\n }\n const elements: AnyCircuitElement[] = [\n createLine({\n index,\n start: location,\n end,\n color,\n strokeWidth: 0.1,\n scale: context.scale,\n suffix: \"pin\",\n }),\n ]\n if (options.includeText === false) return elements\n const name = record.getDecoded(\"NAME\") ?? \"\"\n const designator = record.getDecoded(\"DESIGNATOR\") ?? \"\"\n const showName =\n pinConglomerate === undefined || (pinConglomerate & 0x08) !== 0\n const showDesignator =\n pinConglomerate === undefined || (pinConglomerate & 0x10) !== 0\n const rotation = orientation === 1 || orientation === 3 ? 90 : 0\n const directionMatchesText = orientation === 0 || orientation === 1\n const textOffset = 2\n if (showName && name) {\n elements.push(\n createDirectText({\n id: `schematic_pin_name_altium_${index}`,\n text: name,\n location: {\n x: location.x - direction.x * textOffset,\n y: location.y - direction.y * textOffset,\n },\n fontSize: 6,\n color,\n scale: context.scale,\n rotation,\n anchor: directionMatchesText ? \"right\" : \"left\",\n }),\n )\n }\n if (showDesignator && designator) {\n elements.push(\n createDirectText({\n id: `schematic_pin_designator_altium_${index}`,\n text: designator,\n location: {\n x: location.x + direction.x * textOffset,\n y: location.y + direction.y * textOffset,\n },\n fontSize: 6,\n color,\n scale: context.scale,\n rotation,\n anchor: directionMatchesText ? \"left\" : \"right\",\n }),\n )\n }\n return elements\n}\n\nexport function renderPowerPort({\n record,\n index,\n context,\n options,\n color,\n}: {\n record: AltiumRecord\n index: number\n context: SchematicContext\n options: SymbolRenderOptions\n color: string\n}): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const perpendicular = { x: -direction.y, y: direction.x }\n const point = (along: number, across = 0) => ({\n x: location.x + direction.x * along + perpendicular.x * across,\n y: location.y + direction.y * along + perpendicular.y * across,\n })\n const line = (\n start: { x: number; y: number },\n end: { x: number; y: number },\n suffix: string,\n ) =>\n createLine({\n index,\n start,\n end,\n color,\n strokeWidth: 0.1,\n scale: context.scale,\n suffix,\n })\n const style = Math.round(Number(record.getCaseInsensitive(\"STYLE\") ?? 2))\n const elements: AnyCircuitElement[] = []\n let labelDistance: number\n if (style === 2) {\n elements.push(\n line(location, point(8), \"power_port_stem\"),\n line(point(8, -5), point(8, 5), \"power_port_bar\"),\n )\n labelDistance = 12\n } else if (style === 5) {\n elements.push(line(location, point(4), \"power_port_stem\"), {\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [point(4, -7), point(4, 7), point(12)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n is_filled: false,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 16\n } else if (style === 4) {\n elements.push(\n line(location, point(4), \"power_port_stem\"),\n ...[\n { along: 4, halfWidth: 7 },\n { along: 8, halfWidth: 4.5 },\n { along: 12, halfWidth: 2 },\n ].map(({ along, halfWidth }, lineIndex) =>\n line(\n point(along, -halfWidth),\n point(along, halfWidth),\n `power_port_ground_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 16\n } else if (style === 6) {\n elements.push(\n line(location, point(4), \"power_port_stem\"),\n line(point(4, -7), point(4, 7), \"power_port_chassis_bar\"),\n ...[\n { from: -7, to: -9 },\n { from: 0, to: -2 },\n { from: 7, to: 5 },\n ].map(({ from, to }, lineIndex) =>\n line(point(4, from), point(9, to), `power_port_chassis_${lineIndex}`),\n ),\n )\n labelDistance = 14\n } else {\n elements.push({\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [location, point(10, -5), point(10, 5)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: color,\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 14\n }\n const text = record.getDecoded(\"TEXT\") ?? record.getDecoded(\"NAME\")\n if (\n text &&\n options.includeText !== false &&\n record.getBoolean(\"SHOWNETNAME\") !== false\n ) {\n const vertical = direction.y !== 0\n const anchor: SchematicText[\"anchor\"] = vertical\n ? direction.y > 0\n ? \"bottom_center\"\n : \"top_center\"\n : direction.x > 0\n ? \"center_left\"\n : \"center_right\"\n elements.push(\n createDirectText({\n id: `schematic_power_port_text_altium_${index}`,\n text,\n location: point(labelDistance),\n fontSize: getFontSize(record, context),\n color,\n scale: context.scale,\n rotation: 0,\n anchor,\n }),\n )\n }\n return elements\n}\n","import type { AltiumRecord } from \"altiumts\"\nimport type { AnyCircuitElement, SchematicCircle } from \"circuit-json\"\nimport type { ConvertAltiumSchDocOptions } from \"../convert-altium-sch-doc-to-circuit-json\"\nimport { getLocation, scalePoint } from \"./coordinates\"\nimport { renderPrimitiveRecord } from \"./render-primitives\"\nimport {\n renderHierarchicalPort,\n renderPin,\n renderPowerPort,\n} from \"./render-symbols\"\nimport { altiumColorToCss, createLine, renderTextRecord } from \"./render-text\"\nimport { SCHEMATIC_SHEET_ID, type SchematicContext } from \"./sheet-layout\"\nexport function convertSchematicRecord(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n): AnyCircuitElement[] {\n const kind = record.recordKind\n const scale = context.scale\n const color = altiumColorToCss(record.getCaseInsensitive(\"COLOR\"), \"#1f2937\")\n const strokeWidth = Math.max(\n Number(record.getCaseInsensitive(\"LINEWIDTH\") ?? 1) * scale,\n 0.05,\n )\n\n const primitive = renderPrimitiveRecord({\n record,\n index,\n context,\n color,\n strokeWidth,\n })\n if (primitive) return primitive\n\n if (kind === \"2\") {\n return renderPin({ record, index, context, options, color })\n }\n\n if (kind === \"29\") {\n const location = getLocation(record)\n if (!location) return []\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_junction_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(location, scale),\n radius: Math.max(\n Number(record.getCaseInsensitive(\"SIZE\") ?? 1) * 0.18,\n 0.15,\n ),\n color,\n is_filled: true,\n fill_color: color,\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n\n if (kind === \"22\") {\n const location = getLocation(record)\n if (!location) return []\n // altiumts renders the \"Small Cross\" no-ERC symbol with four Altium\n // coordinate units on either side of its anchor.\n const radius = 4\n const noErcStrokeWidth = Math.max(scale, 0.02)\n return [\n createLine({\n index,\n start: { x: location.x - radius, y: location.y - radius },\n end: { x: location.x + radius, y: location.y + radius },\n color,\n strokeWidth: noErcStrokeWidth,\n scale,\n suffix: \"a\",\n }),\n createLine({\n index,\n start: { x: location.x + radius, y: location.y - radius },\n end: { x: location.x - radius, y: location.y + radius },\n color,\n strokeWidth: noErcStrokeWidth,\n scale,\n suffix: \"b\",\n }),\n ]\n }\n\n if (kind === \"17\") {\n return renderPowerPort({ record, index, context, options, color })\n }\n\n if (kind === \"18\") {\n return renderHierarchicalPort({ record, index, context, options, color })\n }\n\n const textElement = renderTextRecord({\n record,\n index,\n context,\n options,\n color,\n strokeWidth,\n })\n if (textElement) return textElement\n\n return []\n}\n","import type { AltiumSchDoc } from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicGroup,\n SchematicSheet,\n} from \"circuit-json\"\nimport { convertSemanticSchematic } from \"./schematic/convert-semantic-schematic\"\nimport { convertSchematicRecord as renderSchematicRecord } from \"./schematic/render-record\"\nimport {\n createSheetBorder,\n getAltiumSheetDimensions,\n getPageFitScale,\n SCHEMATIC_SHEET_ID,\n type SchematicContext,\n shouldRenderSchematicRecord,\n translateSchematicElement,\n} from \"./schematic/sheet-layout\"\nexport interface ConvertAltiumSchDocOptions {\n centerOnSchematicSheet?: boolean\n includeHidden?: boolean\n includeSheetBorder?: boolean\n includeText?: boolean\n schematicUnitScale?: number\n sheetName?: string\n}\n\nexport function convertAltiumSchDocToCircuitJson(\n document: AltiumSchDoc,\n options: ConvertAltiumSchDocOptions = {},\n): AnyCircuitElement[] {\n const records = document.records\n const sheetRecord = records.find((record) => record.recordKind === \"31\")\n const sheetDimensions = getAltiumSheetDimensions(sheetRecord)\n const scale = options.schematicUnitScale ?? getPageFitScale(sheetDimensions)\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(\"schematicUnitScale must be a positive finite number\")\n }\n\n const context: SchematicContext = { document, records, scale, sheetRecord }\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_sheet\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n name: options.sheetName ?? \"Altium schematic\",\n outline_color: \"#334155\",\n sheet_index: 0,\n } satisfies SchematicSheet,\n ]\n\n if (options.includeSheetBorder === true) {\n elements.push(createSheetBorder(sheetRecord, scale))\n }\n\n const semanticConversion = convertSemanticSchematic(document, {\n includeHidden: options.includeHidden,\n includeText: options.includeText,\n scale,\n schematicSheetId: SCHEMATIC_SHEET_ID,\n })\n elements.push(...semanticConversion.elements)\n\n for (const [index, record] of records.entries()) {\n if (semanticConversion.handledRecords.has(record)) continue\n if (!shouldRenderSchematicRecord(record, context)) continue\n const converted = renderSchematicRecord(record, index, context, options)\n elements.push(...converted)\n }\n\n const schematicComponentIds = elements\n .filter(\n (\n element,\n ): element is Extract<\n AnyCircuitElement,\n { type: \"schematic_component\" }\n > => element.type === \"schematic_component\",\n )\n .map((element) => element.schematic_component_id)\n if (schematicComponentIds.length > 0) {\n elements.push({\n type: \"schematic_group\",\n schematic_group_id: \"schematic_group_altium\",\n source_group_id: \"source_group_altium\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: {\n x: (sheetDimensions.width * scale) / 2,\n y: (sheetDimensions.height * scale) / 2,\n },\n width: sheetDimensions.width * scale,\n height: sheetDimensions.height * scale,\n schematic_component_ids: schematicComponentIds,\n name: options.sheetName ?? \"Altium schematic\",\n } satisfies SchematicGroup)\n }\n\n if (options.centerOnSchematicSheet === false) return elements\n\n const offset = {\n x: (-sheetDimensions.width * scale) / 2,\n y: (-sheetDimensions.height * scale) / 2,\n }\n return elements.map((element) => translateSchematicElement(element, offset))\n}\n","import {\n AltiumBinaryPcbDoc,\n AltiumPcbDoc,\n type AltiumPcbDocument,\n AltiumSchDoc,\n parseAltiumFile,\n parseAltiumPcbDoc,\n parseAltiumSchDoc,\n} from \"altiumts\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport {\n type ConvertAltiumPcbDocOptions,\n convertAltiumPcbDocToCircuitJson,\n} from \"./convert-altium-pcb-doc-to-circuit-json\"\nimport {\n type ConvertAltiumSchDocOptions,\n convertAltiumSchDocToCircuitJson,\n} from \"./convert-altium-sch-doc-to-circuit-json\"\n\nexport type AltiumSourceType = \"auto\" | \"pcb\" | \"schematic\"\n\nexport interface ConvertAltiumToCircuitJsonOptions {\n pcb?: ConvertAltiumPcbDocOptions\n schematic?: ConvertAltiumSchDocOptions\n sourceType?: AltiumSourceType\n}\n\nexport type SupportedAltiumDocument = AltiumPcbDocument | AltiumSchDoc\n\nexport function convertAltiumToCircuitJson(\n source: ArrayBuffer | Uint8Array | string,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n const sourceType = options.sourceType ?? \"auto\"\n\n if (sourceType === \"pcb\") {\n if (typeof source === \"string\") {\n return convertAltiumPcbDocToCircuitJson(\n parseAltiumPcbDoc(source),\n options.pcb,\n )\n }\n const { document } = parseAltiumFile(toUint8Array(source))\n if (\n !(document instanceof AltiumPcbDoc) &&\n !(document instanceof AltiumBinaryPcbDoc)\n ) {\n throw new TypeError(\n `Expected an Altium PCB document, got ${document.type}`,\n )\n }\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n if (sourceType === \"schematic\") {\n return convertAltiumSchDocToCircuitJson(\n parseAltiumSchDoc(normalizeSchematicSource(source)),\n options.schematic,\n )\n }\n\n const bytes = toUint8Array(source)\n const { document } = parseAltiumFile(bytes)\n return convertAltiumDocumentToCircuitJson(document, options)\n}\n\nexport function convertAltiumDocumentToCircuitJson(\n document: unknown,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n if (document instanceof AltiumSchDoc) {\n return convertAltiumSchDocToCircuitJson(document, options.schematic)\n }\n if (\n document instanceof AltiumPcbDoc ||\n document instanceof AltiumBinaryPcbDoc\n ) {\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n const type =\n typeof document === \"object\" && document !== null && \"type\" in document\n ? String(document.type)\n : typeof document\n throw new TypeError(`Unsupported Altium document type: ${type}`)\n}\n\nfunction toUint8Array(source: ArrayBuffer | Uint8Array | string): Uint8Array {\n if (typeof source === \"string\") return new TextEncoder().encode(source)\n if (source instanceof Uint8Array) return source\n return new Uint8Array(source)\n}\n\nfunction normalizeSchematicSource(\n source: ArrayBuffer | Uint8Array | string,\n): Uint8Array | string {\n return source instanceof ArrayBuffer ? new Uint8Array(source) : source\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAmBP,IAAM,sBAAsB;AAC5B,IAAM,WAAW;AACjB,IAAM,8BAA8B;AAY7B,SAAS,iCACd,UACA,UAAsC,CAAC,GAClB;AACrB,QAAM,WAAgC,CAAC;AAEvC,MAAI,QAAQ,wBAAwB,OAAO;AACzC,aAAS,KAAK,YAAY,QAAQ,CAAC;AACnC,eAAW,CAAC,OAAO,MAAM,KAAK,SAAS,cAAc,QAAQ,QAAQ,GAAG;AACtE,UAAI,OAAO,QAAQ,OAAO,SAAS,EAAG;AACtC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,eAAe,qBAAqB,KAAK;AAAA,QACzC,cAAc;AAAA,QACd,OAAO;AAAA,QACP,QAAQ,OAAO,QAAQ,OAAO,IAAI,iBAAiB;AAAA,MACrD,CAAqB;AAAA,IACvB;AAAA,EACF;AAEA,MAAI,QAAQ,sBAAsB,OAAO;AACvC,eAAW,CAAC,OAAO,SAAS,KAAK,SAAS,WAAW,QAAQ,GAAG;AAC9D,YAAM,WAAW,UAAU;AAC3B,UAAI,CAAC,SAAU;AACf,YAAM,SAAS,SAAS,mBAAmB,SAAS;AACpD,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,kBAAkB,YAAY,KAAK;AAAA,QACnC,qBAAqB,2BAA2B,KAAK;AAAA,QACrD,QAAQ,kBAAkB,QAAQ;AAAA,QAClC,OAAO;AAAA,UACL,SAAS,OAAO,OAAO,OAAO,OAAQ,UAAU,cAAc;AAAA,QAChE;AAAA,QACA,QAAQ;AAAA,UACN,SAAS,OAAO,OAAO,OAAO,OAAQ,UAAU,cAAc;AAAA,QAChE;AAAA,QACA,OAAO,UAAU,SAAS,WAAW,WAAW;AAAA,QAChD,UAAU,UAAU;AAAA,QACpB,eAAe;AAAA,QACf,yBAAyB;AAAA,MAC3B,CAAwB;AAAA,IAC1B;AAAA,EACF;AAEA,MACE,QAAQ,sBAAsB,SAC9B,QAAQ,sBAAsB,OAC9B;AACA,aAAS,KAAK,GAAG,kBAAkB,QAAQ,CAAC;AAAA,EAC9C;AAEA,aAAW,CAAC,OAAO,MAAM,KAAK,SAAS,QAAQ,QAAQ,GAAG;AACxD,QAAI,kBAAkB,mBAAmB,QAAQ,gBAAgB,OAAO;AACtE,YAAM,MAAM,WAAW,QAAQ,KAAK;AACpC,UAAI,IAAK,UAAS,KAAK,GAAG;AAC1B;AAAA,IACF;AAEA,QAAI,kBAAkB,mBAAmB;AACvC,UAAI,iBAAiB,OAAO,KAAK,EAAG;AACpC,UAAI,eAAe,OAAO,KAAK,GAAG;AAChC,YAAI,QAAQ,sBAAsB,MAAO;AACzC,cAAM,OAAO,sBAAsB,QAAQ,KAAK;AAChD,YAAI,KAAM,UAAS,KAAK,IAAI;AAAA,MAC9B,WAAW,QAAQ,kBAAkB,OAAO;AAC1C,cAAM,QAAQ,aAAa,QAAQ,KAAK;AACxC,YAAI,MAAO,UAAS,KAAK,KAAK;AAAA,MAChC;AACA;AAAA,IACF;AAEA,QAAI,kBAAkB,mBAAmB,QAAQ,gBAAgB,OAAO;AACtE,YAAM,MAAM,WAAW,QAAQ,KAAK;AACpC,UAAI,IAAK,UAAS,KAAK,GAAG;AAC1B;AAAA,IACF;AAEA,QACE,QAAQ,sBAAsB,SAC9B,CAAC,eAAe,SAAS,MAAM,CAAC,GAChC;AACA;AAAA,IACF;AAEA,QAAI,kBAAkB,iBAAiB;AACrC,YAAM,OAAO,qBAAqB,QAAQ,KAAK;AAC/C,UAAI,KAAM,UAAS,KAAK,IAAI;AAAA,IAC9B,WAAW,kBAAkB,kBAAkB;AAC7C,YAAM,OAAO,sBAAsB,QAAQ,KAAK;AAChD,UAAI,KAAM,UAAS,KAAK,IAAI;AAAA,IAC9B,WAAW,kBAAkB,kBAAkB;AAC7C,YAAM,OAAO,sBAAsB,QAAQ,KAAK;AAChD,UAAI,KAAM,UAAS,KAAK,IAAI;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,kBAAkB,UAAoD;AAC7E,QAAM,eAAe,IAAI;AAAA,IACvB,SAAS,WAAW;AAAA,MAAQ,CAAC,WAAW,UACtC,UAAU,WAAW,CAAC,CAAC,WAAW,YAAY,KAAK,CAAC,CAAU,IAAI,CAAC;AAAA,IACrE;AAAA,EACF;AACA,QAAM,QAAyB,CAAC;AAEhC,aAAW,UAAU,SAAS,SAAS;AACrC,UAAM,QAAQ,SAAS,MAAM;AAC7B,QAAI,CAAC,iBAAiB,KAAK,EAAG;AAC9B,UAAM,YAAY,SAAS,sBAAsB,MAAM;AACvD,UAAM,mBAAmB,YAAY,aAAa,IAAI,SAAS,IAAI;AACnE,QAAI,CAAC,iBAAkB;AACvB,UAAM,SAAS,yBAAyB,MAAM;AAC9C,QAAI,OAAO,SAAS,EAAG;AACvB,UAAM,KAAK;AAAA,MACT,aAAa;AAAA,MACb,OAAO,kBAAkB,KAAK;AAAA,MAC9B;AAAA,MACA,iBACE,kBAAkB,qBAAqB,kBAAkB,kBACpD,OAAO,aAAa,IACrB;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,aAAoC,CAAC;AAC3C,aAAW,QAAQ,qBAAqB,KAAK,GAAG;AAC9C,QAAI,CAAC,mBAAmB,KAAK,MAAM,EAAG;AACtC,UAAM,UAAU,mBAAmB,KAAK,MAAM,EAAE,IAAI,iBAAiB;AACrE,QAAI,QAAQ,SAAS,EAAG;AACxB,eAAW,KAAK;AAAA,MACd,MAAM;AAAA,MACN,0BAA0B,gCAAgC,WAAW,MAAM;AAAA,MAC3E,kBAAkB,KAAK;AAAA,MACvB,OAAO,KAAK;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,QAAqC;AACrE,MAAI,kBAAkB,mBAAmB;AACvC,WAAO,OAAO,SAAS,OAAO,MAAM,CAAC,OAAO,OAAO,OAAO,GAAG,IAAI,CAAC;AAAA,EACpE;AACA,MAAI,kBAAkB,iBAAiB;AACrC,WAAO,OAAO,UAAU,OAAO,aAC3B,eAAe;AAAA,MACb,QAAQ,OAAO;AAAA,MACf,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,IACnB,CAAC,IACD,CAAC;AAAA,EACP;AACA,MAAI,kBAAkB,oBAAoB;AACxC,WAAO,qBAAqB,MAAM,EAAE,QAAQ;AAAA,EAC9C;AACA,SAAO,CAAC;AACV;AAEA,SAAS,qBAAqB,OAAyC;AACrE,QAAM,SAAS,oBAAI,IAA6B;AAChD,aAAW,QAAQ,0BAA0B,KAAK,GAAG;AACnD,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,gBAAgB,QAAQ,CAAC;AAAA,IAChC,EAAE,KAAK,GAAG;AACV,UAAM,QAAQ,OAAO,IAAI,GAAG,KAAK,CAAC;AAClC,UAAM,KAAK,IAAI;AACf,WAAO,IAAI,KAAK,KAAK;AAAA,EACvB;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,QAAQ,wBAAwB;AAC9D;AAEA,SAAS,yBAAyB,OAAyC;AACzE,QAAM,YAAY,CAAC,GAAG,KAAK;AAC3B,QAAM,WAA4B,CAAC;AACnC,SAAO,UAAU,SAAS,GAAG;AAC3B,UAAM,QAAQ,UAAU,MAAM;AAC9B,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,EAAE,GAAG,OAAO,QAAQ,CAAC,GAAG,MAAM,MAAM,EAAE;AACnD,WAAO,6BAA6B,MAAM,SAAS,GAAG;AAAA,IAEtD;AACA,aAAS,KAAK,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,6BACP,UACA,WACS;AACT,QAAM,gBAAgB,SAAS,OAAO,CAAC;AACvC,QAAM,cAAc,SAAS,OAAO,GAAG,EAAE;AACzC,MAAI,CAAC,iBAAiB,CAAC,YAAa,QAAO;AAE3C,aAAW,CAAC,OAAO,SAAS,KAAK,UAAU,QAAQ,GAAG;AACpD,UAAM,iBAAiB,UAAU,OAAO,CAAC;AACzC,UAAM,eAAe,UAAU,OAAO,GAAG,EAAE;AAC3C,QAAI,CAAC,kBAAkB,CAAC,aAAc;AACtC,QAAI,+BAA+B,aAAa,cAAc,GAAG;AAC/D,eAAS,OAAO,KAAK,GAAG,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,IACnD,WAAW,+BAA+B,aAAa,YAAY,GAAG;AACpE,eAAS,OAAO,KAAK,GAAG,UAAU,OAAO,WAAW,EAAE,MAAM,CAAC,CAAC;AAAA,IAChE,WAAW,+BAA+B,eAAe,YAAY,GAAG;AACtE,eAAS,OAAO,QAAQ,GAAG,UAAU,OAAO,MAAM,GAAG,EAAE,CAAC;AAAA,IAC1D,WAAW,+BAA+B,eAAe,cAAc,GAAG;AACxE,eAAS,OAAO,QAAQ,GAAG,UAAU,OAAO,WAAW,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,IACvE,OAAO;AACL;AAAA,IACF;AACA,cAAU,OAAO,OAAO,CAAC;AACzB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,OAAyC;AAC1E,QAAM,aAAa,oBAAI,IAAY;AACnC,SAAO,MAAM,OAAO,CAAC,SAAS;AAC5B,UAAM,gBAAgB,KAAK,OAAO,IAAI,iBAAiB,EAAE,KAAK,GAAG;AACjE,UAAM,gBAAgB,KAAK,OACxB,WAAW,EACX,IAAI,iBAAiB,EACrB,KAAK,GAAG;AACX,UAAM,kBACJ,gBAAgB,gBAAgB,gBAAgB;AAClD,UAAM,YAAY;AAAA,MAChB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,gBAAgB,QAAQ,CAAC;AAAA,MAC9B;AAAA,IACF,EAAE,KAAK,GAAG;AACV,QAAI,WAAW,IAAI,SAAS,EAAG,QAAO;AACtC,eAAW,IAAI,SAAS;AACxB,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,kBAAkB,OAA4B;AACrD,SAAO,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpD;AAEA,SAAS,mBAAmB,QAAgC;AAC1D,QAAM,QAAQ,OAAO,CAAC;AACtB,QAAM,OAAO,OAAO,GAAG,EAAE;AACzB,SAAO,QAAQ,SAAS,QAAQ,+BAA+B,OAAO,IAAI,CAAC;AAC7E;AAEA,SAAS,mBAAmB,QAAsC;AAChE,QAAM,QAAQ,OAAO,CAAC;AACtB,QAAM,OAAO,OAAO,GAAG,EAAE;AACzB,SAAO,SAAS,QAAQ,+BAA+B,OAAO,IAAI,IAC9D,OAAO,MAAM,GAAG,EAAE,IAClB;AACN;AAEA,SAAS,+BACP,MACA,OACS;AACT,SACE,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK;AAExE;AAEA,SAAS,YAAY,UAAuC;AAC1D,QAAM,UAAU,SAAS,cAAc,QAAQ,OAAO,IAAI,iBAAiB;AAC3E,QAAM,SACJ,gBAAgB,SAAS,cAAc,QAAQ,MAAM,KACrD,qBAAqB,SAAS,OAAO;AACvC,QAAM,QAAQ,KAAK,IAAI,kBAAkB,OAAO,OAAO,OAAO,IAAI,GAAG,GAAG;AACxE,QAAM,SAAS,KAAK,IAAI,kBAAkB,OAAO,OAAO,OAAO,IAAI,GAAG,GAAG;AACzE,QAAM,YAAY,SAAS,QACvB,KAAK;AAAA,IACH,iBAAiB,SAAS,KAAK,EAAE,QAAQ;AAAA,MAAO,CAAC,UAC/C,QAAQ,eAAe,MAAM,QAAQ,MAAM,OAAO,CAAC;AAAA,IACrD,EAAE;AAAA,IACF;AAAA,EACF,IACA;AAEJ,SAAO;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,GAAG,mBAAmB,OAAO,OAAO,OAAO,QAAQ,CAAC;AAAA,MACpD,GAAG,mBAAmB,OAAO,OAAO,OAAO,QAAQ,CAAC;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,UAAU,IAAI,EAAE,OAAO,WAAoB,QAAQ,IAAI,CAAC;AAAA,IACpE,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACF;AAEA,SAAS,qBAAqB,SAK5B;AACA,QAAM,SAAwB,CAAC;AAC/B,aAAW,UAAU,SAAS;AAC5B,QACE,kBAAkB,mBAClB,kBAAkB,iBAClB;AACA,UAAI,OAAO,SAAU,QAAO,KAAK,OAAO,QAAQ;AAAA,IAClD,WAAW,kBAAkB,mBAAmB;AAC9C,UAAI,OAAO,MAAO,QAAO,KAAK,OAAO,KAAK;AAC1C,UAAI,OAAO,IAAK,QAAO,KAAK,OAAO,GAAG;AAAA,IACxC;AAAA,EACF;AACA,SAAO,gBAAgB,MAAM,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,KAAM,MAAM,IAAI;AAC9E;AAEA,SAAS,aACP,QACA,OACsB;AACtB,QAAM,QAAQ,OAAO;AACrB,QAAM,MAAM,OAAO;AACnB,QAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,MAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAO,QAAO;AACrC,QAAM,QAAQ,kBAAkB,OAAO,aAAa,CAAC;AACrD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,cAAc,oBAAoB,KAAK;AAAA,IACvC,sBAAsB;AAAA,IACtB,OAAO;AAAA,MACL,EAAE,YAAY,QAAQ,GAAG,kBAAkB,KAAK,GAAG,OAAO,MAAM;AAAA,MAChE,EAAE,YAAY,QAAQ,GAAG,kBAAkB,GAAG,GAAG,OAAO,MAAM;AAAA,IAChE;AAAA,EACF;AACF;AAEA,SAAS,WACP,QACA,OACoB;AACpB,MAAI,CAAC,OAAO,SAAU,QAAO;AAC7B,QAAM,aAAa,eAAe,OAAO,UAAU,KAAK;AACxD,QAAM,WAAW,eAAe,OAAO,QAAQ,KAAK;AACpD,QAAM,SAAS,eAAe,WAAW,CAAC,UAAU,IAAI,CAAC,YAAY,QAAQ;AAC7E,QAAM,gBAAgB,kBAAkB,OAAO,gBAAgB,EAAE;AACjE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY,kBAAkB,KAAK;AAAA,IACnC,GAAG,kBAAkB,OAAO,QAAQ;AAAA,IACpC,gBAAgB;AAAA,IAChB,eAAe;AAAA,MACb,OAAO,iBAAiB,OAAO,gBAAgB,MAAM;AAAA,IACvD;AAAA,IACA;AAAA,IACA,WAAW,OAAO,cAAc,QAAQ,OAAO,iBAAiB;AAAA,EAClE;AACF;AAEA,SAAS,WACP,QACA,OACiD;AACjD,QAAM,WAAW,OAAO;AACxB,QAAM,OAAO,OAAO;AACpB,MAAI,CAAC,YAAY,CAAC,KAAM,QAAO;AAC/B,QAAM,IAAI,kBAAkB,SAAS,CAAC;AACtC,QAAM,IAAI,kBAAkB,SAAS,CAAC;AACtC,QAAM,QAAQ,kBAAkB,KAAK,KAAK;AAC1C,QAAM,SAAS,kBAAkB,KAAK,MAAM;AAC5C,QAAM,eAAe,kBAAkB,OAAO,gBAAgB,CAAC;AAC/D,QAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,QAAM,KAAK,UAAU,KAAK;AAE1B,MAAI,OAAO,WAAW,SAAS,eAAe,GAAG;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa,YAAY,EAAE;AAAA,MAC3B,YAAY;AAAA,MACZ,eAAe;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,aAAa,kBAAkB,eAAe,GAAG;AAC1D,UAAM,iBAAiB,eAAe,QAAQ,YAAY;AAC1D,UAAM,gBAAgB,OAAO,iBAAiB,OAAO;AACrD,UAAM,SACJ,eAAe,OAAO,QAAQ,EAAE,SAAS,MAAM,MAC9C,kBAAkB,MAAM,OAAO,gBAAgB,OAC/C,iBAAiB,MAAM,OAAO,gBAAgB;AACjD,UAAM,SAAqB,CAAC,OAAO,QAAQ;AAE3C,QAAI,QAAQ;AACV,YAAM,YAAY;AAAA,QAChB,KAAK;AAAA,UACH,kBAAkB,iBAAiB,OAAO,gBAAgB;AAAA,UAC1D;AAAA,QACF;AAAA,MACF;AACA,YAAM,aAAa,KAAK,IAAI,cAAc,mBAAmB;AAC7D,UAAI,mBAAmB,KAAK,GAAG;AAC7B,cAAM,UAAU,OAAO,iBAAiB,KAAK,OAAO,aAAa;AACjE,eAAO;AAAA,UACL,MAAM;AAAA,UACN,oBAAoB,mBAAmB,EAAE;AAAA,UACzC,OAAO,UACH,oCACA;AAAA,UACJ,YAAY,UAAU,iBAAiB;AAAA,UACvC,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,aAAa;AAAA,UACb,GAAI,UAAU,EAAE,mBAAmB,OAAO,aAAa,IAAI,CAAC;AAAA,UAC5D,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,UACjB,GAAI,UAAU,EAAE,mBAAmB,OAAO,SAAS,IAAI,CAAC;AAAA,UACxD,eAAe;AAAA,UACf,eAAe;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,oBAAoB,mBAAmB,EAAE;AAAA,QACzC,OAAO;AAAA,QACP,aAAa;AAAA,QACb,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,cAAc,OAAO,gBAAgB,OAAO;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAO;AAAA,QACL,MAAM;AAAA,QACN,oBAAoB,mBAAmB,EAAE;AAAA,QACzC,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,eAAe,KAAK,IAAI,cAAc,mBAAmB;AAAA,QACzD,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,oBAAoB,MAAM,SAAS,WAAW,IAC1C,KAAK,IAAI,OAAO,MAAM,IAAI,OAC1B;AAAA,QACJ,mBAAmB,OAAO;AAAA,QAC1B,eAAe;AAAA,QACf,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,aAAO;AAAA,QACL,MAAM;AAAA,QACN,oBAAoB,mBAAmB,EAAE;AAAA,QACzC,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,eAAe,KAAK,IAAI,cAAc,mBAAmB;AAAA,QACzD,aAAa,oBAAoB;AAAA,UAC/B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,OAAO;AAAA,QACnB,CAAC;AAAA,QACD,eAAe;AAAA,QACf,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,UAAU,YAAY,UAAU,QAAQ;AAC/D,UAAI,KAAK,IAAI,QAAQ,MAAM,KAAK,MAAQ;AACtC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,oBAAoB,mBAAmB,EAAE;AAAA,UACzC,OAAO;AAAA,UACP,aAAa;AAAA,UACb,cAAc;AAAA,UACd,YAAY,KAAK,IAAI,cAAc,mBAAmB;AAAA,UACtD,aAAa,KAAK,IAAI,cAAc,mBAAmB;AAAA,UACvD,cAAc,OAAO;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,oBAAoB,mBAAmB,EAAE;AAAA,MACzC,OAAO;AAAA,MACP,gBAAgB,KAAK,IAAI,OAAO,MAAM;AAAA,MACtC,eAAe,KAAK,IAAI,cAAc,mBAAmB;AAAA,MACzD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO;AAAA,IACX,MAAM;AAAA,IACN,eAAe,cAAc,EAAE;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBACE,OAAO,4BAA4B,SAC/B,SACA,kBAAkB,OAAO,uBAAuB;AAAA,EACxD;AAEA,MAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO;AAAA,MACP,QAAQ,oBAAoB;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,UAAU,WAAW,UAAU,YAAY,UAAU,QAAQ;AAC/D,QAAI,KAAK,IAAI,QAAQ,MAAM,IAAI,MAAQ;AACrC,aAAO,EAAE,GAAG,MAAM,OAAO,UAAU,QAAQ,QAAQ,EAAE;AAAA,IACvD;AACA,WAAO,OAAO,aAAa,IACvB;AAAA,MACE,GAAG;AAAA,MACH,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,QAAQ,KAAK,IAAI,OAAO,MAAM,IAAI;AAAA,IACpC,IACA;AAAA,MACE,GAAG;AAAA,MACH,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,QAAQ,KAAK,IAAI,OAAO,MAAM,IAAI;AAAA,MAClC,cAAc,OAAO;AAAA,IACvB;AAAA,EACN;AAEA,QAAM,eAAe,MAAM,SAAS,WAAW,IAC3C,KAAK,IAAI,OAAO,MAAM,IAAI,OAC1B;AACJ,SAAO,OAAO,aAAa,IACvB,EAAE,GAAG,MAAM,OAAO,QAAQ,OAAO,QAAQ,eAAe,aAAa,IACrE;AAAA,IACE,GAAG;AAAA,IACH,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,cAAc,OAAO;AAAA,EACvB;AACN;AAEA,SAAS,sBACP,QACA,OAC+B;AAC/B,MAAI,CAAC,OAAO,SAAS,CAAC,OAAO,IAAK,QAAO;AACzC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,wBAAwB,8BAA8B,KAAK;AAAA,IAC3D,kBAAkB,wBAAwB,MAAM;AAAA,IAChD,cAAc,kBAAkB,OAAO,aAAa,CAAC;AAAA,IACrD,GAAG,mBAAmB,OAAO,OAAO,OAAO,GAAG;AAAA,IAC9C,OAAO,gBAAgB,OAAO,KAAK;AAAA,EACrC;AACF;AAEA,SAAS,qBACP,QACA,OAC+B;AAC/B,MAAI,CAAC,OAAO,UAAU,CAAC,OAAO,WAAY,QAAO;AACjD,QAAM,SAAS,eAAe;AAAA,IAC5B,QAAQ,OAAO;AAAA,IACf,QAAQ,OAAO;AAAA,IACf,YAAY,OAAO;AAAA,IACnB,UAAU,OAAO;AAAA,EACnB,CAAC;AACD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,wBAAwB,8BAA8B,KAAK;AAAA,IAC3D,kBAAkB,wBAAwB,MAAM;AAAA,IAChD,OAAO,OAAO,IAAI,iBAAiB;AAAA,IACnC,cAAc,kBAAkB,OAAO,aAAa,CAAC;AAAA,IACrD,OAAO,gBAAgB,OAAO,KAAK;AAAA,EACrC;AACF;AAEA,SAAS,sBACP,QACA,OAC+B;AAC/B,MAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,QAAM,QAAQ,kBAAkB,OAAO,OAAO,OAAO,OAAO,OAAO,IAAI;AACvE,QAAM,SAAS,kBAAkB,OAAO,OAAO,OAAO,OAAO,OAAO,IAAI;AACxE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,wBAAwB,8BAA8B,KAAK;AAAA,IAC3D,kBAAkB,wBAAwB,MAAM;AAAA,IAChD,QAAQ;AAAA,MACN,GAAG,mBAAmB,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ,CAAC;AAAA,MAClE,GAAG,mBAAmB,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ,CAAC;AAAA,IACpE;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,KAAK,IAAI,OAAO,MAAM;AAAA,IACpC,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,cAAc,OAAO;AAAA,IACrB,OAAO,gBAAgB,OAAO,KAAK;AAAA,EACrC;AACF;AAEA,SAAS,sBACP,QACA,OAC+B;AAC/B,QAAM,OACJ,uBAAuB,OAAO,WAAW,YAAY,CAAC,KACtD,OAAO,WAAW,MAAM,KACxB,OAAO;AACT,MAAI,CAAC,OAAO,YAAY,CAAC,KAAM,QAAO;AACtC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,wBAAwB,8BAA8B,KAAK;AAAA,IAC3D,kBAAkB,wBAAwB,MAAM;AAAA,IAChD;AAAA,IACA,MAAM;AAAA,IACN,WAAW,kBAAkB,OAAO,cAAc,EAAE;AAAA,IACpD,iBAAiB,kBAAkB,OAAO,QAAQ;AAAA,IAClD,kBAAkB,cAAc,OAAO,aAAa;AAAA,IACpD,cAAc,OAAO;AAAA,IACrB,OAAO,gBAAgB,OAAO,KAAK;AAAA,IACnC,aAAa,OAAO;AAAA,EACtB;AACF;AAEA,SAAS,uBAAuB,KAAiC;AAC/D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,CAAC,kBAAkB,KAAK,GAAG,EAAG,QAAO;AACzC,MAAI;AACF,WAAO,OAAO,cAAc,GAAG,IAAI,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC;AAAA,EAC3D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,wBAAwB,QAA8B;AAC7D,QAAM,QAAQ,OAAO,UAAU,WAAW;AAC1C,SAAO,UAAU,UAAa,QAAQ,IAClC,8BACA,YAAY,KAAK;AACvB;AAEA,SAAS,YAAY,OAAuB;AAC1C,SAAO,wBAAwB,KAAK;AACtC;AAEA,SAAS,cACP,eAC6D;AAC7D,QAAM,aAAa,eAAe,QAAQ,aAAa,EAAE,EAAE,YAAY;AACvE,MAAI,YAAY,SAAS,QAAQ,EAAG,QAAO;AAC3C,MAAI,YAAY,SAAS,OAAO,EAAG,QAAO;AAC1C,MAAI,YAAY,SAAS,MAAM,EAAG,QAAO;AACzC,SAAO;AACT;AAEA,SAAS,eAAe,OAAiD;AACvE,QAAM,aAAa,eAAe,KAAK;AACvC,MAAI,eAAe,SAAS,eAAe,WAAY,QAAO;AAC9D,MAAI,eAAe,YAAY,eAAe,cAAe,QAAO;AACpE,QAAM,aAAa,yCAAyC,KAAK,UAAU;AAC3E,MAAI,CAAC,aAAa,CAAC,EAAG,QAAO;AAC7B,QAAM,cAAc,KAAK,IAAI,KAAK,IAAI,OAAO,WAAW,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AAClE,SAAO,QAAQ,WAAW;AAC5B;AAEA,SAAS,eAAe,OAAoC;AAC1D,QAAM,aAAa,eAAe,KAAK;AACvC,SAAO,eAAe,gBAAgB,eAAe;AACvD;AAEA,SAAS,iBAAiB,OAAoC;AAC5D,QAAM,aAAa,eAAe,KAAK;AACvC,SAAO,eAAe,kBAAkB,eAAe;AACzD;AAEA,SAAS,kBAAkB,OAA6C;AACtE,SAAO,eAAe,KAAK,MAAM,iBAAiB,WAAW;AAC/D;AAEA,SAAS,gBAAgB,OAA6C;AACpE,SAAO,eAAe,KAAK,MAAM,kBAAkB,WAAW;AAChE;AAEA,SAAS,SAAS,QAA0C;AAC1D,SAAO,OAAO,WAAW,OAAO;AAClC;AAEA,SAAS,eAAe,OAAmC;AACzD,UAAQ,SAAS,IAAI,QAAQ,cAAc,EAAE,EAAE,YAAY;AAC7D;AAEA,SAAS,eAAe,OAAmC;AACzD,UAAQ,SAAS,SAAS,QAAQ,aAAa,EAAE,EAAE,YAAY;AACjE;AAEA,SAAS,mBAAmB,OAAwB;AAClD,SAAO,MAAM,SAAS,MAAM,KAAK,UAAU;AAC7C;AAEA,SAAS,eAAe,QAAsB,KAAiC;AAC7E,SAAO,6BAA6B,OAAO,mBAAmB,GAAG,CAAC;AACpE;AAEA,SAAS,kBAAkB,OAAuB;AAChD,SAAO,QAAQ;AACjB;AAEA,SAAS,kBAAkB,OAA8C;AACvE,SAAO,EAAE,GAAG,kBAAkB,MAAM,CAAC,GAAG,GAAG,kBAAkB,MAAM,CAAC,EAAE;AACxE;AAEA,SAAS,mBACP,OACA,KACoD;AACpD,SAAO;AAAA,IACL,IAAI,kBAAkB,MAAM,CAAC;AAAA,IAC7B,IAAI,kBAAkB,MAAM,CAAC;AAAA,IAC7B,IAAI,kBAAkB,IAAI,CAAC;AAAA,IAC3B,IAAI,kBAAkB,IAAI,CAAC;AAAA,EAC7B;AACF;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKkB;AAChB,QAAM,QAAQ,WAAW,cAAc;AACvC,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC;AAC7D,SAAO,MAAM,KAAK,EAAE,QAAQ,WAAW,EAAE,GAAG,CAAC,GAAG,UAAU;AACxD,UAAM,QAAQ,aAAc,QAAQ,QAAS;AAC7C,UAAM,UAAW,QAAQ,KAAK,KAAM;AACpC,WAAO;AAAA,MACL,GAAG,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI;AAAA,MAClC,GAAG,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI;AAAA,IACpC;AAAA,EACF,CAAC;AACH;AAEA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMoC;AAClC,QAAM,YAAY,QAAQ;AAC1B,QAAM,aAAa,SAAS;AAC5B,QAAM,UAAU,KAAK,IAAI,OAAO,MAAM,IAAI;AAC1C,QAAM,SAAS;AAAA,IACb,EAAE,GAAG,CAAC,YAAY,SAAS,GAAG,CAAC,WAAW;AAAA,IAC1C,EAAE,GAAG,YAAY,SAAS,GAAG,CAAC,WAAW;AAAA,IACzC,EAAE,GAAG,WAAW,GAAG,CAAC,aAAa,QAAQ;AAAA,IACzC,EAAE,GAAG,WAAW,GAAG,aAAa,QAAQ;AAAA,IACxC,EAAE,GAAG,YAAY,SAAS,GAAG,WAAW;AAAA,IACxC,EAAE,GAAG,CAAC,YAAY,SAAS,GAAG,WAAW;AAAA,IACzC,EAAE,GAAG,CAAC,WAAW,GAAG,aAAa,QAAQ;AAAA,IACzC,EAAE,GAAG,CAAC,WAAW,GAAG,CAAC,aAAa,QAAQ;AAAA,EAC5C;AACA,QAAM,UAAW,WAAW,KAAK,KAAM;AACvC,SAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC5B,GAAG,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO;AAAA,IAC/D,GAAG,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO;AAAA,EACjE,EAAE;AACJ;;;AC72BA;AAAA,EAIE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAWE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAiC,6BAA6B;AAC9D,SAAyB,eAAe;;;ACdjC,SAAS,gBAAgB,QAAoC;AAClE,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAC7C,SAAO;AAAA,IACL,GAAG,OAAO,OAAO,CAAC,KAAK,UAAU,MAAM,MAAM,GAAG,CAAC,IAAI,OAAO;AAAA,IAC5D,GAAG,OAAO,OAAO,CAAC,KAAK,UAAU,MAAM,MAAM,GAAG,CAAC,IAAI,OAAO;AAAA,EAC9D;AACF;AAEO,SAAS,oBACd,MACA,OACQ;AACR,QAAM,aAAa,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC;AAC5C,QAAM,cAAc,KAAK,MAAM,MAAM,GAAG,MAAM,CAAC;AAC/C,MAAI,eAAe,KAAK,gBAAgB,GAAG;AACzC,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,UACH,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,MAAM,aAAa;AACxD,SAAO,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,MAAM,CAAC;AAC7C;AAEO,SAAS,iBACd,MACA,OACQ;AACR,SAAO,KAAK,MAAM,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC;AACtD;AAEO,SAAS,eACd,MACA,OACa;AACb,SAAO,EAAE,GAAG,KAAK,IAAI,MAAM,GAAG,GAAG,KAAK,IAAI,MAAM,EAAE;AACpD;AAEO,SAAS,sBAAsB,QAAwC;AAC5E,MAAI,KAAK,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,OAAO,CAAC,GAAG;AAC5C,WAAO,OAAO,KAAK,IAAI,UAAU;AAAA,EACnC;AACA,SAAO,OAAO,KAAK,IAAI,OAAO;AAChC;AAEO,SAAS,mBAAmB,QAA+B;AAChE,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG;AACvE,SAAO;AAAA,IACL,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,IAChD,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,IAChD,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,IAChD,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,EAClD;AACF;AAEO,SAAS,YAAY,QAA0B;AACpD,SAAO;AAAA,IACL,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC;AAAA,IACnD,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC;AAAA,IACnD,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC;AAAA,IACnD,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC;AAAA,EACrD;AACF;AAEO,SAAS,gBAAgB,QAA6B;AAC3D,SAAO;AAAA,IACL,IAAI,OAAO,OAAO,OAAO,QAAQ;AAAA,IACjC,IAAI,OAAO,OAAO,OAAO,QAAQ;AAAA,EACnC;AACF;AAEO,SAAS,aAAa,QAA0C;AACrE,QAAM,WAAW,YAAY,MAAM;AACnC,QAAM,SAAS,UAAU,MAAM;AAC/B,MAAI,CAAC,YAAY,CAAC,OAAQ,QAAO;AACjC,SAAO;AAAA,IACL,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,IACnC,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,IACnC,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,IACnC,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,EACrC;AACF;AAEO,SAAS,YAAY,QAA+C;AACzE,QAAM,IAAI,cAAc,QAAQ,YAAY;AAC5C,QAAM,IAAI,cAAc,QAAQ,YAAY;AAC5C,SAAO,MAAM,UAAa,MAAM,SAAY,SAAY,EAAE,GAAG,EAAE;AACjE;AAEO,SAAS,UAAU,QAA+C;AACvE,QAAM,IAAI,cAAc,QAAQ,UAAU;AAC1C,QAAM,IAAI,cAAc,QAAQ,UAAU;AAC1C,SAAO,MAAM,UAAa,MAAM,SAAY,SAAY,EAAE,GAAG,EAAE;AACjE;AAEA,SAAS,cAAc,QAAsB,KAAiC;AAC5E,QAAM,MAAM,OAAO,mBAAmB,GAAG;AACzC,MAAI,QAAQ,OAAW,QAAO;AAC9B,QAAM,UAAU,OAAO,GAAG;AAC1B,MAAI,CAAC,OAAO,SAAS,OAAO,EAAG,QAAO;AACtC,QAAM,cAAc,OAAO,mBAAmB,GAAG,GAAG,OAAO;AAC3D,MAAI,gBAAgB,OAAW,QAAO;AACtC,QAAM,WAAW,OAAO,KAAK,YAAY,QAAQ,UAAU,EAAE,CAAC,EAAE;AAChE,MAAI,CAAC,OAAO,SAAS,QAAQ,EAAG,QAAO;AACvC,SAAO,UAAU,IAAI,UAAU,WAAW,UAAU;AACtD;AAEO,SAAS,WAAW,OAAoB,OAA4B;AACzE,SAAO,EAAE,GAAG,MAAM,IAAI,OAAO,GAAG,MAAM,IAAI,MAAM;AAClD;AAEO,SAAS,SAAS,OAA4B;AACnD,SAAO,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpD;AAEO,SAAS,YACd,MACA,OACS;AACT,SACE,UAAU,UACV,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI,QAC7B,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI;AAEjC;;;ACrIO,SAAS,cAAc,QAA6C;AACzE,SAAO,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC,CAAC,CAAC;AAC/E;AAEO,SAAS,WAAW,OAAuB;AAChD,QAAM,YAAY,MACf,KAAK,EACL,YAAY,EACZ,QAAQ,gBAAgB,GAAG,EAC3B,QAAQ,aAAa,EAAE;AAC1B,SAAO,aAAa;AACtB;AAEO,SAAS,WACd,OACA,KACQ;AACR,QAAM,WAAW,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC5D,QAAM,SAAS,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,IAAI,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtD,SAAO,WAAW,SAAS,GAAG,QAAQ,IAAI,MAAM,KAAK,GAAG,MAAM,IAAI,QAAQ;AAC5E;AAEO,SAAS,YAAY,MAAuB;AACjD,SAAO,iDAAiD,KAAK,IAAI;AACnE;AAEO,SAAS,WAAW,MAAuB;AAChD,SACE,YAAY,IAAI,KAChB,gDAAgD,KAAK,IAAI,KACzD,mDAAmD,KAAK,IAAI;AAEhE;;;ACpBO,SAAS,kBAAkB,QAGN;AAC1B,QAAM,EAAE,YAAY,iBAAiB,IAAI;AACzC,QAAM,SAAS,WAAW,MAAM,WAAW,IAAI,CAAC,GAAG,YAAY,KAAK;AACpE,QAAM,iBAAiB,iBAAiB,YAAY;AACpD,MAAI,WAAW,QAAQ,eAAe,SAAS,WAAW,GAAG;AAC3D,WAAO;AAAA,EACT;AACA,MACE,WAAW,OACX,eAAe,SAAS,SAAS,KACjC,+BAA+B,KAAK,gBAAgB,GACpD;AACA,WAAO;AAAA,EACT;AACA,MAAI,eAAe,SAAS,QAAQ,EAAG,QAAO;AAC9C,MACE,WAAW,QACX,WAAW,QACX,eAAe,SAAS,SAAS,KACjC,eAAe,SAAS,eAAe,GACvC;AACA,WAAO;AAAA,EACT;AACA,MAAI,WAAW,SAAS,eAAe,SAAS,KAAK,EAAG,QAAO;AAC/D,MAAI,WAAW,OAAO,eAAe,SAAS,UAAU,EAAG,QAAO;AAClE,MAAI,WAAW,OAAO,4BAA4B,KAAK,gBAAgB,GAAG;AACxE,WAAO;AAAA,EACT;AACA,MAAI,WAAW,OAAO,eAAe,SAAS,UAAU,EAAG,QAAO;AAClE,MAAI,WAAW,OAAO,eAAe,SAAS,OAAO,EAAG,QAAO;AAC/D,SAAO;AACT;AAEO,SAAS,iBAAiB,kBAG/B;AACA,QAAM,iBAAiB,iBAAiB,YAAY;AACpD,QAAM,aACJ,sCAAsC,KAAK,gBAAgB,KAC3D,eAAe,SAAS,MAAM,KAC9B,eAAe,SAAS,OAAO;AACjC,SAAO;AAAA,IACL,cAAc,aAAa,MAAM;AAAA,IACjC,aAAa,eAAe,SAAS,WAAW,IAC5C,cACA;AAAA,EACN;AACF;AAEO,SAAS,qBAAqB,kBAAmC;AACtE,SAAO,0DAA0D;AAAA,IAC/D;AAAA,EACF;AACF;AAEO,SAAS,yBAAyB,gBAAgC;AACvE,SAAO,eAAe,MAAM,UAAU,EAAE,KAAK,OAAO,KAAK;AAC3D;;;AHiCA,IAAM,2BAAyD;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,sBAAwE;AAAA,EAC5E,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,EACpB,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,EACpB,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACpB,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE;AACnB;AAEA,IAAM,sBAAoD;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB;AACvB,IAAM,eAAe,OAAO,KAAK,cAAc;AAC/C,IAAM,yBAAyB;AAC/B,IAAM,qCAAqC;AAC3C,IAAM,iCAAiC;AACvC,IAAM,mCAAmC;AACzC,IAAM,sCAAsC;AAOrC,SAAS,yBACd,UACA,SAC6B;AAC7B,QAAM,iBAAiB,oBAAI,IAAkB;AAC7C,QAAM,WAAgC,CAAC;AACvC,QAAM,iBAAkC,CAAC;AAEzC,oBAAkB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,mBAAmB,sBAAsB,UAAU,cAAc;AAEvE,QAAM,eAAe,oBAAoB;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,mBAAiB;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,EAAE,UAAU,eAAe;AACpC;AAEA,SAAS,kBAAkB,QAMlB;AACP,QAAM,EAAE,gBAAgB,UAAU,UAAU,gBAAgB,QAAQ,IAAI;AACxE,QAAM,gBAAgB,0BAA0B,QAAQ;AACxD,QAAM,gCAAgC,oBAAI,IAAoB;AAE9D,aAAW,CAAC,gBAAgB,eAAe,KAAK,SAAS,QAAQ,QAAQ,GAAG;AAC1E,QAAI,gBAAgB,eAAe,IAAK;AACxC,mBAAe,IAAI,eAAe;AAElC,UAAM,eAAe,cAAc,gBAAgB,eAAe;AAClE,eAAW,eAAe,aAAc,gBAAe,IAAI,WAAW;AAEtE,UAAM,gBAAgB,gBAAgB,UAAU,eAAe,KAAK;AACpE,UAAM,sBAAsB,aAAa;AAAA,MAAO,CAAC,WAC/C,qBAAqB,QAAQ,aAAa;AAAA,IAC5C;AACA,UAAM,OAAO,oBAAoB;AAAA,MAC/B,CAAC,WACC,OAAO,eAAe,QACrB,CAAC,YAAY,MAAM,KAAK,QAAQ,kBAAkB;AAAA,IACvD;AACA,QAAI,KAAK,WAAW,EAAG;AACvB,UAAM,sBAAsB,IAAI;AAAA,MAC9B,oBACG,OAAO,CAAC,WAAW,OAAO,eAAe,GAAG,EAC5C,QAAQ,CAAC,WAAW;AACnB,cAAM,OAAO,OAAO,WAAW,MAAM,GAAG,KAAK,EAAE,YAAY;AAC3D,eAAO,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,MAC1B,CAAC;AAAA,IACL;AAEA,UAAM,aACJ,cAAc,cAAc,MAAM,YAAY,KAC9C,gBAAgB,WAAW,YAAY,KACvC,IAAI,cAAc;AAKpB,UAAM,QACJ,cAAc,cAAc,MAAM,OAAO,GAAG,KAAK,KACjD,cAAc,cAAc,MAAM,SAAS,GAAG,KAAK,KACnD,gBAAgB,WAAW,SAAS,GAAG,KAAK,KAC5C,gBAAgB,WAAW,cAAc,GAAG,KAAK,KACjD,gBAAgB,WAAW,cAAc,GAAG,KAAK,KACjD;AACF,UAAM,mBACJ,gBAAgB,WAAW,cAAc,KACzC,gBAAgB,WAAW,cAAc,KACzC;AACF,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,uBAAuB,WAAW,KAAK,EAAE,YAAY;AAC3D,UAAM,4BACJ,8BAA8B,IAAI,oBAAoB;AACxD,UAAM,oBACJ,6BAA6B,2BAA2B,cAAc;AACxE,UAAM,uBAAuB,8BAA8B,cAAc;AACzE,QAAI,CAAC,2BAA2B;AAC9B,oCAA8B,IAAI,sBAAsB,iBAAiB;AACzE,eAAS;AAAA,QACP,sBAAsB;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,KAAK;AAAA,UACf;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,iBAAiB,KAAK;AAAA,MAAI,CAAC,KAAK,aACpC,oBAAoB;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AACA,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,eAAe,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,IACzC;AACA,UAAM,kBAAkB,wBAAwB;AAAA,MAC9C;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AACD,UAAM,SAAS,WAAW,gBAAgB,UAAU,GAAG,QAAQ,KAAK;AACpE,UAAM,OAAO,kBACT,EAAE,GAAG,gBAAgB,OAAO,KAAK,IACjC;AAAA,MACE,QAAQ,KAAK;AAAA,SACV,WAAW,OAAO,WAAW,QAAQ,QAAQ;AAAA,QAC9C;AAAA,MACF;AAAA,MACA,OAAO,KAAK;AAAA,SACT,WAAW,OAAO,WAAW,QAAQ,QAAQ;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AACJ,QAAI,iBAAiB;AACnB,oCAA8B;AAAA,QAC5B;AAAA,QACA,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,mBAAe,KAAK,GAAG,cAAc;AACrC,aAAS;AAAA,MACP,GAAG,eAAe;AAAA,QAChB,CAAC,EAAE,oBAAoB,YAAY,cAAc,MAAM;AAAA,UACrD;AAAA,UACA,GAAI,qBAAqB,CAAC,aAAa,IAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AACA,UAAM,qBAAyC;AAAA,MAC7C,MAAM;AAAA,MACN;AAAA;AAAA;AAAA,MAGA,kBAAkB;AAAA,MAClB,wBAAwB;AAAA,MACxB,oBAAoB,QAAQ;AAAA,MAC5B;AAAA,MACA,qBAAqB;AAAA,MACrB,sBAAsB;AAAA,MACtB,GAAI,kBAAkB,EAAE,aAAa,gBAAgB,KAAK,IAAI,CAAC;AAAA,IACjE;AACA,aAAS,KAAK,kBAAkB;AAEhC,QAAI,CAAC,mBAAmB,QAAQ,gBAAgB,OAAO;AACrD,eAAS;AAAA,QACP,oBAAoB;AAAA,UAClB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,IAAI,yCAAyC,cAAc;AAAA,UAC3D,UAAU;AAAA,YACR,GAAG,OAAO,IAAI,KAAK,QAAQ;AAAA,YAC3B,GAAG,OAAO,IAAI,KAAK,SAAS,IAAI;AAAA,UAClC;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AACA,UAAI,OAAO;AACT,iBAAS;AAAA,UACP,oBAAoB;AAAA,YAClB,QAAQ;AAAA,YACR,WAAW;AAAA,YACX,IAAI,oCAAoC,cAAc;AAAA,YACtD,UAAU;AAAA,cACR,GAAG,OAAO,IAAI,KAAK,QAAQ;AAAA,cAC3B,GAAG,OAAO,IAAI,KAAK,SAAS,IAAI;AAAA,YAClC;AAAA,YACA,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,QAQX;AAChB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,cAAc,SAAS,QAAQ,QAAQ,GAAG;AAChD,QAAM,kBAAkB,IAAI,UAAU,iBAAiB;AACvD,QAAM,eAAe,mBAAmB,IAAI,UAAU,aAAa,KAAK,KAAK;AAC7E,QAAM,YAAY,yBAAyB,WAAW,KAAK;AAC3D,QAAM,kBAAkB,oBAAoB,SAAS;AACrD,QAAM,WAAW,YAAY,GAAG,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE;AAClD,QAAM,YAAY,KAAK,IAAI,IAAI,UAAU,WAAW,KAAK,IAAI,CAAC;AAC9D,QAAM,gBAAgB;AAAA,IACpB,GAAG,SAAS,IAAI,gBAAgB,IAAI;AAAA,IACpC,GAAG,SAAS,IAAI,gBAAgB,IAAI;AAAA,EACtC;AACA,QAAM,aAAa,IAAI,WAAW,YAAY,KAAK,GAAG,WAAW,CAAC;AAClE,QAAM,YAAY,eAAe,UAAU;AAC3C,QAAM,OAAO,IAAI,WAAW,MAAM,KAAK;AACvC,QAAM,eAAe,sBAAsB,WAAW;AACtD,QAAM,kBAAkB,yBAAyB,WAAW;AAC5D,QAAM,aAAyB;AAAA,IAC7B,MAAM;AAAA,IACN;AAAA,IACA,YAAY,cAAc;AAAA,MACxB;AAAA,MACA;AAAA,MACA,cAAc,SAAY,SAAY,MAAM,SAAS;AAAA,IACvD,CAAC;AAAA,IACD,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,YAAY,UAAU;AAAA,EAC7D;AACA,QAAM,iBAAiB,IAAI,UAAU,YAAY;AACjD,QAAM,iBAAiB,KAAK,KAAK,EAAE,YAAY;AAC/C,QAAM,iBAAiB,eAAe,QAAQ,SAAS,EAAE;AACzD,QAAM,WACJ,oBAAoB,WACnB,kBAAkB,OAAU,KAC7B,oBAAoB,IAAI,cAAc,KACtC,oBAAoB,IAAI,cAAc;AACxC,QAAM,gBAA+B;AAAA,IACnC,MAAM;AAAA,IACN,QAAQ,WAAW,eAAe,QAAQ,KAAK;AAAA,IAC/C,GAAI,YAAY,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAAA,IACtD,8BAA8B,YAAY,QAAQ;AAAA,IAClD,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,wBAAwB;AAAA,IACxB,mBAAmB;AAAA,IACnB,oBAAoB,QAAQ;AAAA,IAC5B,mBAAmB,gBAAgB,SAAS;AAAA,IAC5C,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,GAAI,cAAc,SAAY,CAAC,IAAI,EAAE,YAAY,UAAU;AAAA,IAC3D,GAAI,mBAAmB,KAAK,mBAAmB,IAC3C,EAAE,iBAAiB,KAAK,IACxB,CAAC;AAAA,IACL,GAAI,mBAAmB,KAAK,mBAAmB,IAC3C,EAAE,kBAAkB,KAAK,IACzB,CAAC;AAAA,EACP;AACA,SAAO;AAAA,IACL,oBAAoB;AAAA,IACpB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,QAOT;AACpB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,iBAAiB,kBAAkB,EAAE,YAAY,iBAAiB,CAAC;AACzE,QAAM,eAAe,yBAAyB,KAAK;AACnD,QAAM,SAAS;AAAA,IACb,MAAM;AAAA,IACN,cAAc;AAAA,IACd,eAAe,SAAS;AAAA,IACxB,0BAA0B;AAAA,IAC1B,MAAM;AAAA,IACN,qBAAqB;AAAA,EACvB;AAEA,MAAI,mBAAmB,YAAY;AACjC,UAAM,aAAa,0BAA0B;AAAA,MAC3C,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,eAAe,QAAW;AAC5B,YAAM,SAAS,uBAAuB,UAAU;AAAA,QAC9C,GAAG;AAAA,QACH,oBAAoB,SAAS;AAAA,QAC7B,OAAO;AAAA,QACP;AAAA,MACF,CAAC;AACD,UAAI,OAAO,QAAS,QAAO,OAAO;AAAA,IACpC;AAAA,EACF;AACA,MAAI,mBAAmB,aAAa;AAClC,UAAM,cAAc,0BAA0B;AAAA,MAC5C,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,gBAAgB,QAAW;AAC7B,YAAM,SAAS,wBAAwB,UAAU;AAAA,QAC/C,GAAG;AAAA,QACH,qBAAqB,SAAS;AAAA,QAC9B,OAAO;AAAA,QACP;AAAA,MACF,CAAC;AACD,UAAI,OAAO,QAAS,QAAO,OAAO;AAAA,IACpC;AAAA,EACF;AACA,MAAI,mBAAmB,YAAY;AACjC,UAAM,aAAa,0BAA0B;AAAA,MAC3C,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,eAAe,QAAW;AAC5B,YAAM,SAAS,uBAAuB,UAAU;AAAA,QAC9C,GAAG;AAAA,QACH,oBAAoB,SAAS;AAAA,QAC7B,OAAO;AAAA,QACP;AAAA,MACF,CAAC;AACD,UAAI,OAAO,QAAS,QAAO,OAAO;AAAA,IACpC;AAAA,EACF;AACA,MAAI,mBAAmB,cAAc,aAAa,KAAK,aAAa,IAAI;AACtE,UAAM,YAAY,0BAA0B;AAAA,MAC1C,eAAe;AAAA,MACf,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,cAAc,QAAW;AAC3B,YAAM,SAAS,sBAAsB,UAAU;AAAA,QAC7C,GAAG;AAAA,QACH;AAAA,QACA,OAAO;AAAA,QACP,aAAa,aAAa,IAAI,aAAa;AAAA,MAC7C,CAAC;AACD,UAAI,OAAO,QAAS,QAAO,OAAO;AAAA,IACpC;AAAA,EACF;AACA,MAAI,mBAAmB,YAAY,YAAY,GAAG;AAChD,UAAM,SAAS,qBAAqB,UAAU;AAAA,MAC5C,GAAG;AAAA,MACH,GAAG,iBAAiB,gBAAgB;AAAA,MACpC,OAAO;AAAA,IACT,CAAC;AACD,QAAI,OAAO,QAAS,QAAO,OAAO;AAAA,EACpC;AAEA,QAAM,QAKJ,mBAAmB,UACf,iBACA,mBAAmB,QACjB,eACA,mBAAmB,cACjB,sBACA;AACV,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,0BAA0B;AAAA,EACjC;AAAA,EACA;AACF,GAGuB;AACrB,QAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,EACF,EAAE;AACF,MACE,OAAO,yBAAyB,YAChC,CAAC,OAAO,SAAS,oBAAoB,GACrC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,QAMX;AAChB,QAAM,EAAE,QAAQ,WAAW,IAAI,UAAU,KAAK,IAAI;AAClD,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP,WAAW;AAAA,IACX;AAAA,IACA,UAAU;AAAA,IACV,wBAAwB,UAAU;AAAA,IAClC,oBAAoB,UAAU;AAAA,IAC9B,mBAAmB;AAAA,IACnB;AAAA,EACF;AACF;AASA,SAAS,sBACP,UACA,gBACkB;AAClB,QAAM,cAAc,IAAI,iBAAiB;AACzC,QAAM,cAAc,oBAAI,IAAyB;AACjD,QAAM,cAAc,SAAS,QAAQ;AAAA,IACnC,CAAC,WAAW,OAAO,eAAe;AAAA,EACpC;AACA,QAAM,WAA+B,CAAC;AAEtC,aAAW,QAAQ,aAAa;AAC9B,UAAM,SAAS,yBAAyB,IAAI;AAC5C,eAAW,SAAS,QAAQ;AAC1B,oBAAc,aAAa,aAAa,KAAK;AAAA,IAC/C;AACA,aAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;AAClD,YAAM,QAAQ,OAAO,QAAQ,CAAC;AAC9B,YAAM,MAAM,OAAO,KAAK;AACxB,UAAI,CAAC,SAAS,CAAC,IAAK;AACpB,kBAAY,MAAM,SAAS,KAAK,GAAG,SAAS,GAAG,CAAC;AAChD,eAAS,KAAK,EAAE,KAAK,MAAM,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,oBAAoB,SAAS,QAAQ,QAAQ,CAAC,WAAW;AAC7D,QAAI,CAAC,CAAC,KAAK,MAAM,MAAM,MAAM,IAAI,EAAE,SAAS,OAAO,cAAc,EAAE,GAAG;AACpE,aAAO,CAAC;AAAA,IACV;AACA,UAAM,QACJ,OAAO,eAAe,OAClB,0BAA0B,QAAQ,QAAQ,GAAG,SAC7C,YAAY,MAAM;AACxB,WAAO,QAAQ,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;AAAA,EACxC,CAAC;AACD,QAAM,iBAAiB,eAAe,IAAI,CAAC,EAAE,OAAO,OAAO,OAAO;AAAA,IAChE;AAAA,IACA;AAAA,EACF,EAAE;AACF,QAAM,aAAa;AAAA,IACjB,GAAG,IAAI;AAAA,MACL,YACG,QAAQ,CAAC,SAAS,yBAAyB,IAAI,CAAC,EAChD,IAAI,CAAC,UAAU,CAAC,SAAS,KAAK,GAAG,KAAK,CAAC;AAAA,IAC5C,EAAE,OAAO;AAAA,IACT,GAAG,kBAAkB,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,IAC7C,GAAG,eAAe,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,EAC5C;AAEA,aAAW,SAAS,YAAY;AAC9B,kBAAc,aAAa,aAAa,KAAK;AAC7C,eAAW,WAAW,UAAU;AAC9B,UAAI,iBAAiB,OAAO,QAAQ,OAAO,QAAQ,GAAG,GAAG;AACvD,oBAAY,MAAM,SAAS,KAAK,GAAG,SAAS,QAAQ,KAAK,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAQA,QAAM,gBAAgB,oBAAI,IAAgC;AAC1D,QAAM,WAAW,CAAC,UAA2C;AAC3D,UAAM,OAAO,YAAY,KAAK,SAAS,KAAK,CAAC;AAC7C,UAAM,WAAW,cAAc,IAAI,IAAI;AACvC,QAAI,SAAU,QAAO;AACrB,UAAM,UAA8B;AAAA,MAClC,IAAI;AAAA,MACJ,OAAO,oBAAI,IAAI;AAAA,MACf,QAAQ,oBAAI,IAAI;AAAA,MAChB,SAAS,oBAAI,IAAI;AAAA,IACnB;AACA,kBAAc,IAAI,MAAM,OAAO;AAC/B,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,YAAY,OAAO,GAAG;AACxC,aAAS,KAAK,EAAE,OAAO,IAAI,SAAS,KAAK,GAAG,KAAK;AAAA,EACnD;AACA,aAAW,QAAQ,aAAa;AAC9B,UAAM,aAAa,yBAAyB,IAAI,EAAE,CAAC;AACnD,QAAI,WAAY,UAAS,UAAU,EAAE,QAAQ,IAAI,IAAI;AAAA,EACvD;AACA,aAAW,EAAE,OAAO,OAAO,KAAK,CAAC,GAAG,mBAAmB,GAAG,cAAc,GAAG;AACzE,UAAM,QAAQ,SAAS,KAAK;AAC5B,UAAM,QAAQ,IAAI,MAAM;AACxB,UAAM,OAAO,wBAAwB,MAAM;AAC3C,QAAI,KAAM,OAAM,MAAM,IAAI,IAAI;AAAA,EAChC;AAEA,QAAM,yBAAyB,oBAAI,IAAkC;AACrE,aAAW,SAAS,cAAc,OAAO,GAAG;AAC1C,UAAM,QAAQ,CAAC,GAAG,MAAM,OAAO,EAAE;AAAA,MAC/B,CAAC,WAAW,OAAO,eAAe;AAAA,IACpC;AACA,eAAW,UAAU,MAAM,SAAS;AAClC,6BAAuB,IAAI,QAAQ,KAAK;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,eAAqC,CAAC;AAC5C,aAAW,SAAS,cAAc,OAAO,GAAG;AAC1C,QAAI,MAAM,QAAQ,SAAS,EAAG;AAC9B,UAAM,kBAAkB,IAAI;AAAA,MAC1B,CAAC,GAAG,MAAM,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,YAAY,CAAC;AAAA,IAC1D;AACA,UAAM,UAAU,aAAa;AAAA,MAAO,CAAC,cACnC,CAAC,GAAG,UAAU,KAAK,EAAE;AAAA,QAAK,CAAC,SACzB,gBAAgB,IAAI,KAAK,KAAK,EAAE,YAAY,CAAC;AAAA,MAC/C;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,KAAK,gBAAgB,SAAS,GAAG;AACtD,mBAAa,KAAK,KAAK;AACvB;AAAA,IACF;AACA,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI,CAAC,OAAQ;AACb,0BAAsB,QAAQ,KAAK;AACnC,eAAW,aAAa,QAAQ,MAAM,CAAC,GAAG;AACxC,4BAAsB,QAAQ,SAAS;AACvC,YAAM,iBAAiB,aAAa,QAAQ,SAAS;AACrD,UAAI,kBAAkB,EAAG,cAAa,OAAO,gBAAgB,CAAC;AAAA,IAChE;AAAA,EACF;AAEA,QAAM,OAAsB,aAAa,IAAI,CAAC,WAAW;AAAA,IACvD,IAAI,MAAM;AAAA,IACV,OAAO,CAAC,GAAG,MAAM,KAAK;AAAA,IACtB,QAAQ,CAAC,GAAG,MAAM,OAAO,OAAO,CAAC;AAAA,IACjC,SAAS,CAAC,GAAG,MAAM,OAAO;AAAA,EAC5B,EAAE;AACF,SAAO;AAAA,IACL,4BAA4B,CAAC,WAC3B,uBAAuB,IAAI,MAAM,KAAK,CAAC;AAAA,IACzC;AAAA,EACF;AACF;AAEA,SAAS,cACP,aACA,aACA,OACM;AACN,QAAM,MAAM,SAAS,KAAK;AAC1B,cAAY,IAAI,GAAG;AACnB,cAAY,IAAI,KAAK,KAAK;AAC5B;AAEA,SAAS,wBAAwB,QAA0C;AACzE,MAAI,OAAO,eAAe,KAAM,QAAO,OAAO,WAAW,MAAM;AAC/D,MAAI,CAAC,KAAK,MAAM,IAAI,EAAE,SAAS,OAAO,cAAc,EAAE,GAAG;AACvD,WAAO,OAAO,WAAW,MAAM;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,sBACP,QAKA,QAKM;AACN,aAAW,QAAQ,OAAO,MAAO,QAAO,MAAM,IAAI,IAAI;AACtD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,OAAQ,QAAO,OAAO,IAAI,KAAK,KAAK;AACtE,aAAW,UAAU,OAAO,QAAS,QAAO,QAAQ,IAAI,MAAM;AAChE;AAEA,SAAS,iBACP,OACA,OACA,KACS;AACT,QAAM,KAAK,IAAI,IAAI,MAAM;AACzB,QAAM,KAAK,IAAI,IAAI,MAAM;AACzB,QAAM,SAAS,MAAM,IAAI,MAAM,KAAK,MAAM,MAAM,IAAI,MAAM,KAAK;AAC/D,QAAM,YAAY,OAAW,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,GAAG,CAAC;AACnE,MAAI,KAAK,IAAI,KAAK,IAAI,UAAW,QAAO;AACxC,QAAM,OAAO,MAAM,IAAI,MAAM,KAAK,MAAM,MAAM,IAAI,MAAM,KAAK;AAC7D,MAAI,MAAM,CAAC,UAAW,QAAO;AAC7B,QAAM,gBAAgB,KAAK,KAAK,KAAK;AACrC,SAAO,OAAO,gBAAgB;AAChC;AAEA,SAAS,qBACP,OACA,KACA,YACe;AACf,QAAM,KAAK,IAAI,IAAI,MAAM;AACzB,QAAM,KAAK,IAAI,IAAI,MAAM;AACzB,QAAM,gBAAgB,KAAK,KAAK,KAAK;AACrC,MAAI,kBAAkB,EAAG,QAAO,CAAC,KAAK;AAEtC,QAAM,cAAc,oBAAI,IAAyB;AAAA,IAC/C,CAAC,SAAS,KAAK,GAAG,KAAK;AAAA,IACvB,CAAC,SAAS,GAAG,GAAG,GAAG;AAAA,EACrB,CAAC;AACD,aAAW,aAAa,YAAY;AAClC,QAAI,iBAAiB,WAAW,OAAO,GAAG,GAAG;AAC3C,kBAAY,IAAI,SAAS,SAAS,GAAG,SAAS;AAAA,IAChD;AAAA,EACF;AACA,SAAO,CAAC,GAAG,YAAY,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,UAAU;AACrD,UAAM,gBAAgB,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK;AACpE,UAAM,iBAAiB,MAAM,IAAI,MAAM,KAAK,MAAM,MAAM,IAAI,MAAM,KAAK;AACvE,WAAO,eAAe;AAAA,EACxB,CAAC;AACH;AAEA,IAAM,mBAAN,MAAuB;AAAA,EACJ,SAAS,oBAAI,IAAoB;AAAA,EAElD,IAAI,OAAqB;AACvB,QAAI,CAAC,KAAK,OAAO,IAAI,KAAK,EAAG,MAAK,OAAO,IAAI,OAAO,KAAK;AAAA,EAC3D;AAAA,EAEA,KAAK,OAAuB;AAC1B,SAAK,IAAI,KAAK;AACd,UAAM,SAAS,KAAK,OAAO,IAAI,KAAK,KAAK;AACzC,QAAI,WAAW,MAAO,QAAO;AAC7B,UAAM,OAAO,KAAK,KAAK,MAAM;AAC7B,SAAK,OAAO,IAAI,OAAO,IAAI;AAC3B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAc,OAAqB;AACvC,UAAM,WAAW,KAAK,KAAK,IAAI;AAC/B,UAAM,YAAY,KAAK,KAAK,KAAK;AACjC,QAAI,aAAa,UAAW,MAAK,OAAO,IAAI,WAAW,QAAQ;AAAA,EACjE;AACF;AAUA,SAAS,oBAAoB,QAOF;AACzB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,EACpB,IAAI;AACJ,QAAM,oBAAoB,oBAAI,IAAoB;AAClD,QAAM,sBAAsB,oBAAI,IAA0B;AAC1D,QAAM,0BAA0B,oBAAI,IAA0B;AAC9D,QAAM,wBAAwB,oBAAI,IAA0B;AAC5D,QAAM,2BAA2B,oBAAI,IAA0B;AAC/D,QAAM,eAAe,aAAa,cAAc;AAEhD,aAAW,CAAC,UAAU,GAAG,KAAK,MAAM,KAAK,QAAQ,GAAG;AAClD,UAAM,QAAQ,IAAI,QAAQ,OAAO,CAAC,WAAW,OAAO,eAAe,IAAI;AACvE,UAAM,0BAA0B;AAAA,MAC9B,IAAI,OAAO,QAAQ,CAAC,UAAU,aAAa,IAAI,SAAS,KAAK,CAAC,KAAK,CAAC,CAAC;AAAA,IACvE;AACA,UAAM,iBAAiB,wBAAwB;AAAA,MAC7C,CAAC,EAAE,WAAW,MAAM,WAAW;AAAA,IACjC;AACA,QACE,MAAM,WAAW,KACjB,EACG,IAAI,MAAM,SAAS,KAAK,eAAe,SAAS,KACjD,eAAe,SAAS,IAE1B;AACA;AAAA,IACF;AACA,UAAM,eAAe,IAAI,MAAM;AAAA,MAAI,CAAC,SAClC,qBAAqB;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AACA,eAAW,UAAU,IAAI,SAAS;AAChC,YAAM,mBAAmB,aAAa,CAAC;AACvC,UAAI,iBAAkB,qBAAoB,IAAI,QAAQ,gBAAgB;AAAA,IACxE;AAEA,UAAM,gBAAgB,uBAAuB,QAAQ;AACrD,eAAW,UAAU,IAAI,SAAS;AAChC,8BAAwB,IAAI,QAAQ,eAAe,MAAM;AACzD,4BAAsB,IAAI,QAAQ,aAAa;AAAA,IACjD;AACA,UAAM,cAA2B;AAAA,MAC/B,MAAM;AAAA,MACN,0BAA0B;AAAA,MAC1B,2BAA2B;AAAA,MAC3B,cAAc,IAAI,MAAM,CAAC;AAAA,MACzB,MAAM,IAAI,MAAM,CAAC;AAAA,MACjB,iBAAiB;AAAA,IACnB;AACA,aAAS,KAAK,WAAW;AAEzB,UAAM,eAAe,SAAS,QAC3B;AAAA,MACC,CAAC,WACC,OAAO,eAAe,QACtB,IAAI,OAAO,KAAK,CAAC,UAAU,YAAY,OAAO,YAAY,MAAM,CAAC,CAAC;AAAA,IACtE,EACC,QAAQ,CAAC,WAAW;AACnB,qBAAe,IAAI,MAAM;AACzB,YAAM,WAAW,YAAY,MAAM;AACnC,aAAO,WAAW,CAAC,WAAW,UAAU,QAAQ,KAAK,CAAC,IAAI,CAAC;AAAA,IAC7D,CAAC;AAEH,eAAW,QAAQ,MAAO,gBAAe,IAAI,IAAI;AACjD,UAAM,oBAAoB,mCAAmC;AAAA,MAC3D,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,oBAAoB;AACxB,eAAW,QAAQ,OAAO;AACxB,YAAM,kBAAkB,SAAS,QAAQ,QAAQ,IAAI;AACrD,YAAM,mBAAmB,0BAA0B,eAAe;AAClE,YAAM,SAAS,yBAAyB,IAAI;AAC5C,YAAM,QAAiC,CAAC;AACxC,eAAS,aAAa,GAAG,aAAa,OAAO,QAAQ,cAAc;AACjE,cAAM,OAAO,OAAO,aAAa,CAAC;AAClC,cAAM,KAAK,OAAO,UAAU;AAC5B,YAAI,CAAC,QAAQ,CAAC,GAAI;AAClB,cAAM,gBAAgB,qBAAqB,MAAM,IAAI,IAAI,MAAM;AAC/D,iBACM,oBAAoB,GACxB,oBAAoB,cAAc,QAClC,qBACA;AACA,gBAAM,cAAc,cAAc,oBAAoB,CAAC;AACvD,gBAAM,YAAY,cAAc,iBAAiB;AACjD,cAAI,CAAC,eAAe,CAAC,UAAW;AAChC,cAAI,kBAAkB,IAAI,WAAW,aAAa,SAAS,CAAC,GAAG;AAC7D;AAAA,UACF;AACA,gBAAM,WAAW,aACd,IAAI,SAAS,WAAW,CAAC,GACxB,KAAK,CAAC,SAAS,KAAK,kBAAkB;AAC1C,gBAAM,SAAS,aACZ,IAAI,SAAS,SAAS,CAAC,GACtB,KAAK,CAAC,SAAS,KAAK,kBAAkB;AAC1C,gBAAM,aAAa;AAAA,YACjB;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AACA,gBAAM,WAAW;AAAA,YACf;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AACA,gBAAM,KAAK;AAAA,YACT,MAAM,WAAW,aAAa,QAAQ,KAAK;AAAA,YAC3C,IAAI,WAAW,WAAW,QAAQ,KAAK;AAAA,YACvC,GAAI,aAAa,EAAE,wBAAwB,WAAW,IAAI,CAAC;AAAA,YAC3D,GAAI,WAAW,EAAE,sBAAsB,SAAS,IAAI,CAAC;AAAA,UACvD,CAAC;AAAA,QACH;AAAA,MACF;AACA,UAAI,MAAM,WAAW,EAAG;AACxB,+BAAyB,IAAI,MAAM,gBAAgB;AACnD,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN;AAAA,QACA,WAAW,sBAAsB,IAAI,eAAe,CAAC;AAAA,QACrD,oBAAoB,QAAQ;AAAA,QAC5B,oBAAoB;AAAA,QACpB,iBAAiB;AAAA,MACnB,CAA0B;AAC1B;AAAA,IACF;AAEA,eAAW,iBAAiB,yBAAyB;AACnD,UAAI,CAAC,cAAc,mBAAoB;AACvC,YAAM,qBAAqB,WAAW,cAAc,OAAO,QAAQ,KAAK;AACxE,UAAI,YAAY,cAAc,cAAc,QAAQ,kBAAkB,GAAG;AACvE;AAAA,MACF;AACA,YAAM,kBAAkB,SAAS,QAAQ,QAAQ,cAAc,MAAM;AACrE,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,OAAO,oBAAoB,eAAe,kBAAkB;AAAA,QAC5D,WAAW,CAAC;AAAA,QACZ,oBAAoB,QAAQ;AAAA,QAC5B,oBAAoB,oCAAoC,eAAe;AAAA,QACvE,iBAAiB;AAAA,MACnB,CAA0B;AAAA,IAC5B;AAEA,UAAM,mBAAmB,IAAI,IAAI,cAAc;AAC/C,eAAW,iBAAiB,gBAAgB;AAC1C,UACE,cAAc,sBACd,iBAAiB,IAAI,cAAc,WAAW,cAAc,GAC5D;AACA,sBAAc,cAAc,eAAe;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,mCAAmC,QAI5B;AACd,QAAM,EAAE,gBAAgB,KAAK,MAAM,IAAI;AACvC,QAAM,mBAAmB,eACtB,OAAO,CAAC,SAAS,CAAC,KAAK,kBAAkB,EACzC,IAAI,CAAC,SAAS,KAAK,KAAK;AAC3B,MAAI,iBAAiB,WAAW,EAAG,QAAO,oBAAI,IAAI;AAElD,QAAM,eAAe,gBAAgB,KAAK;AAC1C,QAAM,qBAAqB,IAAI;AAAA,IAC7B,eACG,OAAO,CAAC,SAAS,KAAK,kBAAkB,EACxC,IAAI,CAAC,SAAS,SAAS,KAAK,KAAK,CAAC;AAAA,EACvC;AACA,aAAW,UAAU,IAAI,SAAS;AAChC,QAAI,CAAC,CAAC,KAAK,MAAM,MAAM,IAAI,EAAE,SAAS,OAAO,cAAc,EAAE,EAAG;AAChE,UAAM,WACJ,OAAO,eAAe,OAClB,0BAA0B,QAAQ,YAAY,GAAG,SACjD,YAAY,MAAM;AACxB,QAAI,SAAU,oBAAmB,IAAI,SAAS,QAAQ,CAAC;AAAA,EACzD;AAOA,QAAM,WAAW,oBAAI,IAA6B;AAClD,QAAM,qBAAqB,oBAAI,IAAyB;AACxD,QAAM,qBAAqB,CAAC,OAAoB,QAAsB;AACpE,UAAM,gBAAgB,mBAAmB,IAAI,SAAS,KAAK,CAAC;AAC5D,QAAI,cAAe,eAAc,IAAI,GAAG;AAAA,QACnC,oBAAmB,IAAI,SAAS,KAAK,GAAG,oBAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AAAA,EAC7D;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,aAAa,yBAAyB,IAAI;AAChD,aAAS,aAAa,GAAG,aAAa,WAAW,QAAQ,cAAc;AACrE,YAAM,OAAO,WAAW,aAAa,CAAC;AACtC,YAAM,KAAK,WAAW,UAAU;AAChC,UAAI,CAAC,QAAQ,CAAC,GAAI;AAClB,YAAM,gBAAgB,qBAAqB,MAAM,IAAI,IAAI,MAAM;AAC/D,eACM,aAAa,GACjB,aAAa,cAAc,QAC3B,cACA;AACA,cAAM,cAAc,cAAc,aAAa,CAAC;AAChD,cAAM,YAAY,cAAc,UAAU;AAC1C,YAAI,CAAC,eAAe,CAAC,UAAW;AAChC,cAAM,MAAM,WAAW,aAAa,SAAS;AAC7C,iBAAS,IAAI,KAAK;AAAA,UAChB,QAAQ,SAAS,SAAS;AAAA,UAC1B;AAAA,UACA,UAAU,SAAS,WAAW;AAAA,QAChC,CAAC;AACD,2BAAmB,aAAa,GAAG;AACnC,2BAAmB,WAAW,GAAG;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,mBAAmB,iBAAiB,IAAI,CAAC,UAAU,SAAS,KAAK,CAAC;AACxE,SAAO,iBAAiB,SAAS,GAAG;AAClC,UAAM,kBAAkB,iBAAiB,MAAM;AAC/C,QAAI,CAAC,mBAAmB,mBAAmB,IAAI,eAAe,EAAG;AACjE,UAAM,oBAAoB;AAAA,MACxB,GAAI,mBAAmB,IAAI,eAAe,KAAK,CAAC;AAAA,IAClD,EAAE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,IAAI,GAAG,CAAC;AAC9C,QAAI,kBAAkB,WAAW,EAAG;AACpC,UAAM,UAAU,SAAS,IAAI,kBAAkB,CAAC,KAAK,EAAE;AACvD,QAAI,CAAC,QAAS;AACd,uBAAmB,IAAI,QAAQ,GAAG;AAClC,qBAAiB;AAAA,MACf,QAAQ,aAAa,kBAAkB,QAAQ,SAAS,QAAQ;AAAA,IAClE;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBACP,eACA,oBACyB;AACzB,QAAM,aAAa,cAAc,cAAc;AAC/C,QAAM,kBACJ,cAAc,cAAc,oBAAoB;AAClD,QAAM,QACJ,oBAAoB,UAAU,oBAAoB,UAC9C,EAAE,GAAG,mBAAmB,GAAG,GAAG,WAAW,EAAE,IAC3C,EAAE,GAAG,WAAW,GAAG,GAAG,mBAAmB,EAAE;AACjD,QAAM,SAAS,CAAC,YAAY,OAAO,kBAAkB,EAAE;AAAA,IACrD,CAAC,OAAO,OAAO,cACb,UAAU,KAAK,CAAC,YAAY,OAAO,UAAU,QAAQ,CAAC,CAAC;AAAA,EAC3D;AAEA,SAAO,OAAO,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,UAAU;AAC5C,UAAM,OAAO,OAAO,KAAK;AACzB,QAAI,CAAC,KAAM,QAAO,CAAC;AACnB,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA,GAAI,UAAU,IACV;AAAA,UACE,wBACE,cAAc,cAAc;AAAA,QAChC,IACA,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,iBAAiB,QAOjB;AACP,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,EACpB,IAAI;AACJ,QAAM,kBAAkB;AAAA,IACtB,SAAS,QAAQ,OAAO,CAAC,WAAW,OAAO,eAAe,IAAI;AAAA,EAChE;AAEA,aAAW,CAAC,aAAa,MAAM,KAAK,SAAS,QAAQ,QAAQ,GAAG;AAC9D,UAAM,aAAa,OAAO;AAC1B,QAAI,CAAC,cAAc,CAAC,CAAC,KAAK,MAAM,MAAM,IAAI,EAAE,SAAS,UAAU,GAAG;AAChE;AAAA,IACF;AACA,QAAI,OAAO,WAAW,UAAU,KAAK,QAAQ,kBAAkB,MAAM;AACnE,qBAAe,IAAI,MAAM;AACzB;AAAA,IACF;AACA,UAAM,OACJ,OAAO,eAAe,OAClB,OAAO,WAAW,MAAM,IACxB,OAAO,WAAW,MAAM;AAC9B,UAAM,iBACJ,eAAe,OACX,0BAA0B,QAAQ,eAAe,IACjD;AACN,UAAM,WAAW,gBAAgB,UAAU,YAAY,MAAM;AAC7D,QAAI,CAAC,QAAQ,CAAC,SAAU;AACxB,UAAM,iBAAiB,MAAM,2BAA2B,MAAM;AAC9D,UAAM,OAAO,eAAe,CAAC;AAG7B,QAAI,eAAe,OAAO,CAAC,KAAM;AACjC,UAAM,gBAAgB,aAAa,sBAAsB,IAAI,MAAM;AACnE,UAAM,qBACJ,QAAQ,aAAa,MACpB,eAAe,QACb,eAAe,SACb,OAAO,UAAU,QAAQ,KAAK,OAAO,KACtC,aAAa,wBAAwB,IAAI,MAAM,MAAM,KACrD,CAAC,WAAW,IAAI;AACtB,QAAI,sBAAsB,eAAe;AACvC,qBAAe,IAAI,MAAM;AACzB,eAAS;AAAA,QACP,yBAAyB;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AACA,mBAAe,IAAI,MAAM;AAEzB,UAAM,cACJ,aAAa,oBAAoB,IAAI,MAAM,KAC3C,qBAAqB;AAAA,MACnB;AAAA,MACA;AAAA,MACA,mBAAmB,aAAa;AAAA,IAClC,CAAC;AACH,UAAM,mBAAmB,OACrB,aAAa,yBAAyB,IAAI,IAAI,IAC9C;AACJ,UAAM,YAAY,mBAAmB,MAAM;AAC3C,UAAM,aACJ,OAAO,eAAe,OAClB,uBAAuB,QAAQ,SAAS,IACxC;AACN,UAAM,oBAAuC;AAAA,MAC3C,MAAM;AAAA,MACN,iBAAiB,WAAW,UAAU,QAAQ,KAAK;AAAA,MACnD,aAAa;AAAA,QACX,gBAAgB,iBAAiB;AAAA,MACnC;AAAA,MACA,QAAQ,WAAW,UAAU,QAAQ,KAAK;AAAA,MAC1C,wBAAwB,8BAA8B,WAAW;AAAA,MACjE,oBAAoB,QAAQ;AAAA,MAC5B,eAAe;AAAA,MACf,MAAM;AAAA,MACN,GAAI,mBAAmB,EAAE,oBAAoB,iBAAiB,IAAI,CAAC;AAAA,MACnE,GAAI,aAAa,EAAE,aAAa,WAAW,IAAI,CAAC;AAAA,IAClD;AACA,aAAS,KAAK,iBAAiB;AAAA,EACjC;AACF;AAEA,SAAS,yBAAyB,QAShB;AAChB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,YAAY,2BAA2B,QAAQ,UAAU,cAAc;AAC7E,QAAM,iBAAiB,WAAW,UAAU,QAAQ,KAAK;AACzD,QAAM,WAAW,0BAA0B,QAAQ,UAAU,QAAQ,KAAK;AAC1E,QAAM,YAAY,WAAW;AAC7B,QAAM,aACH,KAAK,SAAS,mCACb,uCACF;AACF,QAAM,aAAa,cAAc,QAAQ,cAAc;AACvD,QAAM,gBAAgB,cAAc,UAAU,cAAc,SAAS,KAAK;AAC1E,QAAM,iBAAiB,OAAO,eAAe;AAC7C,QAAM,SAAkC,iBACpC,gBAAgB,IACd,SACA,UACF;AACJ,QAAM,WAAW,iBACb,aACE;AAAA,IACE,GAAG,eAAe,IAAI,WAAW;AAAA,IACjC,GAAG,eAAe;AAAA,EACpB,IACA;AAAA,IACE,GAAG,eAAe;AAAA,IAClB,GAAG,eAAe,IAAI,WAAW;AAAA,EACnC,IACF,aACE;AAAA,IACE,GAAG,eAAe,IAAI,WAAW;AAAA,IACjC,GAAG,eAAe,IAAK,gBAAgB,YAAa;AAAA,EACtD,IACA;AAAA,IACE,GAAG,eAAe,IAAK,gBAAgB,YAAa;AAAA,IACpD,GAAG,eAAe,IAAI,WAAW;AAAA,EACnC;AAEN,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP,WAAW;AAAA,IACX;AAAA,IACA,UAAU,aAAa,MAAM;AAAA,IAC7B,oBAAoB,QAAQ;AAAA,IAC5B,mBAAmB,qCAAqC,WAAW;AAAA,IACnE,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AACF;AAEA,SAAS,0BACP,QACA,UACA,OACQ;AACR,QAAM,SAAS,KAAK;AAAA,IAClB,KAAK,MAAM,OAAO,OAAO,mBAAmB,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,QAAM,cAAc,SAAS,QAAQ;AAAA,IACnC,CAAC,cAAc,UAAU,eAAe;AAAA,EAC1C;AACA,QAAM,iBAAiB;AAAA,IACrB,aAAa,mBAAmB,OAAO,MAAM,EAAE,KAC7C,qCAAqC;AAAA,EACzC;AACA,SAAO,KAAK;AAAA,IACV;AAAA,IACA,KAAK,IAAI,gCAAgC,iBAAiB,KAAK;AAAA,EACjE;AACF;AAEA,SAAS,2BACP,QACA,UACA,gBACmB;AACnB,MAAI,OAAO,eAAe,KAAM,QAAO,mBAAmB,MAAM;AAEhE,aAAW,QAAQ,gBAAgB;AACjC,UAAM,SAAS,yBAAyB,IAAI;AAC5C,aAAS,aAAa,GAAG,aAAa,OAAO,QAAQ,cAAc;AACjE,YAAM,QAAQ,OAAO,aAAa,CAAC;AACnC,YAAM,MAAM,OAAO,UAAU;AAC7B,UAAI,CAAC,SAAS,CAAC,OAAO,CAAC,iBAAiB,UAAU,OAAO,GAAG,EAAG;AAC/D,YAAM,QAAQ,YAAY,UAAU,KAAK,IACrC,MACA,YAAY,UAAU,GAAG,IACvB,QACA;AACN,UAAI,CAAC,MAAO;AAGZ,YAAM,KAAK,SAAS,IAAI,MAAM;AAC9B,YAAM,KAAK,SAAS,IAAI,MAAM;AAC9B,UAAI,KAAK,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,EAAG,QAAO,KAAK,IAAI,SAAS;AAC3D,aAAO,KAAK,IAAI,SAAS;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,mBAAmB,MAAM;AAClC;AAEA,SAAS,gBAAgB,OAA2C;AAClE,SAAO,MAAM,QAAQ,CAAC,SAAS;AAC7B,UAAM,SAAS,yBAAyB,IAAI;AAC5C,UAAM,WAA+B,CAAC;AACtC,aAAS,aAAa,GAAG,aAAa,OAAO,QAAQ,cAAc;AACjE,YAAM,QAAQ,OAAO,aAAa,CAAC;AACnC,YAAM,MAAM,OAAO,UAAU;AAC7B,UAAI,SAAS,IAAK,UAAS,KAAK,EAAE,KAAK,MAAM,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,0BACP,QACA,cACuE;AACvE,QAAM,SAAS,YAAY,MAAM;AACjC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,oBAAoB,mBAAmB,MAAM;AACnD,QAAM,kBAAkB,oBAAoB,iBAAiB;AAC7D,QAAM,QAAQ,KAAK,IAAI,OAAO,UAAU,OAAO,KAAK,IAAI,CAAC;AACzD,QAAM,YAAY;AAAA,IAChB,GAAG,OAAO,IAAI,gBAAgB,IAAI;AAAA,IAClC,GAAG,OAAO,IAAI,gBAAgB,IAAI;AAAA,EACpC;AACA,QAAM,sBAAsB,CAAC,UAC3B,aAAa;AAAA,IAAK,CAAC,YACjB,2BAA2B,OAAO,QAAQ,OAAO,QAAQ,GAAG;AAAA,EAC9D;AACF,QAAM,kBAAkB,oBAAoB,MAAM;AAClD,QAAM,qBAAqB,oBAAoB,SAAS;AACxD,QAAM,eAAe,OAAO,UAAU,cAAc;AACpD,QAAM,sBACJ,iBAAiB,KAChB,iBAAiB,KAChB,iBAAiB,KACjB,CAAC,mBACD;AAEJ,SAAO,sBACH;AAAA,IACE,QAAQ;AAAA,IACR,eAAe,qBAAqB,iBAAiB;AAAA,EACvD,IACA,EAAE,QAAQ,QAAQ,eAAe,kBAAkB;AACzD;AAEA,SAAS,2BACP,OACA,OACA,KACS;AACT,SAAO,YAAY,OAAO,KAAK,KAAK,YAAY,OAAO,GAAG;AAC5D;AAEA,SAAS,YAAY,OAAoB,OAA6B;AACpE,QAAM,YAAY;AAClB,UAAQ,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,aAAa;AAC7E;AAEA,SAAS,qBAAqB,WAAiD;AAC7E,MAAI,cAAc,KAAM,QAAO;AAC/B,MAAI,cAAc,OAAQ,QAAO;AACjC,SAAO,cAAc,SAAS,UAAU;AAC1C;AAEA,SAAS,qBAAqB,QAInB;AACT,QAAM,EAAE,UAAU,MAAM,kBAAkB,IAAI;AAC9C,QAAM,iBAAiB,KAAK,KAAK,EAAE,YAAY;AAC/C,QAAM,WAAW,kBAAkB,IAAI,cAAc;AACrD,MAAI,SAAU,QAAO;AAErB,QAAM,kBAAkB,qBAAqB,WAAW,IAAI,CAAC;AAC7D,QAAM,cAAc,IAAI;AAAA,IACtB,SAAS;AAAA,MAAQ,CAAC,YAChB,QAAQ,SAAS,eAAe,CAAC,QAAQ,aAAa,IAAI,CAAC;AAAA,IAC7D;AAAA,EACF;AACA,MAAI,cAAc;AAClB,MAAI,SAAS;AACb,SAAO,YAAY,IAAI,WAAW,GAAG;AACnC,kBAAc,GAAG,eAAe,IAAI,MAAM;AAC1C;AAAA,EACF;AACA,QAAM,YAAuB;AAAA,IAC3B,MAAM;AAAA,IACN,WAAW,YAAY,IAAI;AAAA,IAC3B,UAAU,WAAW,IAAI;AAAA,IACzB,yBAAyB,CAAC;AAAA,IAC1B;AAAA,IACA,eAAe;AAAA,EACjB;AACA,WAAS,KAAK,SAAS;AACvB,oBAAkB,IAAI,gBAAgB,WAAW;AACjD,SAAO;AACT;AAEA,SAAS,wBAAwB,QAID;AAC9B,QAAM,EAAE,YAAY,kBAAkB,MAAM,IAAI;AAChD,QAAM,iBAAiB,kBAAkB,EAAE,YAAY,iBAAiB,CAAC;AACzE,MAAI;AACJ,MAAI,iBAA2B,CAAC;AAChC,MAAI,mBAAmB,eAAe,MAAM,WAAW,GAAG;AACxD,eAAW;AAAA,EACb,WAAW,mBAAmB,aAAa,MAAM,WAAW,GAAG;AAC7D,eAAW;AAAA,EACb,WAAW,mBAAmB,aAAa,MAAM,WAAW,GAAG;AAC7D,eAAW;AAAA,EACb,WACE,mBAAmB,YACnB,MAAM,UAAU,KAChB,kCAAkC,KAAK,GACvC;AACA,UAAM,EAAE,cAAc,YAAY,IAAI,iBAAiB,gBAAgB;AACvE,UAAM,UAAU,iBAAiB,MAAM,MAAM;AAC7C,UAAM,OAAO,gBAAgB,cAAc,MAAM;AACjD,UAAM,SAAS,GAAG,OAAO,YAAY,IAAI;AACzC,qBAAiB,aAAa,OAAO,CAAC,SAAS,KAAK,WAAW,MAAM,CAAC;AAAA,EACxE,WAAW,MAAM,WAAW,GAAG;AAC7B,WAAO;AAAA,EACT,WAAW,mBAAmB,YAAY;AACxC,eAAW;AAAA,EACb,WAAW,mBAAmB,aAAa;AACzC,eAAW,qBAAqB,gBAAgB,IAC5C,wBACA;AAAA,EACN,WAAW,mBAAmB,gBAAgB;AAC5C,eAAW;AAAA,EACb,WAAW,mBAAmB,YAAY;AACxC,eAAW;AAAA,EACb,WAAW,mBAAmB,OAAO;AACnC,eAAW;AAAA,EACb;AACA,MAAI,mBAAmB,SAAS;AAC9B,UAAM,QAAQ,iBAAiB,YAAY;AAC3C,eAAW,MAAM,SAAS,UAAU,IAAI,mBAAmB;AAAA,EAC7D;AACA,MAAI,UAAU;AACZ,qBAAiB,oBAAoB;AAAA,MACnC,CAAC,cAAc,GAAG,QAAQ,IAAI,SAAS;AAAA,IACzC;AAAA,EACF;AACA,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,QAAM,aAAa,eAAe,QAAQ,CAAC,SAAS;AAClD,UAAM,SAAS,eAAe,IAAI;AAClC,UAAM,+BACJ,mBAAmB,YAAY,QAAQ,MAAM,WAAW;AAC1D,QACE,CAAC,UACA,CAAC,gCAAgC,OAAO,MAAM,WAAW,MAAM,QAChE;AACA,aAAO,CAAC;AAAA,IACV;AACA,UAAM,cAAc,kCAAkC,OAAO,QAAQ;AAAA,MACnE,0BAA0B,mBAAmB;AAAA,MAC7C,+BACE,mBAAmB,aAAa,MAAM,WAAW,IAC7C,oBAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAClB;AAAA,IACR,CAAC;AACD,WAAO,YAAY,WAAW,MAAM,SAChC,CAAC,EAAE,aAAa,MAAM,OAAO,CAA2B,IACxD,CAAC;AAAA,EACP,CAAC;AACD,SAAO,WAAW;AAAA,IAChB,CAAC,MAAM,UACL,wBAAwB,IAAI,IAAI,wBAAwB,KAAK;AAAA,EACjE,EAAE,CAAC;AACL;AAEA,SAAS,kCAAkC,OAAiC;AAC1E,QAAM,SAAS,MAAM;AAAA,IAAI,CAAC,SACxB,6BAA6B,KAAK,WAAW,IAAI;AAAA,EACnD;AACA,SACE,OAAO,MAAM,CAAC,UAAU,UAAU,MAAS,KAAK,IAAI,IAAI,MAAM,EAAE,SAAS;AAE7E;AAEA,SAAS,kCACP,OACA,QACA,UAGI,CAAC,GACmB;AACxB,QAAM,oBAAoB,IAAI,IAAI,OAAO,KAAK;AAC9C,QAAM,eAAe,CAAC,GAAG,KAAK,EAAE,KAAK,qBAAqB;AAC1D,QAAM,cAAsC,CAAC;AAC7C,QAAM,kBAAkB,gBAAgB,MAAM,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK,CAAC;AAEvE,aAAW,CAAC,WAAW,aAAa,KAAK,aAAa,QAAQ,GAAG;AAC/D,UAAM,WAAW;AAAA,MACf,cAAc,cAAc,YAAY,SAAS;AAAA,MACjD,cAAc,WAAW;AAAA,MACzB,GAAI,cAAc,WAAW,cAAc,CAAC;AAAA,IAC9C,EAAE,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC;AAChD,UAAM,kBAAkB,IAAI;AAAA,MAC1B,SAAS,QAAQ,CAAC,SAAS;AACzB,cAAM,aAAa,6BAA6B,IAAI;AACpD,eAAO,aAAa,CAAC,UAAU,IAAI,CAAC;AAAA,MACtC,CAAC;AAAA,IACH;AACA,UAAM,2BAA2B,QAAQ,2BACrC,OAAO,QACP,CAAC,GAAG,iBAAiB;AACzB,UAAM,uBAAuB,yBAAyB;AAAA,MAAK,CAACA,gBAC1DA,YAAW,OAAO,KAAK,CAAC,UAAU;AAChC,cAAM,aAAa,6BAA6B,KAAK;AACrD,eAAO,aAAa,gBAAgB,IAAI,UAAU,IAAI;AAAA,MACxD,CAAC;AAAA,IACH;AACA,UAAM,aAAa,IAAI,IAAI,SAAS,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC,CAAC;AACrE,UAAM,kBAAkB,CAAC,GAAG,iBAAiB,EAAE;AAAA,MAAK,CAACA,gBACnDA,YAAW,OAAO,KAAK,CAAC,UAAU,WAAW,IAAI,MAAM,YAAY,CAAC,CAAC;AAAA,IACvE;AACA,UAAM,wBAAwB,QAAQ;AACtC,UAAM,4BAA4B,SAAS;AAAA,MAAK,CAAC,SAC/C,uBAAuB,IAAI,KAAK,YAAY,CAAC;AAAA,IAC/C;AACA,UAAM,qBAAqB,4BACvB,CAAC,GAAG,iBAAiB,EAClB;AAAA,MAAO,CAACA,gBACPA,YAAW,OAAO;AAAA,QAAK,CAAC,UACtB,uBAAuB,IAAI,MAAM,YAAY,CAAC;AAAA,MAChD;AAAA,IACF,EACC;AAAA,MACC,CAAC,MAAM,UACL;AAAA,QACE,eAAe,cAAc,OAAO,eAAe;AAAA,QACnD,eAAe,MAAM,OAAO,MAAM;AAAA,MACpC,IACA;AAAA,QACE,eAAe,cAAc,OAAO,eAAe;AAAA,QACnD,eAAe,OAAO,OAAO,MAAM;AAAA,MACrC;AAAA,IACJ,EAAE,CAAC,IACL;AACJ,UAAM,aACJ,wBACA,sBACA,mBACA,OAAO,MAAM,SAAS,KACtB,CAAC,GAAG,iBAAiB,EAAE,CAAC;AAC1B,QAAI,CAAC,WAAY;AACjB,QAAI,CAAC,wBAAwB,CAAC,QAAQ,0BAA0B;AAC9D,wBAAkB,OAAO,UAAU;AAAA,IACrC;AACA,gBAAY,KAAK,EAAE,eAAe,WAAW,CAAC;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,sBACP,MACA,OACQ;AACR,QAAM,gBAAgB,KAAK,cAAc;AACzC,QAAM,iBAAiB,MAAM,cAAc;AAC3C,MAAI,kBAAkB,UAAa,mBAAmB,QAAW;AAC/D,WAAO,gBAAgB;AAAA,EACzB;AACA,UACG,KAAK,cAAc,kBAAkB,MACrC,MAAM,cAAc,kBAAkB;AAE3C;AAEA,SAAS,wBAAwB,WAAoC;AACnE,QAAM,CAAC,OAAO,MAAM,IAAI,UAAU;AAClC,MAAI,CAAC,MAAO,QAAO,OAAO;AAC1B,MAAI,CAAC,QAAQ;AACX,UAAM,oBACJ,oBACE,MAAM,cAAc,cAAc,oBAAoB,OACxD;AACF,WAAO;AAAA,MACL;AAAA,MACA,eAAe,MAAM,YAAY,UAAU,OAAO,MAAM;AAAA,IAC1D;AAAA,EACF;AACA,MAAI,aAAa;AACjB,MAAI,kBAAkB;AACtB,WACM,aAAa,GACjB,aAAa,UAAU,YAAY,QACnC,cACA;AACA,aACM,cAAc,aAAa,GAC/B,cAAc,UAAU,YAAY,QACpC,eACA;AACA,YAAM,kBAAkB,UAAU,YAAY,UAAU;AACxD,YAAM,mBAAmB,UAAU,YAAY,WAAW;AAC1D,UAAI,CAAC,mBAAmB,CAAC,iBAAkB;AAC3C,YAAM,iBAAiB;AAAA,QACrB;AAAA,UACE,iBAAiB,cAAc;AAAA,UAC/B,gBAAgB,cAAc;AAAA,QAChC;AAAA,QACA,eAAe,iBAAiB,YAAY,gBAAgB,UAAU;AAAA,MACxE;AACA,UAAI,CAAC,OAAO,SAAS,cAAc,EAAG;AACtC,oBAAc;AACd;AAAA,IACF;AAAA,EACF;AACA,SAAO,kBAAkB,IACrB,aAAa,kBACb,OAAO;AACb;AAEA,SAAS,6BAA6B,OAAmC;AACvE,QAAM,aAAa,MAAM,YAAY,EAAE,QAAQ,YAAY,EAAE;AAC7D,MAAI,eAAe,OAAO,eAAe,OAAQ,QAAO;AACxD,MAAI,eAAe,OAAO,eAAe,QAAS,QAAO;AACzD,MAAI,eAAe,OAAO,eAAe,SAAU,QAAO;AAC1D,SAAO;AACT;AAEA,SAAS,8BAA8B,QAG9B;AACP,QAAM,EAAE,QAAQ,UAAU,IAAI;AAC9B,QAAM,0BAA0B,oBAAI,IAGlC;AACF,aAAW,cAAc,UAAU,aAAa;AAC9C,UAAM,cAAc,wBAAwB,IAAI,WAAW,UAAU;AACrE,QAAI,YAAa,aAAY,KAAK,UAAU;AAAA,QACvC,yBAAwB,IAAI,WAAW,YAAY,CAAC,UAAU,CAAC;AAAA,EACtE;AAEA,aAAW,CAAC,YAAY,WAAW,KAAK,yBAAyB;AAC/D,UAAM,SAAS,eAAe,YAAY,UAAU,OAAO,MAAM;AACjE,UAAM,YAAY,sBAAsB,MAAM;AAC9C,UAAM,mBAAmB;AAAA,MACvB,GAAG,OAAO,IAAI,OAAO;AAAA,MACrB,GAAG,OAAO,IAAI,OAAO;AAAA,IACvB;AACA,UAAM,iBAAiB,YAAY;AAAA,MACjC,CAAC,MAAM,UACL;AAAA,QACE,KAAK,cAAc,cAAc;AAAA,QACjC;AAAA,MACF,IACA;AAAA,QACE,MAAM,cAAc,cAAc;AAAA,QAClC;AAAA,MACF;AAAA,IACJ,EAAE,CAAC;AACH,eAAW,EAAE,cAAc,KAAK,aAAa;AAC3C,oBAAc,qBACZ,kBAAkB,gBAAgB;AACpC,oBAAc,cAAc,SAAS;AACrC,oBAAc,cAAc,+BAA+B,KAAK;AAAA,QAC9D,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AACA,oBAAc,cAAc,mBAAmB;AAC/C,oBAAc,cAAc,oBAAoB,gBAAgB,SAAS;AAAA,IAC3E;AAAA,EACF;AACF;AAEA,SAAS,uBACP,QACA,WACQ;AACR,QAAM,QAAQ,KAAK,MAAM,OAAO,UAAU,OAAO,KAAK,CAAC;AACvD,MAAI,UAAU,EAAG,QAAO,UAAU,SAAS;AAC3C,MAAI,UAAU,EAAG,QAAO,UAAU,SAAS;AAC3C,MAAI,UAAU,EAAG,QAAO,iBAAiB,SAAS;AAClD,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,uBACP,SACA,YACQ;AACR,QAAM,aAAa,QAChB,OAAO,CAAC,WAAW,OAAO,eAAe,IAAI,EAC7C,QAAQ,CAAC,WAAW;AACnB,UAAM,YAAY,aAAa,MAAM;AACrC,WAAO,YAAY,CAAC,SAAS,IAAI,CAAC;AAAA,EACpC,CAAC;AACH,MAAI,WAAW,SAAS,EAAG,QAAO,YAAY,UAAU;AAExD,QAAM,SAAwB,CAAC;AAC/B,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,eAAe,IAAK;AAC/B,UAAM,WAAW,YAAY,MAAM;AACnC,UAAM,SAAS,UAAU,MAAM;AAC/B,QAAI,YAAY,OAAQ,QAAO,KAAK,UAAU,MAAM;AACpD,WAAO,KAAK,GAAG,yBAAyB,MAAM,CAAC;AAC/C,QAAI,OAAO,eAAe,OAAO,UAAU;AACzC,YAAM,UAAU,KAAK,IAAI,OAAO,UAAU,QAAQ,KAAK,CAAC;AACxD,YAAM,UAAU,KAAK,IAAI,OAAO,UAAU,iBAAiB,KAAK,OAAO;AACvE,aAAO;AAAA,QACL,EAAE,GAAG,SAAS,IAAI,SAAS,GAAG,SAAS,IAAI,QAAQ;AAAA,QACnD,EAAE,GAAG,SAAS,IAAI,SAAS,GAAG,SAAS,IAAI,QAAQ;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,SAAS,EAAG,QAAO,mBAAmB,MAAM;AACvD,QAAM,SAAS,mBAAmB,UAAU;AAC5C,MAAI,OAAO,SAAS,OAAO,MAAM;AAC/B,WAAO,QAAQ;AACf,WAAO,QAAQ;AAAA,EACjB;AACA,MAAI,OAAO,SAAS,OAAO,MAAM;AAC/B,WAAO,QAAQ;AACf,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AAEA,SAAS,cACP,SACA,YACA,MACoB;AACpB,SAAO,QACJ;AAAA,IACC,CAAC,WACC,OAAO,eAAe,cACtB,OAAO,WAAW,MAAM,GAAG,YAAY,MAAM,KAAK,YAAY;AAAA,EAClE,GACE,WAAW,MAAM;AACvB;AAEA,SAAS,qBACP,QACA,eACS;AACT,QAAM,cAAc,OAAO,UAAU,aAAa;AAClD,QAAM,uBAAuB,OAAO,UAAU,sBAAsB;AACpE,UACG,gBAAgB,UACf,eAAe,KACf,gBAAgB,mBACjB,yBAAyB,UAAa,yBAAyB;AAEpE;AAEA,SAAS,YAAY,KAA4B;AAC/C,QAAM,kBAAkB,IAAI,UAAU,iBAAiB;AACvD,SACE,IAAI,WAAW,UAAU,MAAM,QAC9B,oBAAoB,WAAc,kBAAkB,OAAU;AAEnE;AAEA,SAAS,mBAAmB,QAAyC;AACnE,QAAM,eACF,KAAK,MAAM,OAAO,UAAU,aAAa,KAAK,CAAC,IAAI,IAAK,KAAK;AACjE,SAAO,yBAAyB,WAAW,KAAK;AAClD;AAEA,SAAS,gBACP,WACiD;AACjD,MAAI,cAAc,KAAM,QAAO;AAC/B,MAAI,cAAc,OAAQ,QAAO;AACjC,SAAO;AACT;AAEA,SAAS,wBACP,WACkC;AAClC,MAAI,cAAc,KAAM,QAAO;AAC/B,MAAI,cAAc,OAAQ,QAAO;AACjC,SAAO,cAAc,SAAS,UAAU;AAC1C;AAEA,SAAS,aAAa,OAAsD;AAC1E,QAAM,UAAU,oBAAI,IAA6B;AACjD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,SAAS,KAAK,KAAK;AAC/B,UAAM,WAAW,QAAQ,IAAI,GAAG;AAChC,QAAI,SAAU,UAAS,KAAK,IAAI;AAAA,QAC3B,SAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,OAAyC;AACrE,QAAM,oBAAoB,oBAAI,IAAY;AAC1C,SAAO,MAAM,OAAO,CAAC,SAAS;AAC5B,UAAM,eAAe,KAAK,WAAW;AACrC,QAAI,kBAAkB,IAAI,YAAY,EAAG,QAAO;AAChD,sBAAkB,IAAI,YAAY;AAClC,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,2BACP,MACA,iBACA,OACoB;AACpB,MAAI,CAAC,MAAM,mBAAoB,QAAO;AACtC,SAAO;AAAA,IACL,KAAK,cAAc;AAAA,IACnB,WAAW,iBAAiB,KAAK;AAAA,EACnC,IACI,KAAK,cAAc,oBACnB;AACN;AAEA,SAAS,eAAe,OAAmC;AACzD,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,UAAU,MAAM,KAAK,UAAU,IAAI,SAAS;AAC5D;;;AIx2DO,SAASC,aAAY,QAA+C;AACzE,MACE,OAAO,mBAAmB,YAAY,MAAM,UAC5C,OAAO,mBAAmB,YAAY,MAAM,QAC5C;AACA,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,GAAGC,eAAc,QAAQ,YAAY;AAAA,IACrC,GAAGA,eAAc,QAAQ,YAAY;AAAA,EACvC;AACF;AAEO,SAASC,WAAU,QAA+C;AACvE,MACE,OAAO,mBAAmB,UAAU,MAAM,UAC1C,OAAO,mBAAmB,UAAU,MAAM,QAC1C;AACA,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,GAAGD,eAAc,QAAQ,UAAU;AAAA,IACnC,GAAGA,eAAc,QAAQ,UAAU;AAAA,EACrC;AACF;AAEO,SAASE,cAAa,QAA6C;AACxE,QAAM,WAAWH,aAAY,MAAM;AACnC,QAAM,SAASE,WAAU,MAAM;AAC/B,MAAI,CAAC,YAAY,CAAC,OAAQ,QAAO;AACjC,SAAO;AAAA,IACL,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,IACnC,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,IACnC,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,IACnC,MAAM,KAAK,IAAI,SAAS,GAAG,OAAO,CAAC;AAAA,EACrC;AACF;AAEO,SAASD,eACd,QACA,KACA,WAAW,GACH;AACR,QAAM,cAAc,OAAO,OAAO,mBAAmB,GAAG,KAAK,QAAQ;AACrE,QAAM,cAAc,OAAO,mBAAmB,GAAG,GAAG,OAAO;AAC3D,MAAI,CAAC,OAAO,SAAS,WAAW,KAAK,gBAAgB,QAAW;AAC9D,WAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AAAA,EACtD;AACA,QAAM,WAAW,OAAO,KAAK,YAAY,QAAQ,UAAU,EAAE,CAAC,EAAE;AAChE,MAAI,CAAC,OAAO,SAAS,QAAQ,EAAG,QAAO;AACvC,SAAO,cAAc,IAAI,cAAc,WAAW,cAAc;AAClE;AAEO,SAASG,YAAW,OAAoB,OAA4B;AACzE,SAAO,EAAE,GAAG,MAAM,IAAI,OAAO,GAAG,MAAM,IAAI,MAAM;AAClD;;;AChEA,SAA4B,4BAAAC,iCAAgC;;;ACGrD,IAAM,qBAAqB;AAElC,IAAM,gCAAgC,QAAQ;AAC9C,IAAM,wBAAwB,IAAI;AAClC,IAAM,wBAAwB,MAAM;AACpC,IAAM,yBAAyB,MAAM;AACrC,IAAM,8BACJ,wBAAwB,wBAAwB;AAClD,IAAM,+BACJ,yBAAyB,wBAAwB;AAc5C,SAAS,yBACd,aACiB;AACjB,SAAO;AAAA,IACL,OAAO,kBAAkB,aAAa,mBAAmB,SAAS,GAAG,GAAI;AAAA,IACzE,QAAQ,kBAAkB,aAAa,mBAAmB,SAAS,GAAG,GAAG;AAAA,EAC3E;AACF;AAEO,SAAS,gBAAgB,iBAA0C;AACxE,SAAO,KAAK;AAAA,IACV,8BAA8B,gBAAgB;AAAA,IAC9C,+BAA+B,gBAAgB;AAAA,EACjD;AACF;AAEO,SAAS,kBACd,aACA,OACe;AACf,QAAM,EAAE,QAAQ,MAAM,IAAI,yBAAyB,WAAW;AAC9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,IACpB,QAAQ,EAAE,GAAI,QAAQ,QAAS,GAAG,GAAI,SAAS,QAAS,EAAE;AAAA,IAC1D,OAAO,QAAQ;AAAA,IACf,QAAQ,SAAS;AAAA,IACjB,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AACF;AAEO,SAAS,0BACd,SACA,QACmB;AACnB,QAAM,iBAAiB,CAAC,WAAyB;AAAA,IAC/C,GAAG,MAAM,IAAI,OAAO;AAAA,IACpB,GAAG,MAAM,IAAI,OAAO;AAAA,EACtB;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,GAAG,SAAS,QAAQ,eAAe,QAAQ,MAAM,EAAE;AAAA,IAC9D,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,eAAe,QAAQ,MAAM;AAAA,QACrC,GAAI,QAAQ,kBACR,EAAE,iBAAiB,eAAe,QAAQ,eAAe,EAAE,IAC3D,CAAC;AAAA,MACP;AAAA,IACF,KAAK;AACH,aAAO,EAAE,GAAG,SAAS,UAAU,eAAe,QAAQ,QAAQ,EAAE;AAAA,IAClE,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,QAAQ,OAAO,IAAI,cAAc;AAAA,MAC3C;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,IAAI,QAAQ,KAAK,OAAO;AAAA,QACxB,IAAI,QAAQ,KAAK,OAAO;AAAA,QACxB,IAAI,QAAQ,KAAK,OAAO;AAAA,QACxB,IAAI,QAAQ,KAAK,OAAO;AAAA,MAC1B;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,OAAO,QAAQ,MAAM,IAAI,CAAC,UAAU;AAAA,UAClC,GAAG;AAAA,UACH,MAAM,eAAe,KAAK,IAAI;AAAA,UAC9B,IAAI,eAAe,KAAK,EAAE;AAAA,QAC5B,EAAE;AAAA,QACF,WAAW,QAAQ,UAAU,IAAI,cAAc;AAAA,MACjD;AAAA,IACF;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,4BACd,QACA,SACS;AACT,MAAI,cAAc,OAAO,UAAU,aAAa;AAChD,MAAI,uBAAuB,OAAO,UAAU,sBAAsB;AAClE,MAAI,UAAoC;AACxC,QAAM,UAAU,oBAAI,IAAkB;AAEtC,SAAO,WAAW,CAAC,QAAQ,IAAI,OAAO,GAAG;AACvC,YAAQ,IAAI,OAAO;AACnB,UAAM,SAAS,QAAQ,SAAS,UAAU,OAAO;AACjD,QAAI,CAAC,OAAQ,QAAO;AAEpB,QAAI,gBAAgB,UAAa,eAAe,GAAG;AACjD,oBAAc,QAAQ,UAAU,aAAa;AAAA,IAC/C;AACA,QAAI,yBAAyB,QAAW;AACtC,6BAAuB,QAAQ,UAAU,sBAAsB;AAAA,IACjE;AAEA,QAAI,OAAO,eAAe,KAAK;AAC7B,YAAM,gBAAgB,OAAO,UAAU,eAAe,KAAK;AAC3D,cACG,gBAAgB,UACf,eAAe,KACf,gBAAgB,mBACjB,yBAAyB,UAAa,yBAAyB;AAAA,IAEpE;AACA,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAgB,UAA0B;AACnE,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,SAAS,MAAM,KAAK,SAAS,IAAI,SAAS;AAC1D;;;ACzIO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOoC;AAClC,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,QAAQ;AACtB,MAAI,SAAS,OAAO,SAAS,QAAQ,SAAS,QAAQ,SAAS,MAAM;AACnE,QAAI,QAAQ,gBAAgB,MAAO,QAAO,CAAC;AAC3C,QAAI,OAAO,WAAW,UAAU,KAAK,CAAC,QAAQ,cAAe,QAAO,CAAC;AACrE,UAAM,OACJ,OAAO,WAAW,MAAM,KACxB,OAAO,WAAW,MAAM,KACxB,OAAO,WAAW,YAAY;AAChC,UAAM,WAAWC,aAAY,MAAM;AACnC,QAAI,CAAC,QAAQ,CAAC,SAAU,QAAO,CAAC;AAChC,WAAO,CAAC,WAAW,EAAE,QAAQ,OAAO,MAAM,UAAU,OAAO,QAAQ,CAAC,CAAC;AAAA,EACvE;AAEA,MAAI,SAAS,MAAM;AACjB,UAAM,YAAYC,cAAa,MAAM;AACrC,UAAM,OAAO,oBAAoB,OAAO,WAAW,MAAM,KAAK,EAAE;AAChE,QAAI,CAAC,aAAa,CAAC,QAAQ,QAAQ,gBAAgB,MAAO,QAAO,CAAC;AAClE,UAAM,WAAW,YAAY,QAAQ,OAAO;AAC5C,UAAM,aAAa,cAAc,QAAQ,OAAO;AAChD,UAAM,SAAS,KAAK,IAAIC,eAAc,QAAQ,cAAc,CAAC,GAAG,CAAC;AACjE,UAAM,aAAa,UAAU,OAAO,UAAU;AAC9C,UAAM,cAAc,UAAU,OAAO,UAAU;AAC/C,UAAM,iBAAiB,KAAK,IAAI,aAAa,SAAS,GAAG,QAAQ;AACjE,UAAM,kBAAkB,KAAK,IAAI,cAAc,SAAS,GAAG,QAAQ;AACnE,UAAM,eACJ,OAAO,WAAW,UAAU,MAAM,QAC9B,KAAK,MAAM,IAAI,IACf,kBAAkB,MAAM,gBAAgB,UAAU,UAAU;AAClE,UAAM,aAAa;AACnB,UAAM,eACJ,OAAO,WAAW,YAAY,MAAM,QAChC,eACA,aAAa;AAAA,MACX;AAAA,MACA,KAAK,IAAI,KAAK,KAAK,kBAAkB,UAAU,GAAG,CAAC;AAAA,IACrD;AACN,UAAM,YAAY,OAAO,OAAO,mBAAmB,WAAW,KAAK,CAAC;AACpE,UAAM,mBACJ,cAAc,IAAI,WAAW,cAAc,IAAI,UAAU;AAC3D,UAAM,QACJ,qBAAqB,YAChB,UAAU,OAAO,UAAU,QAAQ,IACpC,qBAAqB,UACnB,UAAU,OAAO,SACjB,UAAU,OAAO;AACzB,UAAM,YAAY;AAAA,MAChB,OAAO,mBAAmB,WAAW,KACnC,OAAO,mBAAmB,OAAO;AAAA,MACnC;AAAA,IACF;AACA,UAAM,WAAgC,aAAa;AAAA,MAAI,CAAC,MAAM,cAC5D,iBAAiB;AAAA,QACf,IAAI,oCAAoC,KAAK,IAAI,SAAS;AAAA,QAC1D,MAAM;AAAA,QACN,UAAU;AAAA,UACR,GAAG;AAAA,UACH,GAAG,UAAU,OAAO,SAAS,YAAY;AAAA,QAC3C;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,OAAO,gBAAgB;AAAA,MACjC,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,OAAO,WAAW,SAAS,MAAM;AACjD,UAAM,aAAa,OAAO,WAAW,YAAY,MAAM;AACvD,QAAI,WAAW,YAAY;AACzB,eAAS,QAAQ;AAAA,QACf,MAAM;AAAA,QACN,mBAAmB,+BAA+B,KAAK;AAAA,QACvD,oBAAoB;AAAA,QACpB,QAAQC;AAAA,UACN;AAAA,YACE,IAAI,UAAU,OAAO,UAAU,QAAQ;AAAA,YACvC,IAAI,UAAU,OAAO,UAAU,QAAQ;AAAA,UACzC;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO,aAAa;AAAA,QACpB,QAAQ,cAAc;AAAA,QACtB,UAAU;AAAA,QACV,cAAc,aAAa,cAAc;AAAA,QACzC,OAAO,aAAa,QAAQ;AAAA,QAC5B,WAAW;AAAA,QACX,YAAY;AAAA,UACV,OAAO,mBAAmB,WAAW;AAAA,UACrC;AAAA,QACF;AAAA,QACA,WAAW;AAAA,MACb,CAAyB;AAAA,IAC3B;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAQkB;AAChB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,mBAAmB,yBAAyB,KAAK,IAAI,MAAM;AAAA,IAC3D,oBAAoB;AAAA,IACpB,IAAI,MAAM,IAAI;AAAA,IACd,IAAI,MAAM,IAAI;AAAA,IACd,IAAI,IAAI,IAAI;AAAA,IACZ,IAAI,IAAI,IAAI;AAAA,IACZ,cAAc;AAAA,IACd;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOkB;AAChB,QAAM,cAAc,mBAAmB,MAAM;AAC7C,SAAO,iBAAiB;AAAA,IACtB,IAAI,yBAAyB,KAAK;AAAA,IAClC;AAAA,IACA;AAAA,IACA,UAAU,YAAY,QAAQ,OAAO;AAAA,IACrC;AAAA,IACA,OAAO,QAAQ;AAAA,IACf,UAAU,YAAY;AAAA,IACtB,QAAQ,YAAY;AAAA,EACtB,CAAC;AACH;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASkB;AAChB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,IACpB;AAAA,IACA,WAAW,KAAK,IAAI,WAAW,OAAO,GAAG;AAAA,IACzC,UAAUA,YAAW,UAAU,KAAK;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,YACd,QACA,SACQ;AACR,QAAM,SAAS,KAAK;AAAA,IAClB,KAAK,MAAM,OAAO,OAAO,mBAAmB,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,KAAK;AAAA,IACV,OAAO,QAAQ,aAAa,mBAAmB,OAAO,MAAM,EAAE,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AACF;AAEO,SAAS,cACd,QACA,SACQ;AACR,QAAM,SAAS,KAAK;AAAA,IAClB,KAAK,MAAM,OAAO,OAAO,mBAAmB,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,QAAQ,aAAa,WAAW,WAAW,MAAM,EAAE,KAAK;AACjE;AAEA,SAAS,mBAAmB,QAG1B;AACA,QAAM,gBAAgB,KAAK;AAAA,IACzB,KAAK,IAAI,KAAK,MAAM,OAAO,UAAU,eAAe,KAAK,CAAC,GAAG,CAAC;AAAA,IAC9D;AAAA,EACF;AACA,QAAM,eACF,KAAK,MAAM,OAAO,UAAU,aAAa,KAAK,CAAC,IAAI,IAAK,KAAK;AACjE,MAAI,SAAS,gBAAgB;AAC7B,QAAM,MAAM,KAAK,MAAM,gBAAgB,CAAC;AACxC,MAAI,gBAAgB,KAAK,gBAAgB,EAAG,UAAS,IAAI;AACzD,QAAM,aAAa,CAAC,QAAQ,UAAU,OAAO,EAAE,MAAM,KAAK;AAC1D,QAAM,WAAW,CAAC,UAAU,UAAU,KAAK,EAAE,GAAG,KAAK;AACrD,QAAM,SACJ,eAAe,YAAY,aAAa,WACpC,WACC,GAAG,QAAQ,IAAI,UAAU;AAChC,SAAO,EAAE,QAAQ,UAAU,gBAAgB,KAAK,gBAAgB,IAAI,KAAK,EAAE;AAC7E;AAEO,SAAS,oBAAoB,MAAsB;AACxD,SAAO,KAAK,WAAW,MAAM,IAAI,EAAE,WAAW,OAAO,IAAI;AAC3D;AAEO,SAAS,kBACd,MACA,cACA,UACA,YACU;AACV,SAAO,KAAK,MAAM,IAAI,EAAE,QAAQ,CAAC,cAAc;AAC7C,QACE,2BAA2B,WAAW,UAAU,UAAU,KAC1D,cACA;AACA,aAAO,CAAC,SAAS;AAAA,IACnB;AACA,UAAM,QAAkB,CAAC;AACzB,QAAI,OAAO;AACX,eAAW,QAAQ,UAAU,MAAM,MAAM,GAAG;AAC1C,UAAI,CAAC,KAAM,QAAO;AAAA,eAEhB,2BAA2B,GAAG,IAAI,IAAI,IAAI,IAAI,UAAU,UAAU,KAClE,cACA;AACA,eAAO,GAAG,IAAI,IAAI,IAAI;AAAA,MACxB,OAAO;AACL,cAAM,KAAK,IAAI;AACf,eAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI,KAAM,OAAM,KAAK,IAAI;AACzB,WAAO,MAAM,SAAS,IAAI,QAAQ,CAAC,SAAS;AAAA,EAC9C,CAAC;AACH;AAEA,SAAS,2BACP,MACA,UACA,YACQ;AACR,MAAI,iBAAiB,KAAK,UAAU,EAAG,QAAO,KAAK,SAAS,WAAW;AACvE,MAAI,CAAC,wBAAwB,KAAK,UAAU,GAAG;AAC7C,WAAO,KAAK,SAAS,WAAW;AAAA,EAClC;AACA,SAAO,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,OAAO,cAAc;AAC5C,UAAM,UACJ,cAAc,MACV,OACA,kBAAkB,KAAK,SAAS,IAC9B,MACA,YAAY,KAAK,SAAS,IACxB,MACA,YAAY,KAAK,SAAS,IACxB,MACA;AACZ,WAAO,QAAQ,UAAU;AAAA,EAC3B,GAAG,CAAC;AACN;AAEO,SAAS,iBACd,KACA,UACQ;AACR,MAAI,QAAQ,OAAW,QAAO;AAC9B,QAAM,aAAa,OAAO,GAAG;AAC7B,MAAI,CAAC,OAAO,UAAU,UAAU,KAAK,aAAa,EAAG,QAAO;AAC5D,QAAM,MAAM,aAAa;AACzB,QAAM,QAAS,eAAe,IAAK;AACnC,QAAM,OAAQ,eAAe,KAAM;AACnC,SAAO,IAAI,MAAM,GAAG,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACpD;AAEA,SAAS,MAAM,OAAuB;AACpC,SAAO,MAAM,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3C;;;AFtUO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMoC;AAClC,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,QAAQ;AACtB,MAAI,SAAS,MAAM;AACjB,UAAM,SAASC,0BAAyB,MAAM,EAAE;AAAA,MAAI,CAAC,UACnDC,YAAW,OAAO,KAAK;AAAA,IACzB;AACA,QAAI,OAAO,SAAS,EAAG,QAAO,CAAC;AAC/B,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,oBAAoB,0BAA0B,KAAK;AAAA,QACnD,oBAAoB;AAAA,QACpB,WAAW,CAAC;AAAA,QACZ,OAAO,OAAO,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,gBAAgB;AAAA,UACjD,MAAM,OAAO,UAAU,KAAK;AAAA,UAC5B,IAAI;AAAA,QACN,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,OAAO,SAAS,KAAK;AAChC,UAAM,SAASD,0BAAyB,MAAM,EAAE;AAAA,MAAI,CAAC,UACnDC,YAAW,OAAO,KAAK;AAAA,IACzB;AACA,QAAI,OAAO,SAAS,EAAG,QAAO,CAAC;AAC/B,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,mBAAmB,yBAAyB,KAAK;AAAA,QACjD,oBAAoB;AAAA,QACpB;AAAA,QACA,cAAc;AAAA,QACd,cAAc;AAAA,QACd,YACE,SAAS,MACL;AAAA,UACE,OAAO,mBAAmB,WAAW;AAAA,UACrC;AAAA,QACF,IACA;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,MAAM;AACjB,UAAM,WAAWC,aAAY,MAAM;AACnC,UAAM,SAASC,WAAU,MAAM;AAC/B,QAAI,CAAC,YAAY,CAAC,OAAQ,QAAO,CAAC;AAClC,WAAO;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,OAAO;AAAA,QACP,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,SAAS,QAAQ,SAAS,MAAM;AAClC,UAAM,YAAYC,cAAa,MAAM;AACrC,QAAI,CAAC,UAAW,QAAO,CAAC;AACxB,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,mBAAmB,yBAAyB,KAAK;AAAA,QACjD,oBAAoB;AAAA,QACpB,QAAQH;AAAA,UACN;AAAA,YACE,IAAI,UAAU,OAAO,UAAU,QAAQ;AAAA,YACvC,IAAI,UAAU,OAAO,UAAU,QAAQ;AAAA,UACzC;AAAA,UACA;AAAA,QACF;AAAA,QACA,QAAQ,UAAU,OAAO,UAAU,QAAQ;AAAA,QAC3C,SAAS,UAAU,OAAO,UAAU,QAAQ;AAAA,QAC5C,UAAU;AAAA,QACV,cAAc;AAAA,QACd;AAAA,QACA,WAAW,OAAO,WAAW,SAAS,MAAM;AAAA,QAC5C,YAAY;AAAA,UACV,OAAO,mBAAmB,WAAW;AAAA,UACrC;AAAA,QACF;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,KAAK;AAChB,UAAM,SAASC,aAAY,MAAM;AACjC,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,UAAM,UAAUG,eAAc,QAAQ,UAAU,CAAC;AACjD,UAAM,UAAUA,eAAc,QAAQ,mBAAmB,OAAO;AAChE,QAAI,KAAK,IAAI,UAAU,OAAO,IAAI,MAAQ;AACxC,aAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,qBAAqB,2BAA2B,KAAK;AAAA,UACrD,oBAAoB;AAAA,UACpB,QAAQJ,YAAW,QAAQ,KAAK;AAAA,UAChC,QAAQ,UAAU;AAAA,UAClB,cAAc;AAAA,UACd;AAAA,UACA,WAAW,OAAO,WAAW,SAAS,MAAM;AAAA,UAC5C,YAAY;AAAA,YACV,OAAO,mBAAmB,WAAW;AAAA,YACrC;AAAA,UACF;AAAA,UACA,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,mBAAmB,4BAA4B,KAAK;AAAA,QACpD,oBAAoB;AAAA,QACpB,QAAQ,mBAAmB,EAAE,QAAQ,SAAS,QAAQ,CAAC,EAAE;AAAA,UAAI,CAAC,UAC5DA,YAAW,OAAO,KAAK;AAAA,QACzB;AAAA,QACA,cAAc;AAAA,QACd,cAAc;AAAA,QACd,YAAY;AAAA,UACV,OAAO,mBAAmB,WAAW;AAAA,UACrC;AAAA,QACF;AAAA,QACA,WAAW,OAAO,WAAW,SAAS,MAAM;AAAA,QAC5C,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,QAAQ,SAAS,MAAM;AAClC,UAAM,SAASC,aAAY,MAAM;AACjC,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,kBAAkB,wBAAwB,KAAK;AAAA,QAC/C,oBAAoB;AAAA,QACpB,QAAQD,YAAW,QAAQ,KAAK;AAAA,QAChC,QAAQI,eAAc,QAAQ,UAAU,CAAC,IAAI;AAAA,QAC7C,qBAAqB;AAAA,UACnB,OAAO,mBAAmB,YAAY,KAAK;AAAA,QAC7C;AAAA,QACA,mBAAmB,OAAO,OAAO,mBAAmB,UAAU,KAAK,GAAG;AAAA,QACtE,WAAW;AAAA,QACX,cAAc;AAAA,QACd;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAIoC;AAClC,SAAO,MAAM,KAAK,EAAE,QAAQ,GAAG,GAAG,CAAC,GAAG,UAAU;AAC9C,UAAM,UAAW,QAAQ,KAAM,KAAK,KAAK;AACzC,WAAO;AAAA,MACL,GAAG,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI;AAAA,MAClC,GAAG,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI;AAAA,IACpC;AAAA,EACF,CAAC;AACH;;;AG/LO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMwB;AACtB,QAAM,WAAWC,aAAY,MAAM;AACnC,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,QAAM,QAAQ,KAAK,IAAI,OAAO,OAAO,mBAAmB,OAAO,KAAK,EAAE,GAAG,EAAE;AAC3E,QAAM,SAAS,KAAK,IAAI,OAAO,OAAO,mBAAmB,QAAQ,KAAK,EAAE,GAAG,CAAC;AAC5E,QAAM,aAAa,SAAS;AAC5B,QAAM,aAAa,KAAK,IAAI,QAAQ,MAAM,MAAM;AAChD,QAAM,SAAS,OAAO,OAAO,mBAAmB,QAAQ,KAAK,CAAC;AAC9D,QAAM,SACJ,WAAW,IACP;AAAA,IACE,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,EAAE;AAAA,IAC/B,EAAE,GAAG,SAAS,IAAI,YAAY,GAAG,SAAS,IAAI,WAAW;AAAA,IACzD,EAAE,GAAG,SAAS,IAAI,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IACpD,EAAE,GAAG,SAAS,IAAI,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IACpD,EAAE,GAAG,SAAS,IAAI,YAAY,GAAG,SAAS,IAAI,WAAW;AAAA,EAC3D,IACA,WAAW,IACT;AAAA,IACE,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,IAAI,WAAW;AAAA,IAC5C;AAAA,MACE,GAAG,SAAS,IAAI,QAAQ;AAAA,MACxB,GAAG,SAAS,IAAI;AAAA,IAClB;AAAA,IACA,EAAE,GAAG,SAAS,IAAI,OAAO,GAAG,SAAS,EAAE;AAAA,IACvC;AAAA,MACE,GAAG,SAAS,IAAI,QAAQ;AAAA,MACxB,GAAG,SAAS,IAAI;AAAA,IAClB;AAAA,IACA,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,IAAI,WAAW;AAAA,EAC9C,IACA;AAAA,IACE,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,IAAI,WAAW;AAAA,IAC5C,EAAE,GAAG,SAAS,IAAI,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IACpD,EAAE,GAAG,SAAS,IAAI,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IACpD,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,IAAI,WAAW;AAAA,EAC9C;AACR,QAAM,WAAgC;AAAA,IACpC;AAAA,MACE,MAAM;AAAA,MACN,mBAAmB,yBAAyB,KAAK;AAAA,MACjD,oBAAoB;AAAA,MACpB,QAAQ,OAAO,IAAI,CAAC,UAAUC,YAAW,OAAO,QAAQ,KAAK,CAAC;AAAA,MAC9D,cAAc;AAAA,MACd,cAAc;AAAA,MACd,YAAY;AAAA,QACV,OAAO,mBAAmB,WAAW;AAAA,QACrC;AAAA,MACF;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAAA,EACF;AACA,QAAM,OAAO,OAAO,WAAW,MAAM;AACrC,MAAI,QAAQ,QAAQ,gBAAgB,OAAO;AACzC,aAAS;AAAA,MACP,iBAAiB;AAAA,QACf,IAAI,8BAA8B,KAAK;AAAA,QACvC,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,SAAS,IAAI,QAAQ,GAAG,GAAG,SAAS,EAAE;AAAA,QACrD,UAAU,YAAY,QAAQ,OAAO;AAAA,QACrC,OAAO,iBAAiB,OAAO,mBAAmB,WAAW,GAAG,KAAK;AAAA,QACrE,OAAO,QAAQ;AAAA,QACf,UAAU;AAAA,QACV,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMwB;AACtB,QAAM,WAAWD,aAAY,MAAM;AACnC,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,QAAM,kBAAkB,OAAO,UAAU,iBAAiB;AAC1D,QAAM,SACJ,OAAO,WAAW,UAAU,KAC3B,oBAAoB,WAAc,kBAAkB,OAAU;AACjE,MAAI,UAAU,CAAC,QAAQ,cAAe,QAAO,CAAC;AAC9C,QAAM,eACH,mBAAmB,OAAO,OAAO,mBAAmB,aAAa,KAAK,CAAC,KACxE;AACF,QAAM,YAAY;AAAA,IAChB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACb,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACb,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACd,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,EAChB,EAAE,WAAW,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE;AAC/B,QAAM,SAAS,KAAK;AAAA,IAClB,OAAO,OAAO,mBAAmB,WAAW,KAAK,EAAE;AAAA,IACnD;AAAA,EACF;AACA,QAAM,MAAM;AAAA,IACV,GAAG,SAAS,IAAI,UAAU,IAAI;AAAA,IAC9B,GAAG,SAAS,IAAI,UAAU,IAAI;AAAA,EAChC;AACA,QAAM,WAAgC;AAAA,IACpC,WAAW;AAAA,MACT;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb,OAAO,QAAQ;AAAA,MACf,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AACA,MAAI,QAAQ,gBAAgB,MAAO,QAAO;AAC1C,QAAM,OAAO,OAAO,WAAW,MAAM,KAAK;AAC1C,QAAM,aAAa,OAAO,WAAW,YAAY,KAAK;AACtD,QAAM,WACJ,oBAAoB,WAAc,kBAAkB,OAAU;AAChE,QAAM,iBACJ,oBAAoB,WAAc,kBAAkB,QAAU;AAChE,QAAM,WAAW,gBAAgB,KAAK,gBAAgB,IAAI,KAAK;AAC/D,QAAM,uBAAuB,gBAAgB,KAAK,gBAAgB;AAClE,QAAM,aAAa;AACnB,MAAI,YAAY,MAAM;AACpB,aAAS;AAAA,MACP,iBAAiB;AAAA,QACf,IAAI,6BAA6B,KAAK;AAAA,QACtC,MAAM;AAAA,QACN,UAAU;AAAA,UACR,GAAG,SAAS,IAAI,UAAU,IAAI;AAAA,UAC9B,GAAG,SAAS,IAAI,UAAU,IAAI;AAAA,QAChC;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,OAAO,QAAQ;AAAA,QACf;AAAA,QACA,QAAQ,uBAAuB,UAAU;AAAA,MAC3C,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,kBAAkB,YAAY;AAChC,aAAS;AAAA,MACP,iBAAiB;AAAA,QACf,IAAI,mCAAmC,KAAK;AAAA,QAC5C,MAAM;AAAA,QACN,UAAU;AAAA,UACR,GAAG,SAAS,IAAI,UAAU,IAAI;AAAA,UAC9B,GAAG,SAAS,IAAI,UAAU,IAAI;AAAA,QAChC;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,OAAO,QAAQ;AAAA,QACf;AAAA,QACA,QAAQ,uBAAuB,SAAS;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMwB;AACtB,QAAM,WAAWA,aAAY,MAAM;AACnC,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,QAAM,eACF,KAAK,MAAM,OAAO,UAAU,aAAa,KAAK,CAAC,IAAI,IAAK,KAAK;AACjE,QAAM,YAAY;AAAA,IAChB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACb,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACb,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACd,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,EAChB,EAAE,WAAW,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE;AAC/B,QAAM,gBAAgB,EAAE,GAAG,CAAC,UAAU,GAAG,GAAG,UAAU,EAAE;AACxD,QAAM,QAAQ,CAAC,OAAe,SAAS,OAAO;AAAA,IAC5C,GAAG,SAAS,IAAI,UAAU,IAAI,QAAQ,cAAc,IAAI;AAAA,IACxD,GAAG,SAAS,IAAI,UAAU,IAAI,QAAQ,cAAc,IAAI;AAAA,EAC1D;AACA,QAAM,OAAO,CACX,OACA,KACA,WAEA,WAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,OAAO,QAAQ;AAAA,IACf;AAAA,EACF,CAAC;AACH,QAAM,QAAQ,KAAK,MAAM,OAAO,OAAO,mBAAmB,OAAO,KAAK,CAAC,CAAC;AACxE,QAAM,WAAgC,CAAC;AACvC,MAAI;AACJ,MAAI,UAAU,GAAG;AACf,aAAS;AAAA,MACP,KAAK,UAAU,MAAM,CAAC,GAAG,iBAAiB;AAAA,MAC1C,KAAK,MAAM,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,gBAAgB;AAAA,IAClD;AACA,oBAAgB;AAAA,EAClB,WAAW,UAAU,GAAG;AACtB,aAAS,KAAK,KAAK,UAAU,MAAM,CAAC,GAAG,iBAAiB,GAAG;AAAA,MACzD,MAAM;AAAA,MACN,mBAAmB,+BAA+B,KAAK;AAAA,MACvD,oBAAoB;AAAA,MACpB,QAAQ,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE;AAAA,QAAI,CAAC,UAClDC,YAAW,OAAO,QAAQ,KAAK;AAAA,MACjC;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,MACd,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAyB;AACzB,oBAAgB;AAAA,EAClB,WAAW,UAAU,GAAG;AACtB,aAAS;AAAA,MACP,KAAK,UAAU,MAAM,CAAC,GAAG,iBAAiB;AAAA,MAC1C,GAAG;AAAA,QACD,EAAE,OAAO,GAAG,WAAW,EAAE;AAAA,QACzB,EAAE,OAAO,GAAG,WAAW,IAAI;AAAA,QAC3B,EAAE,OAAO,IAAI,WAAW,EAAE;AAAA,MAC5B,EAAE;AAAA,QAAI,CAAC,EAAE,OAAO,UAAU,GAAG,cAC3B;AAAA,UACE,MAAM,OAAO,CAAC,SAAS;AAAA,UACvB,MAAM,OAAO,SAAS;AAAA,UACtB,qBAAqB,SAAS;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AACA,oBAAgB;AAAA,EAClB,WAAW,UAAU,GAAG;AACtB,aAAS;AAAA,MACP,KAAK,UAAU,MAAM,CAAC,GAAG,iBAAiB;AAAA,MAC1C,KAAK,MAAM,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,wBAAwB;AAAA,MACxD,GAAG;AAAA,QACD,EAAE,MAAM,IAAI,IAAI,GAAG;AAAA,QACnB,EAAE,MAAM,GAAG,IAAI,GAAG;AAAA,QAClB,EAAE,MAAM,GAAG,IAAI,EAAE;AAAA,MACnB,EAAE;AAAA,QAAI,CAAC,EAAE,MAAM,GAAG,GAAG,cACnB,KAAK,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,EAAE,GAAG,sBAAsB,SAAS,EAAE;AAAA,MACtE;AAAA,IACF;AACA,oBAAgB;AAAA,EAClB,OAAO;AACL,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,mBAAmB,+BAA+B,KAAK;AAAA,MACvD,oBAAoB;AAAA,MACpB,QAAQ,CAAC,UAAU,MAAM,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC,EAAE;AAAA,QAAI,CAAC,UACnDA,YAAW,OAAO,QAAQ,KAAK;AAAA,MACjC;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAyB;AACzB,oBAAgB;AAAA,EAClB;AACA,QAAM,OAAO,OAAO,WAAW,MAAM,KAAK,OAAO,WAAW,MAAM;AAClE,MACE,QACA,QAAQ,gBAAgB,SACxB,OAAO,WAAW,aAAa,MAAM,OACrC;AACA,UAAM,WAAW,UAAU,MAAM;AACjC,UAAM,SAAkC,WACpC,UAAU,IAAI,IACZ,kBACA,eACF,UAAU,IAAI,IACZ,gBACA;AACN,aAAS;AAAA,MACP,iBAAiB;AAAA,QACf,IAAI,oCAAoC,KAAK;AAAA,QAC7C;AAAA,QACA,UAAU,MAAM,aAAa;AAAA,QAC7B,UAAU,YAAY,QAAQ,OAAO;AAAA,QACrC;AAAA,QACA,OAAO,QAAQ;AAAA,QACf,UAAU;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;;;ACpUO,SAAS,uBACd,QACA,OACA,SACA,SACqB;AACrB,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAQ,iBAAiB,OAAO,mBAAmB,OAAO,GAAG,SAAS;AAC5E,QAAM,cAAc,KAAK;AAAA,IACvB,OAAO,OAAO,mBAAmB,WAAW,KAAK,CAAC,IAAI;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,YAAY,sBAAsB;AAAA,IACtC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,UAAW,QAAO;AAEtB,MAAI,SAAS,KAAK;AAChB,WAAO,UAAU,EAAE,QAAQ,OAAO,SAAS,SAAS,MAAM,CAAC;AAAA,EAC7D;AAEA,MAAI,SAAS,MAAM;AACjB,UAAM,WAAWC,aAAY,MAAM;AACnC,QAAI,CAAC,SAAU,QAAO,CAAC;AACvB,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,qBAAqB,6BAA6B,KAAK;AAAA,QACvD,oBAAoB;AAAA,QACpB,QAAQC,YAAW,UAAU,KAAK;AAAA,QAClC,QAAQ,KAAK;AAAA,UACX,OAAO,OAAO,mBAAmB,MAAM,KAAK,CAAC,IAAI;AAAA,UACjD;AAAA,QACF;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,MAAM;AACjB,UAAM,WAAWD,aAAY,MAAM;AACnC,QAAI,CAAC,SAAU,QAAO,CAAC;AAGvB,UAAM,SAAS;AACf,UAAM,mBAAmB,KAAK,IAAI,OAAO,IAAI;AAC7C,WAAO;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,OAAO,EAAE,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,IAAI,OAAO;AAAA,QACxD,KAAK,EAAE,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,IAAI,OAAO;AAAA,QACtD;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAAA,MACD,WAAW;AAAA,QACT;AAAA,QACA,OAAO,EAAE,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,IAAI,OAAO;AAAA,QACxD,KAAK,EAAE,GAAG,SAAS,IAAI,QAAQ,GAAG,SAAS,IAAI,OAAO;AAAA,QACtD;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,SAAS,MAAM;AACjB,WAAO,gBAAgB,EAAE,QAAQ,OAAO,SAAS,SAAS,MAAM,CAAC;AAAA,EACnE;AAEA,MAAI,SAAS,MAAM;AACjB,WAAO,uBAAuB,EAAE,QAAQ,OAAO,SAAS,SAAS,MAAM,CAAC;AAAA,EAC1E;AAEA,QAAM,cAAc,iBAAiB;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,YAAa,QAAO;AAExB,SAAO,CAAC;AACV;;;AClFO,SAAS,iCACd,UACA,UAAsC,CAAC,GAClB;AACrB,QAAM,UAAU,SAAS;AACzB,QAAM,cAAc,QAAQ,KAAK,CAAC,WAAW,OAAO,eAAe,IAAI;AACvE,QAAM,kBAAkB,yBAAyB,WAAW;AAC5D,QAAM,QAAQ,QAAQ,sBAAsB,gBAAgB,eAAe;AAC3E,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACzC,UAAM,IAAI,WAAW,qDAAqD;AAAA,EAC5E;AAEA,QAAM,UAA4B,EAAE,UAAU,SAAS,OAAO,YAAY;AAC1E,QAAM,WAAgC;AAAA,IACpC;AAAA,MACE,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,MAAM,QAAQ,aAAa;AAAA,MAC3B,eAAe;AAAA,MACf,aAAa;AAAA,IACf;AAAA,EACF;AAEA,MAAI,QAAQ,uBAAuB,MAAM;AACvC,aAAS,KAAK,kBAAkB,aAAa,KAAK,CAAC;AAAA,EACrD;AAEA,QAAM,qBAAqB,yBAAyB,UAAU;AAAA,IAC5D,eAAe,QAAQ;AAAA,IACvB,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA,kBAAkB;AAAA,EACpB,CAAC;AACD,WAAS,KAAK,GAAG,mBAAmB,QAAQ;AAE5C,aAAW,CAAC,OAAO,MAAM,KAAK,QAAQ,QAAQ,GAAG;AAC/C,QAAI,mBAAmB,eAAe,IAAI,MAAM,EAAG;AACnD,QAAI,CAAC,4BAA4B,QAAQ,OAAO,EAAG;AACnD,UAAM,YAAY,uBAAsB,QAAQ,OAAO,SAAS,OAAO;AACvE,aAAS,KAAK,GAAG,SAAS;AAAA,EAC5B;AAEA,QAAM,wBAAwB,SAC3B;AAAA,IACC,CACE,YAIG,QAAQ,SAAS;AAAA,EACxB,EACC,IAAI,CAAC,YAAY,QAAQ,sBAAsB;AAClD,MAAI,sBAAsB,SAAS,GAAG;AACpC,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,oBAAoB;AAAA,MACpB,QAAQ;AAAA,QACN,GAAI,gBAAgB,QAAQ,QAAS;AAAA,QACrC,GAAI,gBAAgB,SAAS,QAAS;AAAA,MACxC;AAAA,MACA,OAAO,gBAAgB,QAAQ;AAAA,MAC/B,QAAQ,gBAAgB,SAAS;AAAA,MACjC,yBAAyB;AAAA,MACzB,MAAM,QAAQ,aAAa;AAAA,IAC7B,CAA0B;AAAA,EAC5B;AAEA,MAAI,QAAQ,2BAA2B,MAAO,QAAO;AAErD,QAAM,SAAS;AAAA,IACb,GAAI,CAAC,gBAAgB,QAAQ,QAAS;AAAA,IACtC,GAAI,CAAC,gBAAgB,SAAS,QAAS;AAAA,EACzC;AACA,SAAO,SAAS,IAAI,CAAC,YAAY,0BAA0B,SAAS,MAAM,CAAC;AAC7E;;;ACtGA;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAqBA,SAAS,2BACd,QACA,UAA6C,CAAC,GACzB;AACrB,QAAM,aAAa,QAAQ,cAAc;AAEzC,MAAI,eAAe,OAAO;AACxB,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO;AAAA,QACL,kBAAkB,MAAM;AAAA,QACxB,QAAQ;AAAA,MACV;AAAA,IACF;AACA,UAAM,EAAE,UAAAE,UAAS,IAAI,gBAAgB,aAAa,MAAM,CAAC;AACzD,QACE,EAAEA,qBAAoB,iBACtB,EAAEA,qBAAoB,qBACtB;AACA,YAAM,IAAI;AAAA,QACR,wCAAwCA,UAAS,IAAI;AAAA,MACvD;AAAA,IACF;AACA,WAAO,iCAAiCA,WAAU,QAAQ,GAAG;AAAA,EAC/D;AACA,MAAI,eAAe,aAAa;AAC9B,WAAO;AAAA,MACL,kBAAkB,yBAAyB,MAAM,CAAC;AAAA,MAClD,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,QAAQ,aAAa,MAAM;AACjC,QAAM,EAAE,SAAS,IAAI,gBAAgB,KAAK;AAC1C,SAAO,mCAAmC,UAAU,OAAO;AAC7D;AAEO,SAAS,mCACd,UACA,UAA6C,CAAC,GACzB;AACrB,MAAI,oBAAoB,cAAc;AACpC,WAAO,iCAAiC,UAAU,QAAQ,SAAS;AAAA,EACrE;AACA,MACE,oBAAoB,gBACpB,oBAAoB,oBACpB;AACA,WAAO,iCAAiC,UAAU,QAAQ,GAAG;AAAA,EAC/D;AACA,QAAM,OACJ,OAAO,aAAa,YAAY,aAAa,QAAQ,UAAU,WAC3D,OAAO,SAAS,IAAI,IACpB,OAAO;AACb,QAAM,IAAI,UAAU,qCAAqC,IAAI,EAAE;AACjE;AAEA,SAAS,aAAa,QAAuD;AAC3E,MAAI,OAAO,WAAW,SAAU,QAAO,IAAI,YAAY,EAAE,OAAO,MAAM;AACtE,MAAI,kBAAkB,WAAY,QAAO;AACzC,SAAO,IAAI,WAAW,MAAM;AAC9B;AAEA,SAAS,yBACP,QACqB;AACrB,SAAO,kBAAkB,cAAc,IAAI,WAAW,MAAM,IAAI;AAClE;","names":["symbolPort","getLocation","getCoordinate","getCorner","getRectangle","scalePoint","getSchematicRecordPoints","getLocation","getRectangle","getCoordinate","scalePoint","getSchematicRecordPoints","scalePoint","getLocation","getCorner","getRectangle","getCoordinate","getLocation","scalePoint","getLocation","scalePoint","document"]}
|