simple-circuit-engine 0.0.11 → 0.0.12

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.
Files changed (141) hide show
  1. package/AGENTS.md +10 -7
  2. package/CLAUDE.md +4 -6
  3. package/README.md +5 -2
  4. package/dist/core/index.d.ts +0 -1
  5. package/dist/core/index.js +74 -2114
  6. package/dist/core/setup.d.ts +17 -0
  7. package/dist/core/simulation/CircuitRunner.d.ts +176 -0
  8. package/dist/core/simulation/DirtyTracker.d.ts +87 -0
  9. package/dist/core/simulation/EventQueue.d.ts +68 -0
  10. package/dist/core/simulation/StateManager.d.ts +100 -0
  11. package/dist/core/simulation/behaviors/BehaviorRegistry.d.ts +70 -0
  12. package/dist/core/simulation/behaviors/ComponentBehavior.d.ts +53 -0
  13. package/dist/core/simulation/behaviors/basic/BatteryBehavior.d.ts +14 -0
  14. package/dist/core/simulation/behaviors/basic/ClockBehavior.d.ts +24 -0
  15. package/dist/core/simulation/behaviors/basic/DoubleThrowSwitchBehavior.d.ts +33 -0
  16. package/dist/core/simulation/behaviors/basic/LightbulbBehavior.d.ts +23 -0
  17. package/dist/core/simulation/behaviors/basic/RectangleLEDBehavior.d.ts +24 -0
  18. package/dist/core/simulation/behaviors/basic/RelayBehavior.d.ts +33 -0
  19. package/dist/core/simulation/behaviors/basic/SmallLEDBehavior.d.ts +24 -0
  20. package/dist/core/simulation/behaviors/basic/SwitchBehavior.d.ts +33 -0
  21. package/dist/core/simulation/behaviors/basic/index.d.ts +20 -0
  22. package/dist/core/simulation/behaviors/gates/InverterBehavior.d.ts +29 -0
  23. package/dist/core/simulation/behaviors/gates/Nand4GateBehavior.d.ts +18 -0
  24. package/dist/core/simulation/behaviors/gates/Nand8GateBehavior.d.ts +18 -0
  25. package/dist/core/simulation/behaviors/gates/NandGateBehavior.d.ts +28 -0
  26. package/dist/core/simulation/behaviors/gates/Nor4GateBehavior.d.ts +18 -0
  27. package/dist/core/simulation/behaviors/gates/Nor8GateBehavior.d.ts +18 -0
  28. package/dist/core/simulation/behaviors/gates/NorGateBehavior.d.ts +22 -0
  29. package/dist/core/simulation/behaviors/gates/Xor4GateBehavior.d.ts +18 -0
  30. package/dist/core/simulation/behaviors/gates/Xor8GateBehavior.d.ts +18 -0
  31. package/dist/core/simulation/behaviors/gates/XorGateBehavior.d.ts +22 -0
  32. package/dist/core/simulation/behaviors/gates/index.d.ts +34 -0
  33. package/dist/core/simulation/behaviors/index.d.ts +24 -0
  34. package/dist/core/simulation/behaviors/types.d.ts +101 -0
  35. package/dist/core/simulation/index.d.ts +18 -0
  36. package/dist/core/simulation/states/ComponentState.d.ts +57 -0
  37. package/dist/core/simulation/states/SimulationState.d.ts +46 -0
  38. package/dist/core/simulation/states/basic/BatteryState.d.ts +16 -0
  39. package/dist/core/simulation/states/basic/ClockState.d.ts +16 -0
  40. package/dist/core/simulation/states/basic/DoubleThrowSwitchState.d.ts +21 -0
  41. package/dist/core/simulation/states/basic/LightbulbState.d.ts +21 -0
  42. package/dist/core/simulation/states/basic/RectangleLEDState.d.ts +9 -0
  43. package/dist/core/simulation/states/basic/RelayState.d.ts +25 -0
  44. package/dist/core/simulation/states/basic/SmallLEDState.d.ts +21 -0
  45. package/dist/core/simulation/states/basic/SwitchState.d.ts +25 -0
  46. package/dist/core/simulation/states/gates/InverterState.d.ts +17 -0
  47. package/dist/core/simulation/states/gates/Nand4GateState.d.ts +10 -0
  48. package/dist/core/simulation/states/gates/Nand8GateState.d.ts +10 -0
  49. package/dist/core/simulation/states/gates/NandGateState.d.ts +16 -0
  50. package/dist/core/simulation/states/gates/Nor4GateState.d.ts +10 -0
  51. package/dist/core/simulation/states/gates/Nor8GateState.d.ts +10 -0
  52. package/dist/core/simulation/states/gates/NorGateState.d.ts +10 -0
  53. package/dist/core/simulation/states/gates/Xor4GateState.d.ts +10 -0
  54. package/dist/core/simulation/states/gates/Xor8GateState.d.ts +10 -0
  55. package/dist/core/simulation/states/gates/XorGateState.d.ts +10 -0
  56. package/dist/core/simulation/states/gates/index.d.ts +25 -0
  57. package/dist/core/simulation/states/index.d.ts +26 -0
  58. package/dist/core/simulation/states/types.d.ts +32 -0
  59. package/dist/core/simulation/types.d.ts +155 -0
  60. package/dist/core/topology/Circuit.d.ts +420 -0
  61. package/dist/core/topology/CircuitMetadata.d.ts +24 -0
  62. package/dist/core/topology/CircuitOptions.d.ts +14 -0
  63. package/dist/core/topology/Component.d.ts +152 -0
  64. package/dist/core/topology/ENode.d.ts +200 -0
  65. package/dist/core/topology/Wire.d.ts +130 -0
  66. package/dist/core/topology/delays.d.ts +52 -0
  67. package/dist/core/topology/index.d.ts +14 -0
  68. package/dist/core/topology/types.d.ts +175 -0
  69. package/dist/core/utils/CameraOptions.d.ts +83 -0
  70. package/dist/core/utils/MemoizeDecorator.d.ts +9 -0
  71. package/dist/core/utils/Position.d.ts +166 -0
  72. package/dist/core/utils/Position3D.d.ts +77 -0
  73. package/dist/core/utils/Rotation.d.ts +82 -0
  74. package/dist/core/utils/index.d.ts +24 -0
  75. package/dist/core/utils/types.d.ts +35 -0
  76. package/dist/core-Bjta9Y7_.js +2707 -0
  77. package/dist/core-Bjta9Y7_.js.map +1 -0
  78. package/dist/index.d.ts +13 -6306
  79. package/dist/index.js +117 -110
  80. package/dist/scene/CircuitEngine.d.ts +270 -0
  81. package/dist/scene/index.d.ts +0 -1
  82. package/dist/scene/index.js +43 -39
  83. package/dist/scene/setup.d.ts +18 -0
  84. package/dist/scene/shared/AbstractCircuitController.d.ts +211 -0
  85. package/dist/scene/shared/BranchingPointVisualFactory.d.ts +70 -0
  86. package/dist/scene/shared/EventEmitter.d.ts +92 -0
  87. package/dist/scene/shared/HoverManager.d.ts +151 -0
  88. package/dist/scene/shared/SelectionManager.d.ts +159 -0
  89. package/dist/scene/shared/WireVisualManager.d.ts +242 -0
  90. package/dist/scene/shared/components/ComponentVisualFactory.d.ts +438 -0
  91. package/dist/scene/shared/components/DefaultVisualFactory.d.ts +51 -0
  92. package/dist/scene/shared/components/FactoryRegistry.d.ts +84 -0
  93. package/dist/scene/shared/components/GroupedFactoryRegistry.d.ts +153 -0
  94. package/dist/scene/shared/components/basic/BatteryVisualFactory.d.ts +13 -0
  95. package/dist/scene/shared/components/basic/ClockVisualFactory.d.ts +79 -0
  96. package/dist/scene/shared/components/basic/DoubleThrowSwitchVisualFactory.d.ts +87 -0
  97. package/dist/scene/shared/components/basic/LabelVisualFactory.d.ts +148 -0
  98. package/dist/scene/shared/components/basic/LightbulbVisualFactory.d.ts +72 -0
  99. package/dist/scene/shared/components/basic/RectangleLEDVisualFactory.d.ts +86 -0
  100. package/dist/scene/shared/components/basic/RelayVisualFactory.d.ts +92 -0
  101. package/dist/scene/shared/components/basic/SmallLEDVisualFactory.d.ts +86 -0
  102. package/dist/scene/shared/components/basic/SwitchVisualFactory.d.ts +85 -0
  103. package/dist/scene/shared/components/gates/InverterVisualFactory.d.ts +104 -0
  104. package/dist/scene/shared/components/gates/Nand4GateVisualFactory.d.ts +27 -0
  105. package/dist/scene/shared/components/gates/Nand8GateVisualFactory.d.ts +27 -0
  106. package/dist/scene/shared/components/gates/NandGateVisualFactory.d.ts +101 -0
  107. package/dist/scene/shared/components/gates/Nor4GateVisualFactory.d.ts +27 -0
  108. package/dist/scene/shared/components/gates/Nor8GateVisualFactory.d.ts +27 -0
  109. package/dist/scene/shared/components/gates/NorGateVisualFactory.d.ts +101 -0
  110. package/dist/scene/shared/components/gates/Xor4GateVisualFactory.d.ts +29 -0
  111. package/dist/scene/shared/components/gates/Xor8GateVisualFactory.d.ts +29 -0
  112. package/dist/scene/shared/components/gates/XorGateVisualFactory.d.ts +103 -0
  113. package/dist/scene/shared/components/index.d.ts +29 -0
  114. package/dist/scene/shared/components/types.d.ts +43 -0
  115. package/dist/scene/shared/types.d.ts +476 -0
  116. package/dist/scene/shared/utils/CameraUtils.d.ts +23 -0
  117. package/dist/scene/shared/utils/ColorUtils.d.ts +26 -0
  118. package/dist/scene/shared/utils/ControlsUtils.d.ts +8 -0
  119. package/dist/scene/shared/utils/GeometryUtils.d.ts +261 -0
  120. package/dist/scene/shared/utils/LayerConstants.d.ts +40 -0
  121. package/dist/scene/shared/utils/LightingUtils.d.ts +31 -0
  122. package/dist/scene/shared/utils/MaterialUtils.d.ts +73 -0
  123. package/dist/scene/shared/utils/Options.d.ts +16 -0
  124. package/dist/scene/simulation/CircuitRunnerController.d.ts +227 -0
  125. package/dist/scene/static/CircuitController.d.ts +227 -0
  126. package/dist/scene/static/CircuitWriter.d.ts +146 -0
  127. package/dist/scene/static/PinTooltipWidget.d.ts +26 -0
  128. package/dist/scene/static/tools/BuildTool.d.ts +286 -0
  129. package/dist/scene/static/tools/ComponentPickerWidget.d.ts +82 -0
  130. package/dist/scene/static/tools/ConfigPanelWidget.d.ts +93 -0
  131. package/dist/scene/static/tools/MultiSelectTool.d.ts +265 -0
  132. package/dist/scene-CVsDdySt.js +7357 -0
  133. package/dist/scene-CVsDdySt.js.map +1 -0
  134. package/package.json +24 -25
  135. package/dist/CircuitRunner-BQQlhwjD.js +0 -1981
  136. package/dist/CircuitRunner-BQQlhwjD.js.map +0 -1
  137. package/dist/core/index.js.map +0 -1
  138. package/dist/index.js.map +0 -1
  139. package/dist/scene/index.js.map +0 -1
  140. package/dist/setup-CIq_kgaw.js +0 -10230
  141. package/dist/setup-CIq_kgaw.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-Bjta9Y7_.js","names":[],"sources":["../src/core/utils/MemoizeDecorator.ts","../src/core/utils/Position3D.ts","../src/core/utils/CameraOptions.ts","../src/core/utils/Position.ts","../src/core/utils/Rotation.ts","../src/core/utils/index.ts","../src/core/topology/types.ts","../src/core/topology/ENode.ts","../src/core/topology/Wire.ts","../src/core/topology/Component.ts","../src/core/topology/CircuitOptions.ts","../src/core/topology/CircuitMetadata.ts","../src/core/topology/delays.ts","../src/core/topology/Circuit.ts","../src/core/simulation/types.ts","../src/core/simulation/states/types.ts","../src/core/simulation/states/SimulationState.ts","../src/core/simulation/states/ComponentState.ts","../src/core/simulation/states/basic/BatteryState.ts","../src/core/simulation/states/basic/LightbulbState.ts","../src/core/simulation/states/basic/SmallLEDState.ts","../src/core/simulation/states/basic/RectangleLEDState.ts","../src/core/simulation/states/basic/RelayState.ts","../src/core/simulation/states/basic/SwitchState.ts","../src/core/simulation/states/basic/DoubleThrowSwitchState.ts","../src/core/simulation/states/basic/ClockState.ts","../src/core/simulation/states/gates/index.ts","../src/core/simulation/states/gates/InverterState.ts","../src/core/simulation/states/gates/NandGateState.ts","../src/core/simulation/states/gates/Nand4GateState.ts","../src/core/simulation/states/gates/Nand8GateState.ts","../src/core/simulation/states/gates/NorGateState.ts","../src/core/simulation/states/gates/Nor4GateState.ts","../src/core/simulation/states/gates/Nor8GateState.ts","../src/core/simulation/states/gates/XorGateState.ts","../src/core/simulation/states/gates/Xor4GateState.ts","../src/core/simulation/states/gates/Xor8GateState.ts","../src/core/simulation/behaviors/BehaviorRegistry.ts","../src/core/simulation/behaviors/ComponentBehavior.ts","../src/core/simulation/behaviors/basic/BatteryBehavior.ts","../src/core/simulation/behaviors/basic/index.ts","../src/core/simulation/behaviors/basic/LightbulbBehavior.ts","../src/core/simulation/behaviors/basic/RectangleLEDBehavior.ts","../src/core/simulation/behaviors/basic/RelayBehavior.ts","../src/core/simulation/behaviors/basic/SmallLEDBehavior.ts","../src/core/simulation/behaviors/basic/SwitchBehavior.ts","../src/core/simulation/behaviors/basic/DoubleThrowSwitchBehavior.ts","../src/core/simulation/behaviors/basic/ClockBehavior.ts","../src/core/simulation/behaviors/gates/index.ts","../src/core/simulation/behaviors/gates/InverterBehavior.ts","../src/core/simulation/behaviors/gates/NandGateBehavior.ts","../src/core/simulation/behaviors/gates/Nand4GateBehavior.ts","../src/core/simulation/behaviors/gates/Nand8GateBehavior.ts","../src/core/simulation/behaviors/gates/NorGateBehavior.ts","../src/core/simulation/behaviors/gates/Nor4GateBehavior.ts","../src/core/simulation/behaviors/gates/Nor8GateBehavior.ts","../src/core/simulation/behaviors/gates/XorGateBehavior.ts","../src/core/simulation/behaviors/gates/Xor4GateBehavior.ts","../src/core/simulation/behaviors/gates/Xor8GateBehavior.ts","../src/core/simulation/EventQueue.ts","../src/core/simulation/DirtyTracker.ts","../src/core/simulation/StateManager.ts","../src/core/simulation/CircuitRunner.ts","../src/core/setup.ts"],"sourcesContent":["interface MemoizeArgs {\n expiring?: number;\n hashFunction?: boolean | ((...args: any[]) => any);\n tags?: string[];\n}\n\nexport function Memoize(args?: MemoizeArgs | MemoizeArgs['hashFunction']) {\n let hashFunction: MemoizeArgs['hashFunction'];\n let duration: MemoizeArgs['expiring'];\n let tags: MemoizeArgs['tags'];\n\n if (typeof args === 'object') {\n hashFunction = args.hashFunction;\n duration = args.expiring;\n tags = args.tags;\n } else {\n hashFunction = args;\n }\n\n return (_target: Object, _propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {\n if (descriptor.value != null) {\n descriptor.value = getNewFunction(descriptor.value, hashFunction, duration, tags);\n } else if (descriptor.get != null) {\n descriptor.get = getNewFunction(descriptor.get, hashFunction, duration, tags);\n } else {\n throw 'Only put a Memoize() decorator on a method or get accessor.';\n }\n };\n}\n\nexport function MemoizeExpiring(expiring: number, hashFunction?: MemoizeArgs['hashFunction']) {\n // @ts-ignore\n return Memoize({\n expiring,\n hashFunction,\n });\n}\n\nconst clearCacheTagsMap: Map<string, Map<any, any>[]> = new Map();\n\nexport function clear(tags: string[]): number {\n const cleared: Set<Map<any, any>> = new Set();\n for (const tag of tags) {\n const maps = clearCacheTagsMap.get(tag);\n if (maps) {\n for (const mp of maps) {\n if (!cleared.has(mp)) {\n mp.clear();\n cleared.add(mp);\n }\n }\n }\n }\n return cleared.size;\n}\n\nfunction getNewFunction(\n originalMethod: () => void,\n hashFunction?: MemoizeArgs['hashFunction'],\n duration: number = 0,\n tags?: MemoizeArgs['tags']\n) {\n const propMapName = Symbol(`__memoized_map__`);\n\n // The function returned here gets called instead of originalMethod.\n return function (...args: any[]) {\n let returnedValue: any;\n\n // Get or create map\n // @ts-ignore\n if (!this.hasOwnProperty(propMapName)) {\n // @ts-ignore\n Object.defineProperty(this, propMapName, {\n configurable: false,\n enumerable: false,\n writable: false,\n value: new Map<any, any>(),\n });\n }\n // @ts-ignore\n let myMap: Map<any, any> = this[propMapName];\n\n if (Array.isArray(tags)) {\n for (const tag of tags) {\n if (clearCacheTagsMap.has(tag)) {\n // @ts-ignore\n clearCacheTagsMap.get(tag).push(myMap);\n } else {\n clearCacheTagsMap.set(tag, [myMap]);\n }\n }\n }\n\n if (hashFunction || args.length > 0 || duration > 0) {\n let hashKey: any;\n\n // If true is passed as first parameter, will automatically use every argument, passed to string\n if (hashFunction === true) {\n hashKey = args.map((a) => a.toString()).join('!');\n } else if (hashFunction) {\n // @ts-ignore\n hashKey = hashFunction.apply(this, args);\n } else {\n hashKey = args[0];\n }\n\n const timestampKey = `${hashKey}__timestamp`;\n let isExpired: boolean = false;\n if (duration > 0) {\n if (!myMap.has(timestampKey)) {\n // \"Expired\" since it was never called before\n isExpired = true;\n } else {\n let timestamp = myMap.get(timestampKey);\n isExpired = Date.now() - timestamp > duration;\n }\n }\n\n if (myMap.has(hashKey) && !isExpired) {\n returnedValue = myMap.get(hashKey);\n } else {\n // @ts-ignore\n returnedValue = originalMethod.apply(this, args);\n myMap.set(hashKey, returnedValue);\n if (duration > 0) {\n myMap.set(timestampKey, Date.now());\n }\n }\n } else {\n // @ts-ignore\n const hashKey = this;\n if (myMap.has(hashKey)) {\n returnedValue = myMap.get(hashKey);\n } else {\n // @ts-ignore\n returnedValue = originalMethod.apply(this, args);\n myMap.set(hashKey, returnedValue);\n }\n }\n\n return returnedValue;\n };\n}\n","/**\n * 3D Position Type\n * Represents a 3D position. Used for Camera placement\n * @module core/utils\n */\nimport type { IPosition3D } from './types';\n\n/**\n * 3D position.\n * Positions are immutable once created.\n *\n * @example\n * ```typescript\n * const pos3 = new Position3D(10, 20, 40);\n * console.log(pos.x); // 10\n * console.log(pos.y); // 20\n * console.log(pos.y); // 40\n *\n * ```\n */\nexport class Position3D {\n /**\n * Create a new 3D position.\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param z - Z coordinate\n */\n constructor(\n public readonly x: number,\n public readonly y: number,\n public readonly z: number\n ) {}\n\n /**\n * Check if this position equals another position.\n *\n * @param other - Position to compare with\n * @returns true if x,y and z coordinates are equal\n *\n * @example\n * ```typescript\n * const p1 = new Position(10, 20, 40);\n * const p2 = new Position(10, 20, 40);\n * const p3 = new Position(15, 20, 40);\n *\n * console.log(p1.equals(p2)); // true\n * console.log(p1.equals(p3)); // false\n * ```\n */\n equals(other: Position3D): boolean {\n return this.x === other.x && this.y === other.y && this.z === other.z;\n }\n\n /**\n * Serialize position to JSON.\n *\n * @returns Plain object with x, y and z properties\n *\n * @example\n * ```typescript\n * const pos = new Position(10, 20, 40);\n * const json = pos.toJSON();\n * console.log(json); // { x: 10, y: 20, z: 40 }\n * ```\n */\n toJSON(): IPosition3D {\n return { x: this.x, y: this.y, z: this.z };\n }\n\n /**\n * Deserialize position from JSON.\n *\n * @param json - Plain object with x, y and z properties\n * @returns Position instance\n *\n * @example\n * ```typescript\n * const json = { x: 10, y: 20, z: 40 };\n * const pos = Position.fromJSON(json);\n * console.log(pos.x); // 10\n * ```\n */\n static fromJSON(json: IPosition3D): Position3D {\n return new Position3D(json.x, json.y, json.z);\n }\n\n /**\n * String representation for debugging.\n *\n * @returns String in format \"Position(x, y, z)\"\n */\n toString(): string {\n return `Position(${this.x}, ${this.y}, ${this.z})`;\n }\n}\n","/**\n * Camera Options Type\n *\n * Represents camera configuration options for the 3D scene.\n *\n * @module core/utils\n */\nimport type { ICameraOptions } from './types';\nimport { Position3D } from './Position3D';\n\n/**\n * Camera configuration options.\n *\n * @example\n * ```typescript\n * // Create with defaults\n * const defaultOpts = new CameraOptions();\n *\n * // Create with custom values\n * const customOpts = new CameraOptions(\n * new Position3D(0, 20, 10),\n * new Position3D(5, 0, 0),\n * 60,\n * 0.5,\n * 2000\n * );\n * ```\n */\nexport class CameraOptions {\n /**\n * Create new camera options.\n *\n * @param position - Camera position (default: 0, 15, 15)\n * @param lookAtPosition - Camera look-at target position (default: 0, 0, 0)\n * @param fov - Field of view in degrees (default: 75)\n * @param near - Near clipping plane distance (default: 0.1)\n * @param far - Far clipping plane distance (default: 1000)\n */\n constructor(\n public readonly position: Position3D = new Position3D(0, 15, 15),\n public readonly lookAtPosition: Position3D = new Position3D(0, 0, 0),\n public readonly fov: number = 75,\n public readonly near: number = 0.1,\n public readonly far: number = 1000\n ) {}\n\n /**\n * Serialize camera options to JSON.\n *\n * @returns Plain object with camera configuration\n *\n * @example\n * ```typescript\n * const opts = new CameraOptions();\n * const json = opts.toJSON();\n * console.log(json);\n * // {\n * // position: { x: 0, y: 15, z: 0 },\n * // lookAtPosition: { x: 0, y: 0, z: 0 },\n * // fov: 75,\n * // near: 0.1,\n * // far: 1000\n * // }\n * ```\n */\n toJSON(): ICameraOptions {\n return {\n position: this.position.toJSON(),\n lookAtPosition: this.lookAtPosition.toJSON(),\n fov: this.fov,\n near: this.near,\n far: this.far,\n };\n }\n\n /**\n * Deserialize camera options from JSON.\n *\n * @param json - Plain object with camera configuration\n * @returns CameraOptions instance\n *\n * @example\n * ```typescript\n * const json = {\n * position: { x: 0, y: 20, z: 10 },\n * lookAtPosition: { x: 5, y: 0, z: 0 },\n * fov: 60,\n * near: 0.5,\n * far: 2000\n * };\n * const opts = CameraOptions.fromJSON(json);\n * console.log(opts.position.y); // 20\n * ```\n */\n static fromJSON(json: ICameraOptions): CameraOptions {\n return new CameraOptions(\n Position3D.fromJSON(json.position),\n Position3D.fromJSON(json.lookAtPosition),\n json.fov,\n json.near,\n json.far\n );\n }\n\n /**\n * String representation for debugging.\n *\n * @returns String with camera configuration details\n */\n toString(): string {\n return `CameraOptions(position: ${this.position.toString()}, lookAt: ${this.lookAtPosition.toString()}, fov: ${this.fov}, near: ${this.near}, far: ${this.far})`;\n }\n}\n","/**\n * Position Type for 2D Discrete Grid\n *\n * Represents a position on a 2D discrete (integer) grid. Used for:\n * - Component placement\n * - Branching point ENode positions\n * - Wire intermediate waypoints\n *\n * @module core/utils\n */\n\n/**\n * Position on a 2D discrete grid with integer coordinates.\n *\n * Enforces integer constraint at construction time to ensure all positions\n * align with the discrete grid model. Positions are immutable once created.\n *\n * @example\n * ```typescript\n * const pos = new Position(10, 20);\n * console.log(pos.x); // 10\n * console.log(pos.y); // 20\n *\n * // Invalid: non-integer coordinates\n * const invalid = new Position(10.5, 20); // TypeError\n * ```\n */\nexport class Position {\n /**\n * Create a new position on the discrete grid.\n *\n * @param x - X coordinate (must be integer)\n * @param y - Y coordinate (must be integer)\n * @throws {TypeError} If x or y are not integers\n */\n constructor(\n public readonly x: number,\n public readonly y: number\n ) {\n if (!Number.isInteger(x) || !Number.isInteger(y)) {\n throw new TypeError(`Position coordinates must be integers (got x=${x}, y=${y})`);\n }\n }\n\n /**\n * Check if this position equals another position.\n *\n * @param other - Position to compare with\n * @returns true if both x and y coordinates are equal\n *\n * @example\n * ```typescript\n * const p1 = new Position(10, 20);\n * const p2 = new Position(10, 20);\n * const p3 = new Position(15, 20);\n *\n * console.log(p1.equals(p2)); // true\n * console.log(p1.equals(p3)); // false\n * ```\n */\n equals(other: Position): boolean {\n return this.x === other.x && this.y === other.y;\n }\n\n /**\n * Serialize position to JSON.\n *\n * @returns Plain object with x and y properties\n *\n * @example\n * ```typescript\n * const pos = new Position(10, 20);\n * const json = pos.toJSON();\n * console.log(json); // { x: 10, y: 20 }\n * ```\n */\n toJSON(): { x: number; y: number } {\n return { x: this.x, y: this.y };\n }\n\n /**\n * Deserialize position from JSON.\n *\n * @param json - Plain object with x and y properties\n * @returns Position instance\n * @throws {TypeError} If coordinates are not integers\n *\n * @example\n * ```typescript\n * const json = { x: 10, y: 20 };\n * const pos = Position.fromJSON(json);\n * console.log(pos.x); // 10\n * ```\n */\n static fromJSON(json: { x: number; y: number }): Position {\n return new Position(json.x, json.y);\n }\n\n /**\n * String representation for debugging.\n *\n * @returns String in format \"Position(x, y)\"\n */\n toString(): string {\n return `Position(${this.x}, ${this.y})`;\n }\n}\n\n/**\n * Given a path defined by an array of 2D positions, find the best index to insert\n * a target position so that the path shape is preserved as much as possible.\n *\n * This is used when splitting a wire at a position: we need to determine which\n * segment of the path the target falls on, and return the insertion index.\n *\n * Algorithm:\n * 1. For each consecutive pair of positions (segment), calculate the perpendicular\n * distance from target to that segment\n * 2. Return the index after the start of the closest segment\n *\n * @param positions - Array of positions defining the path (typically includes\n * start endpoint, intermediate positions, and end endpoint)\n * @param target - Position to insert\n * @param minDistance - Optional maximum distance to consider (default: Infinity)\n * @returns Index where target should be inserted (0 to positions.length)\n *\n * @example\n * ```typescript\n * // Path: (0,0) -> (10,0) -> (10,10) -> (20,10)\n * const path = [\n * new Position(0, 0),\n * new Position(10, 0),\n * new Position(10, 10),\n * new Position(20, 10)\n * ];\n * // Target at (5, 0) - on first segment\n * findPositionBestIndex(path, new Position(5, 0)); // Returns 1\n * // Target at (10, 5) - on second segment\n * findPositionBestIndex(path, new Position(10, 5)); // Returns 2\n * ```\n */\nexport function findPositionBestIndex(\n positions: Position[],\n target: Position,\n minDistance = Infinity\n): number {\n // Edge case: empty array - insert at beginning\n if (positions.length === 0) {\n return 0;\n }\n\n // Edge case: single position - insert after it\n if (positions.length === 1) {\n return 1;\n }\n\n let bestIndex = 1; // Default: insert after first position\n\n // Iterate through all segments\n for (let i = 0; i < positions.length - 1; i++) {\n const segmentStart = positions[i]!;\n const segmentEnd = positions[i + 1]!;\n\n const distance = pointToSegmentDistance(target, segmentStart, segmentEnd);\n\n if (distance < minDistance) {\n minDistance = distance;\n bestIndex = i + 1; // Insert after the segment start\n }\n }\n\n return bestIndex;\n}\n\n/**\n * Calculate the shortest distance from a point to a line segment.\n *\n * @param point - The point to measure from\n * @param segmentStart - Start of the line segment\n * @param segmentEnd - End of the line segment\n * @returns The shortest distance from point to the segment\n */\nfunction pointToSegmentDistance(\n point: Position,\n segmentStart: Position,\n segmentEnd: Position\n): number {\n const dx = segmentEnd.x - segmentStart.x;\n const dy = segmentEnd.y - segmentStart.y;\n\n // If segment is a point, return distance to that point\n const segmentLengthSquared = dx * dx + dy * dy;\n if (segmentLengthSquared === 0) {\n return Math.sqrt((point.x - segmentStart.x) ** 2 + (point.y - segmentStart.y) ** 2);\n }\n\n // Calculate projection of point onto the line (as parameter t)\n // t = 0 means closest point is segmentStart, t = 1 means segmentEnd\n const t = Math.max(\n 0,\n Math.min(\n 1,\n ((point.x - segmentStart.x) * dx + (point.y - segmentStart.y) * dy) / segmentLengthSquared\n )\n );\n\n // Calculate closest point on segment\n const closestX = segmentStart.x + t * dx;\n const closestY = segmentStart.y + t * dy;\n\n // Return distance to closest point\n return Math.sqrt((point.x - closestX) ** 2 + (point.y - closestY) ** 2);\n}\n\n/**\n * Simplify a path by removing collinear intermediate positions.\n *\n * Given an ordered array of positions representing a line path, this function\n * removes positions that lie on the same line as their neighbors (collinear points).\n * The resulting path is visually identical but with fewer redundant points.\n *\n * Three points A, B, C are collinear if B lies on the line from A to C.\n * When collinear, B is redundant and can be removed without changing the path shape.\n *\n * @param positions - Ordered array of positions representing the path\n * @param tolerance - Optional tolerance for collinearity check (default: 5)\n * @returns Simplified array with collinear intermediate points removed\n *\n * @example\n * ```typescript\n * // Horizontal line with redundant middle points\n * const path = [\n * new Position(0, 0),\n * new Position(5, 0), // collinear - will be removed\n * new Position(10, 0), // collinear - will be removed\n * new Position(15, 0)\n * ];\n * simplifyPositions(path);\n * // Returns: [Position(0, 0), Position(15, 0)]\n *\n * // L-shaped path - corner point is NOT collinear\n * const lPath = [\n * new Position(0, 0),\n * new Position(10, 0), // corner - kept\n * new Position(10, 10)\n * ];\n * simplifyPositions(lPath);\n * // Returns: [Position(0, 0), Position(10, 0), Position(10, 10)]\n * ```\n */\nexport function simplifyPositions(positions: Position[], tolerance: number = 5): Position[] {\n // Edge cases: 0, 1, or 2 points can't be simplified\n if (positions.length <= 2) {\n return [...positions];\n }\n\n // Start with the first point\n const result: Position[] = [positions[0]!];\n\n // Check each intermediate point\n for (let i = 1; i < positions.length - 1; i++) {\n const prev = result[result.length - 1]!;\n const current = positions[i]!;\n const next = positions[i + 1]!;\n\n // Keep the point only if it's NOT collinear with prev and next\n if (!areCollinear(prev, current, next, tolerance)) {\n result.push(current);\n }\n // If collinear, skip current (it's redundant)\n }\n\n // Always add the last point\n result.push(positions[positions.length - 1]!);\n\n return result;\n}\n\n/**\n * Check if three points are collinear (lie on the same line).\n *\n * Uses the cross product of vectors AB and AC. If the cross product\n * is zero, the points are collinear.\n *\n * @param a - First point\n * @param b - Second point (middle)\n * @param c - Third point\n * @param tolerance - Optional tolerance for collinearity check (default: 5)\n * @returns true if the three points are collinear\n */\nfunction areCollinear(a: Position, b: Position, c: Position, tolerance: number = 5): boolean {\n // Cross product of vectors AB and AC\n // crossProduct = (B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x)\n // If zero, points are collinear\n const crossProduct = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n return Math.abs(crossProduct) <= tolerance;\n}\n","/**\n * Rotation Type for Component Orientation\n * Represents orientation angle for components on the 2D grid.\n * Uses integer degrees for discrete rotation values.\n * @module core/utils\n */\n\n/**\n * Rotation angle for component orientation.\n *\n * Enforces integer constraint at construction time. Typically used with\n * values like 0, 90, 180, 270 degrees, but any integer is valid.\n * Rotations are immutable once created.\n *\n * @example\n * ```typescript\n * const rotation = new Rotation(90);\n * console.log(rotation.angle); // 90\n *\n * // Invalid: non-integer angle\n * const invalid = new Rotation(45.5); // TypeError\n * ```\n */\nexport class Rotation {\n /**\n * Create a new rotation with the specified angle.\n *\n * @param angle - Rotation angle in degrees (must be integer)\n * @throws {TypeError} If angle is not an integer\n */\n constructor(public readonly angle: number) {\n if (!Number.isInteger(angle)) {\n throw new TypeError(`Rotation angle must be an integer (got ${angle})`);\n }\n }\n\n /**\n * Serialize rotation to JSON.\n *\n * @returns The angle value as a number\n *\n * @example\n * ```typescript\n * const rotation = new Rotation(90);\n * const json = rotation.toJSON();\n * console.log(json); // 90\n * ```\n */\n toJSON(): number {\n return this.angle;\n }\n\n /**\n * Deserialize rotation from JSON.\n *\n * @param angle - Angle value\n * @returns Rotation instance\n * @throws {TypeError} If angle is not an integer\n *\n * @example\n * ```typescript\n * const rotation = Rotation.fromJSON(90);\n * console.log(rotation.angle); // 90\n * ```\n */\n static fromJSON(angle: number): Rotation {\n return new Rotation(angle);\n }\n\n /**\n * Check if this rotation equals another rotation.\n *\n * @param other - Rotation to compare with\n * @returns true if angles are equal\n *\n * @example\n * ```typescript\n * const r1 = new Rotation(90);\n * const r2 = new Rotation(90);\n * const r3 = new Rotation(180);\n *\n * console.log(r1.equals(r2)); // true\n * console.log(r1.equals(r3)); // false\n * ```\n */\n equals(other: Rotation): boolean {\n return this.angle === other.angle;\n }\n\n /**\n * String representation for debugging.\n *\n * @returns String in format \"Rotation(angle°)\"\n */\n toString(): string {\n return `Rotation(${this.angle}°)`;\n }\n}\n","/**\n * Various Utilities\n * @module core/utils\n */\nimport type { UUID } from './types';\n\nexport type { UUID, IPosition, IPosition3D, ICameraOptions } from './types';\n\n/**\n * Generate a new RFC 4122 UUID v4 identifier.\n *\n * Uses the native `crypto.randomUUID()` API when available (ES2022+ browsers,\n * Node 19+). For older Node.js environments in testing, falls back to a\n * polyfill implementation.\n *\n * @returns A newly generated UUID string\n *\n * @example\n * ```typescript\n * const componentId = generateUUID();\n * const wireId = generateUUID();\n * console.log(componentId !== wireId); // true (collision probability: ~10^-36)\n * ```\n */\nexport function generateUUID(): UUID {\n // Native crypto API (modern browsers and Node 19+)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older Node.js (testing environments)\n // Simple UUID v4 implementation without external dependencies\n // Based on RFC 4122 specification\n const hexDigits = '0123456789abcdef';\n const sections = [8, 4, 4, 4, 12];\n const parts: string[] = [];\n\n for (const length of sections) {\n let part = '';\n for (let i = 0; i < length; i++) {\n const randomByte = Math.floor(Math.random() * 16);\n part += hexDigits[randomByte];\n }\n parts.push(part);\n }\n\n // Set version (4) and variant (10) bits as per RFC 4122\n const uuid = parts.join('-');\n const chars = uuid.split('');\n\n // Set version 4 in the time_hi_and_version field\n chars[14] = '4';\n\n // Set variant (10xx in binary) in the clock_seq_hi_and_reserved field\n const variantChar = parseInt(chars[19] ?? '0', 16);\n const variantIndex = (variantChar & 0x3) | 0x8;\n chars[19] = hexDigits[variantIndex] ?? '0';\n\n return chars.join('');\n}\n\nexport { Memoize, MemoizeExpiring } from './MemoizeDecorator.js';\nexport { CameraOptions } from './CameraOptions';\nexport { Position, simplifyPositions, findPositionBestIndex } from './Position';\nexport { Position3D } from './Position3D';\nexport { Rotation } from './Rotation';\n","/**\n * types for core electrical/logical topology\n * @module core/topology\n */\n\nimport type { ICameraOptions, IPosition, UUID } from '../utils';\n\n/**\n * canonic version for circuit files produced\n */\nexport const CIRCUIT_FILE_VERSION = '0.0.11';\n\n/**\n * Type of electrical pinSources in the circuit.\n *\n * ENodes have a sourceType which can be undefined or one of the following:\n * - **Voltage**: ENode that provides a voltage source to the circuit. All Enodes of this type are considered at the same positive potential.\n * - **Current**: Ground/neutral ENodes that provides a current source to the circuit. All Enodes of this type are considered as points at\n * the same 0V-GROUND potential and are points from where electrons enters the circuit.\n */\nexport enum ENodeSourceType {\n Voltage = 'Voltage',\n Current = 'Current',\n}\n\n/**\n * Type of electrical node (ENode) in the circuit.\n *\n * ENodes represent atomic electrical connection points and come in two variants (immutable after node creation)\n *\n * - **Pin**: Connection point belonging to a Component. Position is derived\n * from the parent component's position, rotation, and pin index. Automatically\n * created when a component is added, deleted when component is removed.\n *\n * - **BranchingPoint**: Junction point where wires split. Has an independent\n * position on the grid. Automatically created when wires are split, deleted\n * when no wires remain connected (orphaned).\n */\nexport enum ENodeType {\n /**\n * Component pin connection point.\n *\n * Properties:\n * - Has parent component reference\n * - Has pin label within component\n * - Position derived from component\n * - Lifecycle tied to component (cascade deletion)\n */\n Pin = 'Pin',\n /**\n * Wire branching point (junction).\n *\n * Properties:\n * - Independent position on grid\n * - Created when wire is split\n * - Deleted when last wire is removed (orphaned cleanup)\n * - No parent component\n */\n BranchingPoint = 'BranchingPoint',\n}\n\n/**\n * Metadata describing a component pin's source type and subtype.\n *\n * @property sourceType - Voltage/Current source or undefined for passive pins\n * @property subtype - Pin role classification: 'free', 'vcc', 'logicInput', 'logicOutput'\n */\nexport interface IPinMetadata {\n readonly subtype: string;\n readonly sourceType: ENodeSourceType | undefined;\n}\n/**\n * Metadata for a component type.\n *\n * @property id - Unique string identifier matching the enum value\n * @property name - Human-readable display name\n * @property pins - Array of pin labels (order-significant)\n * @property config - Default configuration parameters (depends on the component, e.g., initialState, activationLogic, color...)\n */\nexport interface IComponentTypeMetadata {\n readonly id: string;\n readonly name: string;\n readonly pins: Map<string, IPinMetadata>;\n readonly config: Map<string, string>;\n}\n\n/**\n * Available logic families\n *\n * - `CMOS1`: CMOS technology, base unit 1 inverter = 1 tick\n * - `TTL1`: TTL technology, base unit 1 NAND2 = 1 tick\n * - `Sandbox`: User-defined delays, no technology constraints\n */\nexport type LogicFamily = 'CMOS1' | 'TTL1' | 'Sandbox';\n\n/** All supported logic families */\nexport const ALL_LOGIC_FAMILIES: LogicFamily[] = ['CMOS1', 'TTL1', 'Sandbox'];\n\n/** Default logic family applied when none is specified */\nexport const DEFAULT_LOGIC_FAMILY: LogicFamily = 'CMOS1';\n\n/** Interface defining an ElectricalNode **/\nexport interface IENode {\n id: UUID;\n type: ENodeType;\n component?: UUID | null;\n pinLabel?: string | null;\n position?: IPosition | null;\n source?: ENodeSourceType | null;\n subtype: string;\n}\n/** Interface defining a Wire (link between 2 ENodes supporting intermediate position to tune its path) **/\nexport interface IWire {\n id: UUID;\n node1: UUID;\n node2: UUID;\n intermediatePositions: IPosition[];\n}\n/** Interface defining a Component **/\nexport interface IComponent {\n id: UUID;\n type: ComponentType;\n position: IPosition;\n rotation: number;\n pins: UUID[];\n config: { [key: string]: string };\n editable: boolean;\n}\n\n/**\n * User editable options for a Circuit\n */\nexport type ICircuitOptions = {\n name: string;\n defaultLogicFamily: LogicFamily;\n};\n/** circuit metadata type — combines user writable options and managed metadata */\nexport type ICircuitMetadata = {\n version: string;\n options: ICircuitOptions;\n cameraOptions: ICameraOptions;\n size: number;\n divisions: number;\n};\n/** circuit type */\nexport type ICircuit = {\n metadata: ICircuitMetadata;\n components: Iterable<IComponent>;\n enodes: Iterable<IENode>;\n wires: Iterable<IWire>;\n};\n\n/**\n * Enumeration of ALL available component types.\n *\n * Each component type represents a specific electrical element that can be\n * placed in a circuit (battery, LED, transistor, etc.).\n */\nexport enum ComponentType {\n // basic components\n Cube = 'cube', // no pins component for testing purposes mainly\n Label = 'label', // decorative text label with no pins\n Battery = 'battery',\n Switch = 'switch',\n DoubleThrowSwitch = 'doubleThrowSwitch',\n Lightbulb = 'lightbulb',\n Relay = 'relay',\n SmallLED = 'smallLED',\n RectangleLED = 'rectangleLED',\n Clock = 'clock',\n // Gates\n Inverter = 'inverter',\n NandGate = 'nandGate',\n Nand4Gate = 'nand4Gate',\n Nand8Gate = 'nand8Gate',\n NorGate = 'norGate',\n Nor4Gate = 'nor4Gate',\n Nor8Gate = 'nor8Gate',\n XorGate = 'xorGate',\n Xor4Gate = 'xor4Gate',\n Xor8Gate = 'xor8Gate',\n}\n\n/**\n * Component type metadata lookup table.\n *\n * Maps each ComponentType enum value to its associated metadata\n * (id, display name, pins, and default configuration arguments).\n *\n */\nexport const COMPONENT_TYPE_METADATA: Readonly<Record<ComponentType, IComponentTypeMetadata>> = {\n [ComponentType.Switch]: {\n id: ComponentType.Switch,\n name: 'Switch',\n pins: new Map([\n ['input', { subtype: 'free', sourceType: undefined }],\n ['output', { subtype: 'free', sourceType: undefined }],\n ]),\n config: new Map([\n ['initialState', 'open'],\n ['transitionSpan', '1'],\n ['size', '1'],\n ]),\n },\n [ComponentType.DoubleThrowSwitch]: {\n id: ComponentType.DoubleThrowSwitch, // SPDT (Single-Pole Double-Throw) Switch\n name: 'DoubleThrowSwitch',\n pins: new Map([\n ['input1', { subtype: 'free', sourceType: undefined }],\n ['input2', { subtype: 'free', sourceType: undefined }],\n ['output', { subtype: 'free', sourceType: undefined }],\n ]),\n config: new Map([\n ['initialState', 'input1'],\n ['transitionSpan', '1'],\n ['size', '1'],\n ]),\n },\n [ComponentType.Battery]: {\n id: ComponentType.Battery,\n name: 'Battery',\n pins: new Map([\n ['cathode', { subtype: 'mainVcc', sourceType: ENodeSourceType.Voltage }],\n ['anode', { subtype: 'mainGnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([]),\n },\n [ComponentType.Lightbulb]: {\n id: ComponentType.Lightbulb,\n name: 'Lightbulb',\n pins: new Map([\n ['pin1', { subtype: 'free', sourceType: undefined }],\n ['pin2', { subtype: 'free', sourceType: undefined }],\n ]),\n config: new Map([\n ['transitionSpan', '1'],\n ['size', '1'],\n ]),\n },\n [ComponentType.Relay]: {\n id: ComponentType.Relay,\n name: 'Relay',\n pins: new Map([\n ['cmd_in', { subtype: 'free', sourceType: undefined }],\n ['cmd_out', { subtype: 'free', sourceType: undefined }],\n ['power_in', { subtype: 'free', sourceType: undefined }],\n ['power_out', { subtype: 'free', sourceType: undefined }],\n ]),\n config: new Map([\n ['activationLogic', 'positive'],\n ['transitionSpan', '1'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.SmallLED]: {\n id: ComponentType.SmallLED,\n name: 'SmallLED',\n pins: new Map([\n ['pin1', { subtype: 'free', sourceType: undefined }],\n ['pin2', { subtype: 'free', sourceType: undefined }],\n ]),\n config: new Map([\n ['transitionSpan', '1'],\n ['idleColor', 'white'],\n ['activeColor', '#ffff00'],\n ['size', '1'],\n ['ywRatio', '1'],\n ]),\n },\n [ComponentType.RectangleLED]: {\n id: ComponentType.RectangleLED,\n name: 'RectangleLED',\n pins: new Map([\n ['pin1', { subtype: 'free', sourceType: undefined }],\n ['pin2', { subtype: 'free', sourceType: undefined }],\n ]),\n config: new Map([\n ['transitionSpan', '1'],\n ['idleColor', 'white'],\n ['activeColor', '#ffff00'],\n ['size', '1'],\n ['hwRatio', '1'],\n ['ywRatio', '1'],\n ]),\n },\n [ComponentType.Cube]: {\n id: ComponentType.Cube,\n name: 'Cube',\n pins: new Map([]),\n config: new Map([['color', 'red']]),\n },\n [ComponentType.Label]: {\n id: ComponentType.Label,\n name: 'Label',\n pins: new Map([]),\n config: new Map([\n ['text', 'Label'],\n ['size', '1'],\n ]),\n },\n [ComponentType.Clock]: {\n id: ComponentType.Clock,\n name: 'Clock',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['startHigh', 'true'],\n ['halfPeriod', '2'],\n ]),\n },\n [ComponentType.Inverter]: {\n id: ComponentType.Inverter,\n name: 'Inverter',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '1'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.NandGate]: {\n id: ComponentType.NandGate,\n name: 'NAND Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '1'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.Nand4Gate]: {\n id: ComponentType.Nand4Gate,\n name: 'NAND4 Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['input3', { subtype: 'logicInput', sourceType: undefined }],\n ['input4', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '2'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.Nand8Gate]: {\n id: ComponentType.Nand8Gate,\n name: 'NAND8 Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['input3', { subtype: 'logicInput', sourceType: undefined }],\n ['input4', { subtype: 'logicInput', sourceType: undefined }],\n ['input5', { subtype: 'logicInput', sourceType: undefined }],\n ['input6', { subtype: 'logicInput', sourceType: undefined }],\n ['input7', { subtype: 'logicInput', sourceType: undefined }],\n ['input8', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '3'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.NorGate]: {\n id: ComponentType.NorGate,\n name: 'NOR Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '1'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.Nor4Gate]: {\n id: ComponentType.Nor4Gate,\n name: 'NOR4 Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['input3', { subtype: 'logicInput', sourceType: undefined }],\n ['input4', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '2'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.Nor8Gate]: {\n id: ComponentType.Nor8Gate,\n name: 'NOR8 Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['input3', { subtype: 'logicInput', sourceType: undefined }],\n ['input4', { subtype: 'logicInput', sourceType: undefined }],\n ['input5', { subtype: 'logicInput', sourceType: undefined }],\n ['input6', { subtype: 'logicInput', sourceType: undefined }],\n ['input7', { subtype: 'logicInput', sourceType: undefined }],\n ['input8', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'negative'],\n ['transitionSpan', '3'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.XorGate]: {\n id: ComponentType.XorGate,\n name: 'XOR Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'positive'],\n ['transitionSpan', '2'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.Xor4Gate]: {\n id: ComponentType.Xor4Gate,\n name: 'XOR4 Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['input3', { subtype: 'logicInput', sourceType: undefined }],\n ['input4', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'positive'],\n ['transitionSpan', '4'],\n ['initializationOrder', ''],\n ]),\n },\n [ComponentType.Xor8Gate]: {\n id: ComponentType.Xor8Gate,\n name: 'XOR8 Gate',\n pins: new Map([\n ['vcc', { subtype: 'vcc', sourceType: ENodeSourceType.Voltage }],\n ['input1', { subtype: 'logicInput', sourceType: undefined }],\n ['input2', { subtype: 'logicInput', sourceType: undefined }],\n ['input3', { subtype: 'logicInput', sourceType: undefined }],\n ['input4', { subtype: 'logicInput', sourceType: undefined }],\n ['input5', { subtype: 'logicInput', sourceType: undefined }],\n ['input6', { subtype: 'logicInput', sourceType: undefined }],\n ['input7', { subtype: 'logicInput', sourceType: undefined }],\n ['input8', { subtype: 'logicInput', sourceType: undefined }],\n ['output', { subtype: 'logicOutput', sourceType: undefined }],\n ['gnd', { subtype: 'gnd', sourceType: ENodeSourceType.Current }],\n ]),\n config: new Map([\n ['defaultLogicFamily', 'CMOS1'],\n ['activationLogic', 'positive'],\n ['transitionSpan', '6'],\n ['initializationOrder', ''],\n ]),\n },\n};\n","/**\n * ENode Class (Electrical Node)\n *\n * Represents atomic electrical connection points in the circuit.\n * ENodes come in two types: component pins and wire branching points.\n *\n * @module core/topology\n */\nimport { type UUID, Position, generateUUID } from '../utils';\nimport { ENodeSourceType, ENodeType, type IENode } from './types';\nimport type { Circuit } from './Circuit';\n\n/**\n * Electrical connection point (component pin or wire branching point).\n *\n * ENodes are automatically managed by the Circuit:\n * - **Pin nodes**: Created when components are added, deleted when components removed\n * - **Branching nodes**: Created when wires split, deleted when orphaned (no wires)\n *\n * **Position Handling**:\n * - Pin nodes: Position derived from parent component\n * - Branching nodes: Independent position stored directly\n *\n * @example\n * ```typescript\n * // Pin node (created automatically by Circuit)\n * const circuit = new Circuit();\n * const component = circuit.addComponent(new Position(10, 20), new Rotation(0), 2);\n * const pinNode = circuit.getENode(component.pins[0]);\n *\n * console.log(pinNode.type); // ENodeType.Pin\n * console.log(pinNode.component); // component UUID\n * console.log(pinNode.pinLabel); // '0'\n *\n * // Branching node (created during wire split)\n * const branchNode = new ENode(\n * ENodeType.BranchingPoint,\n * undefined,\n * undefined,\n * new Position(15, 25)\n * );\n * console.log(branchNode.position); // Position { x: 15, y: 25 }\n * ```\n */\nexport class ENode {\n /**\n * Unique identifier for this ENode.\n * @readonly\n */\n public readonly id: UUID;\n\n /**\n * Type of electrical node (Pin or BranchingPoint).\n * @readonly\n */\n public readonly type: ENodeType;\n\n /**\n * Parent component UUID (only for pin nodes).\n * Undefined for branching point nodes.\n * @readonly\n */\n public readonly component: UUID | undefined;\n\n /**\n * Pin label within component (only for pin nodes).\n * Undefined for branching point nodes.\n * @readonly\n */\n public readonly pinLabel: string | undefined;\n\n /**\n * Grid position (only for branching point nodes).\n * Undefined for pin nodes (position derived from component).\n * @readonly\n */\n public readonly position: Position | undefined;\n\n /**\n * Set of wire UUIDs connected to this node.\n * Mutable to allow wire connections/disconnections.\n */\n public readonly wires: Set<UUID>;\n\n /**\n * Is the ENode a source of voltage or current?\n */\n public source: ENodeSourceType | undefined;\n\n /**\n * Pin role classification: free, mainVcc, vcc, mainGnd, gnd, logicInput, logicOutput.\n * @readonly\n */\n public readonly subtype: string;\n\n /**\n * Create a new electrical node.\n *\n * **Note**: Typically ENodes are created automatically by Circuit.\n * This constructor is used internally.\n *\n * @param type - Node type (Pin or BranchingPoint)\n * @param component - Parent component UUID (pin nodes only)\n * @param pinLabel - Pin label (pin nodes only)\n * @param position - Grid position (branching points only)\n * @param source - Source type (Voltage/Current) or undefined\n *\n * @param subtype\n * @example\n * ```typescript\n * // Pin node (internal to Circuit)\n * const pinNode = new ENode(\n * ENodeType.Pin,\n * componentId,\n * '0', // first pin\n * undefined,\n * undefined\n * );\n *\n * // Branching point node\n * const branchNode = new ENode(\n * ENodeType.BranchingPoint,\n * undefined,\n * undefined,\n * new Position(15, 25),\n * undefined\n * );\n * ```\n */\n constructor(\n type: ENodeType,\n component: UUID | undefined,\n pinLabel: string | undefined,\n position: Position | undefined,\n source: ENodeSourceType | undefined = undefined,\n subtype: string = 'free'\n ) {\n this.id = generateUUID();\n this.type = type;\n this.component = component;\n this.pinLabel = pinLabel;\n this.position = position;\n this.wires = new Set();\n this.source = source;\n this.subtype = subtype;\n }\n\n /**\n * Get the position of this electrical node.\n *\n * **Pin nodes**: Derives position from parent component.\n * **Branching nodes**: Returns stored position directly.\n *\n * @param circuit - Circuit instance (needed to look up component for pin nodes)\n * @returns Position on the grid\n *\n * @example\n * ```typescript\n * const circuit = new Circuit();\n * const component = circuit.addComponent(\n * new Position(10, 20),\n * new Rotation(0),\n * 1\n * );\n *\n * const pinNode = circuit.getENode(component.pins[0]);\n * const position = pinNode.getPosition(circuit);\n * console.log(position.x); // 10 (derived from component)\n * ```\n */\n getPosition(circuit: Circuit): Position {\n if (this.type === ENodeType.Pin) {\n // Derive position from parent component\n if (!this.component) {\n throw new Error('Pin node missing component reference');\n }\n\n const component = circuit.getComponent(this.component);\n if (!component) {\n throw new Error(`Component ${this.component} not found for pin node ${this.id}`);\n }\n\n // For now, return component position directly\n // Future enhancement: could calculate pin offset based on pinLabel\n return component.position;\n }\n\n // Branching point: return stored position\n if (!this.position) {\n throw new Error('Branching point node missing position');\n }\n\n return this.position;\n }\n\n /**\n * Update the enode (branching point only)'s position.\n *\n * @param newPosition - The new position for the enode\n *\n * @example\n * ```typescript\n * const component = circuit.getComponent(componentId);\n * component.setPosition(new Position(15, 25));\n * ```\n */\n setPosition(newPosition: Position): void {\n Object.defineProperty(this, 'position', {\n value: newPosition,\n writable: false,\n enumerable: true,\n configurable: true,\n });\n }\n\n /**\n * Update the enode's source type.\n * @param sourceType\n */\n setSourceType(sourceType?: ENodeSourceType | undefined): void {\n Object.defineProperty(this, 'source', {\n value: sourceType,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n\n /**\n * Serialize ENode to JSON.\n *\n * @returns Plain object representation\n *\n * @example\n * ```typescript\n * const json = enode.toJSON();\n * console.log(json);\n * // Pin node:\n * // {\n * // id: \"uuid\",\n * // type: \"Pin\",\n * // component: \"component-uuid\",\n * // pinLabel: \"0\"\n * // }\n *\n * // Branching node:\n * // {\n * // id: \"uuid\",\n * // type: \"BranchingPoint\",\n * // position: { x: 15, y: 25 }\n * // }\n * ```\n */\n toJSON(): IENode {\n const json: IENode = {\n id: this.id,\n type: this.type,\n source: this.source || null,\n subtype: this.subtype,\n };\n\n if (this.type === ENodeType.Pin) {\n json.component = this.component || null;\n json.pinLabel = this.pinLabel || null;\n } else {\n json.position = this.position?.toJSON() || null;\n }\n\n return json;\n }\n\n /**\n * Deserialize ENode from JSON.\n *\n * @param json - ENode data\n * @returns ENode instance\n *\n * @example\n * ```typescript\n * const json = {\n * id: \"uuid\",\n * type: \"Pin\",\n * component: \"component-uuid\",\n * pinLabel: \"0\"\n * };\n *\n * const enode = ENode.fromJSON(json);\n * ```\n */\n static fromJSON(json: IENode): ENode {\n const position = json.position ? Position.fromJSON(json.position) : undefined;\n\n const enode = new ENode(\n json.type,\n json.component || undefined,\n json.pinLabel || undefined,\n position,\n json.source || undefined,\n json.subtype ?? 'free'\n );\n\n // Override generated ID with the one from JSON\n Object.defineProperty(enode, 'id', {\n value: json.id,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return enode;\n }\n}\n","/**\n * Wire Class\n *\n * Represents electrical connection between exactly two ENodes.\n * Wires can have intermediate positions for custom routing paths.\n *\n * @module core/topology\n */\nimport type { UUID } from '../utils';\nimport { generateUUID, Position } from '../utils';\nimport type { IWire } from './types';\n\n/**\n * Electrical connection between two ENodes.\n *\n * Wires connect exactly two electrical nodes (component pins or branching points).\n * They support intermediate positions for ad-hoc routing paths in rendering.\n *\n * **Lifecycle**: Wires are created and removed via the Circuit class.\n * - Creating a wire updates bidirectional references (Wire ↔ ENodes)\n * - Removing a wire triggers orphaned branching point cleanup\n * - Splitting a wire creates new branching ENode and multiple wires\n *\n * @example\n * ```typescript\n * const circuit = new Circuit();\n * const comp1 = circuit.addComponent(new Position(0, 0), new Rotation(0), 1);\n * const comp2 = circuit.addComponent(new Position(10, 10), new Rotation(0), 1);\n *\n * // Straight wire\n * const wire = circuit.addWire(comp1.pins[0], comp2.pins[0]);\n *\n * // Wire with custom path\n * const curvedWire = circuit.addWire(\n * comp1.pins[0],\n * comp2.pins[0],\n * [new Position(5, 5), new Position(8, 7)]\n * );\n * ```\n */\nexport class Wire {\n /**\n * Unique identifier for this wire.\n * @readonly\n */\n public readonly id: UUID;\n\n /**\n * First connected ENode UUID.\n * @readonly\n */\n public readonly node1: UUID;\n\n /**\n * Second connected ENode UUID.\n * @readonly\n */\n public readonly node2: UUID;\n\n /**\n * Optional intermediate positions for wire routing.\n * Empty array indicates straight-line connection.\n * @readonly\n */\n public intermediatePositions: Array<Position>;\n\n /**\n * Create a new wire.\n *\n * **Note**: Typically wires are created via `Circuit.addWire()` which\n * handles validation and bidirectional reference updates. This constructor\n * is used internally by Circuit.\n *\n * @param node1 - First ENode UUID\n * @param node2 - Second ENode UUID\n * @param intermediatePositions - Optional waypoints for rendering\n *\n * @example\n * ```typescript\n * // Usually created via Circuit:\n * const wire = circuit.addWire(nodeId1, nodeId2);\n *\n * // With intermediate positions:\n * const wire = circuit.addWire(\n * nodeId1,\n * nodeId2,\n * [new Position(5, 10), new Position(15, 10)]\n * );\n * ```\n */\n constructor(node1: UUID, node2: UUID, intermediatePositions: Array<Position> = []) {\n this.id = generateUUID();\n this.node1 = node1;\n this.node2 = node2;\n this.intermediatePositions = intermediatePositions;\n }\n\n /**\n * Check if this is a straight-line wire.\n *\n * @returns true if no intermediate positions, false otherwise\n *\n * @example\n * ```typescript\n * const straightWire = new Wire(node1, node2);\n * console.log(straightWire.isStraightLine()); // true\n *\n * const curvedWire = new Wire(node1, node2, [new Position(5, 5)]);\n * console.log(curvedWire.isStraightLine()); // false\n * ```\n */\n isStraightLine(): boolean {\n return this.intermediatePositions.length === 0;\n }\n\n /**\n * Serialize wire to JSON.\n *\n * @returns Plain object representation\n *\n * @example\n * ```typescript\n * const json = wire.toJSON();\n * console.log(json);\n * // {\n * // id: \"uuid\",\n * // node1: \"node-uuid-1\",\n * // node2: \"node-uuid-2\",\n * // intermediatePositions: [{ x: 5, y: 10 }]\n * // }\n * ```\n */\n toJSON(): IWire {\n return {\n id: this.id,\n node1: this.node1,\n node2: this.node2,\n intermediatePositions: this.intermediatePositions.map((p) => p.toJSON()),\n };\n }\n\n /**\n * Deserialize wire from JSON.\n *\n * @param json - Wire data\n * @returns Wire instance\n *\n * @example\n * ```typescript\n * const json = {\n * id: \"uuid\",\n * node1: \"node-uuid-1\",\n * node2: \"node-uuid-2\",\n * intermediatePositions: [{ x: 5, y: 10 }]\n * };\n *\n * const wire = Wire.fromJSON(json);\n * ```\n */\n static fromJSON(json: IWire): Wire {\n const positions = json.intermediatePositions.map((p) => Position.fromJSON(p));\n\n const wire = new Wire(json.node1, json.node2, positions);\n\n // Override generated ID with the one from JSON\n Object.defineProperty(wire, 'id', {\n value: json.id,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return wire;\n }\n}\n","/**\n * Component Class\n *\n * Base class for electrical components in the circuit.\n * Components have a position, rotation, and collection of pin ENodes.\n *\n * @module core/topology\n */\nimport type { UUID } from '../utils';\nimport { generateUUID, Position, Rotation } from '../utils';\nimport { COMPONENT_TYPE_METADATA, ComponentType, type IComponent } from './types';\n\n/**\n * Electrical component placed on the circuit grid.\n *\n * Components represent physical circuit elements (lightbulbs, transistors, etc.)\n * with a specific position, orientation, and set of electrical connection pins.\n *\n * **Lifecycle**: Components are created and removed via the Circuit class.\n * When a component is added to a circuit, pin ENodes are automatically created\n * for each pin. When removed, pins and connected wires are cascade-deleted.\n *\n * @example\n * ```typescript\n * const position = new Position(10, 20);\n * const rotation = new Rotation(90);\n * const pins = ['pin-uuid-1', 'pin-uuid-2'];\n *\n * const component = new Component(position, rotation, pins);\n *\n * console.log(component.id); // \"550e8400-...\"\n * console.log(component.position); // Position { x: 10, y: 20 }\n * console.log(component.rotation); // Rotation { angle: 90 }\n * console.log(component.pins); // ['pin-uuid-1', 'pin-uuid-2']\n * ```\n */\nexport class Component {\n /**\n * Unique identifier for this component.\n * @readonly\n */\n public readonly id: UUID;\n\n /**\n * Component type (Battery, Switch, LED, etc.).\n * @readonly\n */\n public readonly type: ComponentType;\n\n /**\n * Position on the 2D discrete grid.\n * @readonly\n */\n public readonly position: Position;\n\n /**\n * Orientation angle in degrees.\n * @readonly\n */\n public readonly rotation: Rotation;\n\n /**\n * Array of pin ENode UUIDs.\n * Pin order is significant (index 0 is first pin, etc.).\n * @readonly\n */\n public readonly pins: ReadonlyArray<UUID>;\n\n /**\n * Configuration parameters for this component instance.\n *\n * This map holds key-value pairs representing configurable settings\n * The available configuration keys depend on the component type see IComponentTypeMetadata for details.\n *\n */\n public config: Map<string, string>;\n\n /**\n * allow to flag a component as non editable (feature to implement)\n */\n public editable: boolean;\n\n /**\n * Create a new component.\n *\n * **Note**: Typically components are created via `Circuit.addComponent()`\n * which handles pin ENode creation automatically. This constructor is used\n * internally by Circuit.\n *\n * @param type - Component type (Battery, Switch, LED, etc.)\n * @param position - Grid position (integer x, y)\n * @param rotation - Orientation angle (integer degrees)\n * @param pins - Array of pin ENode UUIDs\n *\n * @param editable\n * @example\n * ```typescript\n * // Usually created via Circuit:\n * const component = circuit.addComponent(\n * new Position(10, 20),\n * new Rotation(90),\n * ComponentType.Battery\n * );\n *\n * // Direct construction (for deserialization):\n * const component = new Component(\n * ComponentType.Battery,\n * new Position(10, 20),\n * new Rotation(90),\n * ['pin-id-1', 'pin-id-2']\n * );\n * ```\n */\n constructor(\n type: ComponentType,\n position: Position,\n rotation: Rotation,\n pins: ReadonlyArray<UUID>,\n editable: boolean = true\n ) {\n this.id = generateUUID();\n this.type = type;\n this.position = position;\n this.rotation = rotation;\n\n // add a check on the unicity of pins\n if (new Set(pins).size !== pins.length) {\n const duplicates = pins.filter((item, index) => pins.indexOf(item) !== index);\n throw new Error(\n `Duplicate pin names are not allowed: ${[...new Set(duplicates)].join(', ')}`\n );\n }\n\n this.pins = pins;\n // instanciate component config from metadata's default config\n this.config = new Map<string, string>(COMPONENT_TYPE_METADATA[type].config);\n this.editable = editable;\n }\n\n getPinLabel(pinId: UUID): string | undefined {\n const pinIndex = this.pins.indexOf(pinId);\n if (pinIndex === -1) {\n return undefined;\n }\n const pinLabels = COMPONENT_TYPE_METADATA[this.type].pins.keys();\n // convert to array to access by index\n return Array.from(pinLabels)[pinIndex] || undefined;\n }\n\n setAllParameters(config: Map<string, string>): void {\n this.config = new Map<string, string>(config);\n }\n\n setParameter(key: string, value: string): void {\n this.config.set(key, value);\n }\n\n /**\n * Update the component's position.\n *\n * @param newPosition - The new position for the component\n *\n * @example\n * ```typescript\n * const component = circuit.getComponent(componentId);\n * component.setPosition(new Position(15, 25));\n * ```\n */\n setPosition(newPosition: Position): void {\n Object.defineProperty(this, 'position', {\n value: newPosition,\n writable: false,\n enumerable: true,\n configurable: true,\n });\n }\n\n /**\n * Update the component's rotation.\n *\n * @param newRotation - The new rotation for the component\n *\n * @example\n * ```typescript\n * const component = circuit.getComponent(componentId);\n * component.setRotation(new Rotation(90));\n * ```\n */\n setRotation(newRotation: Rotation): void {\n Object.defineProperty(this, 'rotation', {\n value: newRotation,\n writable: false,\n enumerable: true,\n configurable: true,\n });\n }\n\n /**\n * Serialize component to JSON.\n *\n * @returns Plain object representation\n *\n * @example\n * ```typescript\n * const json = component.toJSON();\n * console.log(json);\n * // {\n * // id: \"550e8400-...\",\n * // type: \"battery\",\n * // position: { x: 10, y: 20 },\n * // rotation: 90,\n * // pins: ['pin-uuid-1', 'pin-uuid-2']\n * // }\n * ```\n */\n toJSON(): IComponent {\n return {\n id: this.id,\n type: this.type,\n position: this.position.toJSON(),\n rotation: this.rotation.toJSON(),\n pins: [...this.pins],\n config: Object.fromEntries(this.config),\n editable: this.editable,\n };\n }\n\n /**\n * Deserialize component from JSON.\n *\n * @param json - Component data\n * @returns Component instance\n *\n */\n static fromJSON(json: IComponent): Component {\n // Create temporary component to get position/rotation instances\n const component = new Component(\n json.type,\n Position.fromJSON(json.position),\n Rotation.fromJSON(json.rotation),\n json.pins,\n json.editable\n );\n component.config = new Map<string, string>(Object.entries(json.config));\n\n // Override the generated ID with the one from JSON\n // Using Object.defineProperty to bypass readonly\n Object.defineProperty(component, 'id', {\n value: json.id,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return component;\n }\n}\n","/**\n * Circuit Options\n * Encapsulate user writable circuit options\n * @module core/topology\n */\nimport { DEFAULT_LOGIC_FAMILY, type ICircuitOptions, type LogicFamily } from './types';\n\nexport class CircuitOptions implements ICircuitOptions {\n /**\n * Create new circuit options.\n *\n * @param name - Circuit name (default: Untitled Circuit)\n * @param defaultLogicFamily - Circuit default logic family (default: CMOS1)\n */\n constructor(\n public name: string = 'Untitled Circuit',\n public defaultLogicFamily: LogicFamily = DEFAULT_LOGIC_FAMILY\n ) {}\n\n toJSON(): ICircuitOptions {\n return {\n name: this.name,\n defaultLogicFamily: this.defaultLogicFamily,\n };\n }\n\n static fromJSON(json: ICircuitOptions): CircuitOptions {\n return new CircuitOptions(json.name, json.defaultLogicFamily);\n }\n}\n","/**\n * Circuit Metadata\n * Encapsulate user writable circuit options and system managed metadata (camera, size,...)\n * @module core/topology\n */\n\nimport { CameraOptions } from '../utils';\nimport { CircuitOptions } from './CircuitOptions';\nimport { CIRCUIT_FILE_VERSION, DEFAULT_LOGIC_FAMILY, type ICircuitMetadata } from './types';\n\nexport class CircuitMetadata implements ICircuitMetadata {\n /**\n * Create a new CircuitMetadata holding general information about the Circuit.\n *\n * @param version - Circuit version\n * @param options - Circuit options\n * @param size - Size of the circuit grid\n * @param divisions - Divisions in the circuit grid\n * @param cameraOptions - Camera Options at startup\n * @throws {TypeError} If size or divisions are not integers\n */\n constructor(\n public version: string,\n public options: CircuitOptions,\n public size: number,\n public divisions: number,\n public cameraOptions: CameraOptions\n ) {\n if (!Number.isInteger(size) || !Number.isInteger(divisions)) {\n throw new TypeError(\n `Size and divisions must be integers (got size=${size}, divisions=${divisions})`\n );\n }\n }\n\n toJSON(): ICircuitMetadata {\n return {\n version: this.version,\n options: this.options.toJSON(),\n size: this.size,\n divisions: this.divisions,\n cameraOptions: this.cameraOptions.toJSON(),\n };\n }\n\n static fromJSON(json: ICircuitMetadata): CircuitMetadata {\n if (CIRCUIT_FILE_VERSION !== json.version) {\n console.warn(`This version of the engine supports v${CIRCUIT_FILE_VERSION} circuit version files. \n Unexpected behavior may occurs loading v${json.version}.`);\n }\n\n const options = json.options\n ? CircuitOptions.fromJSON(json.options)\n : new CircuitOptions('Untitled Circuit', DEFAULT_LOGIC_FAMILY);\n return new CircuitMetadata(\n json.version,\n options,\n json.size,\n json.divisions,\n CameraOptions.fromJSON(json.cameraOptions)\n );\n }\n\n toString(): string {\n return `CircuitMetadata(${this.version}, ${this.options.name}, ${this.options.defaultLogicFamily}, ${this.size}, ${this.divisions}, ${this.cameraOptions.toString()})`;\n }\n}\n","/**\n * Logic Family Types and Delay Computation\n *\n * Provides the logic family model for gate components, mapping technology\n * choices (CMOS, TTL) to propagation delays derived from physical principles.\n *\n * @module core/topology\n */\n\nimport { ComponentType, type LogicFamily } from './types';\nimport { Component } from './Component';\n\n// TTL1 delay lookup tables indexed by input count\n// Physical basis: multi-emitter BJTs mean NAND4 is still single-stage; NOR is disadvantaged\nconst TTL1_NAND: Record<number, number> = { 2: 1, 4: 1, 8: 2, 16: 2 };\nconst TTL1_AND: Record<number, number> = { 2: 2, 4: 2, 8: 3, 16: 3 };\nconst TTL1_NOR: Record<number, number> = { 2: 1, 4: 2, 8: 2, 16: 3 };\nconst TTL1_OR: Record<number, number> = { 2: 2, 4: 3, 8: 3, 16: 4 };\n\n/**\n * Gate family classification used for delay table lookup.\n * Maps to the logical function regardless of physical implementation.\n */\ntype GateFamily = 'NOT' | 'Buffer' | 'NAND' | 'AND' | 'NOR' | 'OR' | 'XOR' | 'XNOR';\n\n/**\n * Given a component compute the basis transitionSpan from its logicFamily if applicable\n * if not applicable / already implemented returns undefined\n * @param component\n */\nexport function computeTransitionSpan(component: Component): number | undefined {\n const logicFamily = component.config.get('defaultLogicFamily') as LogicFamily | undefined;\n if (!logicFamily || logicFamily === 'Sandbox') {\n return undefined;\n }\n\n if (isLogicGate(component.type)) {\n const activationLogic = component.config.get('activationLogic') ?? 'negative';\n const classif = classifyGate(component.type, activationLogic);\n if (!classif) return undefined;\n const delay = computeGateDelay(logicFamily, classif.gateFamily, classif.inputCount);\n return delay || undefined;\n }\n\n // other component families will be to implement as they come\n return undefined;\n}\n\nfunction isLogicGate(type: ComponentType): boolean {\n return [\n ComponentType.Inverter,\n ComponentType.NandGate,\n ComponentType.Nand4Gate,\n ComponentType.Nand8Gate,\n ComponentType.NorGate,\n ComponentType.Nor4Gate,\n ComponentType.Nor8Gate,\n ComponentType.XorGate,\n ComponentType.Xor4Gate,\n ComponentType.Xor8Gate,\n ].includes(type);\n}\n\n/**\n * Classify a ComponentType + activationLogic combination into a GateFamily and input count.\n *\n * Returns null for non-gate component types (Battery, Switch, LED, etc.).\n *\n * @param componentType - The component type to classify\n * @param activationLogic - 'positive' or 'negative' from the component config\n * @returns Object with gateFamily and inputCount, or null if not a gate\n */\nexport function classifyGate(\n componentType: ComponentType,\n activationLogic: string\n): { gateFamily: GateFamily; inputCount: number } | null {\n switch (componentType) {\n case ComponentType.Inverter:\n return { gateFamily: activationLogic === 'negative' ? 'NOT' : 'Buffer', inputCount: 1 };\n case ComponentType.NandGate:\n return { gateFamily: activationLogic === 'negative' ? 'NAND' : 'AND', inputCount: 2 };\n case ComponentType.Nand4Gate:\n return { gateFamily: activationLogic === 'negative' ? 'NAND' : 'AND', inputCount: 4 };\n case ComponentType.Nand8Gate:\n return { gateFamily: activationLogic === 'negative' ? 'NAND' : 'AND', inputCount: 8 };\n case ComponentType.NorGate:\n return { gateFamily: activationLogic === 'negative' ? 'NOR' : 'OR', inputCount: 2 };\n case ComponentType.Nor4Gate:\n return { gateFamily: activationLogic === 'negative' ? 'NOR' : 'OR', inputCount: 4 };\n case ComponentType.Nor8Gate:\n return { gateFamily: activationLogic === 'negative' ? 'NOR' : 'OR', inputCount: 8 };\n case ComponentType.XorGate:\n return { gateFamily: activationLogic === 'negative' ? 'XNOR' : 'XOR', inputCount: 2 };\n case ComponentType.Xor4Gate:\n return { gateFamily: activationLogic === 'negative' ? 'XNOR' : 'XOR', inputCount: 4 };\n case ComponentType.Xor8Gate:\n return { gateFamily: activationLogic === 'negative' ? 'XNOR' : 'XOR', inputCount: 8 };\n default:\n return null;\n }\n}\n\n/**\n * Compute the propagation delay in ticks for a gate given its logic family, gate family, and input count.\n *\n * CMOS1 formulas (base unit: 1 inverter = 1 tick):\n * - NOT: 1 (constant)\n * - Buffer: 2 (constant)\n * - NAND/NOR: log2(n)\n * - AND/OR: log2(n) + 1\n * - XOR: log2(n) * 2\n * - XNOR: log2(n) * 2 + 1\n *\n * This table assumes inverter, NAND, NAND4, NAND8, NOR, NOR4, NOR8 and XOR(2) are transistor level primitives\n *\n * TTL1 uses lookup tables (base unit: NAND2 = 1 tick).\n * NOT and Buffer: same as CMOS1 (1 and 2 ticks).\n * XOR/XNOR: same as CMOS1.\n *\n * @param logicFamily - The technology family\n * @param gateFamily - The logical gate function\n * @param inputCount - Number of data inputs (not counting Vcc)\n * @returns Propagation delay in ticks (integer >= 1)\n * @throws {Error} If called with Sandbox family (caller must not invoke for Sandbox)\n * @throws {Error} If input count is unsupported for the given family\n */\nexport function computeGateDelay(\n logicFamily: LogicFamily,\n gateFamily: GateFamily,\n inputCount: number\n): number {\n if (logicFamily === 'Sandbox') {\n throw new Error('computeGateDelay must not be called for Sandbox family');\n }\n\n // NOT and Buffer are constant across both CMOS1 and TTL1\n if (gateFamily === 'NOT') return 1;\n if (gateFamily === 'Buffer') return 2;\n\n // XOR and XNOR are the same across CMOS1 and TTL1\n if (gateFamily === 'XOR') return Math.log2(inputCount) * 2;\n if (gateFamily === 'XNOR') return Math.log2(inputCount) * 2 + 1;\n\n if (logicFamily === 'CMOS1') {\n const log2n = Math.log2(inputCount);\n switch (gateFamily) {\n case 'NAND':\n return log2n;\n case 'NOR':\n return log2n;\n case 'AND':\n return log2n + 1;\n case 'OR':\n return log2n + 1;\n }\n }\n\n if (logicFamily === 'TTL1') {\n let table: Record<number, number>;\n switch (gateFamily) {\n case 'NAND':\n table = TTL1_NAND;\n break;\n case 'AND':\n table = TTL1_AND;\n break;\n case 'NOR':\n table = TTL1_NOR;\n break;\n case 'OR':\n table = TTL1_OR;\n break;\n }\n const delay = table![inputCount];\n if (delay === undefined) {\n throw new Error(`Unsupported input count ${inputCount} for TTL1 ${gateFamily}`);\n }\n return delay;\n }\n\n // Should be unreachable\n throw new Error(`Unsupported logic family: ${logicFamily}`);\n}\n","/**\n * Circuit Class\n *\n * Core Topology object encapsulating and binding all electrical/logical topology elements together\n * Provides the primary API for creating and manipulating topology data\n *\n * @module core/topology\n */\n\nimport {\n type UUID,\n Rotation,\n CameraOptions,\n Position,\n findPositionBestIndex,\n simplifyPositions,\n} from '../utils';\nimport {\n CIRCUIT_FILE_VERSION,\n COMPONENT_TYPE_METADATA,\n ComponentType,\n ENodeSourceType,\n ENodeType,\n type ICircuit,\n type IComponent,\n type IENode,\n type IWire,\n} from './types';\nimport { CircuitOptions } from './CircuitOptions';\nimport { CircuitMetadata } from './CircuitMetadata';\nimport { Component } from './Component';\nimport { ENode } from './ENode';\nimport { Wire } from './Wire';\nimport { computeTransitionSpan } from './delays';\n\n/**\n * Circuit container managing components, ENodes, and wires.\n *\n * The Circuit class provides:\n * - Component management (add/remove with automatic pin ENode creation)\n * - Topology queries (get by ID, enumerate all)\n * - Automatic lifecycle management (cascade deletion, orphan cleanup)\n * - JSON serialization for persistence\n *\n * **Key Principles**:\n * - Users manage Components and Wires; ENodes are managed automatically\n * - Removing a Component cascades to remove its pins and connected wires\n * - Orphaned branching ENodes (no wires) are automatically removed\n * - All operations maintain bidirectional consistency\n *\n * @example\n * ```typescript\n * const circuit = new Circuit();\n *\n * // Add a component at position (10, 20) with 2 pins\n * const lightbulb = circuit.addComponent(\n * new Position(10, 20),\n * new Rotation(90),\n * 2\n * );\n *\n * console.log(lightbulb.id); // UUID\n * console.log(lightbulb.pins); // [pin-uuid-1, pin-uuid-2]\n *\n * // Query components\n * const comp = circuit.getComponent(lightbulb.id);\n * const all = circuit.getAllComponents();\n *\n * // Remove component (cascade deletes pins and wires)\n * circuit.removeComponent(lightbulb.id);\n * ```\n */\nexport class Circuit {\n /**\n * Circuit metadata holding general information.\n * @private\n */\n public metadata: CircuitMetadata;\n\n /**\n * Map of all components in the circuit (UUID → Component).\n * @private\n */\n private components: Map<UUID, Component>;\n\n /**\n * Map of all electrical nodes in the circuit (UUID → ENode).\n * Includes both pin nodes and branching point nodes.\n * @private\n */\n private enodes: Map<UUID, ENode>;\n\n /**\n * Map of all wires in the circuit (UUID → Wire).\n * @private\n */\n private wires: Map<UUID, Wire>;\n\n /**\n * Create a new empty circuit.\n */\n constructor(options: CircuitOptions) {\n this.metadata = new CircuitMetadata(CIRCUIT_FILE_VERSION, options, 10, 10, new CameraOptions());\n\n this.components = new Map();\n this.enodes = new Map();\n this.wires = new Map();\n }\n\n get name(): string {\n return this.metadata.options.name;\n }\n\n set name(value: string) {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new TypeError('Circuit name must be a non-empty string');\n }\n this.metadata.options.name = value;\n }\n\n /**\n * Add a new component to the circuit.\n *\n * Automatically creates pin ENodes for the component and links them\n * bidirectionally. Pin ENode UUIDs are stored in the component's pins array.\n * Pin labels are derived from the ComponentType metadata.\n *\n * @param type - Component type (Battery, Switch, LED, etc.)\n * @param position - Grid position (x, y integers)\n * @param rotation - Orientation angle (integer degrees)\n * @param config - Optional configuration map for component-specific settings\n * @returns The created Component\n * @throws {TypeError} If position/rotation coordinates are not integers\n *\n * @example\n * ```typescript\n * const lightbulb = circuit.addComponent(\n * new Position(10, 20),\n * new Rotation(90),\n * ComponentType.Lightbulb\n * );\n *\n * console.log(lightbulb.type); // ComponentType.Lightbulb\n * console.log(lightbulb.pins.length); // 2\n * console.log(lightbulb.position.x); // 10\n * ```\n */\n addComponent(\n type: ComponentType,\n position: Position,\n rotation: Rotation,\n config?: Map<string, string> | undefined\n ): Component {\n // Get component type metadata\n const metadata = COMPONENT_TYPE_METADATA[type];\n\n // Create component first (to get its ID)\n const component = new Component(type, position, rotation, []);\n if (config) {\n for (const [key, value] of config) {\n component.config.set(key, value);\n }\n }\n\n // If component has defaultLogicFamily config and it is empty, inherit from grid default\n if (component.config.has('defaultLogicFamily') && !component.config.get('defaultLogicFamily')) {\n component.config.set('defaultLogicFamily', this.metadata.options.defaultLogicFamily);\n }\n\n // Resolve transitionSpan from logic family and gate classification\n this.resolveTransitionSpan(component);\n\n // Create pin ENodes for the component using metadata pin labels\n const pins: UUID[] = [];\n for (const [pinLabel, pinMeta] of metadata.pins) {\n const pinNode = new ENode(\n ENodeType.Pin,\n component.id,\n pinLabel,\n undefined, // Pin position derived from component\n pinMeta.sourceType,\n pinMeta.subtype\n );\n\n // Add ENode to circuit\n this.enodes.set(pinNode.id, pinNode);\n\n // Store pin ID\n pins.push(pinNode.id);\n }\n\n // Update component with pin IDs using Object.defineProperty\n // (Component.pins is readonly, but we're in the trusted Circuit context)\n Object.defineProperty(component, 'pins', {\n value: pins,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n // Add component to circuit\n this.components.set(component.id, component);\n\n return component;\n }\n\n /**\n * Resolve and update the transitionSpan config for a component\n * if automatic resolution returns undefined nothing is done on the component\n *\n * @param component - Component to resolve transitionSpan for\n */\n resolveTransitionSpan(component: Component): void {\n if (!component.config.has('transitionSpan')) {\n return;\n }\n const delay = computeTransitionSpan(component);\n if (!!delay) {\n component.config.set('transitionSpan', String(delay));\n }\n }\n\n /**\n * Remove a component from the circuit.\n *\n * **Cascade deletion** removes:\n * - All pin ENodes belonging to the component\n * - All Wires connected to those pins\n *\n * @param id - Component UUID\n * @throws {Error} If component does not exist\n * @returns Object containing arrays of deleted Wires and ENodes IDs\n *\n * @example\n * ```typescript\n * circuit.removeComponent(componentId);\n * // Component, its pins, and connected wires are all removed\n * ```\n */\n removeComponent(id: UUID): {\n deletedWires: UUID[];\n deletedENodes: UUID[];\n } {\n const component = this.components.get(id);\n\n if (!component) {\n throw new Error(`Component ${id} does not exist`);\n }\n\n const deletedWires: UUID[] = [];\n const deletedENodes: UUID[] = [];\n\n // Remove all wires connected to this component's pins\n for (const pinId of component.pins) {\n const enode = this.enodes.get(pinId);\n if (enode) {\n // Remove all wires connected to this pin\n const wireIds = Array.from(enode.wires);\n for (const wireId of wireIds) {\n this.removeWire(wireId);\n deletedWires.push(wireId);\n }\n }\n // Remove the pin ENode\n this.enodes.delete(pinId);\n deletedENodes.push(pinId);\n }\n\n // Remove component from map\n this.components.delete(id);\n return { deletedWires, deletedENodes };\n }\n\n hasComponent(id: UUID): boolean {\n return this.components.has(id);\n }\n\n /**\n * Get a component by ID.\n *\n * @param id - Component UUID\n * @returns The Component or undefined if not found\n *\n * @example\n * ```typescript\n * const component = circuit.getComponent(componentId);\n * if (component) {\n * console.log(component.position);\n * }\n * ```\n */\n getComponent(id: UUID): Component | undefined {\n return this.components.get(id);\n }\n\n /**\n * Get all components in the circuit.\n *\n * Returns a new array on each call (defensive copy).\n *\n * @returns Array of all Components\n *\n * @example\n * ```typescript\n * const components = circuit.getAllComponents();\n * console.log(`Circuit has ${components.length} components`);\n *\n * for (const comp of components) {\n * console.log(comp.id, comp.position);\n * }\n * ```\n */\n getAllComponents(): Component[] {\n return Array.from(this.components.values());\n }\n\n getAllComponentsByType(type: ComponentType): Component[] {\n const result: Component[] = [];\n for (const component of this.components.values()) {\n if (component.type === type) {\n result.push(component);\n }\n }\n return result;\n }\n\n getFirstComponentOfType(type: ComponentType): Component | undefined {\n for (const component of this.components.values()) {\n if (component.type === type) {\n return component;\n }\n }\n return undefined;\n }\n\n /**\n * Get an electrical node by ID.\n *\n * Note: ENodes are automatically managed and not directly created\n * or removed by users.\n *\n * @param id - ENode UUID\n * @returns The ENode or undefined if not found\n *\n * @example\n * ```typescript\n * const component = circuit.addComponent(\n * new Position(10, 20),\n * new Rotation(0),\n * 2\n * );\n *\n * const pinId = component.pins[0];\n * const enode = circuit.getENode(pinId);\n * console.log(enode.type); // ENodeType.Pin\n * ```\n */\n getENode(id: UUID): ENode | undefined {\n return this.enodes.get(id);\n }\n\n /**\n * Get all electrical nodes in the circuit.\n *\n * Includes both pin nodes (from components) and branching point nodes\n * (from wire splits).\n *\n * Returns a new array on each call (defensive copy).\n *\n * @returns Array of all ENodes\n *\n * @example\n * ```typescript\n * const enodes = circuit.getAllENodes();\n * console.log(`Circuit has ${enodes.length} electrical nodes`);\n *\n * for (const enode of enodes) {\n * console.log(enode.id, enode.type);\n * }\n * ```\n */\n getAllENodes(): ENode[] {\n return Array.from(this.enodes.values());\n }\n\n /**\n * Add a branching point electrical node at a specific position.\n *\n * Branching points are used to split wires and create junctions.\n * @param position - Grid position for the branching point\n * @param sourceType - Optional source type (voltage/current)\n * @returns The created ENode\n */\n addBranchingPoint(position: Position, sourceType?: ENodeSourceType): ENode {\n const branchingPoint = new ENode(\n ENodeType.BranchingPoint,\n undefined,\n undefined,\n position,\n sourceType\n );\n\n // Add ENode to circuit\n this.enodes.set(branchingPoint.id, branchingPoint);\n\n return branchingPoint;\n }\n\n /**\n * Remove a branching point electrical node from the circuit.\n * Also removes all wires connected to this branching point if there are ony one or more than 2.\n * In the case there are exactly two wires, they will be merged before removing the branching point.\n *\n * @param id - Branching point ENode UUID\n * @throws {Error} If ENode does not exist or is not a branching point\n */\n removeBranchingPoint(id: UUID): {\n deletedWires?: UUID[] | undefined;\n mergedWires?: UUID[] | undefined;\n newWire?: Wire | undefined;\n } {\n const enode = this.enodes.get(id);\n\n if (!enode) {\n throw new Error(`Enode ${id} does not exist`);\n }\n if (enode.type !== ENodeType.BranchingPoint) {\n throw new Error(\n `Enode ${id} is not a branching point, it must be removed with its component.`\n );\n }\n\n const result = {};\n\n // Remove all wires connected to this branching point\n const wires = this.getWiresByNode(id);\n\n if (wires.length === 1 || wires.length > 2) {\n const deletedWires: UUID[] = [];\n for (const wire of wires) {\n this.removeWire(wire.id);\n deletedWires.push(wire.id);\n }\n Object.assign(result, { deletedWires });\n } else if (wires.length === 2) {\n // Merge the two wires into one\n const wire1 = wires[0]!;\n const wire2 = wires[1]!;\n\n // Determine the two nodes to connect\n const otherNode1 = wire1.node1 === id ? wire1.node2 : wire1.node1;\n const otherNode2 = wire2.node1 === id ? wire2.node2 : wire2.node1;\n\n // compute intermediate positions for the new wire\n const intermediatePositions: Position[] = [];\n if (otherNode1 === wire1.node1) {\n intermediatePositions.push(...wire1.intermediatePositions);\n } else if (otherNode1 === wire1.node2) {\n intermediatePositions.push(...[...wire1.intermediatePositions].reverse());\n }\n intermediatePositions.push(enode.getPosition(this));\n if (otherNode2 === wire2.node1) {\n intermediatePositions.push(...[...wire2.intermediatePositions].reverse());\n } else if (otherNode2 === wire2.node2) {\n intermediatePositions.push(...wire2.intermediatePositions);\n }\n\n // Remove the old wires\n this.removeWire(wire1.id);\n this.removeWire(wire2.id);\n\n // Create new wire connecting the two other nodes\n const newWire = this.addWire(otherNode1, otherNode2, intermediatePositions);\n if (newWire instanceof Error) {\n throw new Error(`Failed to merge wires at branching point ${id}: ${newWire.message}`);\n }\n Object.assign(result, { mergedWires: [wire1.id, wire2.id] });\n Object.assign(result, { newWire: newWire });\n }\n\n // Remove the branching point ENode\n this.enodes.delete(id);\n return result;\n }\n\n /**\n * Add a wire connecting two electrical nodes.\n *\n * Validates that both nodes exist, not a self-connection, and no duplicate.\n * Updates bidirectional references (Wire ↔ ENodes).\n *\n * @param node1 - First ENode UUID\n * @param node2 - Second ENode UUID\n * @param intermediatePositions - Optional path waypoints for rendering\n * @returns The created Wire, or Error if validation fails\n *\n * @example\n * ```typescript\n * const comp1 = circuit.addComponent(new Position(0, 0), new Rotation(0), 1);\n * const comp2 = circuit.addComponent(new Position(10, 10), new Rotation(0), 1);\n *\n * const wire = circuit.addWire(comp1.pins[0], comp2.pins[0]);\n * if (wire instanceof Error) {\n * console.error('Failed:', wire.message);\n * }\n * ```\n */\n addWire(node1: UUID, node2: UUID, intermediatePositions?: Position[]): Wire | Error {\n // Validate self-connection\n if (node1 === node2) {\n return new Error('Cannot create wire connecting node to itself');\n }\n\n // Validate both nodes exist\n const enode1 = this.enodes.get(node1);\n const enode2 = this.enodes.get(node2);\n\n if (!enode1 || !enode2) {\n return new Error('Wire requires at least one existing ENode');\n }\n\n // Check for duplicate wire\n if (this.hasWireBetween(node1, node2)) {\n return new Error('Duplicate wire between same nodes');\n }\n\n // Create wire\n const wire = new Wire(node1, node2, intermediatePositions || []);\n\n // Add wire to circuit\n this.wires.set(wire.id, wire);\n\n // Update bidirectional references: ENode → Wire\n enode1.wires.add(wire.id);\n enode2.wires.add(wire.id);\n\n return wire;\n }\n\n /**\n * Remove a wire from the circuit.\n *\n * @param id - Wire UUID\n * @throws {Error} If wire does not exist\n *\n * @example\n * ```typescript\n * circuit.removeWire(wireId);\n * // Wire is removed\n * ```\n */\n removeWire(id: UUID): void {\n const wire = this.wires.get(id);\n\n if (!wire) {\n throw new Error(`Wire ${id} does not exist`);\n }\n\n // Get connected nodes\n const enode1 = this.enodes.get(wire.node1);\n const enode2 = this.enodes.get(wire.node2);\n\n // Remove wire from nodes' wire sets\n if (enode1) {\n enode1.wires.delete(id);\n }\n if (enode2) {\n enode2.wires.delete(id);\n }\n\n // Remove wire from circuit\n this.wires.delete(id);\n }\n\n /**\n * Split a wire in the circuit.\n *\n * It creates two new wires connected by either the target enode or a new branching point ENode at the specified position.\n * Returns 2 UUIDS of the new wires.\n *\n * @param id - Wire UUID\n * @param position\n * @throws {Error} If wire does not exist\n *\n * @example\n * ```typescript\n * circuit.splitWire(wireId);\n * // Wire and any orphaned branching points are removed\n * ```\n */\n /**\n * Split an existing wire at a position, creating a branching point.\n * The original wire is removed and replaced with two new wires\n * connecting through the new branching point.\n * NB : in the special case where targetEnode belongs to a component where the wire is already connected\n * only one new wire will be created as this method don't allow a wire directly connecting two pins of the same component.\n *\n * @param wireId - Wire to split\n * @param position - Position for the new branching point : no effect if targetEnodeId provided\n * @param targetEnodeId - if provided, the existing enode to split the wire at\n * @returns Object containing the new branching point and an array of the two new wires\n * @throws Error if wireId not found\n */\n splitWire(\n wireId: UUID,\n position: Position,\n targetEnodeId: UUID | null = null\n ): {\n branchingPoint: ENode;\n wires: Array<Wire>;\n } {\n const wire = this.wires.get(wireId);\n\n if (!wire) {\n throw new Error(`Wire ${wireId} does not exist`);\n }\n\n // Get connected nodes\n const enode1 = this.enodes.get(wire.node1);\n const enode2 = this.enodes.get(wire.node2);\n\n if (!enode1 || !enode2) {\n throw new Error(`Wire ${wireId} is connected to non-existent ENodes`);\n }\n\n // computing best intermediate positions for the two new wires\n const fullPositions = [\n enode1.getPosition(this),\n ...wire.intermediatePositions,\n enode2.getPosition(this),\n ];\n const index = findPositionBestIndex(fullPositions, position);\n const positionsWire1 = fullPositions.slice(1, index);\n const positionsWire2 = fullPositions.slice(index, fullPositions.length - 1);\n\n // deleting and dereferencing the old wire\n this.wires.delete(wireId);\n enode1.wires.delete(wireId);\n enode2.wires.delete(wireId);\n\n let eNode: ENode;\n if (targetEnodeId) {\n if (!this.enodes.get(targetEnodeId)) {\n throw new Error(`Target ENode ${targetEnodeId} does not exist`);\n } else {\n eNode = this.enodes.get(targetEnodeId)!;\n }\n } else {\n // Create new branching point ENode at specified position\n eNode = this.addBranchingPoint(position);\n }\n\n const newWires = [];\n\n if (\n (!eNode.component || enode1.component !== eNode.component) &&\n !this.hasWireBetween(enode1.id, eNode.id)\n ) {\n const result = this.addWire(enode1.id, eNode.id, positionsWire1);\n if (result instanceof Wire) {\n this.simplifyWireIntermediatePositions(result.id);\n newWires.push(result);\n } else {\n console.warn(`Failure to create wire at split : ${result.message}`);\n }\n }\n if (\n (!eNode.component || enode2.component !== eNode.component) &&\n !this.hasWireBetween(enode2.id, eNode.id)\n ) {\n const result = this.addWire(eNode.id, enode2.id, positionsWire2);\n if (result instanceof Wire) {\n this.simplifyWireIntermediatePositions(result.id);\n newWires.push(result);\n } else {\n console.warn(`Failure to create wire at split : ${result.message}`);\n }\n }\n\n return {\n branchingPoint: eNode,\n wires: newWires,\n };\n }\n\n getWireBetweenNodes(node1: UUID, node2: UUID): Wire | undefined {\n const enode1 = this.enodes.get(node1);\n if (!enode1) {\n return undefined;\n }\n // Check if any wire from node1 connects to node2\n for (const wireId of enode1.wires) {\n const wire = this.wires.get(wireId);\n if (wire && (wire.node2 === node2 || wire.node1 === node2)) {\n return wire;\n }\n }\n return undefined;\n }\n\n /**\n * Get a wire by ID.\n *\n * @param id - Wire UUID\n * @returns The Wire or undefined if not found\n */\n getWire(id: UUID): Wire | undefined {\n return this.wires.get(id);\n }\n\n /**\n * Get all wires in the circuit.\n *\n * Returns a new array on each call (defensive copy).\n *\n * @returns Array of all Wires\n */\n getAllWires(): Wire[] {\n return Array.from(this.wires.values());\n }\n\n /**\n * Get all wires connected to a specific ENode.\n *\n * @param nodeId - ENode UUID\n * @returns Array of connected Wires, or empty array if node not found\n */\n getWiresByNode(nodeId: UUID): Wire[] {\n const enode = this.enodes.get(nodeId);\n if (!enode) {\n return [];\n }\n\n const wires: Wire[] = [];\n for (const wireId of enode.wires) {\n const wire = this.wires.get(wireId);\n if (wire) {\n wires.push(wire);\n }\n }\n\n return wires;\n }\n\n /**\n * Get all wires connected to a component, e.g to any pin enode of the component.\n *\n * @param componentId - Component UUID\n * @returns Array of connected Wires, or empty array if component not found\n */\n getWiresByComponent(componentId: UUID): Wire[] {\n const component = this.components.get(componentId);\n if (!component) {\n return [];\n }\n const wires: Wire[] = [];\n\n for (const pinId of component.pins) {\n wires.push(...this.getWiresByNode(pinId));\n }\n\n return wires;\n }\n\n /**\n * Get both ENodes connected by a wire.\n *\n * @param wireId - Wire UUID\n * @returns Tuple [node1, node2] or undefined if wire not found\n */\n getNodesByWire(wireId: UUID): [ENode, ENode] | undefined {\n const wire = this.wires.get(wireId);\n if (!wire) {\n return undefined;\n }\n\n const node1 = this.enodes.get(wire.node1);\n const node2 = this.enodes.get(wire.node2);\n\n if (!node1 || !node2) {\n return undefined;\n }\n\n return [node1, node2];\n }\n\n /**\n * Check if a wire already exists between two nodes.\n *\n * Order-independent: returns true for (A, B) or (B, A).\n *\n * @param node1 - First ENode UUID\n * @param node2 - Second ENode UUID\n * @returns true if wire exists, false otherwise\n */\n hasWireBetween(node1: UUID, node2: UUID): boolean {\n const enode1 = this.enodes.get(node1);\n if (!enode1) {\n return false;\n }\n\n // Check if any wire from node1 connects to node2\n for (const wireId of enode1.wires) {\n const wire = this.wires.get(wireId);\n if (wire && (wire.node2 === node2 || wire.node1 === node2)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Find all components with pins among the provided enode IDs set.\n *\n * @param pinIds - Set of pins UUIDs\n * @returns Set of components UUIDs\n */\n getComponentsOfPins(pinIds: Set<UUID>): Set<UUID> {\n const componentIds = new Set<UUID>();\n\n for (const enodeId of pinIds) {\n const enode = this.enodes.get(enodeId);\n if (!!enode?.component) {\n componentIds.add(enode.component);\n }\n }\n return componentIds;\n }\n\n /**\n * Get a component's pin ENode by its label.\n * @param component\n * @param pinLabel\n */\n getComponentPinByLabel(component: Component, pinLabel: string): ENode | undefined {\n let pinIndex = 0;\n const typeMetadata = COMPONENT_TYPE_METADATA[component.type];\n const pinLabels = Array.from(typeMetadata.pins.keys());\n for (const pinId of component.pins) {\n const enode = this.enodes.get(pinId);\n const label = pinLabels[pinIndex];\n if (!label) continue;\n if (enode && label === pinLabel) {\n return enode;\n }\n pinIndex++;\n }\n return undefined;\n }\n\n /**\n * Update the intermediate positions of a wire.\n * Update the wire in place.\n *\n * @param wireId - Wire to update\n * @param intermediatePositions - New intermediate positions\n * @param simplify - Whether to simplify positions by removing collinear points : useful when finalizing wire routing\n * @returns The updated Wire\n * @throws Error if wireId not found\n */\n updateWireIntermediatePositions(\n wireId: UUID,\n intermediatePositions: Position[],\n simplify: boolean = false\n ): Wire {\n const wire = this.wires.get(wireId);\n\n if (!wire) {\n throw new Error(`Wire ${wireId} does not exist`);\n }\n if (simplify) {\n // remove collinear positions if simplify\n const fullPositions = [\n this.enodes.get(wire.node1)!.getPosition(this),\n ...intermediatePositions,\n this.enodes.get(wire.node2)!.getPosition(this),\n ];\n const simplifiedFullPositions = simplifyPositions(fullPositions, 10);\n // remove first and last positions (they are the positions of the nodes)\n wire.intermediatePositions = simplifiedFullPositions.slice(\n 1,\n simplifiedFullPositions.length - 1\n );\n } else {\n wire.intermediatePositions = intermediatePositions;\n }\n\n return wire;\n }\n\n /**\n * Simplify intermediate positions of a wire.\n * Update the wire in place.\n * @param wireId - Wire to simplify\n * @returns The updated Wire\n * @throws Error if wireId not found\n */\n simplifyWireIntermediatePositions(wireId: UUID): Wire {\n const wire = this.wires.get(wireId);\n if (!wire) {\n throw new Error(`Wire ${wireId} does not exist`);\n }\n\n // remove collinear positions if simplify\n const fullPositions = [\n this.enodes.get(wire.node1)!.getPosition(this),\n ...wire.intermediatePositions,\n this.enodes.get(wire.node2)!.getPosition(this),\n ];\n const simplifiedFullPositions = simplifyPositions(fullPositions, 5);\n // remove first and last positions (they are the positions of the nodes)\n wire.intermediatePositions = simplifiedFullPositions.slice(\n 1,\n simplifiedFullPositions.length - 1\n );\n\n wire.intermediatePositions = simplifyPositions(wire.intermediatePositions);\n return wire;\n }\n\n /**\n * Update the source type of an ENode (branching point or component pin).\n * @param enodeId - ENode to update\n * @param sourceType - New source type (null to clear)\n * @throws Error if enodeId not found\n */\n updateENodeSourceType(enodeId: UUID, sourceType: ENodeSourceType | null): void {\n const enode = this.enodes.get(enodeId);\n\n if (!enode) {\n throw new Error(`ENode ${enodeId} does not exist`);\n }\n\n // Update sourceType (ENode.source is mutable)\n enode.source = sourceType || undefined;\n }\n\n /**\n * iterate through all components, enodes and wires positions to get the size that allows to enclose all elements.\n * @param margin - optional margin to add to the size\n * @returns size that allows to enclose all elements plus margin\n * @todo if calls to this method at each build operation ends causes slowness see to optimize by restricting checked elements\n */\n getEnclosingSize(margin: number = 0): number {\n let maxPos = 0;\n for (const component of this.components.values()) {\n maxPos = Math.max(maxPos, Math.abs(component.position.x), Math.abs(component.position.y));\n }\n for (const enode of this.enodes.values()) {\n if (enode.type === ENodeType.Pin) continue; // handled with components\n const pos = enode.position;\n if (!pos) continue;\n maxPos = Math.max(maxPos, Math.abs(pos.x), Math.abs(pos.y));\n }\n for (const wire of this.wires.values()) {\n for (const pos of wire.intermediatePositions) {\n maxPos = Math.max(maxPos, Math.abs(pos.x), Math.abs(pos.y));\n }\n }\n return Math.ceil(maxPos * 2 + Math.max(margin, 0));\n }\n\n /**\n * Serialize circuit to JSON.\n *\n * @returns JSON-serializable object containing all components, enodes, and wires\n *\n * @example\n * ```typescript\n * const json = circuit.toJSON();\n * localStorage.setItem('my-circuit', JSON.stringify(json));\n * ```\n */\n toJSON(): ICircuit {\n return {\n metadata: this.metadata.toJSON(),\n components: this.getAllComponents().map((c) => c.toJSON()),\n enodes: this.getAllENodes().map((e) => e.toJSON()),\n wires: this.getAllWires().map((w) => w.toJSON()),\n };\n }\n\n /**\n * Deserialize circuit from JSON.\n *\n * @param json - Circuit data\n * @returns Circuit instance\n * @throws {Error} If JSON is invalid or violates invariants\n *\n * @example\n * ```typescript\n * const jsonStr = localStorage.getItem('my-circuit');\n * const json = JSON.parse(jsonStr);\n * const circuit = Circuit.fromJSON(json);\n * ```\n */\n static fromJSON(json: ICircuit): Circuit {\n const finalMetadata = CircuitMetadata.fromJSON(json.metadata);\n const circuit = new Circuit(finalMetadata.options);\n circuit.metadata = finalMetadata;\n\n // Restore components\n for (const compData of json.components) {\n const component = Component.fromJSON(compData as IComponent);\n circuit.components.set(component.id, component);\n }\n\n // Restore ENodes\n for (const enodeData of json.enodes) {\n const enode = ENode.fromJSON(enodeData as IENode);\n circuit.enodes.set(enode.id, enode);\n }\n\n // Restore wires (if present)\n if (json.wires) {\n for (const wireData of json.wires) {\n const wire = Wire.fromJSON(wireData as IWire);\n circuit.wires.set(wire.id, wire);\n\n // Restore bidirectional references\n const enode1 = circuit.enodes.get(wire.node1);\n const enode2 = circuit.enodes.get(wire.node2);\n if (enode1) {\n enode1.wires.add(wire.id);\n }\n if (enode2) {\n enode2.wires.add(wire.id);\n }\n }\n }\n\n return circuit;\n }\n}\n","/**\n * Simulation type definitions\n * @module core/simulation\n */\nimport type { UUID } from '../utils';\n\n/**\n * Simulation speed bounds and defaults for ticks per second (TPS).\n * @public\n */\nexport const SIMULATION_SPEED = {\n /**\n * Minimum simulation speed in ticks per second\n */\n MIN_TPS: 1,\n /**\n * Maximum simulation speed in ticks per second\n */\n MAX_TPS: 50,\n /**\n * Default simulation speed in ticks per second\n */\n DEFAULT_TPS: 3,\n /**\n * Default tick interval in milliseconds (1000 / DEFAULT_TPS)\n */\n DEFAULT_INTERVAL_MS: 500,\n} as const;\n\n/**\n * Default transition timing values for components.\n * @public\n */\nexport const TRANSITION_DEFAULTS = {\n /**\n * Default transitionSpan for relays and transistors in ticks (instant transition)\n */\n TRANSITION_SPAN_TICKS: 1,\n /**\n * Default transitionUserSpan for switches in milliseconds\n */\n TRANSITION_USER_SPAN_MS: 200,\n} as const;\n\n/**\n * User command to be executed during simulation.\n * Commands can be queued for future ticks or executed immediately.\n *\n * @public\n */\nexport interface IUserCommand {\n /**\n * Type of command.\n */\n readonly type: 'toggle_switch';\n /**\n * UUID of target component.\n */\n readonly targetId: UUID;\n /**\n * tick when this command was scheduled.\n */\n scheduledAtTick: number;\n /**\n * Extra parameters associated with this command.\n *\n * For `toggle_switch` commands:\n * - `tickCount`: Number of ticks for the switch transition. Computed at toggle time\n * using the formula: `ceil(transitionUserSpan × simulationSpeed / 1000)` with minimum of 1.\n * If not provided, behavior uses default transition timing.\n */\n readonly parameters?: Map<string, string> | null;\n}\n\n/**\n * all reachable nodes and wires from a seed\n */\nexport type IReachabilityResult = {\n nodes: Set<UUID>;\n wires: Set<UUID>;\n};\n\n/**\n * Configuration options for CircuitRunner\n */\nexport interface IRunnerOptions {\n /**\n * Enable historical state tracking.\n * When true, past simulation states are preserved up to historyLimit.\n * When false (default), only current state is retained for better performance.\n * @default false\n */\n enableHistory?: boolean;\n\n /**\n * Maximum number of historical states to retain when enableHistory is true.\n * Uses circular buffer—oldest states are overwritten when limit is reached.\n * Must be a positive integer.\n * @default 1000\n */\n historyLimit?: number;\n}\n\n/**\n * Result statistics of one simulation tick run\n */\nexport interface IRunnerResult {\n startTick: number;\n\n endTick: number;\n\n componentUpdateCount: number;\n\n nodeUpdateCount: number;\n\n wireUpdateCount: number;\n\n processedCommandCount: number;\n\n scheduledEventCount: number;\n\n firedEventCount: number;\n}\n\n/**\n * Scheduled event for delayed component transitions.\n * Events are ordered by readyAtTick in a min-heap priority queue.\n * Events with same readyAtTick are processed in FIFO order (by scheduledAtTick).\n *\n * @public\n */\nexport interface IScheduledEvent {\n /**\n * UUID of target component.\n */\n readonly targetId: UUID;\n /**\n * Tick when this event was scheduled (for FIFO ordering).\n * @readonly\n */\n readonly scheduledAtTick: number;\n /**\n * Tick when this event should be processed.\n * @readonly\n */\n readonly readyAtTick: number;\n /**\n * Indicates the type of this event, eg 'ClosingEnd', 'OpeningEnd', etc.\n */\n readonly type: string;\n /**\n * extra parameters associated with this event.\n */\n readonly parameters?: Map<string, string> | undefined;\n}\n\n/**\n * Dirty elements collected during a tick, returned by getDirtyElements().\n *\n * @public\n */\nexport interface IDirtyElements {\n /**\n * Components that changed state.\n */\n readonly components: ReadonlySet<UUID>;\n\n /**\n * Wires that changed electrical state.\n */\n readonly wires: ReadonlySet<UUID>;\n\n /**\n * ENodes that changed electrical state.\n */\n readonly enodes: ReadonlySet<UUID>;\n}\n","/**\n * Binary electrical state for wires and enodes (connection points)\n * @module core/simulation/states\n * @public\n */\nexport interface INodeElectricalState {\n /**\n * True if voltage is present at this node (potential > 0V).\n * False if node is at ground potential or floating.\n */\n hasVoltage: boolean;\n /**\n * True if current is actively flowing through this node.\n * False if no current flow (open circuit or equilibrium).\n */\n hasCurrent: boolean;\n /**\n * True only if the node is locked from state changes at circuit build time (ex: battery pins or other fixed-voltage/current pinSources).\n * Important: Those nodes should never have their electrical state modified by the simulation controller!\n * Always false for wires\n */\n locked: boolean;\n}\n\n/**\n * Compute the union of multiple electrical states.\n * Useful to derive a combined pin state from two or more pins\n * (e.g. cmd_in + cmd_out → coil state).\n *\n * @param states - Two or more electrical states to combine\n * @returns A new state where hasVoltage/hasCurrent are OR'd across inputs, locked is always false\n */\nexport function unionElectricalStates(...states: INodeElectricalState[]): INodeElectricalState {\n return {\n hasVoltage: states.some((s) => s.hasVoltage),\n hasCurrent: states.some((s) => s.hasCurrent),\n locked: false,\n };\n}\n","/**\n * Complete snapshot of circuit electrical state at a specific simulation tick\n * @module core/simulation\n */\n\nimport type { ComponentState, INodeElectricalState } from './index';\nimport type { UUID } from '../../utils';\n\n/**\n * Represents the complete electrical state of the circuit at a specific time step.\n * Immutable snapshot that can be stored in history.\n *\n * @public\n */\nexport class SimulationState {\n /**\n * Current simulation step number (starts at 0).\n * @readonly\n */\n tick: number;\n\n /**\n * Electrical state for each ENode (component pins and branching points).\n * Key: ENode UUID, Value: INodeElectricalState\n * @readonly\n */\n readonly nodeStates: ReadonlyMap<UUID, INodeElectricalState>;\n\n /**\n * Electrical state for each Wire connecting ENodes.\n * Key: Wire UUID, Value: INodeElectricalState\n * @readonly\n */\n readonly wireStates: ReadonlyMap<UUID, INodeElectricalState>;\n\n /**\n * Component-specific state for each component.\n * Key: Component UUID, Value: ComponentState subclass\n * @readonly\n */\n readonly componentStates: ReadonlyMap<UUID, ComponentState>;\n\n /**\n * Create a new simulation state snapshot.\n *\n * @param tick - Current simulation step number\n */\n constructor(tick: number) {\n if (tick < 0 || !Number.isInteger(tick)) {\n throw new RangeError(`Tick must be a non-negative integer (got ${tick})`);\n }\n\n this.tick = tick;\n this.nodeStates = new Map();\n this.wireStates = new Map();\n this.componentStates = new Map();\n }\n\n setTick(tick: number) {\n this.tick = tick;\n }\n\n /**\n * Create a deep copy of this state for historical storage.\n *\n * @returns Cloned SimulationState\n */\n clone(): SimulationState {\n const clonedState = new SimulationState(this.tick);\n\n const clonedNodeStates: Map<UUID, INodeElectricalState> = new Map();\n for (const [id, state] of this.nodeStates.entries()) {\n clonedNodeStates.set(id, { ...state });\n }\n const clonedWireStates: Map<UUID, INodeElectricalState> = new Map();\n for (const [id, state] of this.wireStates.entries()) {\n clonedWireStates.set(id, { ...state });\n }\n const clonedComponentStates: Map<UUID, ComponentState> = new Map();\n for (const [id, state] of this.componentStates.entries()) {\n clonedComponentStates.set(\n id,\n Object.assign(Object.create(Object.getPrototypeOf(state)), state)\n );\n }\n\n Object.defineProperty(clonedState, 'nodeStates', {\n value: clonedNodeStates,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n Object.defineProperty(clonedState, 'wireStates', {\n value: clonedWireStates,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n Object.defineProperty(clonedState, 'componentStates', {\n value: clonedComponentStates,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n\n return clonedState;\n }\n}\n","/**\n * Base state for all component types\n * @module core/simulation/states\n */\n\nimport type { UUID } from '../../utils/types';\nimport type { INodeElectricalState } from './types';\n\n/**\n * Base class for component simulation state.\n * Extended by specific component types (BatteryState, LEDState, etc.)\n * One instance per component throughout simulation that will be mutated in place.\n *\n * @abstract\n * @public\n */\nexport abstract class ComponentState {\n /**\n * Component UUID this state belongs to.\n * @readonly\n */\n readonly componentId: UUID;\n\n /**\n * Current operational state (varies by component type).\n * Examples: \"on\", \"off\", \"open\", \"closed\", \"activating\", \"active\"\n */\n protected _state: string;\n\n /**\n * Tick when this state started.\n */\n protected _startTick: number;\n\n /**\n * until when this state should last (-1 for no previsional expiration)\n */\n protected _expirationTick: number;\n\n /**\n * previsional nextState (null if current state has no expiration tick)\n */\n protected _nextState: string | null;\n\n /**\n * extra state parameters\n */\n parameters: Map<string, string> = new Map();\n\n /**\n * Pin electrical states, keyed by pin label (e.g. 'cmd_in', 'power_out').\n * Composite keys use '*' separator for unions (e.g. 'cmd_in*cmd_out').\n */\n pinStates: Map<string, INodeElectricalState> = new Map();\n\n /**\n * Create a new component state.\n *\n * @param componentId - UUID of the component\n * @param initialState - Initial operational state\n */\n protected constructor(componentId: UUID, initialState: string) {\n this.componentId = componentId;\n this._state = initialState;\n this._startTick = 0;\n this._expirationTick = -1;\n this._nextState = null;\n }\n\n public get state(): string {\n return this._state;\n }\n\n public setState(state: string, startTick: number): void {\n this._state = state;\n this._startTick = startTick;\n this._expirationTick = -1;\n this._nextState = null;\n }\n\n public get startTick(): number {\n return this._startTick;\n }\n\n public get expirationTick(): number {\n return this._expirationTick;\n }\n\n public get nextState(): string | null {\n return this._nextState;\n }\n\n public get hasExpiration(): boolean {\n return this._expirationTick >= 0 && !!this._nextState && this._nextState !== this.state;\n }\n\n public setNextState(nextState: string, expirationTick: number): void {\n this._nextState = nextState;\n this._expirationTick = expirationTick;\n }\n}\n","/**\n * Battery component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\n\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for Battery components.\n * Batteries are stateless always-on pinSources.\n *\n * @public\n */\nexport class BatteryState extends ComponentState {\n /**\n * Create a new battery state.\n *\n * @param componentId - UUID of the battery component\n */\n constructor(componentId: UUID) {\n super(componentId, 'on');\n }\n}\n","/**\n * Lightbulb component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\n\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for Lightbulb components.\n * Lightbulbs can be \"on\" (emitting light) or \"off\".\n *\n * @public\n */\nexport class LightbulbState extends ComponentState {\n /**\n * Create a new Lightbulb state.\n *\n * @param componentId - UUID of the Lightbulb component\n * @param initialState - Initial operational state (default: \"off\")\n */\n constructor(componentId: UUID, initialState: string = 'off') {\n super(componentId, initialState);\n }\n\n /**\n * Check if Lightbulb is in lit state (on or going_on)\n */\n get isLit(): boolean {\n return this.state === 'on' || this.state === 'goingOn';\n }\n}\n","/**\n * LED component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\n\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for SmallLED components.\n * LEDs can be \"on\" (emitting light) or \"off\".\n *\n * @public\n */\nexport class SmallLEDState extends ComponentState {\n /**\n * Create a new SmallLED state.\n *\n * @param componentId - UUID of the LED component\n * @param initialState - Initial operational state (default: \"off\")\n */\n constructor(componentId: UUID, initialState: string = 'off') {\n super(componentId, initialState);\n }\n\n /**\n * Check if LED is in lit state (on or going_on)\n */\n get isLit(): boolean {\n return this.state === 'on' || this.state === 'goingOn';\n }\n}\n","import { SmallLEDState } from './SmallLEDState';\n\n/**\n * Simulation state for RectangleLED components. Same as SmallLEDState.\n * LEDs can be \"on\" (emitting light) or \"off\".\n *\n * @public\n */\nexport class RectangleLEDState extends SmallLEDState {}\n","/**\n * Relay component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\n\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for mechanical Relay components.\n * Relays can be \"open\", \"closing\", \"closed\", or \"opening\".\n *\n * @public\n */\nexport class RelayState extends ComponentState {\n /**\n * Create a new Relay state.\n *\n * @param componentId - UUID of the Relay component\n * @param initialState - Initial operational state (default: \"open\")\n */\n constructor(componentId: UUID, initialState: string = 'open') {\n super(componentId, initialState);\n }\n\n /**\n * Check if relay is in opening or closing state\n */\n get isInTransition(): boolean {\n return this.state === 'closing' || this.state === 'opening';\n }\n\n /**\n * Check if relay is in closed or closing state\n */\n get isClosed(): boolean {\n return this.state === 'closed' || this.state === 'closing';\n }\n}\n","/**\n * Switch component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\n\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for Switch components.\n * Switches can be \"open\", \"closing\", \"closed\", or \"opening\".\n *\n * @public\n */\nexport class SwitchState extends ComponentState {\n /**\n * Create a new Switch state.\n *\n * @param componentId - UUID of the Switch component\n * @param initialState - Initial operational state (default: \"open\")\n */\n constructor(componentId: UUID, initialState: string = 'open') {\n super(componentId, initialState);\n }\n\n /**\n * Check if switch is in opening or closing state\n */\n get isInTransition(): boolean {\n return this.state === 'closing' || this.state === 'opening';\n }\n\n /**\n * Check if switch is in closed or closing state\n */\n get isClosed(): boolean {\n return this.state === 'closed' || this.state === 'closing';\n }\n}\n","/**\n * Double Switch component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\n\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for DoubleSwitch (SPDT - Single-Pole Double-Throw - switch) components.\n * These switches can be \"input1\", \"1to2\", \"input2\" or \"2to1\"\n *\n * @public\n */\nexport class DoubleThrowSwitchState extends ComponentState {\n /**\n * Create a new double Switch state.\n *\n * @param componentId - UUID of the double Switch component\n * @param initialState - Initial operational state (default: \"input1\")\n */\n constructor(componentId: UUID, initialState: string = 'input1') {\n super(componentId, initialState);\n }\n\n /**\n * Check if switch is in 1to2 or 2to1 state\n */\n get isInTransition(): boolean {\n return this.state === '1to2' || this.state === '2to1';\n }\n}\n","/**\n * Clock component simulation state\n * @module core/simulation/states\n */\nimport type { UUID } from '../../../utils';\nimport { ComponentState } from '../ComponentState';\n\n/**\n * Simulation state for Clock components.\n * Clock output either voltage (LOGIC HIGH) or LOGIC LOW switching periodically\n *\n * @public\n */\nexport class ClockState extends ComponentState {\n /**\n * Create a new Clock state, either gnd or vcc\n *\n * @param componentId - UUID of the Clock component\n */\n constructor(componentId: UUID) {\n super(componentId, 'high');\n }\n}\n","/**\n * Logic gates components simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from '../ComponentState';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for Logic gates components\n * Gates can be \"low\", \"rising\", \"high\", \"falling\" or \"indeterminate\" (if their input is not well-defined)\n *\n * @public\n */\nexport abstract class LogicGateState extends ComponentState {\n /**\n * Create a new Inverter state.\n *\n * @param componentId - UUID of the Inverter component\n * @param initialState - Initial operational state (default: \"low\")\n */\n protected constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n\n /**\n * Check if output is in a rising or falling transition\n */\n get isInTransition(): boolean {\n return this.state === 'rising' || this.state === 'falling';\n }\n\n /**\n * Check if output is high\n */\n get isHigh(): boolean {\n return this.state === 'high';\n }\n}\n","/**\n * Inverter component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for Inverter components\n * Inverters can be \"low\", \"rising\", \"high\", or \"falling\".\n *\n * @public\n */\nexport class InverterState extends LogicGateState {\n /**\n * Create a new Inverter state.\n *\n * @param componentId - UUID of the Inverter component\n * @param initialState - Initial operational state (default: \"low\")\n */\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * NAND Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for NAND Gate components.\n *\n * @public\n */\nexport class NandGateState extends LogicGateState {\n /**\n * Create a new NAND Gate state.\n *\n * @param componentId - UUID of the NAND Gate component\n * @param initialState - Initial operational state (default: \"low\")\n */\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * NAND4 Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for NAND4 Gate components (4 inputs).\n *\n * @public\n */\nexport class Nand4GateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * NAND8 Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for NAND8 Gate components (8 inputs).\n *\n * @public\n */\nexport class Nand8GateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * NOR Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for NOR Gate components.\n *\n * @public\n */\nexport class NorGateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * NOR4 Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for NOR4 Gate components (4 inputs).\n *\n * @public\n */\nexport class Nor4GateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * NOR8 Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for NOR8 Gate components (8 inputs).\n *\n * @public\n */\nexport class Nor8GateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * XOR Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for XOR Gate components.\n *\n * @public\n */\nexport class XorGateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * XOR4 Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for XOR4 Gate components (4 inputs).\n *\n * @public\n */\nexport class Xor4GateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * XOR8 Gate component simulation state\n * @module core/simulation/states\n */\n\nimport { LogicGateState } from './index';\nimport type { UUID } from '../../../utils/types';\n\n/**\n * Simulation state for XOR8 Gate components (8 inputs).\n *\n * @public\n */\nexport class Xor8GateState extends LogicGateState {\n constructor(componentId: UUID, initialState: string = 'low') {\n super(componentId, initialState);\n }\n}\n","/**\n * Registry for component behavior implementations\n * @module core/simulation/behaviors\n */\n\nimport type { IComponentBehavior } from './types';\n\n/**\n * Registry for component behavior implementations.\n * Maps component types to their behavior handlers.\n *\n * This allows the simulation controller to be extended with new component types\n * without modifying core simulation logic.\n *\n * @public\n */\nexport class BehaviorRegistry {\n private behaviors: Map<string, IComponentBehavior>;\n\n /**\n * Create a new empty behavior registry.\n */\n constructor() {\n this.behaviors = new Map();\n }\n\n /**\n * Register a behavior for a component type.\n * Overwrites any existing behavior for the same type.\n *\n * @param behavior - The component behavior to register\n * @throws TypeError if behavior is null/undefined or componentType is empty\n * @returns The registry instance for chaining\n */\n register(behavior: IComponentBehavior): BehaviorRegistry {\n if (!behavior) {\n throw new TypeError('Behavior cannot be null or undefined');\n }\n\n if (!behavior.componentType || behavior.componentType.trim() === '') {\n throw new TypeError('Behavior componentType cannot be empty');\n }\n\n this.behaviors.set(behavior.componentType, behavior);\n return this;\n }\n\n /**\n * Register multiple behaviors at once.\n * Convenience method for bulk registration.\n *\n * @param behaviors - Array of behaviors to register\n */\n registerAll(behaviors: IComponentBehavior[]): void {\n behaviors.forEach((behavior) => this.register(behavior));\n }\n\n /**\n * Get the behavior for a component type.\n *\n * @param componentType - Type identifier (e.g., \"battery\", \"led\")\n * @returns The registered behavior, or undefined if not found\n */\n get(componentType: string): IComponentBehavior | undefined {\n return this.behaviors.get(componentType);\n }\n\n /**\n * Check if a behavior is registered for a component type.\n *\n * @param componentType - Type identifier to check\n * @returns True if behavior is registered\n */\n has(componentType: string): boolean {\n return this.behaviors.has(componentType);\n }\n\n /**\n * Unregister a behavior for a component type.\n *\n * @param componentType - Type identifier to unregister\n * @returns True if behavior was found and removed\n */\n unregister(componentType: string): boolean {\n return this.behaviors.delete(componentType);\n }\n\n /**\n * Clear all registered behaviors.\n */\n clear(): void {\n this.behaviors.clear();\n }\n\n /**\n * Get all registered component types.\n *\n * @returns Array of component type identifiers\n */\n getRegisteredTypes(): string[] {\n return Array.from(this.behaviors.keys());\n }\n\n /**\n * Get count of registered behaviors.\n *\n * @returns Number of registered behaviors\n */\n size(): number {\n return this.behaviors.size;\n }\n}\n","/**\n * Component behavior interface for registry-based extensibility\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../topology/Component';\nimport { ComponentState } from '../states/ComponentState.js';\nimport { type IScheduledEvent, type IUserCommand, TRANSITION_DEFAULTS } from '../types';\nimport type { IBehaviorResult } from './types';\nimport type { INodeElectricalState } from '../states/types';\nimport type { UUID } from '../../utils/types';\nimport {\n COMPONENT_TYPE_METADATA,\n ComponentType,\n ENodeSourceType,\n type IComponentTypeMetadata,\n} from '../../topology/types';\n\n/**\n * to factorize default implementations in component behaviors\n */\nexport abstract class ComponentBehaviorMixin {\n /**\n * Component type this behavior handles (e.g., \"battery\", \"led\", \"switch\").\n * Used as the key in BehaviorRegistry.\n */\n protected readonly _componentType: ComponentType;\n\n constructor(componentType: ComponentType) {\n this._componentType = componentType;\n }\n\n get componentType(): ComponentType {\n return this._componentType;\n }\n\n protected get typeMetadata(): IComponentTypeMetadata {\n const metadata = COMPONENT_TYPE_METADATA[this._componentType];\n if (!metadata) {\n throw new Error(`Unknown metadata for Component type ${this._componentType}`);\n }\n return metadata;\n }\n\n protected getPinStates(\n component: Component,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>\n ): Map<string, INodeElectricalState> {\n const pinStates: Map<string, INodeElectricalState> = new Map();\n for (const pinId of component.pins) {\n pinStates.set(component.getPinLabel(pinId)!, nodeStates.get(pinId as UUID)!);\n }\n return pinStates;\n }\n\n protected getChangedPins(\n newPinStates: Map<string, INodeElectricalState>,\n prevPinStates: Map<string, INodeElectricalState>\n ): Set<string> {\n const changedPins = new Set<string>();\n\n for (const [key, newState] of newPinStates) {\n if (!prevPinStates.has(key)) {\n continue;\n }\n const prevState = prevPinStates.get(key);\n if (\n newState.hasVoltage !== prevState?.hasVoltage ||\n newState.hasCurrent !== prevState?.hasCurrent\n ) {\n changedPins.add(key);\n }\n }\n return changedPins;\n }\n\n /**\n * Default: no custom onStart behavior\n * @param _component\n * @param _componentState\n */\n onStart(_component: Component, _componentState: ComponentState): IBehaviorResult | null {\n return null;\n }\n\n /**\n * Default: nothing happens\n * @param _component\n * @param componentState\n * @param _nodeStates\n * @param _targetTick\n */\n onPinsChange(\n _component: Component,\n componentState: ComponentState,\n _nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n _targetTick: number\n ): IBehaviorResult {\n return {\n componentState: componentState,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n /**\n * Default: no conductivity between pins\n * @param _component\n * @param _state\n * @param _conductivityType\n * @param _pinId\n * @param _otherPinId\n */\n allowConductivity(\n _component: Component,\n _state: ComponentState,\n _conductivityType: ENodeSourceType,\n _pinId: string,\n _otherPinId: string\n ): boolean {\n return false;\n }\n\n onUserCommand(\n _component: Component,\n state: ComponentState,\n _command: IUserCommand\n ): IBehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n _event: IScheduledEvent\n ): IBehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n}\n\n/**\n * Get the transition span from component config.\n * @param config - Component config map\n * @returns Number of ticks for transition (minimum 1)\n */\nexport function getTransitionSpan(config: Map<string, string>): number {\n const value = parseInt(config.get('transitionSpan') || '', 10);\n if (isNaN(value) || value < 1) {\n return TRANSITION_DEFAULTS.TRANSITION_SPAN_TICKS;\n }\n return value;\n}\n","/**\n * Battery component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport { Component } from '../../../topology/Component';\nimport { ComponentBehaviorMixin } from '../ComponentBehavior';\nimport { BatteryState } from '../../states/basic/BatteryState';\nimport type { ComponentState } from '../../states/ComponentState';\nimport type { IComponentBehavior } from '../types';\nimport { ComponentType } from '../../../topology/types';\n\nexport class BatteryBehavior extends ComponentBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Battery);\n }\n\n /**\n * Create initial state for a battery.\n *\n * @param component - The Battery component\n * @returns Battery Initial state (always active and delivering voltage)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for BatteryBehavior: ${component.type}`);\n }\n return new BatteryState(component.id);\n }\n}\n","import type { Component } from '../../../topology/Component';\nimport { ComponentState } from '../../states/ComponentState.js';\nimport { type IScheduledEvent, TRANSITION_DEFAULTS } from '../../types';\nimport { ComponentBehaviorMixin, getTransitionSpan } from '../ComponentBehavior';\nimport { ENodeSourceType } from '../../../topology/types';\nimport type { IBehaviorResult } from '../types';\n\n/**\n * to factorize behaviors of bipolar components emitting light (lightbulb/ LEDs even if it's a big simplification...)\n */\nexport abstract class BipolarLightEmitterBehaviorMixin extends ComponentBehaviorMixin {\n protected getBehavior(\n component: Component,\n state: ComponentState,\n activationCondition: boolean,\n targetTick: number\n ): IBehaviorResult {\n let hasChanged = false;\n const scheduledEvents: IScheduledEvent[] = [];\n\n const transitionSpan = getTransitionSpan(component.config);\n const span =\n state.expirationTick < 1 ? transitionSpan : Math.max(targetTick - state.startTick, 1);\n\n if (activationCondition) {\n if (state.state === 'off' || state.state === 'goingOff') {\n hasChanged = true;\n state.setState('goingOn', targetTick);\n state.setNextState('on', targetTick + span);\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'GoingOnEnd',\n parameters: undefined,\n });\n }\n } else {\n if (state.state === 'on' || state.state === 'goingOn') {\n hasChanged = true;\n state.setState('goingOff', targetTick);\n state.setNextState('off', targetTick + span);\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'GoingOffEnd',\n parameters: undefined,\n });\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: true,\n scheduledEvents: scheduledEvents,\n };\n }\n\n override allowConductivity(\n _component: Component,\n _state: ComponentState,\n _conductivityType: ENodeSourceType,\n _pinId: string,\n _otherPinId: string\n ): boolean {\n return true;\n }\n\n override onEventFiring(\n _component: Component,\n state: ComponentState,\n event: IScheduledEvent\n ): IBehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'GoingOffEnd') {\n if (state.state !== 'off') {\n hasChanged = true;\n state.setState('off', event.readyAtTick);\n }\n } else if (event.type === 'GoingOnEnd') {\n if (state.state !== 'on') {\n hasChanged = true;\n state.setState('on', event.readyAtTick);\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n}\n\n/**\n * Get the tick count from command parameters.\n * @param parameters - Command parameters map\n * @returns Number of ticks for transition (minimum 1)\n */\nexport function getTickCount(parameters: Map<string, string> | null | undefined): number {\n if (!parameters) {\n return TRANSITION_DEFAULTS.TRANSITION_SPAN_TICKS;\n }\n const value = parseInt(parameters.get('tickCount') || '', 10);\n if (isNaN(value) || value < 1) {\n return TRANSITION_DEFAULTS.TRANSITION_SPAN_TICKS;\n }\n return value;\n}\n","/**\n * lightbulb behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { LightbulbState } from '../../states/basic/LightbulbState';\nimport { BipolarLightEmitterBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport { unionElectricalStates, type INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\nexport class LightbulbBehavior\n extends BipolarLightEmitterBehaviorMixin\n implements IComponentBehavior\n{\n constructor() {\n super(ComponentType.Lightbulb);\n }\n\n /**\n * Create initial state for a lightbulb.\n *\n * @param component - The lightbulb component\n * @returns lightbulbInitial state (always active and delivering voltage)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for lightbulbBehavior: ${component.type}`);\n }\n return new LightbulbState(component.id);\n }\n\n /**\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const union = unionElectricalStates(newPinStates.get('pin1')!, newPinStates.get('pin2')!);\n const activationCondition = union.hasVoltage && union.hasCurrent;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * RectangleLED component behavior implementation (just an extension of SmallLEDBehavior)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { RectangleLEDState } from '../../states/basic/RectangleLEDState';\nimport { unionElectricalStates, type INodeElectricalState } from '../../states';\nimport { BipolarLightEmitterBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\nexport class RectangleLEDBehavior\n extends BipolarLightEmitterBehaviorMixin\n implements IComponentBehavior\n{\n constructor() {\n super(ComponentType.RectangleLED);\n }\n\n /**\n * Create initial state for a RectangleLED.\n *\n * @param component - The smallLED component\n * @returns LED Initial state (always active and delivering voltage)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for RectangleLEDBehavior: ${component.type}`);\n }\n return new RectangleLEDState(component.id);\n }\n\n /**\n * only symmetrical behavior of LEDS is handled for now\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const union = unionElectricalStates(newPinStates.get('pin1')!, newPinStates.get('pin2')!);\n const activationCondition = union.hasVoltage && union.hasCurrent;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * relay component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { type IScheduledEvent, TRANSITION_DEFAULTS } from '../../types';\nimport { ComponentBehaviorMixin } from '../ComponentBehavior';\nimport { RelayState } from '../../states/basic/RelayState';\n\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport { unionElectricalStates, type INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType, ENodeSourceType } from '../../../topology/types';\n\n/**\n * Get the transition span from component config.\n * @param config - Component config map\n * @returns Number of ticks for transition (minimum 1)\n */\nfunction getTransitionSpan(config: Map<string, string>): number {\n const value = parseInt(config.get('transitionSpan') || '', 10);\n if (isNaN(value) || value < 1) {\n return TRANSITION_DEFAULTS.TRANSITION_SPAN_TICKS;\n }\n return value;\n}\n\n/**\n * Behavior implementation for relays components.\n *\n * @public\n */\nexport class RelayBehavior extends ComponentBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Relay);\n }\n\n /**\n * Create initial state for a relay.\n *\n * @param component - The Relay component\n * @returns Relay Initial state (open by default)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for RelayBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'closed' : 'open';\n return new RelayState(component.id, state);\n }\n\n override allowConductivity(\n component: Component,\n state: ComponentState,\n _conductivityType: ENodeSourceType,\n pinId: string,\n otherPinId: string\n ): boolean {\n if (pinId === otherPinId) return true;\n const pinLabel = component.getPinLabel(pinId);\n const otherPinLabel = component.getPinLabel(otherPinId);\n if (!pinLabel || !otherPinLabel) return false;\n const pinLabels = [pinLabel, otherPinLabel];\n\n if (pinLabels.includes('cmd_in') && pinLabels.includes('cmd_out')) {\n return true;\n }\n if (pinLabels.includes('power_in') && pinLabels.includes('power_out')) {\n return state.state === 'closed' || state.state === 'opening';\n }\n return false;\n }\n\n /**\n * Relay cmd pins need to have voltage and current so that relay contactor stays closed\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n newPinStates.set(\n 'cmd_in*cmd_out',\n unionElectricalStates(newPinStates.get('cmd_in')!, newPinStates.get('cmd_out')!)\n );\n newPinStates.set(\n 'power_in*power_out',\n unionElectricalStates(newPinStates.get('power_in')!, newPinStates.get('power_out')!)\n );\n const prevPinStates = state.pinStates;\n state.pinStates = newPinStates;\n const changedPins = this.getChangedPins(newPinStates, prevPinStates);\n\n const cmdUnion = newPinStates.get('cmd_in*cmd_out')!;\n const isCommanded = cmdUnion.hasVoltage && cmdUnion.hasCurrent;\n const shouldBeClosed =\n component.config.get('activationLogic') === 'negative' ? !isCommanded : isCommanded;\n\n let hasChanged = changedPins.size > 0;\n const scheduledEvents: IScheduledEvent[] = [];\n const transitionSpan = getTransitionSpan(component.config);\n\n if (shouldBeClosed) {\n if (state.state === 'open' || state.state === 'opening') {\n // test to handle input transitions faster than component's own transitionSpan\n let span =\n state.state === 'open' ? transitionSpan : Math.max(targetTick - state.startTick, 1);\n hasChanged = true;\n state.setState('closing', targetTick);\n state.setNextState('closed', targetTick + span);\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'ClosingEnd',\n parameters: new Map([['exclusive', 'true']]),\n });\n }\n } else {\n if (state.state === 'closed' || state.state === 'closing') {\n // test to handle input transitions faster than component's own transitionSpan\n let span =\n state.state === 'closed' ? transitionSpan : Math.max(targetTick - state.startTick, 1);\n hasChanged = true;\n state.setState('opening', targetTick);\n state.setNextState('open', targetTick + span);\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'OpeningEnd',\n parameters: new Map([['exclusive', 'true']]),\n });\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: hasChanged,\n scheduledEvents: scheduledEvents,\n };\n }\n\n override onEventFiring(\n _component: Component,\n state: ComponentState,\n event: IScheduledEvent\n ): IBehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'ClosingEnd') {\n if (state.state !== 'closed') {\n state.setState('closed', event.readyAtTick);\n hasChanged = true;\n }\n } else if (event.type === 'OpeningEnd') {\n if (state.state !== 'open') {\n state.setState('open', event.readyAtTick);\n hasChanged = true;\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * LED component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport { SmallLEDState } from '../../states/basic/SmallLEDState';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { BipolarLightEmitterBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport { unionElectricalStates, type INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\nexport class SmallLEDBehavior\n extends BipolarLightEmitterBehaviorMixin\n implements IComponentBehavior\n{\n constructor() {\n super(ComponentType.SmallLED);\n }\n\n /**\n * Create initial state for a smallLED.\n *\n * @param component - The smallLED component\n * @returns LED Initial state (always active and delivering voltage)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for SmallLEDBehavior: ${component.type}`);\n }\n return new SmallLEDState(component.id);\n }\n\n /**\n * only symmetrical behavior of LEDS is handled for now\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const union = unionElectricalStates(newPinStates.get('pin1')!, newPinStates.get('pin2')!);\n const activationCondition = union.hasVoltage && union.hasCurrent;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * switch component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState, INodeElectricalState } from '../../states';\nimport { SwitchState } from '../../states';\nimport type { IScheduledEvent, IUserCommand } from '../../types';\nimport { ComponentBehaviorMixin, getTransitionSpan } from '../ComponentBehavior';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport { ComponentType, ENodeSourceType } from '../../../topology/types';\nimport type { UUID } from '../../../utils';\n\n/**\n * Behavior implementation for switches components.\n *\n * @public\n */\nexport class SwitchBehavior extends ComponentBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Switch);\n }\n\n /**\n * Create initial state for a switch.\n *\n * @param component - The Switch component\n * @returns Switch Initial state (open by default)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for SwitchBehavior: ${component.type}`);\n }\n const state = component.config.get('initialState') || 'open';\n return new SwitchState(component.id, state);\n }\n\n override allowConductivity(\n _component: Component,\n _state: ComponentState,\n _conductivityType: ENodeSourceType,\n _pinId: string,\n _otherPinId: string\n ): boolean {\n return _state.state === 'closed' || _state.state === 'opening';\n }\n\n /**\n * used for contactor color change\n * @param component\n * @param state\n * @param nodeStates\n * @param _targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n _targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n const prevPinStates = state.pinStates;\n state.pinStates = newPinStates;\n const changedPins = this.getChangedPins(newPinStates, prevPinStates);\n\n if (changedPins.size < 1 || !changedPins.has('output')) {\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n override onUserCommand(\n component: Component,\n state: ComponentState,\n command: IUserCommand\n ): IBehaviorResult {\n let hasChanged = false;\n const scheduledEvents: IScheduledEvent[] = [];\n\n const transitionSpan = getTransitionSpan(component.config);\n\n if (command.type === 'toggle_switch' && ['open', 'closed'].includes(state.state)) {\n state.setState(state.state === 'open' ? 'closing' : 'opening', command.scheduledAtTick);\n state.setNextState(\n state.state === 'closing' ? 'closed' : 'open',\n command.scheduledAtTick + transitionSpan\n );\n hasChanged = true;\n\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: state.state === 'closing' ? 'ClosingEnd' : 'OpeningEnd',\n parameters: new Map([['exclusive', 'true']]),\n });\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: true,\n scheduledEvents: scheduledEvents,\n };\n }\n\n override onEventFiring(\n _component: Component,\n state: ComponentState,\n event: IScheduledEvent\n ): IBehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'ClosingEnd') {\n if (state.state !== 'closed') {\n state.setState('closed', event.readyAtTick);\n hasChanged = true;\n }\n } else if (event.type === 'OpeningEnd') {\n if (state.state !== 'open') {\n state.setState('open', event.readyAtTick);\n hasChanged = true;\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * Double switch component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport {\n type ComponentState,\n DoubleThrowSwitchState,\n type INodeElectricalState,\n} from '../../states';\nimport type { IScheduledEvent, IUserCommand } from '../../types';\nimport { ComponentBehaviorMixin, getTransitionSpan } from '../ComponentBehavior';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport { ComponentType, ENodeSourceType } from '../../../topology/types';\nimport type { UUID } from '../../../utils';\n\n/**\n * Behavior implementation for switches components.\n *\n * @public\n */\nexport class DoubleThrowSwitchBehavior\n extends ComponentBehaviorMixin\n implements IComponentBehavior\n{\n constructor() {\n super(ComponentType.DoubleThrowSwitch);\n }\n\n /**\n * Create initial state for a double throw switch (SPDT).\n *\n * @param component - The double Switch component\n * @returns double Switch Initial state (input1 by default)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for DoubleThrowSwitchBehavior: ${component.type}`);\n }\n const state = component.config.get('initialState') || 'input1';\n return new DoubleThrowSwitchState(component.id, state);\n }\n\n override allowConductivity(\n component: Component,\n state: ComponentState,\n _conductivityType: ENodeSourceType,\n pinId: string,\n otherPinId: string\n ): boolean {\n if (pinId === otherPinId) return true;\n const pinLabel = component.getPinLabel(pinId);\n const otherPinLabel = component.getPinLabel(otherPinId);\n if (!pinLabel || !otherPinLabel) return false;\n const pinLabels = [pinLabel, otherPinLabel];\n\n if (pinLabels.includes('output') && pinLabels.includes('input1')) {\n return state.state === 'input1' || state.state === '1to2';\n }\n if (pinLabels.includes('output') && pinLabels.includes('input2')) {\n return state.state === 'input2' || state.state === '2to1';\n }\n return false;\n }\n\n /**\n * used for contactor color change\n * @param component\n * @param state\n * @param nodeStates\n * @param _targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n _targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n const prevPinStates = state.pinStates;\n state.pinStates = newPinStates;\n const changedPins = this.getChangedPins(newPinStates, prevPinStates);\n\n if (changedPins.size < 1 || !changedPins.has('output')) {\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n override onUserCommand(\n component: Component,\n state: ComponentState,\n command: IUserCommand\n ): IBehaviorResult {\n let hasChanged = false;\n const scheduledEvents: IScheduledEvent[] = [];\n\n const transitionSpan = getTransitionSpan(component.config);\n\n if (command.type === 'toggle_switch' && ['input1', 'input2'].includes(state.state)) {\n state.setState(state.state === 'input1' ? '1to2' : '2to1', command.scheduledAtTick);\n state.setNextState(\n state.state === '1to2' ? 'input2' : 'input1',\n command.scheduledAtTick + transitionSpan\n );\n hasChanged = true;\n\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: state.state === '1to2' ? 'ContactedInput2' : 'ContactedInput1',\n parameters: new Map([['exclusive', 'true']]),\n });\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: true,\n scheduledEvents: scheduledEvents,\n };\n }\n\n override onEventFiring(\n _component: Component,\n state: ComponentState,\n event: IScheduledEvent\n ): IBehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'ContactedInput2') {\n if (state.state !== 'input2') {\n state.setState('input2', event.readyAtTick);\n hasChanged = true;\n }\n } else if (event.type === 'ContactedInput1') {\n if (state.state !== 'input1') {\n state.setState('input1', event.readyAtTick);\n hasChanged = true;\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * Clock component behavior implementation\n * @module core/simulation/behaviors\n */\nimport { Component } from '../../../topology/Component';\nimport { ComponentBehaviorMixin } from '../ComponentBehavior';\nimport { type ComponentState } from '../../states/ComponentState';\nimport type { IComponentBehavior, IBehaviorResult } from '../types';\nimport { ComponentType, ENodeSourceType } from '../../../topology/types';\nimport { ClockState } from '../../states/basic/ClockState';\n\nimport { type IScheduledEvent } from '../../types';\n\nexport class ClockBehavior extends ComponentBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Clock);\n }\n\n /**\n * Create initial state for a Clock.\n *\n * @param component - The Clock component\n * @returns Clock Initial state (needle rotation)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for ClockBehavior: ${component.type}`);\n }\n const state = new ClockState(component.id);\n const startHigh = component.config.get('startHigh') == 'true';\n state.setState(startHigh ? 'high' : 'low', 0);\n const halfPeriod = Number(component.config.get('halfPeriod'));\n state.setNextState(startHigh ? 'low' : 'high', halfPeriod);\n\n return state;\n }\n\n override allowConductivity(\n component: Component,\n state: ComponentState,\n _conductivityType: ENodeSourceType,\n pinId: string,\n otherPinId: string\n ): boolean {\n if (pinId === otherPinId) return true;\n const pinLabel = component.getPinLabel(pinId);\n const otherPinLabel = component.getPinLabel(otherPinId);\n if (!pinLabel || !otherPinLabel) return false;\n const pinLabels = [pinLabel, otherPinLabel];\n\n if (pinLabels.includes('gnd') && pinLabels.includes('vcc')) {\n return false;\n }\n\n if (pinLabels.includes('gnd') && pinLabels.includes('output')) {\n const result = state.state === 'low';\n //console.log('clock conductivity gnd-output', state.state, result);\n return result;\n }\n\n if (pinLabels.includes('vcc') && pinLabels.includes('output')) {\n const result = state.state === 'high';\n //console.warn('clock conductivity vcc-output', state.state, result);\n return result;\n }\n return false;\n }\n\n /**\n * Clock onStart allows to bootstrap cycling\n * @param component\n * @param state\n */\n override onStart(component: Component, state: ComponentState): IBehaviorResult | null {\n const targetTick = 0;\n const halfPeriod = Number(component.config.get('halfPeriod'));\n //console.log('onStart', targetTick);\n state.setNextState(state.state === 'high' ? 'low' : 'high', targetTick + halfPeriod);\n\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: true,\n scheduledEvents: [\n {\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'tick',\n parameters: new Map([['exclusive', 'true']]),\n },\n ],\n };\n }\n\n override onEventFiring(\n component: Component,\n state: ComponentState,\n event: IScheduledEvent\n ): IBehaviorResult {\n if (event.type !== 'tick') {\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n\n const halfPeriod = Number(component.config.get('halfPeriod'));\n state.setState(state.state === 'high' ? 'low' : 'high', event.readyAtTick);\n state.setNextState(state.state === 'high' ? 'low' : 'high', event.readyAtTick + halfPeriod);\n\n //console.warn(`Clock ticking at ${event.readyAtTick} to ${state.state}`);\n\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: true,\n scheduledEvents: [\n {\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'tick',\n parameters: new Map([['exclusive', 'true']]),\n },\n ],\n };\n }\n}\n","import { ENodeSourceType } from '../../../topology/types';\nimport type { Component } from '../../../topology/Component';\nimport { type INodeElectricalState } from '../../states/types';\nimport { ComponentState } from '../../states/ComponentState.js';\nimport { type IScheduledEvent } from '../../types';\nimport { ComponentBehaviorMixin, getTransitionSpan } from '../ComponentBehavior';\nimport type { IBehaviorResult } from '../types';\n\n/**\n * to factorize default implementations in logic gates behaviors\n */\nexport abstract class LogicGateBehaviorMixin extends ComponentBehaviorMixin {\n /**\n * default return for all logic gates when vcc fails -> go low immediately\n * @param state\n * @param pinStates\n * @protected\n */\n protected vccGuardBehavior(\n state: ComponentState,\n pinStates: Map<string, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult | null {\n const vccVoltage = pinStates.get('vcc')!.hasVoltage;\n if (vccVoltage) {\n return null;\n }\n\n let hasChanged = false;\n let shouldCancelPending = false;\n const previousState = state.state;\n // go low immediately if no voltage\n if (previousState !== 'low') {\n state.setState('low', targetTick);\n hasChanged = true;\n shouldCancelPending = true;\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: shouldCancelPending,\n scheduledEvents: [],\n };\n }\n\n /**\n * guard scanning all inputs of logic gates to detect if Any has:\n * - both voltage and ground hence with established flowing current\n * - neither voltage nor ground\n * it makes a not well-defined input between LOW and HIGH\n * in that case gate goes to state indeterminate and output nothing too\n * @param state\n * @param pinStates\n * @param targetTick\n * @protected\n */\n protected nonLogicInputGuardBehavior(\n state: ComponentState,\n pinStates: Map<string, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult | null {\n let activateGuard = false;\n\n const pinsMeta = this.typeMetadata.pins;\n for (const [pinLabel, pinState] of pinStates) {\n if (!pinsMeta.has(pinLabel)) continue;\n const pinMeta = pinsMeta.get(pinLabel);\n if (!pinMeta) continue; // shouldn't occur but here as technical let pass\n if (pinMeta?.subtype !== 'logicInput') continue;\n // case both voltage and ground\n if (pinState.hasVoltage && pinState.hasCurrent) {\n activateGuard = true;\n break;\n }\n // case neither voltage nor ground\n if (!pinState.hasVoltage && !pinState.hasCurrent) {\n activateGuard = true;\n break;\n }\n }\n\n if (!activateGuard) {\n return null;\n }\n\n let hasChanged = false;\n let shouldCancelPending = false;\n const previousState = state.state;\n // go indeterminate immediately\n if (previousState !== 'indeterminate') {\n state.setState('indeterminate', targetTick);\n hasChanged = true;\n shouldCancelPending = true;\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: shouldCancelPending,\n scheduledEvents: [],\n };\n }\n\n protected getBehavior(\n component: Component,\n state: ComponentState,\n activationCondition: boolean,\n targetTick: number\n ): IBehaviorResult {\n // technical guard clause: if state isn't a known value it's considered low (shouldn't happen but allow to simplify logic beneath)\n if (!['low', 'rising', 'high', 'falling', 'indeterminate'].includes(state.state)) {\n state.setState('low', targetTick);\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: true, // goes back to low immediately and cancel pending RisingComplete event\n scheduledEvents: [],\n };\n }\n\n const transitionSpan = getTransitionSpan(component.config);\n const span =\n state.expirationTick < 1 ? transitionSpan : Math.max(targetTick - state.startTick, 1);\n\n if (activationCondition) {\n if (state.state === 'low' || state.state === 'falling' || state.state === 'indeterminate') {\n state.setState('rising', targetTick);\n state.setNextState('high', targetTick + span);\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: true,\n scheduledEvents: [\n {\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'RisingComplete',\n parameters: undefined,\n },\n ],\n };\n }\n if (state.state === 'rising' || state.state === 'high') {\n // still rising or high\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n }\n // case should deactivate\n if (state.state === 'falling' || state.state === 'low') {\n // still falling or low\n return {\n componentState: state,\n hasChanged: false,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n if (state.state === 'high' || state.state === 'rising' || state.state === 'indeterminate') {\n state.setState('falling', targetTick);\n state.setNextState('low', targetTick + span);\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: true,\n scheduledEvents: [\n {\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.expirationTick,\n type: 'FallingComplete',\n parameters: undefined,\n },\n ],\n };\n }\n // last case: shouldn't arrive here\n state.setState('low', targetTick);\n return {\n componentState: state,\n hasChanged: true,\n shouldCancelPending: true, // goes back to low immediately and cancel pending RisingComplete event\n scheduledEvents: [],\n };\n }\n\n override allowConductivity(\n component: Component,\n state: ComponentState,\n _conductivityType: ENodeSourceType,\n pinId: string,\n otherPinId: string\n ): boolean {\n if (pinId === otherPinId) return true;\n const pinLabel = component.getPinLabel(pinId);\n const otherPinLabel = component.getPinLabel(otherPinId);\n if (!pinLabel || !otherPinLabel) return false;\n const pinLabels = [pinLabel, otherPinLabel];\n\n if (pinLabels.includes('vcc') && pinLabels.includes('output')) {\n return state.state === 'high' || state.state === 'falling';\n }\n if (pinLabels.includes('gnd') && pinLabels.includes('output')) {\n return state.state === 'low' || state.state === 'rising';\n }\n return false;\n }\n\n override onEventFiring(\n _component: Component,\n state: ComponentState,\n event: IScheduledEvent\n ): IBehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'RisingComplete') {\n if (state.state !== 'high') {\n hasChanged = true;\n state.setState('high', event.readyAtTick);\n }\n } else if (event.type === 'FallingComplete') {\n if (state.state !== 'low') {\n hasChanged = true;\n state.setState('low', event.readyAtTick);\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n shouldCancelPending: false,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * Inverter component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport { type ComponentState } from '../../states/ComponentState';\nimport { InverterState } from '../../states/gates/InverterState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for Inverters components.\n *\n * @public\n */\nexport class InverterBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Inverter);\n }\n\n /**\n * Create initial state for a Inverter.\n *\n * @param component - The Inverter component\n * @returns Inverter Initial state (HIGH if input LOW, LOW if input LOW for positive activation logic)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for InverterBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new InverterState(component.id, state);\n }\n\n /**\n * Inverter needs LOW on input to drive the output HIGH, and on the contrary Buffer needs HIGH on input to output HIGH\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const isCommanded = newPinStates.get('input')!.hasVoltage;\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !isCommanded : isCommanded;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * NAND Gate component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { NandGateState } from '../../states/gates/NandGateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for NAND Gate components.\n * With negative (default) activationLogic: NAND gate (output high when ANY input is low).\n * With positive activationLogic: AND gate (output high when ALL inputs are high).\n *\n * @public\n */\nexport class NandGateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.NandGate);\n }\n\n /**\n * Create initial state for an NAND Gate.\n *\n * @param component - The NAND Gate component\n * @returns Initial state (low by default, high for negative activation logic)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for NandGateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new NandGateState(component.id, state);\n }\n\n /**\n * NAND gate output goes high when ANY inputs LACK voltage.\n * With positive activationLogic (AND), output goes high when ALL inputs HAS voltage.\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const allInputsHigh =\n newPinStates.get('input1')!.hasVoltage && newPinStates.get('input2')!.hasVoltage;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !allInputsHigh : allInputsHigh;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * NAND4 Gate component behavior implementation (4 inputs)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { Nand4GateState } from '../../states/gates/Nand4GateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for NAND4 Gate components (4 inputs).\n * With negative (default) activationLogic: NAND gate (output high when ANY input is low).\n * With positive activationLogic: AND gate (output high when ALL 4 inputs are high).\n *\n * @public\n */\nexport class Nand4GateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Nand4Gate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for Nand4GateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new Nand4GateState(component.id, state);\n }\n\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const allInputsHigh =\n newPinStates.get('input1')!.hasVoltage &&\n newPinStates.get('input2')!.hasVoltage &&\n newPinStates.get('input3')!.hasVoltage &&\n newPinStates.get('input4')!.hasVoltage;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !allInputsHigh : allInputsHigh;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * NAND8 Gate component behavior implementation (8 inputs)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { Nand8GateState } from '../../states/gates/Nand8GateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states/types';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for NAND8 Gate components (8 inputs).\n * With negative (default) activationLogic: NAND gate (output high when ANY input is low).\n * With positive activationLogic: AND gate (output high when ALL 8 inputs are high).\n *\n * @public\n */\nexport class Nand8GateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Nand8Gate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for Nand8GateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new Nand8GateState(component.id, state);\n }\n\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const allInputsHigh =\n newPinStates.get('input1')!.hasVoltage &&\n newPinStates.get('input2')!.hasVoltage &&\n newPinStates.get('input3')!.hasVoltage &&\n newPinStates.get('input4')!.hasVoltage &&\n newPinStates.get('input5')!.hasVoltage &&\n newPinStates.get('input6')!.hasVoltage &&\n newPinStates.get('input7')!.hasVoltage &&\n newPinStates.get('input8')!.hasVoltage;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !allInputsHigh : allInputsHigh;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * NOR Gate component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { NorGateState } from '../../states/gates/NorGateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states/types';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for NOR Gate components.\n * With negative (default) activationLogic: NOR gate (output high when ALL inputs are low).\n * With positive activationLogic: OR gate (output high when ANY input is high).\n *\n * @public\n */\nexport class NorGateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.NorGate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for NorGateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new NorGateState(component.id, state);\n }\n\n /**\n * NOR gate output goes high when ALL inputs LACK voltage.\n * With positive activationLogic (OR), output goes high when ANY inputs HAS voltage.\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const anyInputHigh =\n newPinStates.get('input1')!.hasVoltage || newPinStates.get('input2')!.hasVoltage;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !anyInputHigh : anyInputHigh;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * NOR4 Gate component behavior implementation (4 inputs)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { Nor4GateState } from '../../states/gates/Nor4GateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for NOR4 Gate components (4 inputs).\n * With negative (default) activationLogic: NOR gate (output high when ALL 4 inputs are low).\n * With positive activationLogic: OR gate (output high when ANY of 4 inputs is high).\n *\n * @public\n */\nexport class Nor4GateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Nor4Gate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for Nor4GateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new Nor4GateState(component.id, state);\n }\n\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const anyInputHigh =\n newPinStates.get('input1')!.hasVoltage ||\n newPinStates.get('input2')!.hasVoltage ||\n newPinStates.get('input3')!.hasVoltage ||\n newPinStates.get('input4')!.hasVoltage;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !anyInputHigh : anyInputHigh;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * NOR8 Gate component behavior implementation (8 inputs)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { Nor8GateState } from '../../states/gates/Nor8GateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for NOR8 Gate components (8 inputs).\n * With negative (default) activationLogic: NOR gate (output high when ALL 8 inputs are low).\n * With positive activationLogic: OR gate (output high when ANY of 8 inputs is high).\n *\n * @public\n */\nexport class Nor8GateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Nor8Gate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for Nor8GateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new Nor8GateState(component.id, state);\n }\n\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const anyInputHigh =\n newPinStates.get('input1')!.hasVoltage ||\n newPinStates.get('input2')!.hasVoltage ||\n newPinStates.get('input3')!.hasVoltage ||\n newPinStates.get('input4')!.hasVoltage ||\n newPinStates.get('input5')!.hasVoltage ||\n newPinStates.get('input6')!.hasVoltage ||\n newPinStates.get('input7')!.hasVoltage ||\n newPinStates.get('input8')!.hasVoltage;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !anyInputHigh : anyInputHigh;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * XOR Gate component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { XorGateState } from '../../states/gates/XorGateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for XOR Gate components.\n * With positive activationLogic: XOR gate (output high when inputs differ / odd parity).\n * With negative activationLogic: XNOR gate (output high when inputs are equal / even parity).\n *\n * @public\n */\nexport class XorGateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.XorGate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for XorGateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new XorGateState(component.id, state);\n }\n\n /**\n * XOR gate output goes high when inputs differ (odd parity).\n * With negative activationLogic (XNOR), output goes high when inputs are equal (even parity).\n */\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const input1High = newPinStates.get('input1')!.hasVoltage;\n const input2High = newPinStates.get('input2')!.hasVoltage;\n const oddParity = input1High !== input2High;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !oddParity : oddParity;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * XOR4 Gate component behavior implementation (4 inputs)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { Xor4GateState } from '../../states/gates/Xor4GateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for XOR4 Gate components (4 inputs).\n * With positive activationLogic: XOR gate (output high when odd number of inputs are high).\n * With negative activationLogic: XNOR gate (output high when even number of inputs are high).\n *\n * @public\n */\nexport class Xor4GateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Xor4Gate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for Xor4GateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new Xor4GateState(component.id, state);\n }\n\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const highCount =\n (newPinStates.get('input1')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input2')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input3')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input4')!.hasVoltage ? 1 : 0);\n\n const oddParity = highCount % 2 === 1;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !oddParity : oddParity;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * XOR8 Gate component behavior implementation (8 inputs)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../../topology/Component';\nimport type { ComponentState } from '../../states/ComponentState';\nimport { Xor8GateState } from '../../states/gates/Xor8GateState';\nimport { LogicGateBehaviorMixin } from './index';\nimport type { IBehaviorResult, IComponentBehavior } from '../types';\nimport type { INodeElectricalState } from '../../states';\nimport type { UUID } from '../../../utils/types';\nimport { ComponentType } from '../../../topology/types';\n\n/**\n * Behavior implementation for XOR8 Gate components (8 inputs).\n * With positive activationLogic: XOR gate (output high when odd number of inputs are high).\n * With negative activationLogic: XNOR gate (output high when even number of inputs are high).\n *\n * @public\n */\nexport class Xor8GateBehavior extends LogicGateBehaviorMixin implements IComponentBehavior {\n constructor() {\n super(ComponentType.Xor8Gate);\n }\n\n createInitialState(component: Component): ComponentState {\n if (component.type !== this._componentType) {\n throw new Error(`Invalid component type for Xor8GateBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'high' : 'low';\n return new Xor8GateState(component.id, state);\n }\n\n override onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, INodeElectricalState>,\n targetTick: number\n ): IBehaviorResult {\n const newPinStates = this.getPinStates(component, nodeStates);\n state.pinStates = newPinStates;\n\n const vccGuardBehavior = this.vccGuardBehavior(state, newPinStates, targetTick);\n if (vccGuardBehavior) {\n return vccGuardBehavior;\n }\n const nonLogicInputGuardBehavior = this.nonLogicInputGuardBehavior(\n state,\n newPinStates,\n targetTick\n );\n if (nonLogicInputGuardBehavior) {\n return nonLogicInputGuardBehavior;\n }\n\n const highCount =\n (newPinStates.get('input1')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input2')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input3')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input4')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input5')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input6')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input7')!.hasVoltage ? 1 : 0) +\n (newPinStates.get('input8')!.hasVoltage ? 1 : 0);\n\n const oddParity = highCount % 2 === 1;\n\n const activationCondition =\n component.config.get('activationLogic') === 'negative' ? !oddParity : oddParity;\n\n return this.getBehavior(component, state, activationCondition, targetTick);\n }\n}\n","/**\n * Min-heap priority queue for scheduled events\n * @module core/simulation\n */\n\nimport type { IScheduledEvent } from './types';\n\n/**\n * Min-heap priority queue for scheduling future component transitions.\n * Events are ordered by readyAtTick (earliest first).\n * Events with same readyAtTick are returned in FIFO order (by scheduledAtTick).\n *\n * @public\n */\nexport class EventQueue {\n private heap: IScheduledEvent[];\n\n /**\n * Create a new empty event queue.\n */\n constructor() {\n this.heap = [];\n }\n\n /**\n * Schedule a future event.\n * Inserted with O(log N) complexity using heap operations.\n *\n * @param event - Event to schedule\n */\n schedule(event: IScheduledEvent): void {\n if (event.readyAtTick < event.scheduledAtTick) {\n throw new RangeError(\n `readyAtTick (${event.readyAtTick}) cannot be before scheduledAtTick (${event.scheduledAtTick})`\n );\n }\n this.heap.push(event);\n this.bubbleUp(this.heap.length - 1);\n }\n\n /**\n * Get all events ready to fire at or before current tick.\n * Returns events in FIFO order for same readyAtTick.\n * Removes returned events from the queue.\n *\n * @param currentTick - Current simulation tick\n * @returns Array of ready events (removed from queue)\n */\n getReadyEvents(currentTick: number): IScheduledEvent[] {\n const ready: IScheduledEvent[] = [];\n\n while (this.heap.length > 0 && this.heap[0]!.readyAtTick <= currentTick) {\n const event = this.extractMin();\n if (event) {\n ready.push(event);\n }\n }\n\n // Sort by scheduledAtTick for FIFO within same readyAtTick\n ready.sort((a, b) => {\n if (a.readyAtTick === b.readyAtTick) {\n return a.scheduledAtTick - b.scheduledAtTick;\n }\n return a.readyAtTick - b.readyAtTick;\n });\n\n return ready;\n }\n\n /**\n * Check if any events are pending.\n *\n * @returns True if queue contains events\n */\n hasEvents(): boolean {\n return this.heap.length > 0;\n }\n\n /**\n * Clear all pending events.\n */\n clear(): void {\n this.heap = [];\n }\n\n /**\n * Schedule multiple events at once, optionally cancelling pending events for specific targets.\n * More efficient than individual schedule() + removeEventsForTarget() calls:\n * single filter pass for all cancellations, batch push, single heap rebuild.\n *\n * @param events - Events to schedule\n * @param cancelTargets - Target IDs whose pending events should be removed before inserting\n */\n scheduleMany(events: ReadonlyArray<IScheduledEvent>, cancelTargets?: ReadonlySet<string>): void {\n for (const event of events) {\n if (event.readyAtTick < event.scheduledAtTick) {\n throw new RangeError(\n `readyAtTick (${event.readyAtTick}) cannot be before scheduledAtTick (${event.scheduledAtTick})`\n );\n }\n }\n\n if (cancelTargets && cancelTargets.size > 0) {\n this.heap = this.heap.filter((e) => !cancelTargets.has(e.targetId));\n }\n\n for (const event of events) {\n this.heap.push(event);\n }\n\n if (events.length > 0 || (cancelTargets && cancelTargets.size > 0)) {\n this.rebuildHeap();\n }\n }\n\n /**\n * Remove all pending events targeting a specific component.\n * Used when a behavior signals shouldCancelPending (e.g., Vcc loss, input change during transition).\n *\n * @param targetId - UUID of the component whose events should be removed\n * @returns Number of events removed\n */\n removeEventsForTarget(targetId: string): number {\n const initialLength = this.heap.length;\n this.heap = this.heap.filter((event) => event.targetId !== targetId);\n\n // Rebuild heap if events were removed\n if (this.heap.length !== initialLength) {\n this.rebuildHeap();\n }\n return initialLength - this.heap.length;\n }\n\n /**\n * Get number of pending events.\n *\n * @returns Event count\n */\n size(): number {\n return this.heap.length;\n }\n\n private rebuildHeap(): void {\n for (let i = Math.floor(this.heap.length / 2) - 1; i >= 0; i--) {\n this.bubbleDown(i);\n }\n }\n\n private bubbleUp(index: number): void {\n while (index > 0) {\n const parentIndex = Math.floor((index - 1) / 2);\n if (this.heap[index]!.readyAtTick < this.heap[parentIndex]!.readyAtTick) {\n [this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex]!, this.heap[index]!];\n index = parentIndex;\n } else {\n break;\n }\n }\n }\n\n private bubbleDown(index: number): void {\n const length = this.heap.length;\n\n while (true) {\n const leftChild = 2 * index + 1;\n const rightChild = 2 * index + 2;\n let smallest = index;\n\n if (\n leftChild < length &&\n this.heap[leftChild]!.readyAtTick < this.heap[smallest]!.readyAtTick\n ) {\n smallest = leftChild;\n }\n\n if (\n rightChild < length &&\n this.heap[rightChild]!.readyAtTick < this.heap[smallest]!.readyAtTick\n ) {\n smallest = rightChild;\n }\n\n if (smallest !== index) {\n [this.heap[index], this.heap[smallest]] = [this.heap[smallest]!, this.heap[index]!];\n index = smallest;\n } else {\n break;\n }\n }\n }\n\n private extractMin(): IScheduledEvent | undefined {\n if (this.heap.length === 0) {\n return undefined;\n }\n\n const min = this.heap[0];\n const last = this.heap.pop();\n\n if (this.heap.length > 0 && last) {\n this.heap[0] = last;\n this.bubbleDown(0);\n }\n\n return min;\n }\n}\n","/**\n * Tracks which circuit elements have changed state during the current tick\n * @module core/simulation\n */\n\nimport type { IDirtyElements } from './types';\nimport type { UUID } from '../utils/types';\n\n/**\n * Tracks per-element changes for optimized state propagation.\n * Provides granular dirty tracking at component/wire/enode level.\n *\n * Used to avoid re-processing unchanged elements during simulation ticks.\n *\n * @public\n */\nexport class DirtyTracker {\n private dirtyComponents: Set<UUID>;\n private dirtyWires: Set<UUID>;\n private dirtyEnodes: Set<UUID>;\n\n /**\n * Create a new dirty tracker with no marked elements.\n */\n constructor() {\n this.dirtyComponents = new Set();\n this.dirtyWires = new Set();\n this.dirtyEnodes = new Set();\n }\n\n /**\n * Mark a component as having changed state this tick.\n *\n * @param componentId - UUID of the component\n */\n markComponentDirty(componentId: UUID): void {\n this.dirtyComponents.add(componentId);\n }\n\n /**\n * Mark a wire as having changed electrical state this tick.\n *\n * @param wireId - UUID of the wire\n */\n markWireDirty(wireId: UUID): void {\n this.dirtyWires.add(wireId);\n }\n\n /**\n * Mark an ENode as having changed electrical state this tick.\n *\n * @param enodeId - UUID of the ENode\n */\n markEnodeDirty(enodeId: UUID): void {\n this.dirtyEnodes.add(enodeId);\n }\n\n /**\n * Set the entire set of dirty components. Should be only used at CircuitRunner initialization.\n * @param componentIds\n */\n setDirtyComponents(componentIds: Set<UUID>): void {\n this.dirtyComponents = new Set(componentIds);\n }\n\n /**\n * Set the entire set of dirty components. Should be only used at CircuitRunner initialization.\n * @param enodeIds\n */\n setDirtyEnodes(enodeIds: Set<UUID>): void {\n this.dirtyEnodes = new Set(enodeIds);\n }\n\n /**\n * Set the entire set of dirty components. Should be only used at CircuitRunner initialization.\n * @param wireIds\n */\n setDirtyWires(wireIds: Set<UUID>): void {\n this.dirtyWires = new Set(wireIds);\n }\n\n /**\n * Get all dirty elements and clear the tracker.\n * This is typically called at the end of a tick to collect changes.\n *\n * @returns Object containing sets of dirty component/wire/enode UUIDs\n */\n getDirtyElements(): IDirtyElements {\n const result: IDirtyElements = {\n components: new Set(this.dirtyComponents),\n wires: new Set(this.dirtyWires),\n enodes: new Set(this.dirtyEnodes),\n };\n\n this.clear();\n\n return result;\n }\n\n /**\n * Check if any elements are marked dirty.\n *\n * @returns True if at least one element is dirty\n */\n hasDirtyElements(): boolean {\n return this.dirtyComponents.size > 0 || this.dirtyWires.size > 0 || this.dirtyEnodes.size > 0;\n }\n\n /**\n * Clear all dirty markers without returning them.\n */\n clear(): void {\n this.dirtyComponents.clear();\n this.dirtyWires.clear();\n this.dirtyEnodes.clear();\n }\n\n /**\n * Get current count of dirty components (for debugging/metrics).\n *\n * @returns Number of dirty components\n */\n getDirtyComponentCount(): number {\n return this.dirtyComponents.size;\n }\n\n /**\n * Get current count of dirty wires (for debugging/metrics).\n *\n * @returns Number of dirty wires\n */\n getDirtyWireCount(): number {\n return this.dirtyWires.size;\n }\n\n /**\n * Get current count of dirty enodes (for debugging/metrics).\n *\n * @returns Number of dirty enodes\n */\n getDirtyEnodeCount(): number {\n return this.dirtyEnodes.size;\n }\n}\n","/**\n * Manages simulation state and optional history tracking\n * @module core/simulation\n */\n\nimport { SimulationState } from './states/SimulationState';\n\n/**\n * Manages current simulation state and historical state storage.\n * Uses a circular buffer for efficient memory-bounded history.\n *\n * @public\n */\nexport class StateManager {\n private currentState: SimulationState;\n private history: SimulationState[];\n private readonly historyEnabled: boolean;\n private readonly historyLimit: number;\n private historyWriteIndex: number;\n\n /**\n * Create a new state controllerType.\n *\n * @param enableHistory - Whether to store state history (default: false)\n * @param historyLimit - Maximum number of historical states to keep (default: 1000)\n */\n constructor(enableHistory: boolean = false, historyLimit: number = 1000) {\n if (historyLimit < 1) {\n throw new RangeError(`historyLimit must be at least 1 (got ${historyLimit})`);\n }\n\n this.historyEnabled = enableHistory;\n this.historyLimit = historyLimit;\n this.currentState = new SimulationState(0);\n this.history = [];\n this.historyWriteIndex = 0;\n }\n\n /**\n * Get the current simulation state.\n *\n * @returns Current state (mutable for simulation controller use)\n */\n getCurrentState(): SimulationState {\n return this.currentState;\n }\n\n /**\n * Get current tick number.\n *\n * @returns Current simulation tick\n */\n getCurrentTick(): number {\n return this.currentState.tick;\n }\n\n /**\n * Advance to next tick, optionally saving current state to history.\n * Creates a new SimulationState for the next tick.\n *\n * @returns New current state for the next tick\n */\n advanceToNextTick(): SimulationState {\n const nextTick = this.currentState.tick + 1;\n\n // Save current state to history if enabled\n if (this.historyEnabled) {\n this.saveToHistory(this.currentState.clone());\n }\n\n // update current state to new tick\n this.currentState.tick = nextTick;\n\n return this.currentState;\n }\n\n /**\n * Get a historical state by tick number.\n * Only works if history is enabled.\n *\n * @param tick - Tick number to retrieve\n * @returns State at that tick, or undefined if not available\n */\n getStateAtTick(tick: number): SimulationState | undefined {\n if (!this.historyEnabled) {\n return undefined;\n }\n\n return this.history.find((state) => state.tick === tick);\n }\n\n /**\n * Get all available historical states.\n * Returns empty array if history is disabled.\n *\n * @returns Array of historical states, sorted by tick (oldest first)\n */\n getHistory(): ReadonlyArray<SimulationState> {\n if (!this.historyEnabled) {\n return [];\n }\n\n // Return sorted copy\n return [...this.history].sort((a, b) => a.tick - b.tick);\n }\n\n /**\n * Get the oldest tick number available in history.\n *\n * @returns Oldest tick number, or undefined if no history\n */\n getOldestTick(): number | undefined {\n if (!this.historyEnabled || this.history.length === 0) {\n return undefined;\n }\n\n return Math.min(...this.history.map((state) => state.tick));\n }\n\n /**\n * Get the newest tick number in history (not including current tick).\n *\n * @returns Newest historical tick, or undefined if no history\n */\n getNewestHistoricalTick(): number | undefined {\n if (!this.historyEnabled || this.history.length === 0) {\n return undefined;\n }\n\n return Math.max(...this.history.map((state) => state.tick));\n }\n\n /**\n * Clear all history.\n */\n clearHistory(): void {\n this.history = [];\n this.historyWriteIndex = 0;\n }\n\n /**\n * Reset to tick 0, clearing current state and all history.\n */\n reset(): void {\n this.currentState = new SimulationState(0);\n this.clearHistory();\n }\n\n /**\n * Check if history tracking is enabled.\n *\n * @returns True if history is enabled\n */\n isHistoryEnabled(): boolean {\n return this.historyEnabled;\n }\n\n /**\n * Get the configured history limit.\n *\n * @returns Maximum number of historical states\n */\n getHistoryLimit(): number {\n return this.historyLimit;\n }\n\n /**\n * Get current history size.\n *\n * @returns Number of states in history\n */\n getHistorySize(): number {\n return this.history.length;\n }\n\n /**\n * Save a state to history using circular buffer.\n * Private helper for advanceToNextTick.\n *\n * @param state - State to save\n */\n private saveToHistory(state: SimulationState): void {\n if (this.history.length < this.historyLimit) {\n // History not yet full, just append\n this.history.push(state);\n } else {\n // Circular buffer: overwrite oldest entry\n this.history[this.historyWriteIndex] = state;\n this.historyWriteIndex = (this.historyWriteIndex + 1) % this.historyLimit;\n }\n }\n}\n","/**\n * Main simulation controller for discrete-time circuit simulation\n * @module core/simulation\n */\n\nimport type { Circuit } from '../topology/Circuit';\nimport type { ComponentState } from './states/ComponentState.js';\nimport { SimulationState } from './states/SimulationState';\nimport { StateManager } from './StateManager.js';\nimport { EventQueue } from './EventQueue.js';\nimport { DirtyTracker } from './DirtyTracker.js';\nimport { BehaviorRegistry, type IBehaviorResult } from './behaviors';\nimport type { ENode } from '../topology/ENode';\nimport type { Component } from '../topology/Component';\nimport type { INodeElectricalState } from './states';\nimport type {\n IUserCommand,\n IScheduledEvent,\n IReachabilityResult,\n IRunnerOptions,\n IRunnerResult,\n} from './types';\nimport type { UUID } from '../utils/types';\nimport { ENodeSourceType, ENodeType } from '../topology/types';\n\n/**\n * Main circuit simulation controller.\n * Manages discrete-time simulation with event-driven state propagation.\n *\n * Features:\n * - Boolean electrical state (voltage/current present or not)\n * - Event-driven delayed transitions\n * - Dirty tracking for optimization\n * - Configurable history storage\n * - Registry-based component behaviors\n *\n * @public\n */\nexport class CircuitRunner {\n public readonly circuit: Circuit;\n public readonly stateManager: StateManager;\n public readonly eventQueue: EventQueue;\n public readonly commands: Map<UUID, IUserCommand>;\n public readonly dirtyTracker: DirtyTracker;\n public readonly behaviorRegistry: BehaviorRegistry;\n\n /**\n * Create a new circuit simulation runner.\n *\n * @param circuit - The circuit topology to simulate\n * @param behaviorRegistry - Registry of component behaviors\n * @param options - Simulation options (history settings)\n */\n constructor(circuit: Circuit, behaviorRegistry: BehaviorRegistry, options: IRunnerOptions = {}) {\n this.circuit = circuit;\n this.behaviorRegistry = behaviorRegistry;\n\n const enableHistory = options.enableHistory ?? false;\n const historyLimit = options.historyLimit ?? 1000;\n\n this.stateManager = new StateManager(enableHistory, historyLimit);\n this.eventQueue = new EventQueue();\n this.commands = new Map<UUID, IUserCommand>();\n this.dirtyTracker = new DirtyTracker();\n\n // Initialize simulation state\n try {\n this.initializeState();\n } catch (e) {\n console.error('Error during CircuitRunner initialization:', e);\n throw e;\n }\n }\n\n /**\n * Execute one simulation tick.\n * Process scheduled events, update state (electrical propagation), process user commands and advance tick.\n *\n * @returns the result of the tick execution\n */\n tick(): IRunnerResult {\n const eventQueueStartSize = this.eventQueue.size();\n const currentTick = this.stateManager.getCurrentTick();\n\n // 1. Process scheduled events ready at this tick end\n const eventResults = this.applyReadyEvents(currentTick + 1);\n\n // 2. Update state\n const result = this.updateState(currentTick + 1);\n result.firedEventCount = eventResults.length;\n\n // 3. Process user commands scheduled for this tick\n const userCommandResults = this.processCommands();\n result.processedCommandCount = userCommandResults.length;\n\n result.scheduledEventCount =\n this.eventQueue.size() + result.firedEventCount - eventQueueStartSize;\n\n // 3H. due to orchestration difficulties this hotfix handles component dirty tracking\n for (const eventResult of eventResults) {\n if (eventResult.hasChanged) {\n this.dirtyTracker.markComponentDirty(eventResult.componentState.componentId);\n }\n }\n result.componentUpdateCount = this.dirtyTracker.getDirtyComponentCount();\n\n // 4. Advance to next tick\n this.stateManager.advanceToNextTick();\n result.endTick = this.stateManager.getCurrentTick();\n return result;\n }\n\n /**\n * Execute multiple simulation ticks.\n *\n * @param count - Number of ticks to execute\n * @returns an array of IRunnerResult for each tick executed\n */\n tickN(count: number): IRunnerResult[] {\n if (count < 1) {\n throw new RangeError(`Tick count must be at least 1 (got ${count})`);\n }\n\n const results = [];\n for (let i = 0; i < count; i++) {\n results.push(this.tick());\n }\n\n return results;\n }\n\n /**\n * Reset simulation to tick 0.\n * Clears all state, history, and scheduled events.\n */\n reset(): void {\n this.stateManager.reset();\n this.eventQueue.clear();\n this.dirtyTracker.clear();\n this.initializeState();\n }\n\n /**\n * Get current simulation tick number.\n *\n * @returns Current tick\n */\n getCurrentTick(): number {\n return this.stateManager.getCurrentTick();\n }\n\n /**\n * Get current simulation state snapshot.\n *\n * @returns Current state (readonly)\n */\n getCurrentState(): SimulationState {\n return this.stateManager.getCurrentState();\n }\n\n /**\n * Get electrical state of a specific ENode.\n *\n * @param enodeId - UUID of the ENode\n * @returns Electrical state, or undefined if not found\n */\n getEnodeState(enodeId: UUID): INodeElectricalState | undefined {\n return this.stateManager.getCurrentState().nodeStates.get(enodeId);\n }\n\n /**\n * Get electrical state of a specific Wire.\n *\n * @param wireId - UUID of the Wire\n * @returns Electrical state, or undefined if not found\n */\n getWireState(wireId: UUID): INodeElectricalState | undefined {\n return this.stateManager.getCurrentState().wireStates.get(wireId);\n }\n\n /**\n * Get component state for a specific component.\n *\n * @param componentId - UUID of the component\n * @returns Component state, or undefined if not found\n */\n getComponentState(componentId: UUID): ComponentState | undefined {\n return this.stateManager.getCurrentState().componentStates.get(componentId);\n }\n\n /**\n * Get historical state at a specific tick.\n * Only works if history is enabled.\n *\n * @param tick - Tick number to retrieve\n * @returns Historical state, or undefined if not available\n */\n getStateAtTick(tick: number): SimulationState | undefined {\n return this.stateManager.getStateAtTick(tick);\n }\n\n /**\n * Check if a component is registered in behavior registry.\n *\n * @param componentType - Component type to check\n * @returns True if behavior is registered\n */\n hasBehavior(componentType: string): boolean {\n return this.behaviorRegistry.has(componentType);\n }\n\n /**\n * Submit a user command to execute at the next tick.\n * only one command per component per tick is allowed.\n * Subsequent commands for the same component at this tick will be discarded.\n *\n * @param command - User command to submit\n */\n submitCommand(command: IUserCommand): boolean {\n if (!this.circuit.hasComponent(command.targetId)) {\n throw Error(`Cannot submit command for unknown component ID '${command.targetId}'`);\n }\n if (this.commands.has(command.targetId)) {\n return false; // currently we only allow one command per component and tick\n }\n command.scheduledAtTick = this.getCurrentTick();\n this.commands.set(command.targetId, command);\n return true;\n }\n\n /**\n * Process all scheduled user commands.\n * Mark changed components as Dirty and enqueue consequent scheduled events\n * Finally clears command queue after processing.\n *\n * @returns Array of IBehaviorResult for each processed command\n */\n private processCommands(): IBehaviorResult[] {\n const currentState = this.stateManager.getCurrentState();\n\n const results: IBehaviorResult[] = [];\n const cancelTargets = new Set<UUID>();\n const eventsToSchedule: IScheduledEvent[] = [];\n\n for (const command of this.commands.values()) {\n const component = this.circuit.getComponent(command.targetId) as Component;\n const behavior = this.behaviorRegistry.get(component.type)!;\n\n const result = behavior.onUserCommand(\n component,\n currentState.componentStates.get(component.id)!,\n command\n );\n if (result.shouldCancelPending) {\n cancelTargets.add(component.id);\n }\n for (const event of result.scheduledEvents) {\n eventsToSchedule.push(event);\n }\n results.push(result);\n if (result.hasChanged) {\n this.dirtyTracker.markComponentDirty(component.id);\n }\n }\n\n this.eventQueue.scheduleMany(eventsToSchedule, cancelTargets);\n this.commands.clear();\n\n return results;\n }\n\n /**\n * Helper function to extract initializationOrder from component config.\n * Returns numeric order value, with empty string or null defaulting to 0.\n *\n * @param config - Component configuration map\n * @returns Order value (lower = processed first)\n */\n private getInitializationOrder(config: Map<string, string>): number {\n const value = config.get('initializationOrder');\n if (!value || value === '') return 0;\n const parsed = parseInt(value, 10);\n return isNaN(parsed) ? 0 : parsed;\n }\n\n /**\n * Initialize simulation state for all components.\n * Called on construction and reset.\n *\n * Uses order-based initialization to resolve feedback loops:\n * 1. Components are grouped by initializationOrder (higher = processed LAST)\n * 2. Within each group, components are sorted by UUID (ascending) for determinism\n * 3. Conductivity is propagated after each component\n *\n * In feedback circuits, the component processed LAST \"wins\" because earlier\n * components react to the initial symmetric state and open, while later\n * components see the updated (asymmetric) state and stay closed.\n */\n private initializeState(): IRunnerResult {\n const currentState = this.stateManager.getCurrentState();\n\n // Initialize component states using behaviors\n for (const component of this.circuit.getAllComponents()) {\n if (component.pins.length < 1) continue;\n\n const behavior = this.behaviorRegistry.get(component.type);\n if (!behavior) {\n // console.warn(\n // `No behavior registered for component type '${component.type}' (${component.id})`\n // );\n continue;\n }\n\n const initialState = behavior.createInitialState(component);\n (currentState.componentStates as Map<UUID, ComponentState>).set(component.id, initialState);\n\n // Mark component as dirty for initial evaluation\n this.dirtyTracker.markComponentDirty(component.id);\n }\n\n // Initialize all ENode initial states based on their topology source type\n for (const enode of this.circuit.getAllENodes()) {\n (currentState.nodeStates as Map<UUID, INodeElectricalState>).set(enode.id, {\n hasVoltage: enode.source === ENodeSourceType.Voltage,\n hasCurrent: enode.source === ENodeSourceType.Current,\n locked: !!enode.source,\n });\n }\n // Initialize all Wire states unlocked without voltage/current\n for (const wire of this.circuit.getAllWires()) {\n (currentState.wireStates as Map<UUID, INodeElectricalState>).set(wire.id, {\n hasVoltage: false,\n hasCurrent: false,\n locked: false,\n });\n }\n\n // Order-based initialization for feedback loop resolution\n // Group components by order level\n const allComponents = this.circuit.getAllComponents();\n const componentsByOrder = new Map<number, Component[]>();\n\n for (const component of allComponents) {\n const order = this.getInitializationOrder(component.config);\n const group = componentsByOrder.get(order) ?? [];\n group.push(component);\n componentsByOrder.set(order, group);\n }\n\n // Sort order levels (ascending - lower order first, higher order last)\n const sortedOrders = Array.from(componentsByOrder.keys()).sort((a, b) => a - b);\n\n // Sort components within each order group by UUID for determinism\n for (const order of sortedOrders) {\n const group = componentsByOrder.get(order)!;\n group.sort((a, b) => a.id.localeCompare(b.id));\n }\n\n // Iterate until stable state is reached (for feedback loop resolution)\n // This is necessary because feedback circuits may require multiple passes\n // to reach equilibrium after initial state changes propagate through the loop.\n //\n // KEY: During initialization, we fire events IMMEDIATELY after each component\n // processes (bypassing the normal tick delay). This allows the first component\n // in a feedback loop to complete its transition before the next component sees\n // the state, thereby breaking symmetry in cross-coupled feedback circuits.\n let hasChanges = true;\n let iterations = 0;\n const maxIterations = 100; // Safety limit to prevent infinite loops\n\n while (hasChanges && iterations < maxIterations) {\n hasChanges = false;\n iterations++;\n\n // Process each order group sequentially\n for (const order of sortedOrders) {\n const group = componentsByOrder.get(order)!;\n\n // Process each component sequentially with immediate event firing\n for (const component of group) {\n const behavior = this.behaviorRegistry.get(component.type);\n if (!behavior) continue;\n\n const componentState = currentState.componentStates.get(component.id);\n if (!componentState) continue;\n\n // Propagate before processing this component so it sees current electrical state\n this.propagateConductivity();\n\n // Components returning a onStart behavior override the standard initialization process\n // Notably they can schedule events ahead\n const customOnStartResult = behavior.onStart(component, componentState);\n if (!!customOnStartResult) {\n (currentState.componentStates as Map<UUID, ComponentState>).set(\n component.id,\n customOnStartResult.componentState\n );\n if (customOnStartResult.shouldCancelPending) {\n this.eventQueue.removeEventsForTarget(component.id);\n }\n for (const event of customOnStartResult.scheduledEvents) {\n this.eventQueue.schedule(event);\n }\n continue;\n }\n\n // Let the component react to current pin states\n const result = behavior.onPinsChange(\n component,\n componentState,\n currentState.nodeStates,\n 0\n );\n\n // Update component state if it changed\n if (result.hasChanged) {\n hasChanges = true;\n (currentState.componentStates as Map<UUID, ComponentState>).set(\n component.id,\n result.componentState\n );\n }\n\n // During initialization, fire any scheduled events IMMEDIATELY\n // This is the key to breaking feedback symmetry: the first component\n // completes its full transition (e.g., opening → open) before the\n // next component in the feedback loop sees the new electrical state.\n for (const event of result.scheduledEvents) {\n const eventResult = behavior.onEventFiring(component, componentState, event);\n if (eventResult.hasChanged) {\n hasChanges = true;\n (currentState.componentStates as Map<UUID, ComponentState>).set(\n component.id,\n eventResult.componentState\n );\n }\n }\n }\n }\n }\n\n const result = this.updateState(0);\n\n // at initialization everything is dirty\n this.dirtyTracker.setDirtyComponents(\n new Set([...this.circuit.getAllComponents().map((c) => c.id)])\n );\n this.dirtyTracker.setDirtyEnodes(new Set([...this.circuit.getAllENodes().map((n) => n.id)]));\n this.dirtyTracker.setDirtyWires(new Set([...this.circuit.getAllWires().map((w) => w.id)]));\n\n return result;\n }\n\n /**\n * Core method that orchestrates nodes, wires and components state updates\n * enqueue resulting events and update dirty tracker accordingly\n * @param targetTick - Tick at which to perform the update\n */\n private updateState(targetTick: number): IRunnerResult {\n const currentState = this.stateManager.getCurrentState();\n\n const { updatedNodes, updatedWires } = this.propagateConductivity();\n const componentsToAssess = this.circuit.getComponentsOfPins(updatedNodes);\n const results: IBehaviorResult[] = [];\n\n const updatedComponents = new Set<UUID>();\n\n // During initialization (tick 0), sort components by order to resolve feedback loops\n let sortedComponentIds = Array.from(componentsToAssess);\n if (targetTick === 0) {\n sortedComponentIds = sortedComponentIds.sort((idA, idB) => {\n const compA = this.circuit.getComponent(idA) as Component;\n const compB = this.circuit.getComponent(idB) as Component;\n const orderA = this.getInitializationOrder(compA.config);\n const orderB = this.getInitializationOrder(compB.config);\n\n // Lower order first, higher order last (ascending)\n if (orderA !== orderB) {\n return orderA - orderB;\n }\n\n // Tie-break by UUID (ascending)\n return idA.localeCompare(idB);\n });\n }\n\n const cancelTargets = new Set<UUID>();\n const eventsToSchedule: IScheduledEvent[] = [];\n\n for (const componentId of sortedComponentIds) {\n const component = this.circuit.getComponent(componentId) as Component;\n const behavior = this.behaviorRegistry.get(component.type);\n if (!behavior) continue;\n\n const res = behavior.onPinsChange(\n component,\n currentState.componentStates.get(componentId)!,\n currentState.nodeStates,\n targetTick\n );\n if (res.shouldCancelPending) {\n cancelTargets.add(componentId);\n }\n if (res.hasChanged) {\n updatedComponents.add(componentId);\n results.push(res);\n }\n for (const event of res.scheduledEvents) {\n eventsToSchedule.push(event);\n }\n }\n\n this.eventQueue.scheduleMany(eventsToSchedule, cancelTargets);\n\n this.dirtyTracker.setDirtyComponents(updatedComponents);\n this.dirtyTracker.setDirtyEnodes(updatedNodes);\n this.dirtyTracker.setDirtyWires(updatedWires);\n\n return {\n startTick: this.getCurrentTick(),\n endTick: this.getCurrentTick(),\n componentUpdateCount: updatedComponents.size,\n nodeUpdateCount: updatedNodes.size,\n wireUpdateCount: updatedWires.size,\n processedCommandCount: 0,\n scheduledEventCount: eventsToSchedule.length,\n firedEventCount: 0,\n };\n }\n\n /**\n * runs BFS (Breadth First Search) on voltage and current conductivity\n * to propagate voltage/current conductivity\n * and update enodes/wires electrical states throughout the circuit\n * update is performed in place and updated nodes and wires returned\n */\n private propagateConductivity(): { updatedNodes: Set<UUID>; updatedWires: Set<UUID> } {\n const currentState = this.stateManager.getCurrentState();\n\n const updateConductivity = (\n type: ENodeSourceType\n ): {\n updatedNodes: Set<UUID>;\n updatedWires: Set<UUID>;\n } => {\n const updatedNodes = new Set<UUID>();\n const updatedWires = new Set<UUID>();\n\n const sources = this.circuit\n .getAllENodes()\n .filter((node) => node.source == type)\n .map((node) => node.id);\n const uncheckedNodes = new Set([\n ...this.circuit\n .getAllENodes()\n .filter((node) => !node.source)\n .map((node) => node.id),\n ]); // pool of all other nodes whose state is to assess\n const uncheckedWires = new Set([...this.circuit.getAllWires().map((wire) => wire.id)]); // pool of all other wires whose state is to assess\n\n const { nodes, wires } = this.computeReachability(\n type,\n sources,\n currentState.componentStates\n );\n\n const attribute = type == ENodeSourceType.Voltage ? 'hasVoltage' : 'hasCurrent';\n\n for (const nodeId of nodes) {\n const nodeState = currentState.nodeStates.get(nodeId);\n if (nodeState && !nodeState.locked) {\n if (!nodeState[attribute]) {\n nodeState[attribute] = true;\n updatedNodes.add(nodeId);\n }\n uncheckedNodes.delete(nodeId);\n }\n }\n // at this point all uncheckedNodes can be considered without conductivity : hence they are updated if necessary\n for (const nodeId of uncheckedNodes) {\n const nodeState = currentState.nodeStates.get(nodeId);\n if (nodeState && !nodeState.locked) {\n if (nodeState[attribute]) {\n nodeState[attribute] = false;\n updatedNodes.add(nodeId);\n }\n }\n }\n\n for (const wireId of wires) {\n const wireState = currentState.wireStates.get(wireId);\n if (!!wireState) {\n if (!wireState[attribute]) {\n wireState[attribute] = true;\n updatedWires.add(wireId);\n }\n uncheckedWires.delete(wireId);\n }\n }\n // at this point all uncheckedWires can be considered without conductivity : hence they are updated if necessary\n for (const wireId of uncheckedWires) {\n const wireState = currentState.wireStates.get(wireId);\n if (!!wireState) {\n if (wireState[attribute]) {\n wireState[attribute] = false;\n updatedWires.add(wireId);\n }\n }\n }\n\n return { updatedNodes, updatedWires };\n };\n\n const { updatedNodes: voltageUpdateNodes, updatedWires: voltageUpdatedWires } =\n updateConductivity(ENodeSourceType.Voltage);\n const { updatedNodes: currentUpdateNodes, updatedWires: currentUpdatedWires } =\n updateConductivity(ENodeSourceType.Current);\n\n return {\n updatedNodes: new Set([...voltageUpdateNodes, ...currentUpdateNodes]) as Set<UUID>,\n updatedWires: new Set([...voltageUpdatedWires, ...currentUpdatedWires]) as Set<UUID>,\n };\n }\n\n /**\n * given a conductivity conductivityType and a set of seed nodes, compute all reachable nodes and wires\n * depends on componentStates to determine if conductivity is allowed through components\n * this method doesn't mutate any state, it's a pure function\n * @param conductivityType\n * @param seeds\n * @param componentStates\n */\n private computeReachability(\n conductivityType: ENodeSourceType,\n seeds: UUID[],\n componentStates: ReadonlyMap<UUID, ComponentState>\n ): IReachabilityResult {\n const reachableNodes = new Set<UUID>();\n const reachableWires = new Set<UUID>();\n const frontier: UUID[] = [];\n\n // Seed the frontier\n for (const seed of seeds) {\n frontier.push(seed);\n reachableNodes.add(seed);\n }\n\n while (frontier.length > 0) {\n const currentId = frontier.shift() as UUID;\n\n // Traverse via wires\n for (const wire of this.circuit.getWiresByNode(currentId)) {\n const otherNodeId = wire.node1 === currentId ? wire.node2 : wire.node1;\n\n if (!reachableNodes.has(otherNodeId)) {\n reachableNodes.add(otherNodeId);\n frontier.push(otherNodeId);\n }\n if (!reachableWires.has(wire.id)) {\n reachableWires.add(wire.id);\n }\n }\n\n // Traverse through components in case of pin\n const node = this.circuit.getENode(currentId) as ENode;\n if (node.type === ENodeType.Pin) {\n const component = this.circuit.getComponent(node.component!) as Component;\n const behavior = this.behaviorRegistry.get(component.type);\n if (!behavior) {\n // console.warn(\n // `No behavior registered for component type '${component.type}' (${component.id})`\n // );\n continue;\n }\n\n const state = componentStates.get(component.id)!;\n\n for (const otherPinId of component.pins) {\n if (otherPinId === currentId) continue;\n if (reachableNodes.has(otherPinId)) continue;\n\n // Check if component allows traversal\n const res = behavior.allowConductivity(\n component,\n state,\n conductivityType,\n currentId,\n otherPinId\n );\n\n if (res) {\n reachableNodes.add(otherPinId);\n frontier.push(otherPinId);\n }\n }\n }\n }\n\n return { nodes: reachableNodes, wires: reachableWires };\n }\n\n /**\n * Fire ready events and update current state accordingly\n * eventual subsequent events are enqueued\n *\n * @param targetTick - Tick at which to process events\n * @param events - Events to apply\n * @param state - Current simulation state\n * @param targetTick - Target tick for event processing\n */\n private applyReadyEvents(targetTick: number): IBehaviorResult[] {\n const currentState = this.stateManager.getCurrentState();\n const readyEvents = this.eventQueue.getReadyEvents(targetTick);\n\n const results: IBehaviorResult[] = [];\n const cancelTargets = new Set<UUID>();\n const eventsToSchedule: IScheduledEvent[] = [];\n\n for (const event of readyEvents) {\n const component = this.circuit.getComponent(event.targetId) as Component;\n const behavior = this.behaviorRegistry.get(component.type);\n if (!behavior) continue;\n\n const componentState = currentState.componentStates.get(component.id)!;\n const result = behavior.onEventFiring(component, componentState, event);\n if (result.shouldCancelPending) {\n cancelTargets.add(component.id);\n }\n for (const event of result.scheduledEvents) {\n eventsToSchedule.push(event);\n }\n results.push(result);\n }\n\n this.eventQueue.scheduleMany(eventsToSchedule, cancelTargets);\n return results;\n }\n}\n","/**\n * Core setup helper methods\n * @module core/setup\n */\n\nimport {\n BehaviorRegistry,\n BatteryBehavior,\n LightbulbBehavior,\n RectangleLEDBehavior,\n RelayBehavior,\n SmallLEDBehavior,\n SwitchBehavior,\n InverterBehavior,\n DoubleThrowSwitchBehavior,\n NandGateBehavior,\n Nand4GateBehavior,\n Nand8GateBehavior,\n NorGateBehavior,\n Nor4GateBehavior,\n Nor8GateBehavior,\n XorGateBehavior,\n Xor4GateBehavior,\n Xor8GateBehavior,\n ClockBehavior,\n} from './simulation';\n\n/**\n * Register all basic component behaviors in the given registry\n * Basic components are : Battery, Lightbulb, RectangleLED, Relay, SmallLED, Switch, double switch\n * @public\n * @param registry\n * @return the input behavior registry for chaining\n */\nexport function registerBasicComponentsBehaviors(registry: BehaviorRegistry): BehaviorRegistry {\n registry\n .register(new BatteryBehavior())\n .register(new LightbulbBehavior())\n .register(new RectangleLEDBehavior())\n .register(new RelayBehavior())\n .register(new SmallLEDBehavior())\n .register(new SwitchBehavior())\n .register(new DoubleThrowSwitchBehavior())\n .register(new ClockBehavior());\n return registry;\n}\n\n/**\n * Register all gates component behaviors in the given registry\n * Gates components are : Inverter, NandGate (2,4,8), NorGate (2,4,8), XorGate (2,4,8)\n * @public\n * @param registry\n * @return the input behavior registry for chaining\n */\nexport function registerGatesComponentsBehaviors(registry: BehaviorRegistry): BehaviorRegistry {\n registry\n .register(new InverterBehavior())\n .register(new NandGateBehavior())\n .register(new Nand4GateBehavior())\n .register(new Nand8GateBehavior())\n .register(new NorGateBehavior())\n .register(new Nor4GateBehavior())\n .register(new Nor8GateBehavior())\n .register(new XorGateBehavior())\n .register(new Xor4GateBehavior())\n .register(new Xor8GateBehavior());\n return registry;\n}\n"],"mappings":"AAMA,SAAgB,GAAQ,GAAkD;AACxE,MAAI,GACA,GACA;AAEJ,SAAI,OAAO,KAAS,YAClB,IAAe,EAAK,cACpB,IAAW,EAAK,UAChB,IAAO,EAAK,QAEZ,IAAe,GAGjB,CAAQ,GAAiB,GAAsB,MAA6C;AAC1F,QAAI,EAAW,SAAS,KACtB,CAAA,EAAW,QAAQ,EAAe,EAAW,OAAO,GAAc,GAAU,CAAA;AAAA,aACnE,EAAW,OAAO,KAC3B,CAAA,EAAW,MAAM,EAAe,EAAW,KAAK,GAAc,GAAU,CAAA;AAAA,QAExE,OAAM;AAAA;;AAKZ,SAAgB,GAAgB,GAAkB,GAA4C;AAE5F,SAAO,GAAQ;AAAA,IACb,UAAA;AAAA,IACA,cAAA;AAAA,GACD;;AAGH,IAAM,IAAkD,oBAAI,IAAA;AAkB5D,SAAS,EACP,GACA,GACA,IAAmB,GACnB,GACA;AACA,QAAM,IAAc,uBAAO,kBAAA;AAG3B,SAAO,YAAa,GAAa;AAC/B,QAAI;AAIJ,IAAK,KAAK,eAAe,CAAA,KAEvB,OAAO,eAAe,MAAM,GAAa;AAAA,MACvC,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,OAAO,oBAAI,IAAA;AAAA,KACZ;AAGH,QAAI,IAAuB,KAAK,CAAA;AAEhC,QAAI,MAAM,QAAQ,CAAA,EAChB,YAAW,KAAO,EAChB,CAAI,EAAkB,IAAI,CAAA,IAExB,EAAkB,IAAI,CAAA,EAAK,KAAK,CAAA,IAEhC,EAAkB,IAAI,GAAK,CAAC,CAAA,CAAM;AAKxC,QAAI,KAAgB,EAAK,SAAS,KAAK,IAAW,GAAG;AACnD,UAAI;AAGJ,MAAI,MAAiB,KACnB,IAAU,EAAK,IAAA,CAAK,MAAM,EAAE,SAAA,CAAU,EAAE,KAAK,GAAA,IACpC,IAET,IAAU,EAAa,MAAM,MAAM,CAAA,IAEnC,IAAU,EAAK,CAAA;AAGjB,YAAM,IAAe,GAAG,CAAA;AACxB,UAAI,IAAqB;AACzB,UAAI,IAAW,EACb,KAAI,CAAC,EAAM,IAAI,CAAA,EAEb,CAAA,IAAY;AAAA,WACP;AACL,YAAI,IAAY,EAAM,IAAI,CAAA;AAC1B,QAAA,IAAY,KAAK,IAAA,IAAQ,IAAY;AAAA;AAIzC,MAAI,EAAM,IAAI,CAAA,KAAY,CAAC,IACzB,IAAgB,EAAM,IAAI,CAAA,KAG1B,IAAgB,EAAe,MAAM,MAAM,CAAA,GAC3C,EAAM,IAAI,GAAS,CAAA,GACf,IAAW,KACb,EAAM,IAAI,GAAc,KAAK,IAAA,CAAK;AAAA,WAGjC;AAEL,YAAM,IAAU;AAChB,MAAI,EAAM,IAAI,CAAA,IACZ,IAAgB,EAAM,IAAI,CAAA,KAG1B,IAAgB,EAAe,MAAM,MAAM,CAAA,GAC3C,EAAM,IAAI,GAAS,CAAA;AAAA;AAIvB,WAAO;AAAA;;ACxHX,IAAa,IAAb,MAAa,EAAW;AAAA,EAQtB,YACE,GACA,GACA,GACA;AAHgB,SAAA,IAAA,GACA,KAAA,IAAA,GACA,KAAA,IAAA;AAAA;EAmBlB,OAAO,GAA4B;AACjC,WAAO,KAAK,MAAM,EAAM,KAAK,KAAK,MAAM,EAAM,KAAK,KAAK,MAAM,EAAM;AAAA;EAetE,SAAsB;AACpB,WAAO;AAAA,MAAE,GAAG,KAAK;AAAA,MAAG,GAAG,KAAK;AAAA,MAAG,GAAG,KAAK;AAAA;;EAgBzC,OAAO,SAAS,GAA+B;AAC7C,WAAO,IAAI,EAAW,EAAK,GAAG,EAAK,GAAG,EAAK,CAAA;AAAA;EAQ7C,WAAmB;AACjB,WAAO,YAAY,KAAK,CAAA,KAAM,KAAK,CAAA,KAAM,KAAK,CAAA;AAAA;GCjErC,IAAb,MAAa,EAAc;AAAA,EAUzB,YACE,IAAuC,IAAI,EAAW,GAAG,IAAI,EAAA,GAC7D,IAA6C,IAAI,EAAW,GAAG,GAAG,CAAA,GAClE,IAA8B,IAC9B,IAA+B,KAC/B,IAA8B,KAC9B;AALgB,SAAA,WAAA,GACA,KAAA,iBAAA,GACA,KAAA,MAAA,GACA,KAAA,OAAA,GACA,KAAA,MAAA;AAAA;EAsBlB,SAAyB;AACvB,WAAO;AAAA,MACL,UAAU,KAAK,SAAS,OAAA;AAAA,MACxB,gBAAgB,KAAK,eAAe,OAAA;AAAA,MACpC,KAAK,KAAK;AAAA,MACV,MAAM,KAAK;AAAA,MACX,KAAK,KAAK;AAAA;;EAuBd,OAAO,SAAS,GAAqC;AACnD,WAAO,IAAI,EACT,EAAW,SAAS,EAAK,QAAA,GACzB,EAAW,SAAS,EAAK,cAAA,GACzB,EAAK,KACL,EAAK,MACL,EAAK,GAAA;AAAA;EAST,WAAmB;AACjB,WAAO,2BAA2B,KAAK,SAAS,SAAA,CAAU,aAAa,KAAK,eAAe,SAAA,CAAU,UAAU,KAAK,GAAA,WAAc,KAAK,IAAA,UAAc,KAAK,GAAA;AAAA;GCnFjJ,IAAb,MAAa,EAAS;AAAA,EAQpB,YACE,GACA,GACA;AACA,QAHgB,KAAA,IAAA,GACA,KAAA,IAAA,GAEZ,CAAC,OAAO,UAAU,CAAA,KAAM,CAAC,OAAO,UAAU,CAAA,EAC5C,OAAM,IAAI,UAAU,gDAAgD,CAAA,OAAQ,CAAA,GAAE;AAAA;EAoBlF,OAAO,GAA0B;AAC/B,WAAO,KAAK,MAAM,EAAM,KAAK,KAAK,MAAM,EAAM;AAAA;EAehD,SAAmC;AACjC,WAAO;AAAA,MAAE,GAAG,KAAK;AAAA,MAAG,GAAG,KAAK;AAAA;;EAiB9B,OAAO,SAAS,GAA0C;AACxD,WAAO,IAAI,EAAS,EAAK,GAAG,EAAK,CAAA;AAAA;EAQnC,WAAmB;AACjB,WAAO,YAAY,KAAK,CAAA,KAAM,KAAK,CAAA;AAAA;;AAqCvC,SAAgB,GACd,GACA,GACA,IAAc,OACN;AAER,MAAI,EAAU,WAAW,EACvB,QAAO;AAIT,MAAI,EAAU,WAAW,EACvB,QAAO;AAGT,MAAI,IAAY;AAGhB,WAAS,IAAI,GAAG,IAAI,EAAU,SAAS,GAAG,KAAK;AAC7C,UAAM,IAAe,EAAU,CAAA,GACzB,IAAa,EAAU,IAAI,CAAA,GAE3B,IAAW,GAAuB,GAAQ,GAAc,CAAA;AAE9D,IAAI,IAAW,MACb,IAAc,GACd,IAAY,IAAI;AAAA;AAIpB,SAAO;;AAWT,SAAS,GACP,GACA,GACA,GACQ;AACR,QAAM,IAAK,EAAW,IAAI,EAAa,GACjC,IAAK,EAAW,IAAI,EAAa,GAGjC,IAAuB,IAAK,IAAK,IAAK;AAC5C,MAAI,MAAyB,EAC3B,QAAO,KAAK,MAAM,EAAM,IAAI,EAAa,MAAM,KAAK,EAAM,IAAI,EAAa,MAAM,CAAA;AAKnF,QAAM,IAAI,KAAK,IACb,GACA,KAAK,IACH,KACE,EAAM,IAAI,EAAa,KAAK,KAAM,EAAM,IAAI,EAAa,KAAK,KAAM,CAAA,CACvE,GAIG,IAAW,EAAa,IAAI,IAAI,GAChC,IAAW,EAAa,IAAI,IAAI;AAGtC,SAAO,KAAK,MAAM,EAAM,IAAI,MAAa,KAAK,EAAM,IAAI,MAAa,CAAA;;AAuCvE,SAAgB,EAAkB,GAAuB,IAAoB,GAAe;AAE1F,MAAI,EAAU,UAAU,EACtB,QAAO,CAAC,GAAG,CAAA;AAIb,QAAM,IAAqB,CAAC,EAAU,CAAA,CAAA;AAGtC,WAAS,IAAI,GAAG,IAAI,EAAU,SAAS,GAAG,KAAK;AAC7C,UAAM,IAAO,EAAO,EAAO,SAAS,CAAA,GAC9B,IAAU,EAAU,CAAA,GACpB,IAAO,EAAU,IAAI,CAAA;AAG3B,IAAK,GAAa,GAAM,GAAS,GAAM,CAAA,KACrC,EAAO,KAAK,CAAA;AAAA;AAMhB,SAAA,EAAO,KAAK,EAAU,EAAU,SAAS,CAAA,CAAA,GAElC;;AAeT,SAAS,GAAa,GAAa,GAAa,GAAa,IAAoB,GAAY;AAI3F,QAAM,KAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AACxE,SAAO,KAAK,IAAI,CAAA,KAAiB;;AChRnC,IAAa,KAAb,MAAa,EAAS;AAAA,EAOpB,YAAY,GAA+B;AACzC,QAD0B,KAAA,QAAA,GACtB,CAAC,OAAO,UAAU,CAAA,EACpB,OAAM,IAAI,UAAU,0CAA0C,CAAA,GAAM;AAAA;EAgBxE,SAAiB;AACf,WAAO,KAAK;AAAA;EAgBd,OAAO,SAAS,GAAyB;AACvC,WAAO,IAAI,EAAS,CAAA;AAAA;EAmBtB,OAAO,GAA0B;AAC/B,WAAO,KAAK,UAAU,EAAM;AAAA;EAQ9B,WAAmB;AACjB,WAAO,YAAY,KAAK,KAAA;AAAA;;ACvE5B,SAAgB,IAAqB;AAEnC,MAAI,OAAO,SAAW,OAAe,OAAO,WAC1C,QAAO,OAAO,WAAA;AAMhB,QAAM,IAAY,oBACZ,IAAW;AAAA,IAAC;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,KACxB,IAAkB,CAAA;AAExB,aAAW,KAAU,GAAU;AAC7B,QAAI,IAAO;AACX,aAAS,IAAI,GAAG,IAAI,GAAQ,KAAK;AAC/B,YAAM,IAAa,KAAK,MAAM,KAAK,OAAA,IAAW,EAAA;AAC9C,MAAA,KAAQ,EAAU,CAAA;AAAA;AAEpB,IAAA,EAAM,KAAK,CAAA;AAAA;AAKb,QAAM,IADO,EAAM,KAAK,GAAA,EACL,MAAM,EAAA;AAGzB,SAAA,EAAM,EAAA,IAAM,KAKZ,EAAM,EAAA,IAAM,EAFQ,SAAS,EAAM,EAAA,KAAO,KAAK,EAAA,IACX,IAAO,CAAA,KACJ,KAEhC,EAAM,KAAK,EAAA;;AChDpB,IAAa,IAAuB,UAUxB,IAAL,0BAAA,GAAA;AACL,SAAA,EAAA,UAAA,WACA,EAAA,UAAA;QAgBU,IAAL,0BAAA,GAAA;AAUL,SAAA,EAAA,MAAA,OAUA,EAAA,iBAAA;QAsCW,KAAoC;AAAA,EAAC;AAAA,EAAS;AAAA,EAAQ;GAGtD,IAAoC,SA2DrC,IAAL,0BAAA,GAAA;AAEL,SAAA,EAAA,OAAA,QACA,EAAA,QAAA,SACA,EAAA,UAAA,WACA,EAAA,SAAA,UACA,EAAA,oBAAA,qBACA,EAAA,YAAA,aACA,EAAA,QAAA,SACA,EAAA,WAAA,YACA,EAAA,eAAA,gBACA,EAAA,QAAA,SAEA,EAAA,WAAA,YACA,EAAA,WAAA,YACA,EAAA,YAAA,aACA,EAAA,YAAA,aACA,EAAA,UAAA,WACA,EAAA,WAAA,YACA,EAAA,WAAA,YACA,EAAA,UAAA,WACA,EAAA,WAAA,YACA,EAAA,WAAA;QAUW,IAAmF;AAAA,GAC7F,EAAc,MAAA,GAAS;AAAA,IACtB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CACZ,CAAC,SAAS;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,GACpD,CAAC,UAAU;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,CAAC,CACvD;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,gBAAgB,MAAA;AAAA,MACjB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,QAAQ,GAAA;AAAA,KACV;AAAA;GAEF,EAAc,iBAAA,GAAoB;AAAA,IACjC,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,MACrD,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,MACrD,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,KACtD;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,gBAAgB,QAAA;AAAA,MACjB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,QAAQ,GAAA;AAAA,KACV;AAAA;GAEF,EAAc,OAAA,GAAU;AAAA,IACvB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CACZ,CAAC,WAAW;AAAA,MAAE,SAAS;AAAA,MAAW,YAAY,EAAgB;AAAA,KAAS,GACvE,CAAC,SAAS;AAAA,MAAE,SAAS;AAAA,MAAW,YAAY,EAAgB;AAAA,KAAS,CAAC,CACvE;AAAA,IACD,QAAQ,oBAAI,IAAI,CAAA,CAAE;AAAA;GAEnB,EAAc,SAAA,GAAY;AAAA,IACzB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CACZ,CAAC,QAAQ;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,GACnD,CAAC,QAAQ;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,CAAC,CACrD;AAAA,IACD,QAAQ,oBAAI,IAAI,CACd,CAAC,kBAAkB,GAAA,GACnB,CAAC,QAAQ,GAAA,CAAI,CACd;AAAA;GAEF,EAAc,KAAA,GAAQ;AAAA,IACrB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,MACrD,CAAC,WAAW;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,MACtD,CAAC,YAAY;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,MACvD,CAAC,aAAa;AAAA,QAAE,SAAS;AAAA,QAAQ,YAAY;AAAA,OAAW;AAAA,KACzD;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CACZ,CAAC,QAAQ;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,GACnD,CAAC,QAAQ;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,CAAC,CACrD;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,aAAa,OAAA;AAAA,MACd,CAAC,eAAe,SAAA;AAAA,MAChB,CAAC,QAAQ,GAAA;AAAA,MACT,CAAC,WAAW,GAAA;AAAA,KACb;AAAA;GAEF,EAAc,YAAA,GAAe;AAAA,IAC5B,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CACZ,CAAC,QAAQ;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,GACnD,CAAC,QAAQ;AAAA,MAAE,SAAS;AAAA,MAAQ,YAAY;AAAA,KAAW,CAAC,CACrD;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,aAAa,OAAA;AAAA,MACd,CAAC,eAAe,SAAA;AAAA,MAChB,CAAC,QAAQ,GAAA;AAAA,MACT,CAAC,WAAW,GAAA;AAAA,MACZ,CAAC,WAAW,GAAA;AAAA,KACb;AAAA;GAEF,EAAc,IAAA,GAAO;AAAA,IACpB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CAAA,CAAE;AAAA,IAChB,QAAQ,oBAAI,IAAI,CAAC,CAAC,SAAS,KAAA,CAAM,CAAC;AAAA;GAEnC,EAAc,KAAA,GAAQ;AAAA,IACrB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI,CAAA,CAAE;AAAA,IAChB,QAAQ,oBAAI,IAAI,CACd,CAAC,QAAQ,OAAA,GACT,CAAC,QAAQ,GAAA,CAAI,CACd;AAAA;GAEF,EAAc,KAAA,GAAQ;AAAA,IACrB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI,CACd,CAAC,aAAa,MAAA,GACd,CAAC,cAAc,GAAA,CAAI,CACpB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,SAAS;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC1D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,SAAA,GAAY;AAAA,IACzB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,SAAA,GAAY;AAAA,IACzB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,OAAA,GAAU;AAAA,IACvB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,OAAA,GAAU;AAAA,IACvB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GAEF,EAAc,QAAA,GAAW;AAAA,IACxB,IAAI,EAAc;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,oBAAI,IAAI;AAAA,MACZ,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,MAC/D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAc,YAAY;AAAA,OAAW;AAAA,MAC3D,CAAC,UAAU;AAAA,QAAE,SAAS;AAAA,QAAe,YAAY;AAAA,OAAW;AAAA,MAC5D,CAAC,OAAO;AAAA,QAAE,SAAS;AAAA,QAAO,YAAY,EAAgB;AAAA,OAAS;AAAA,KAChE;AAAA,IACD,QAAQ,oBAAI,IAAI;AAAA,MACd,CAAC,sBAAsB,OAAA;AAAA,MACvB,CAAC,mBAAmB,UAAA;AAAA,MACpB,CAAC,kBAAkB,GAAA;AAAA,MACnB,CAAC,uBAAuB,EAAA;AAAA,KACzB;AAAA;GC5cQ,IAAb,MAAa,EAAM;AAAA,EAKjB;AAAA,EAMA;AAAA,EAOA;AAAA,EAOA;AAAA,EAOA;AAAA,EAMA;AAAA,EAKA;AAAA,EAMA;AAAA,EAoCA,YACE,GACA,GACA,GACA,GACA,IAAsC,QACtC,IAAkB,QAClB;AACA,SAAK,KAAK,EAAA,GACV,KAAK,OAAO,GACZ,KAAK,YAAY,GACjB,KAAK,WAAW,GAChB,KAAK,WAAW,GAChB,KAAK,QAAQ,oBAAI,IAAA,GACjB,KAAK,SAAS,GACd,KAAK,UAAU;AAAA;EA0BjB,YAAY,GAA4B;AACtC,QAAI,KAAK,SAAS,EAAU,KAAK;AAE/B,UAAI,CAAC,KAAK,UACR,OAAM,IAAI,MAAM,sCAAA;AAGlB,YAAM,IAAY,EAAQ,aAAa,KAAK,SAAA;AAC5C,UAAI,CAAC,EACH,OAAM,IAAI,MAAM,aAAa,KAAK,SAAA,2BAAoC,KAAK,EAAA,EAAA;AAK7E,aAAO,EAAU;AAAA;AAInB,QAAI,CAAC,KAAK,SACR,OAAM,IAAI,MAAM,uCAAA;AAGlB,WAAO,KAAK;AAAA;EAcd,YAAY,GAA6B;AACvC,WAAO,eAAe,MAAM,YAAY;AAAA,MACtC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf;AAAA;EAOH,cAAc,GAAgD;AAC5D,WAAO,eAAe,MAAM,UAAU;AAAA,MACpC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf;AAAA;EA4BH,SAAiB;AACf,UAAM,IAAe;AAAA,MACnB,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK,UAAU;AAAA,MACvB,SAAS,KAAK;AAAA;AAGhB,WAAI,KAAK,SAAS,EAAU,OAC1B,EAAK,YAAY,KAAK,aAAa,MACnC,EAAK,WAAW,KAAK,YAAY,QAEjC,EAAK,WAAW,KAAK,UAAU,OAAA,KAAY,MAGtC;AAAA;EAqBT,OAAO,SAAS,GAAqB;AACnC,UAAM,IAAW,EAAK,WAAW,EAAS,SAAS,EAAK,QAAA,IAAY,QAE9D,IAAQ,IAAI,EAChB,EAAK,MACL,EAAK,aAAa,QAClB,EAAK,YAAY,QACjB,GACA,EAAK,UAAU,QACf,EAAK,WAAW,MAAA;AAIlB,kBAAO,eAAe,GAAO,MAAM;AAAA,MACjC,OAAO,EAAK;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf,GAEM;AAAA;GC7QE,IAAb,MAAa,EAAK;AAAA,EAKhB;AAAA,EAMA;AAAA,EAMA;AAAA,EAOA;AAAA,EA0BA,YAAY,GAAa,GAAa,IAAyC,CAAA,GAAI;AACjF,SAAK,KAAK,EAAA,GACV,KAAK,QAAQ,GACb,KAAK,QAAQ,GACb,KAAK,wBAAwB;AAAA;EAiB/B,iBAA0B;AACxB,WAAO,KAAK,sBAAsB,WAAW;AAAA;EAoB/C,SAAgB;AACd,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,uBAAuB,KAAK,sBAAsB,IAAA,CAAK,MAAM,EAAE,OAAA,CAAQ;AAAA;;EAsB3E,OAAO,SAAS,GAAmB;AACjC,UAAM,IAAY,EAAK,sBAAsB,IAAA,CAAK,MAAM,EAAS,SAAS,CAAA,CAAE,GAEtE,IAAO,IAAI,EAAK,EAAK,OAAO,EAAK,OAAO,CAAA;AAG9C,kBAAO,eAAe,GAAM,MAAM;AAAA,MAChC,OAAO,EAAK;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf,GAEM;AAAA;GCxIE,IAAb,MAAa,EAAU;AAAA,EAKrB;AAAA,EAMA;AAAA,EAMA;AAAA,EAMA;AAAA,EAOA;AAAA,EASA;AAAA,EAKA;AAAA,EAiCA,YACE,GACA,GACA,GACA,GACA,IAAoB,IACpB;AAOA,QANA,KAAK,KAAK,EAAA,GACV,KAAK,OAAO,GACZ,KAAK,WAAW,GAChB,KAAK,WAAW,GAGZ,IAAI,IAAI,CAAA,EAAM,SAAS,EAAK,QAAQ;AACtC,YAAM,IAAa,EAAK,OAAA,CAAQ,GAAM,MAAU,EAAK,QAAQ,CAAA,MAAU,CAAA;AACvE,YAAM,IAAI,MACR,wCAAwC,CAAC,GAAG,IAAI,IAAI,CAAA,CAAW,EAAE,KAAK,IAAA,CAAK,EAAA;AAAA;AAI/E,SAAK,OAAO,GAEZ,KAAK,SAAS,IAAI,IAAoB,EAAwB,CAAA,EAAM,MAAA,GACpE,KAAK,WAAW;AAAA;EAGlB,YAAY,GAAiC;AAC3C,UAAM,IAAW,KAAK,KAAK,QAAQ,CAAA;AACnC,QAAI,MAAa,GACf;AAEF,UAAM,IAAY,EAAwB,KAAK,IAAA,EAAM,KAAK,KAAA;AAE1D,WAAO,MAAM,KAAK,CAAA,EAAW,CAAA,KAAa;AAAA;EAG5C,iBAAiB,GAAmC;AAClD,SAAK,SAAS,IAAI,IAAoB,CAAA;AAAA;EAGxC,aAAa,GAAa,GAAqB;AAC7C,SAAK,OAAO,IAAI,GAAK,CAAA;AAAA;EAcvB,YAAY,GAA6B;AACvC,WAAO,eAAe,MAAM,YAAY;AAAA,MACtC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf;AAAA;EAcH,YAAY,GAA6B;AACvC,WAAO,eAAe,MAAM,YAAY;AAAA,MACtC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf;AAAA;EAqBH,SAAqB;AACnB,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,UAAU,KAAK,SAAS,OAAA;AAAA,MACxB,UAAU,KAAK,SAAS,OAAA;AAAA,MACxB,MAAM,CAAC,GAAG,KAAK,IAAA;AAAA,MACf,QAAQ,OAAO,YAAY,KAAK,MAAA;AAAA,MAChC,UAAU,KAAK;AAAA;;EAWnB,OAAO,SAAS,GAA6B;AAE3C,UAAM,IAAY,IAAI,EACpB,EAAK,MACL,EAAS,SAAS,EAAK,QAAA,GACvB,GAAS,SAAS,EAAK,QAAA,GACvB,EAAK,MACL,EAAK,QAAA;AAEP,WAAA,EAAU,SAAS,IAAI,IAAoB,OAAO,QAAQ,EAAK,MAAA,CAAO,GAItE,OAAO,eAAe,GAAW,MAAM;AAAA,MACrC,OAAO,EAAK;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf,GAEM;AAAA;GCvPE,IAAb,MAAa,EAA0C;AAAA,EAOrD,YACE,IAAsB,oBACtB,IAAyC,GACzC;AAFO,SAAA,OAAA,GACA,KAAA,qBAAA;AAAA;EAGT,SAA0B;AACxB,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,oBAAoB,KAAK;AAAA;;EAI7B,OAAO,SAAS,GAAuC;AACrD,WAAO,IAAI,EAAe,EAAK,MAAM,EAAK,kBAAA;AAAA;GCjBjC,IAAb,MAAa,EAA4C;AAAA,EAWvD,YACE,GACA,GACA,GACA,GACA,GACA;AACA,QANO,KAAA,UAAA,GACA,KAAA,UAAA,GACA,KAAA,OAAA,GACA,KAAA,YAAA,GACA,KAAA,gBAAA,GAEH,CAAC,OAAO,UAAU,CAAA,KAAS,CAAC,OAAO,UAAU,CAAA,EAC/C,OAAM,IAAI,UACR,iDAAiD,CAAA,eAAmB,CAAA,GAAU;AAAA;EAKpF,SAA2B;AACzB,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,SAAS,KAAK,QAAQ,OAAA;AAAA,MACtB,MAAM,KAAK;AAAA,MACX,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK,cAAc,OAAA;AAAA;;EAItC,OAAO,SAAS,GAAyC;AACvD,IAA6B,EAAK,YAAlC,YACE,QAAQ,KAAK,wCAAwC,CAAA;AAAA,gDACX,EAAK,OAAA,GAAQ;AAGzD,UAAM,IAAU,EAAK,UACjB,EAAe,SAAS,EAAK,OAAA,IAC7B,IAAI,EAAe,oBAAoB,CAAA;AAC3C,WAAO,IAAI,EACT,EAAK,SACL,GACA,EAAK,MACL,EAAK,WACL,EAAc,SAAS,EAAK,aAAA,CAAc;AAAA;EAI9C,WAAmB;AACjB,WAAO,mBAAmB,KAAK,OAAA,KAAY,KAAK,QAAQ,IAAA,KAAS,KAAK,QAAQ,kBAAA,KAAuB,KAAK,IAAA,KAAS,KAAK,SAAA,KAAc,KAAK,cAAc,SAAA,CAAU;AAAA;GClDjK,KAAoC;AAAA,EAAE,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,IAAI;GAC5D,KAAmC;AAAA,EAAE,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,IAAI;GAC3D,KAAmC;AAAA,EAAE,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,IAAI;GAC3D,KAAkC;AAAA,EAAE,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,GAAG;AAAA,EAAG,IAAI;;AAahE,SAAgB,GAAsB,GAA0C;AAC9E,QAAM,IAAc,EAAU,OAAO,IAAI,oBAAA;AACzC,MAAI,GAAC,KAAe,MAAgB,cAIhC,GAAY,EAAU,IAAA,GAAO;AAC/B,UAAM,IAAkB,EAAU,OAAO,IAAI,iBAAA,KAAsB,YAC7D,IAAU,GAAa,EAAU,MAAM,CAAA;AAC7C,WAAK,KACS,GAAiB,GAAa,EAAQ,YAAY,EAAQ,UAAA,KACxD;AAAA;;AAOpB,SAAS,GAAY,GAA8B;AACjD,SAAO;AAAA,IACL,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,EAAc;AAAA,IACd,SAAS,CAAA;;AAYb,SAAgB,GACd,GACA,GACuD;AACvD,UAAQ,GAAR;AAAA,IACE,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,QAAQ;AAAA,QAAU,YAAY;AAAA;IACtF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,SAAS;AAAA,QAAO,YAAY;AAAA;IACpF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,SAAS;AAAA,QAAO,YAAY;AAAA;IACpF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,SAAS;AAAA,QAAO,YAAY;AAAA;IACpF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,QAAQ;AAAA,QAAM,YAAY;AAAA;IAClF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,QAAQ;AAAA,QAAM,YAAY;AAAA;IAClF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,QAAQ;AAAA,QAAM,YAAY;AAAA;IAClF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,SAAS;AAAA,QAAO,YAAY;AAAA;IACpF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,SAAS;AAAA,QAAO,YAAY;AAAA;IACpF,KAAK,EAAc;AACjB,aAAO;AAAA,QAAE,YAAY,MAAoB,aAAa,SAAS;AAAA,QAAO,YAAY;AAAA;IACpF;AACE,aAAO;AAAA;;AA4Bb,SAAgB,GACd,GACA,GACA,GACQ;AACR,MAAI,MAAgB,UAClB,OAAM,IAAI,MAAM,wDAAA;AAIlB,MAAI,MAAe,MAAO,QAAO;AACjC,MAAI,MAAe,SAAU,QAAO;AAGpC,MAAI,MAAe,MAAO,QAAO,KAAK,KAAK,CAAA,IAAc;AACzD,MAAI,MAAe,OAAQ,QAAO,KAAK,KAAK,CAAA,IAAc,IAAI;AAE9D,MAAI,MAAgB,SAAS;AAC3B,UAAM,IAAQ,KAAK,KAAK,CAAA;AACxB,YAAQ,GAAR;AAAA,MACE,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,IAAQ;AAAA,MACjB,KAAK;AACH,eAAO,IAAQ;AAAA;;AAIrB,MAAI,MAAgB,QAAQ;AAC1B,QAAI;AACJ,YAAQ,GAAR;AAAA,MACE,KAAK;AACH,QAAA,IAAQ;AACR;AAAA,MACF,KAAK;AACH,QAAA,IAAQ;AACR;AAAA,MACF,KAAK;AACH,QAAA,IAAQ;AACR;AAAA,MACF,KAAK;AACH,QAAA,IAAQ;AACR;AAAA;AAEJ,UAAM,IAAQ,EAAO,CAAA;AACrB,QAAI,MAAU,OACZ,OAAM,IAAI,MAAM,2BAA2B,CAAA,aAAuB,CAAA,EAAA;AAEpE,WAAO;AAAA;AAIT,QAAM,IAAI,MAAM,6BAA6B,CAAA,EAAA;;AC7G/C,IAAa,KAAb,MAAa,EAAQ;AAAA,EAKnB;AAAA,EAMA;AAAA,EAOA;AAAA,EAMA;AAAA,EAKA,YAAY,GAAyB;AACnC,SAAK,WAAW,IAAI,EAAgB,GAAsB,GAAS,IAAI,IAAI,IAAI,EAAA,CAAe,GAE9F,KAAK,aAAa,oBAAI,IAAA,GACtB,KAAK,SAAS,oBAAI,IAAA,GAClB,KAAK,QAAQ,oBAAI,IAAA;AAAA;EAGnB,IAAI,OAAe;AACjB,WAAO,KAAK,SAAS,QAAQ;AAAA;EAG/B,IAAI,KAAK,GAAe;AACtB,QAAI,OAAO,KAAU,YAAY,EAAM,KAAA,MAAW,GAChD,OAAM,IAAI,UAAU,yCAAA;AAEtB,SAAK,SAAS,QAAQ,OAAO;AAAA;EA8B/B,aACE,GACA,GACA,GACA,GACW;AAEX,UAAM,IAAW,EAAwB,CAAA,GAGnC,IAAY,IAAI,EAAU,GAAM,GAAU,GAAU,CAAA,CAAE;AAC5D,QAAI,EACF,YAAW,CAAC,GAAK,CAAA,KAAU,EACzB,CAAA,EAAU,OAAO,IAAI,GAAK,CAAA;AAK9B,IAAI,EAAU,OAAO,IAAI,oBAAA,KAAyB,CAAC,EAAU,OAAO,IAAI,oBAAA,KACtE,EAAU,OAAO,IAAI,sBAAsB,KAAK,SAAS,QAAQ,kBAAA,GAInE,KAAK,sBAAsB,CAAA;AAG3B,UAAM,IAAe,CAAA;AACrB,eAAW,CAAC,GAAU,CAAA,KAAY,EAAS,MAAM;AAC/C,YAAM,IAAU,IAAI,EAClB,EAAU,KACV,EAAU,IACV,GACA,QACA,EAAQ,YACR,EAAQ,OAAA;AAIV,WAAK,OAAO,IAAI,EAAQ,IAAI,CAAA,GAG5B,EAAK,KAAK,EAAQ,EAAA;AAAA;AAKpB,kBAAO,eAAe,GAAW,QAAQ;AAAA,MACvC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,KACf,GAGD,KAAK,WAAW,IAAI,EAAU,IAAI,CAAA,GAE3B;AAAA;EAST,sBAAsB,GAA4B;AAChD,QAAI,CAAC,EAAU,OAAO,IAAI,gBAAA,EACxB;AAEF,UAAM,IAAQ,GAAsB,CAAA;AACpC,IAAM,KACJ,EAAU,OAAO,IAAI,kBAAkB,OAAO,CAAA,CAAM;AAAA;EAqBxD,gBAAgB,GAGd;AACA,UAAM,IAAY,KAAK,WAAW,IAAI,CAAA;AAEtC,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,aAAa,CAAA,iBAAG;AAGlC,UAAM,IAAuB,CAAA,GACvB,IAAwB,CAAA;AAG9B,eAAW,KAAS,EAAU,MAAM;AAClC,YAAM,IAAQ,KAAK,OAAO,IAAI,CAAA;AAC9B,UAAI,GAAO;AAET,cAAM,IAAU,MAAM,KAAK,EAAM,KAAA;AACjC,mBAAW,KAAU;AACnB,eAAK,WAAW,CAAA,GAChB,EAAa,KAAK,CAAA;AAAA;AAItB,WAAK,OAAO,OAAO,CAAA,GACnB,EAAc,KAAK,CAAA;AAAA;AAIrB,gBAAK,WAAW,OAAO,CAAA,GAChB;AAAA,MAAE,cAAA;AAAA,MAAc,eAAA;AAAA;;EAGzB,aAAa,GAAmB;AAC9B,WAAO,KAAK,WAAW,IAAI,CAAA;AAAA;EAiB7B,aAAa,GAAiC;AAC5C,WAAO,KAAK,WAAW,IAAI,CAAA;AAAA;EAoB7B,mBAAgC;AAC9B,WAAO,MAAM,KAAK,KAAK,WAAW,OAAA,CAAQ;AAAA;EAG5C,uBAAuB,GAAkC;AACvD,UAAM,IAAsB,CAAA;AAC5B,eAAW,KAAa,KAAK,WAAW,OAAA,EACtC,CAAI,EAAU,SAAS,KACrB,EAAO,KAAK,CAAA;AAGhB,WAAO;AAAA;EAGT,wBAAwB,GAA4C;AAClE,eAAW,KAAa,KAAK,WAAW,OAAA,EACtC,KAAI,EAAU,SAAS,EACrB,QAAO;AAAA;EA4Bb,SAAS,GAA6B;AACpC,WAAO,KAAK,OAAO,IAAI,CAAA;AAAA;EAuBzB,eAAwB;AACtB,WAAO,MAAM,KAAK,KAAK,OAAO,OAAA,CAAQ;AAAA;EAWxC,kBAAkB,GAAoB,GAAqC;AACzE,UAAM,IAAiB,IAAI,EACzB,EAAU,gBACV,QACA,QACA,GACA,CAAA;AAIF,gBAAK,OAAO,IAAI,EAAe,IAAI,CAAA,GAE5B;AAAA;EAWT,qBAAqB,GAInB;AACA,UAAM,IAAQ,KAAK,OAAO,IAAI,CAAA;AAE9B,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,SAAS,CAAA,iBAAG;AAE9B,QAAI,EAAM,SAAS,EAAU,eAC3B,OAAM,IAAI,MACR,SAAS,CAAA,mEAAG;AAIhB,UAAM,IAAS,CAAA,GAGT,IAAQ,KAAK,eAAe,CAAA;AAElC,QAAI,EAAM,WAAW,KAAK,EAAM,SAAS,GAAG;AAC1C,YAAM,IAAuB,CAAA;AAC7B,iBAAW,KAAQ;AACjB,aAAK,WAAW,EAAK,EAAA,GACrB,EAAa,KAAK,EAAK,EAAA;AAEzB,aAAO,OAAO,GAAQ,EAAE,cAAA,EAAA,CAAc;AAAA,eAC7B,EAAM,WAAW,GAAG;AAE7B,YAAM,IAAQ,EAAM,CAAA,GACd,IAAQ,EAAM,CAAA,GAGd,IAAa,EAAM,UAAU,IAAK,EAAM,QAAQ,EAAM,OACtD,IAAa,EAAM,UAAU,IAAK,EAAM,QAAQ,EAAM,OAGtD,IAAoC,CAAA;AAC1C,MAAI,MAAe,EAAM,QACvB,EAAsB,KAAK,GAAG,EAAM,qBAAA,IAC3B,MAAe,EAAM,SAC9B,EAAsB,KAAK,GAAG,CAAC,GAAG,EAAM,qBAAA,EAAuB,QAAA,CAAS,GAE1E,EAAsB,KAAK,EAAM,YAAY,IAAA,CAAK,GAC9C,MAAe,EAAM,QACvB,EAAsB,KAAK,GAAG,CAAC,GAAG,EAAM,qBAAA,EAAuB,QAAA,CAAS,IAC/D,MAAe,EAAM,SAC9B,EAAsB,KAAK,GAAG,EAAM,qBAAA,GAItC,KAAK,WAAW,EAAM,EAAA,GACtB,KAAK,WAAW,EAAM,EAAA;AAGtB,YAAM,IAAU,KAAK,QAAQ,GAAY,GAAY,CAAA;AACrD,UAAI,aAAmB,MACrB,OAAM,IAAI,MAAM,4CAA4C,CAAA,KAAO,EAAQ,OAAA,EAAA;AAE7E,aAAO,OAAO,GAAQ,EAAE,aAAa,CAAC,EAAM,IAAI,EAAM,EAAA,EAAG,CAAE,GAC3D,OAAO,OAAO,GAAQ,EAAW,SAAA,EAAA,CAAS;AAAA;AAI5C,gBAAK,OAAO,OAAO,CAAA,GACZ;AAAA;EAyBT,QAAQ,GAAa,GAAa,GAAkD;AAElF,QAAI,MAAU,EACZ,QAAO,oBAAI,MAAM,8CAAA;AAInB,UAAM,IAAS,KAAK,OAAO,IAAI,CAAA,GACzB,IAAS,KAAK,OAAO,IAAI,CAAA;AAE/B,QAAI,CAAC,KAAU,CAAC,EACd,QAAO,oBAAI,MAAM,2CAAA;AAInB,QAAI,KAAK,eAAe,GAAO,CAAA,EAC7B,QAAO,oBAAI,MAAM,mCAAA;AAInB,UAAM,IAAO,IAAI,EAAK,GAAO,GAAO,KAAyB,CAAA,CAAE;AAG/D,gBAAK,MAAM,IAAI,EAAK,IAAI,CAAA,GAGxB,EAAO,MAAM,IAAI,EAAK,EAAA,GACtB,EAAO,MAAM,IAAI,EAAK,EAAA,GAEf;AAAA;EAeT,WAAW,GAAgB;AACzB,UAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAE5B,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,QAAQ,CAAA,iBAAG;AAI7B,UAAM,IAAS,KAAK,OAAO,IAAI,EAAK,KAAA,GAC9B,IAAS,KAAK,OAAO,IAAI,EAAK,KAAA;AAGpC,IAAI,KACF,EAAO,MAAM,OAAO,CAAA,GAElB,KACF,EAAO,MAAM,OAAO,CAAA,GAItB,KAAK,MAAM,OAAO,CAAA;AAAA;EAgCpB,UACE,GACA,GACA,IAA6B,MAI7B;AACA,UAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAE5B,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,QAAQ,CAAA,iBAAO;AAIjC,UAAM,IAAS,KAAK,OAAO,IAAI,EAAK,KAAA,GAC9B,IAAS,KAAK,OAAO,IAAI,EAAK,KAAA;AAEpC,QAAI,CAAC,KAAU,CAAC,EACd,OAAM,IAAI,MAAM,QAAQ,CAAA,sCAAO;AAIjC,UAAM,IAAgB;AAAA,MACpB,EAAO,YAAY,IAAA;AAAA,MACnB,GAAG,EAAK;AAAA,MACR,EAAO,YAAY,IAAA;AAAA,OAEf,IAAQ,GAAsB,GAAe,CAAA,GAC7C,IAAiB,EAAc,MAAM,GAAG,CAAA,GACxC,IAAiB,EAAc,MAAM,GAAO,EAAc,SAAS,CAAA;AAGzE,SAAK,MAAM,OAAO,CAAA,GAClB,EAAO,MAAM,OAAO,CAAA,GACpB,EAAO,MAAM,OAAO,CAAA;AAEpB,QAAI;AACJ,QAAI,EACF,KAAK,KAAK,OAAO,IAAI,CAAA,EAGnB,CAAA,IAAQ,KAAK,OAAO,IAAI,CAAA;AAAA,QAFxB,OAAM,IAAI,MAAM,gBAAgB,CAAA,iBAAc;AAAA,QAMhD,CAAA,IAAQ,KAAK,kBAAkB,CAAA;AAGjC,UAAM,IAAW,CAAA;AAEjB,SACG,CAAC,EAAM,aAAa,EAAO,cAAc,EAAM,cAChD,CAAC,KAAK,eAAe,EAAO,IAAI,EAAM,EAAA,GACtC;AACA,YAAM,IAAS,KAAK,QAAQ,EAAO,IAAI,EAAM,IAAI,CAAA;AACjD,MAAI,aAAkB,KACpB,KAAK,kCAAkC,EAAO,EAAA,GAC9C,EAAS,KAAK,CAAA,KAEd,QAAQ,KAAK,qCAAqC,EAAO,OAAA,EAAA;AAAA;AAG7D,SACG,CAAC,EAAM,aAAa,EAAO,cAAc,EAAM,cAChD,CAAC,KAAK,eAAe,EAAO,IAAI,EAAM,EAAA,GACtC;AACA,YAAM,IAAS,KAAK,QAAQ,EAAM,IAAI,EAAO,IAAI,CAAA;AACjD,MAAI,aAAkB,KACpB,KAAK,kCAAkC,EAAO,EAAA,GAC9C,EAAS,KAAK,CAAA,KAEd,QAAQ,KAAK,qCAAqC,EAAO,OAAA,EAAA;AAAA;AAI7D,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,OAAO;AAAA;;EAIX,oBAAoB,GAAa,GAA+B;AAC9D,UAAM,IAAS,KAAK,OAAO,IAAI,CAAA;AAC/B,QAAK;AAIL,iBAAW,KAAU,EAAO,OAAO;AACjC,cAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAC5B,YAAI,MAAS,EAAK,UAAU,KAAS,EAAK,UAAU,GAClD,QAAO;AAAA;;EAYb,QAAQ,GAA4B;AAClC,WAAO,KAAK,MAAM,IAAI,CAAA;AAAA;EAUxB,cAAsB;AACpB,WAAO,MAAM,KAAK,KAAK,MAAM,OAAA,CAAQ;AAAA;EASvC,eAAe,GAAsB;AACnC,UAAM,IAAQ,KAAK,OAAO,IAAI,CAAA;AAC9B,QAAI,CAAC,EACH,QAAO,CAAA;AAGT,UAAM,IAAgB,CAAA;AACtB,eAAW,KAAU,EAAM,OAAO;AAChC,YAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAC5B,MAAI,KACF,EAAM,KAAK,CAAA;AAAA;AAIf,WAAO;AAAA;EAST,oBAAoB,GAA2B;AAC7C,UAAM,IAAY,KAAK,WAAW,IAAI,CAAA;AACtC,QAAI,CAAC,EACH,QAAO,CAAA;AAET,UAAM,IAAgB,CAAA;AAEtB,eAAW,KAAS,EAAU,KAC5B,CAAA,EAAM,KAAK,GAAG,KAAK,eAAe,CAAA,CAAM;AAG1C,WAAO;AAAA;EAST,eAAe,GAA0C;AACvD,UAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAC5B,QAAI,CAAC,EACH;AAGF,UAAM,IAAQ,KAAK,OAAO,IAAI,EAAK,KAAA,GAC7B,IAAQ,KAAK,OAAO,IAAI,EAAK,KAAA;AAEnC,QAAI,GAAC,KAAS,CAAC;AAIf,aAAO,CAAC,GAAO,CAAA;AAAA;EAYjB,eAAe,GAAa,GAAsB;AAChD,UAAM,IAAS,KAAK,OAAO,IAAI,CAAA;AAC/B,QAAI,CAAC,EACH,QAAO;AAIT,eAAW,KAAU,EAAO,OAAO;AACjC,YAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAC5B,UAAI,MAAS,EAAK,UAAU,KAAS,EAAK,UAAU,GAClD,QAAO;AAAA;AAIX,WAAO;AAAA;EAST,oBAAoB,GAA8B;AAChD,UAAM,IAAe,oBAAI,IAAA;AAEzB,eAAW,KAAW,GAAQ;AAC5B,YAAM,IAAQ,KAAK,OAAO,IAAI,CAAA;AAC9B,MAAM,GAAO,aACX,EAAa,IAAI,EAAM,SAAA;AAAA;AAG3B,WAAO;AAAA;EAQT,uBAAuB,GAAsB,GAAqC;AAChF,QAAI,IAAW;AACf,UAAM,IAAe,EAAwB,EAAU,IAAA,GACjD,IAAY,MAAM,KAAK,EAAa,KAAK,KAAA,CAAM;AACrD,eAAW,KAAS,EAAU,MAAM;AAClC,YAAM,IAAQ,KAAK,OAAO,IAAI,CAAA,GACxB,IAAQ,EAAU,CAAA;AACxB,UAAK,GACL;AAAA,YAAI,KAAS,MAAU,EACrB,QAAO;AAET,QAAA;AAAA;AAAA;;EAeJ,gCACE,GACA,GACA,IAAoB,IACd;AACN,UAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAE5B,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,QAAQ,CAAA,iBAAO;AAEjC,QAAI,GAAU;AAOZ,YAAM,IAA0B,EALV;AAAA,QACpB,KAAK,OAAO,IAAI,EAAK,KAAA,EAAQ,YAAY,IAAA;AAAA,QACzC,GAAG;AAAA,QACH,KAAK,OAAO,IAAI,EAAK,KAAA,EAAQ,YAAY,IAAA;AAAA,SAEsB,EAAA;AAEjE,MAAA,EAAK,wBAAwB,EAAwB,MACnD,GACA,EAAwB,SAAS,CAAA;AAAA,UAGnC,CAAA,EAAK,wBAAwB;AAG/B,WAAO;AAAA;EAUT,kCAAkC,GAAoB;AACpD,UAAM,IAAO,KAAK,MAAM,IAAI,CAAA;AAC5B,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,QAAQ,CAAA,iBAAO;AASjC,UAAM,IAA0B,EALV;AAAA,MACpB,KAAK,OAAO,IAAI,EAAK,KAAA,EAAQ,YAAY,IAAA;AAAA,MACzC,GAAG,EAAK;AAAA,MACR,KAAK,OAAO,IAAI,EAAK,KAAA,EAAQ,YAAY,IAAA;AAAA,OAEsB,CAAA;AAEjE,WAAA,EAAK,wBAAwB,EAAwB,MACnD,GACA,EAAwB,SAAS,CAAA,GAGnC,EAAK,wBAAwB,EAAkB,EAAK,qBAAA,GAC7C;AAAA;EAST,sBAAsB,GAAe,GAA0C;AAC7E,UAAM,IAAQ,KAAK,OAAO,IAAI,CAAA;AAE9B,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,SAAS,CAAA,iBAAQ;AAInC,IAAA,EAAM,SAAS,KAAc;AAAA;EAS/B,iBAAiB,IAAiB,GAAW;AAC3C,QAAI,IAAS;AACb,eAAW,KAAa,KAAK,WAAW,OAAA,EACtC,CAAA,IAAS,KAAK,IAAI,GAAQ,KAAK,IAAI,EAAU,SAAS,CAAA,GAAI,KAAK,IAAI,EAAU,SAAS,CAAA,CAAE;AAE1F,eAAW,KAAS,KAAK,OAAO,OAAA,GAAU;AACxC,UAAI,EAAM,SAAS,EAAU,IAAK;AAClC,YAAM,IAAM,EAAM;AAClB,MAAK,MACL,IAAS,KAAK,IAAI,GAAQ,KAAK,IAAI,EAAI,CAAA,GAAI,KAAK,IAAI,EAAI,CAAA,CAAE;AAAA;AAE5D,eAAW,KAAQ,KAAK,MAAM,OAAA,EAC5B,YAAW,KAAO,EAAK,sBACrB,CAAA,IAAS,KAAK,IAAI,GAAQ,KAAK,IAAI,EAAI,CAAA,GAAI,KAAK,IAAI,EAAI,CAAA,CAAE;AAG9D,WAAO,KAAK,KAAK,IAAS,IAAI,KAAK,IAAI,GAAQ,CAAA,CAAE;AAAA;EAcnD,SAAmB;AACjB,WAAO;AAAA,MACL,UAAU,KAAK,SAAS,OAAA;AAAA,MACxB,YAAY,KAAK,iBAAA,EAAmB,IAAA,CAAK,MAAM,EAAE,OAAA,CAAQ;AAAA,MACzD,QAAQ,KAAK,aAAA,EAAe,IAAA,CAAK,MAAM,EAAE,OAAA,CAAQ;AAAA,MACjD,OAAO,KAAK,YAAA,EAAc,IAAA,CAAK,MAAM,EAAE,OAAA,CAAQ;AAAA;;EAkBnD,OAAO,SAAS,GAAyB;AACvC,UAAM,IAAgB,EAAgB,SAAS,EAAK,QAAA,GAC9C,IAAU,IAAI,EAAQ,EAAc,OAAA;AAC1C,IAAA,EAAQ,WAAW;AAGnB,eAAW,KAAY,EAAK,YAAY;AACtC,YAAM,IAAY,EAAU,SAAS,CAAA;AACrC,MAAA,EAAQ,WAAW,IAAI,EAAU,IAAI,CAAA;AAAA;AAIvC,eAAW,KAAa,EAAK,QAAQ;AACnC,YAAM,IAAQ,EAAM,SAAS,CAAA;AAC7B,MAAA,EAAQ,OAAO,IAAI,EAAM,IAAI,CAAA;AAAA;AAI/B,QAAI,EAAK,MACP,YAAW,KAAY,EAAK,OAAO;AACjC,YAAM,IAAO,EAAK,SAAS,CAAA;AAC3B,MAAA,EAAQ,MAAM,IAAI,EAAK,IAAI,CAAA;AAG3B,YAAM,IAAS,EAAQ,OAAO,IAAI,EAAK,KAAA,GACjC,IAAS,EAAQ,OAAO,IAAI,EAAK,KAAA;AACvC,MAAI,KACF,EAAO,MAAM,IAAI,EAAK,EAAA,GAEpB,KACF,EAAO,MAAM,IAAI,EAAK,EAAA;AAAA;AAK5B,WAAO;AAAA;GC9/BE,KAAmB;AAAA,EAI9B,SAAS;AAAA,EAIT,SAAS;AAAA,EAIT,aAAa;AAAA,EAIb,qBAAqB;GAOV,IAAsB;AAAA,EAIjC,uBAAuB;AAAA,EAIvB,yBAAyB;;ACT3B,SAAgB,KAAyB,GAAsD;AAC7F,SAAO;AAAA,IACL,YAAY,EAAO,KAAA,CAAM,MAAM,EAAE,UAAA;AAAA,IACjC,YAAY,EAAO,KAAA,CAAM,MAAM,EAAE,UAAA;AAAA,IACjC,QAAQ;AAAA;;ACtBZ,IAAa,IAAb,MAAa,GAAgB;AAAA,EAK3B;AAAA,EAOA;AAAA,EAOA;AAAA,EAOA;AAAA,EAOA,YAAY,GAAc;AACxB,QAAI,IAAO,KAAK,CAAC,OAAO,UAAU,CAAA,EAChC,OAAM,IAAI,WAAW,4CAA4C,CAAA,GAAK;AAGxE,SAAK,OAAO,GACZ,KAAK,aAAa,oBAAI,IAAA,GACtB,KAAK,aAAa,oBAAI,IAAA,GACtB,KAAK,kBAAkB,oBAAI,IAAA;AAAA;EAG7B,QAAQ,GAAc;AACpB,SAAK,OAAO;AAAA;EAQd,QAAyB;AACvB,UAAM,IAAc,IAAI,GAAgB,KAAK,IAAA,GAEvC,IAAoD,oBAAI,IAAA;AAC9D,eAAW,CAAC,GAAI,CAAA,KAAU,KAAK,WAAW,QAAA,EACxC,CAAA,EAAiB,IAAI,GAAI,EAAE,GAAG,EAAA,CAAO;AAEvC,UAAM,IAAoD,oBAAI,IAAA;AAC9D,eAAW,CAAC,GAAI,CAAA,KAAU,KAAK,WAAW,QAAA,EACxC,CAAA,EAAiB,IAAI,GAAI,EAAE,GAAG,EAAA,CAAO;AAEvC,UAAM,IAAmD,oBAAI,IAAA;AAC7D,eAAW,CAAC,GAAI,CAAA,KAAU,KAAK,gBAAgB,QAAA,EAC7C,CAAA,EAAsB,IACpB,GACA,OAAO,OAAO,OAAO,OAAO,OAAO,eAAe,CAAA,CAAM,GAAG,CAAA,CAAM;AAIrE,kBAAO,eAAe,GAAa,cAAc;AAAA,MAC/C,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,KACb,GACD,OAAO,eAAe,GAAa,cAAc;AAAA,MAC/C,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,KACb,GACD,OAAO,eAAe,GAAa,mBAAmB;AAAA,MACpD,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,YAAY;AAAA,KACb,GAEM;AAAA;GCzFW,IAAtB,MAAqC;AAAA,EAKnC;AAAA,EAMA;AAAA,EAKA;AAAA,EAKA;AAAA,EAKA;AAAA,EAKA,aAAkC,oBAAI,IAAA;AAAA,EAMtC,YAA+C,oBAAI,IAAA;AAAA,EAQnD,YAAsB,GAAmB,GAAsB;AAC7D,SAAK,cAAc,GACnB,KAAK,SAAS,GACd,KAAK,aAAa,GAClB,KAAK,kBAAkB,IACvB,KAAK,aAAa;AAAA;EAGpB,IAAW,QAAgB;AACzB,WAAO,KAAK;AAAA;EAGd,SAAgB,GAAe,GAAyB;AACtD,SAAK,SAAS,GACd,KAAK,aAAa,GAClB,KAAK,kBAAkB,IACvB,KAAK,aAAa;AAAA;EAGpB,IAAW,YAAoB;AAC7B,WAAO,KAAK;AAAA;EAGd,IAAW,iBAAyB;AAClC,WAAO,KAAK;AAAA;EAGd,IAAW,YAA2B;AACpC,WAAO,KAAK;AAAA;EAGd,IAAW,gBAAyB;AAClC,WAAO,KAAK,mBAAmB,KAAK,CAAC,CAAC,KAAK,cAAc,KAAK,eAAe,KAAK;AAAA;EAGpF,aAAoB,GAAmB,GAA8B;AACnE,SAAK,aAAa,GAClB,KAAK,kBAAkB;AAAA;GCnFd,KAAb,cAAkC,EAAe;AAAA,EAM/C,YAAY,GAAmB;AAC7B,UAAM,GAAa,IAAA;AAAA;GCPV,KAAb,cAAoC,EAAe;AAAA,EAOjD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;EAMrB,IAAI,QAAiB;AACnB,WAAO,KAAK,UAAU,QAAQ,KAAK,UAAU;AAAA;GCfpC,KAAb,cAAmC,EAAe;AAAA,EAOhD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;EAMrB,IAAI,QAAiB;AACnB,WAAO,KAAK,UAAU,QAAQ,KAAK,UAAU;AAAA;GCtBpC,KAAb,cAAuC,GAAc;AAAA,GCOxC,KAAb,cAAgC,EAAe;AAAA,EAO7C,YAAY,GAAmB,IAAuB,QAAQ;AAC5D,UAAM,GAAa,CAAA;AAAA;EAMrB,IAAI,iBAA0B;AAC5B,WAAO,KAAK,UAAU,aAAa,KAAK,UAAU;AAAA;EAMpD,IAAI,WAAoB;AACtB,WAAO,KAAK,UAAU,YAAY,KAAK,UAAU;AAAA;GCtBxC,KAAb,cAAiC,EAAe;AAAA,EAO9C,YAAY,GAAmB,IAAuB,QAAQ;AAC5D,UAAM,GAAa,CAAA;AAAA;EAMrB,IAAI,iBAA0B;AAC5B,WAAO,KAAK,UAAU,aAAa,KAAK,UAAU;AAAA;EAMpD,IAAI,WAAoB;AACtB,WAAO,KAAK,UAAU,YAAY,KAAK,UAAU;AAAA;GCtBxC,KAAb,cAA4C,EAAe;AAAA,EAOzD,YAAY,GAAmB,IAAuB,UAAU;AAC9D,UAAM,GAAa,CAAA;AAAA;EAMrB,IAAI,iBAA0B;AAC5B,WAAO,KAAK,UAAU,UAAU,KAAK,UAAU;AAAA;GCjBtC,KAAb,cAAgC,EAAe;AAAA,EAM7C,YAAY,GAAmB;AAC7B,UAAM,GAAa,MAAA;AAAA;GCND,IAAtB,cAA6C,EAAe;AAAA,EAO1D,YAAsB,GAAmB,IAAuB,OAAO;AACrE,UAAM,GAAa,CAAA;AAAA;EAMrB,IAAI,iBAA0B;AAC5B,WAAO,KAAK,UAAU,YAAY,KAAK,UAAU;AAAA;EAMnD,IAAI,SAAkB;AACpB,WAAO,KAAK,UAAU;AAAA;GCtBb,KAAb,cAAmC,EAAe;AAAA,EAOhD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCTV,KAAb,cAAmC,EAAe;AAAA,EAOhD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCRV,KAAb,cAAoC,EAAe;AAAA,EACjD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAoC,EAAe;AAAA,EACjD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAkC,EAAe;AAAA,EAC/C,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAmC,EAAe;AAAA,EAChD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAmC,EAAe;AAAA,EAChD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAkC,EAAe;AAAA,EAC/C,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAmC,EAAe;AAAA,EAChD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCFV,KAAb,cAAmC,EAAe;AAAA,EAChD,YAAY,GAAmB,IAAuB,OAAO;AAC3D,UAAM,GAAa,CAAA;AAAA;GCCV,KAAb,MAA8B;AAAA,EAC5B;AAAA,EAKA,cAAc;AACZ,SAAK,YAAY,oBAAI,IAAA;AAAA;EAWvB,SAAS,GAAgD;AACvD,QAAI,CAAC,EACH,OAAM,IAAI,UAAU,sCAAA;AAGtB,QAAI,CAAC,EAAS,iBAAiB,EAAS,cAAc,KAAA,MAAW,GAC/D,OAAM,IAAI,UAAU,wCAAA;AAGtB,gBAAK,UAAU,IAAI,EAAS,eAAe,CAAA,GACpC;AAAA;EAST,YAAY,GAAuC;AACjD,IAAA,EAAU,QAAA,CAAS,MAAa,KAAK,SAAS,CAAA,CAAS;AAAA;EASzD,IAAI,GAAuD;AACzD,WAAO,KAAK,UAAU,IAAI,CAAA;AAAA;EAS5B,IAAI,GAAgC;AAClC,WAAO,KAAK,UAAU,IAAI,CAAA;AAAA;EAS5B,WAAW,GAAgC;AACzC,WAAO,KAAK,UAAU,OAAO,CAAA;AAAA;EAM/B,QAAc;AACZ,SAAK,UAAU,MAAA;AAAA;EAQjB,qBAA+B;AAC7B,WAAO,MAAM,KAAK,KAAK,UAAU,KAAA,CAAM;AAAA;EAQzC,OAAe;AACb,WAAO,KAAK,UAAU;AAAA;GCxFJ,IAAtB,MAA6C;AAAA,EAK3C;AAAA,EAEA,YAAY,GAA8B;AACxC,SAAK,iBAAiB;AAAA;EAGxB,IAAI,gBAA+B;AACjC,WAAO,KAAK;AAAA;EAGd,IAAc,eAAuC;AACnD,UAAM,IAAW,EAAwB,KAAK,cAAA;AAC9C,QAAI,CAAC,EACH,OAAM,IAAI,MAAM,uCAAuC,KAAK,cAAA,EAAA;AAE9D,WAAO;AAAA;EAGT,aACE,GACA,GACmC;AACnC,UAAM,IAA+C,oBAAI,IAAA;AACzD,eAAW,KAAS,EAAU,KAC5B,CAAA,EAAU,IAAI,EAAU,YAAY,CAAA,GAAS,EAAW,IAAI,CAAA,CAAc;AAE5E,WAAO;AAAA;EAGT,eACE,GACA,GACa;AACb,UAAM,IAAc,oBAAI,IAAA;AAExB,eAAW,CAAC,GAAK,CAAA,KAAa,GAAc;AAC1C,UAAI,CAAC,EAAc,IAAI,CAAA,EACrB;AAEF,YAAM,IAAY,EAAc,IAAI,CAAA;AACpC,OACE,EAAS,eAAe,GAAW,cACnC,EAAS,eAAe,GAAW,eAEnC,EAAY,IAAI,CAAA;AAAA;AAGpB,WAAO;AAAA;EAQT,QAAQ,GAAuB,GAAyD;AACtF,WAAO;AAAA;EAUT,aACE,GACA,GACA,GACA,GACiB;AACjB,WAAO;AAAA,MACW,gBAAA;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAYrB,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,WAAO;AAAA;EAGT,cACE,GACA,GACA,GACiB;AACjB,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAIrB,cACE,GACA,GACA,GACiB;AACjB,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;;AAUvB,SAAgB,EAAkB,GAAqC;AACrE,QAAM,IAAQ,SAAS,EAAO,IAAI,gBAAA,KAAqB,IAAI,EAAA;AAC3D,SAAI,MAAM,CAAA,KAAU,IAAQ,IACnB,EAAoB,wBAEtB;;ACrJT,IAAa,KAAb,cAAqC,EAAqD;AAAA,EACxF,cAAc;AACZ,UAAM,EAAc,OAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,+CAA+C,EAAU,IAAA,EAAA;AAE3E,WAAO,IAAI,GAAa,EAAU,EAAA;AAAA;GCjBhB,IAAtB,cAA+D,EAAuB;AAAA,EACpF,YACE,GACA,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AACjB,UAAM,IAAqC,CAAA,GAErC,IAAiB,EAAkB,EAAU,MAAA,GAC7C,IACJ,EAAM,iBAAiB,IAAI,IAAiB,KAAK,IAAI,IAAa,EAAM,WAAW,CAAA;AAErF,WAAI,KACE,EAAM,UAAU,SAAS,EAAM,UAAU,gBAC3C,IAAa,IACb,EAAM,SAAS,WAAW,CAAA,GAC1B,EAAM,aAAa,MAAM,IAAa,CAAA,GACtC,EAAgB,KAAK;AAAA,MACnB,UAAU,EAAU;AAAA,MACpB,iBAAiB,EAAM;AAAA,MACvB,aAAa,EAAM;AAAA,MACnB,MAAM;AAAA,MACN,YAAY;AAAA,KACb,MAGC,EAAM,UAAU,QAAQ,EAAM,UAAU,eAC1C,IAAa,IACb,EAAM,SAAS,YAAY,CAAA,GAC3B,EAAM,aAAa,OAAO,IAAa,CAAA,GACvC,EAAgB,KAAK;AAAA,MACnB,UAAU,EAAU;AAAA,MACpB,iBAAiB,EAAM;AAAA,MACvB,aAAa,EAAM;AAAA,MACnB,MAAM;AAAA,MACN,YAAY;AAAA,KACb,IAIE;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACJ,iBAAA;AAAA;;EAIrB,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,WAAO;AAAA;EAGT,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AAEjB,WAAI,EAAM,SAAS,gBACb,EAAM,UAAU,UAClB,IAAa,IACb,EAAM,SAAS,OAAO,EAAM,WAAA,KAErB,EAAM,SAAS,gBACpB,EAAM,UAAU,SAClB,IAAa,IACb,EAAM,SAAS,MAAM,EAAM,WAAA,IAIxB;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;GC/EV,KAAb,cACU,EAEV;AAAA,EACE,cAAc;AACZ,UAAM,EAAc,SAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,iDAAiD,EAAU,IAAA,EAAA;AAE7E,WAAO,IAAI,GAAe,EAAU,EAAA;AAAA;EAStC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAQ,EAAsB,EAAa,IAAI,MAAA,GAAU,EAAa,IAAI,MAAA,CAAO,GACjF,IAAsB,EAAM,cAAc,EAAM;AAEtD,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GCvCtD,KAAb,cACU,EAEV;AAAA,EACE,cAAc;AACZ,UAAM,EAAc,YAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,oDAAoD,EAAU,IAAA,EAAA;AAEhF,WAAO,IAAI,GAAkB,EAAU,EAAA;AAAA;EAUzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAQ,EAAsB,EAAa,IAAI,MAAA,GAAU,EAAa,IAAI,MAAA,CAAO,GACjF,IAAsB,EAAM,cAAc,EAAM;AAEtD,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;;ACjCnE,SAAS,GAAkB,GAAqC;AAC9D,QAAM,IAAQ,SAAS,EAAO,IAAI,gBAAA,KAAqB,IAAI,EAAA;AAC3D,SAAI,MAAM,CAAA,KAAU,IAAQ,IACnB,EAAoB,wBAEtB;;AAQT,IAAa,KAAb,cAAmC,EAAqD;AAAA,EACtF,cAAc;AACZ,UAAM,EAAc,KAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,6CAA6C,EAAU,IAAA,EAAA;AAEzE,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,WAAW;AAClF,WAAO,IAAI,GAAW,EAAU,IAAI,CAAA;AAAA;EAGtC,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,QAAI,MAAU,EAAY,QAAO;AACjC,UAAM,IAAW,EAAU,YAAY,CAAA,GACjC,IAAgB,EAAU,YAAY,CAAA;AAC5C,QAAI,CAAC,KAAY,CAAC,EAAe,QAAO;AACxC,UAAM,IAAY,CAAC,GAAU,CAAA;AAE7B,WAAI,EAAU,SAAS,QAAA,KAAa,EAAU,SAAS,SAAA,IAC9C,KAEL,EAAU,SAAS,UAAA,KAAe,EAAU,SAAS,WAAA,IAChD,EAAM,UAAU,YAAY,EAAM,UAAU,YAE9C;AAAA;EAUT,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAa,IACX,kBACA,EAAsB,EAAa,IAAI,QAAA,GAAY,EAAa,IAAI,SAAA,CAAU,CAAE,GAElF,EAAa,IACX,sBACA,EAAsB,EAAa,IAAI,UAAA,GAAc,EAAa,IAAI,WAAA,CAAY,CAAE;AAEtF,UAAM,IAAgB,EAAM;AAC5B,IAAA,EAAM,YAAY;AAClB,UAAM,IAAc,KAAK,eAAe,GAAc,CAAA,GAEhD,IAAW,EAAa,IAAI,gBAAA,GAC5B,IAAc,EAAS,cAAc,EAAS,YAC9C,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAc;AAE1E,QAAI,IAAa,EAAY,OAAO;AACpC,UAAM,IAAqC,CAAA,GACrC,IAAiB,GAAkB,EAAU,MAAA;AAEnD,QAAI;UACE,EAAM,UAAU,UAAU,EAAM,UAAU,WAAW;AAEvD,YAAI,IACF,EAAM,UAAU,SAAS,IAAiB,KAAK,IAAI,IAAa,EAAM,WAAW,CAAA;AACnF,QAAA,IAAa,IACb,EAAM,SAAS,WAAW,CAAA,GAC1B,EAAM,aAAa,UAAU,IAAa,CAAA,GAC1C,EAAgB,KAAK;AAAA,UACnB,UAAU,EAAU;AAAA,UACpB,iBAAiB,EAAM;AAAA,UACvB,aAAa,EAAM;AAAA,UACnB,MAAM;AAAA,UACN,YAAY,oBAAI,IAAI,CAAC,CAAC,aAAa,MAAA,CAAO,CAAC;AAAA,SAC5C;AAAA;eAGC,EAAM,UAAU,YAAY,EAAM,UAAU,WAAW;AAEzD,UAAI,IACF,EAAM,UAAU,WAAW,IAAiB,KAAK,IAAI,IAAa,EAAM,WAAW,CAAA;AACrF,MAAA,IAAa,IACb,EAAM,SAAS,WAAW,CAAA,GAC1B,EAAM,aAAa,QAAQ,IAAa,CAAA,GACxC,EAAgB,KAAK;AAAA,QACnB,UAAU,EAAU;AAAA,QACpB,iBAAiB,EAAM;AAAA,QACvB,aAAa,EAAM;AAAA,QACnB,MAAM;AAAA,QACN,YAAY,oBAAI,IAAI,CAAC,CAAC,aAAa,MAAA,CAAO,CAAC;AAAA,OAC5C;AAAA;AAIL,WAAO;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACJ,iBAAA;AAAA;;EAIrB,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AAEjB,WAAI,EAAM,SAAS,eACb,EAAM,UAAU,aAClB,EAAM,SAAS,UAAU,EAAM,WAAA,GAC/B,IAAa,MAEN,EAAM,SAAS,gBACpB,EAAM,UAAU,WAClB,EAAM,SAAS,QAAQ,EAAM,WAAA,GAC7B,IAAa,KAIV;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;GCjKV,KAAb,cACU,EAEV;AAAA,EACE,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,WAAO,IAAI,GAAc,EAAU,EAAA;AAAA;EAUrC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAQ,EAAsB,EAAa,IAAI,MAAA,GAAU,EAAa,IAAI,MAAA,CAAO,GACjF,IAAsB,EAAM,cAAc,EAAM;AAEtD,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GCnCtD,KAAb,cAAoC,EAAqD;AAAA,EACvF,cAAc;AACZ,UAAM,EAAc,MAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,8CAA8C,EAAU,IAAA,EAAA;AAE1E,UAAM,IAAQ,EAAU,OAAO,IAAI,cAAA,KAAmB;AACtD,WAAO,IAAI,GAAY,EAAU,IAAI,CAAA;AAAA;EAGvC,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,WAAO,EAAO,UAAU,YAAY,EAAO,UAAU;AAAA;EAUvD,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA,GAC5C,IAAgB,EAAM;AAC5B,IAAA,EAAM,YAAY;AAClB,UAAM,IAAc,KAAK,eAAe,GAAc,CAAA;AAEtD,WAAI,EAAY,OAAO,KAAK,CAAC,EAAY,IAAI,QAAA,IACpC;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA,QAId;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAIrB,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AACjB,UAAM,IAAqC,CAAA,GAErC,IAAiB,EAAkB,EAAU,MAAA;AAEnD,WAAI,EAAQ,SAAS,mBAAmB,CAAC,QAAQ,QAAA,EAAU,SAAS,EAAM,KAAA,MACxE,EAAM,SAAS,EAAM,UAAU,SAAS,YAAY,WAAW,EAAQ,eAAA,GACvE,EAAM,aACJ,EAAM,UAAU,YAAY,WAAW,QACvC,EAAQ,kBAAkB,CAAA,GAE5B,IAAa,IAEb,EAAgB,KAAK;AAAA,MACnB,UAAU,EAAU;AAAA,MACpB,iBAAiB,EAAM;AAAA,MACvB,aAAa,EAAM;AAAA,MACnB,MAAM,EAAM,UAAU,YAAY,eAAe;AAAA,MACjD,YAAY,oBAAI,IAAI,CAAC,CAAC,aAAa,MAAA,CAAO,CAAC;AAAA,KAC5C,IAGI;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACJ,iBAAA;AAAA;;EAIrB,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AAEjB,WAAI,EAAM,SAAS,eACb,EAAM,UAAU,aAClB,EAAM,SAAS,UAAU,EAAM,WAAA,GAC/B,IAAa,MAEN,EAAM,SAAS,gBACpB,EAAM,UAAU,WAClB,EAAM,SAAS,QAAQ,EAAM,WAAA,GAC7B,IAAa,KAIV;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;GCvHV,KAAb,cACU,EAEV;AAAA,EACE,cAAc;AACZ,UAAM,EAAc,iBAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,yDAAyD,EAAU,IAAA,EAAA;AAErF,UAAM,IAAQ,EAAU,OAAO,IAAI,cAAA,KAAmB;AACtD,WAAO,IAAI,GAAuB,EAAU,IAAI,CAAA;AAAA;EAGlD,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,QAAI,MAAU,EAAY,QAAO;AACjC,UAAM,IAAW,EAAU,YAAY,CAAA,GACjC,IAAgB,EAAU,YAAY,CAAA;AAC5C,QAAI,CAAC,KAAY,CAAC,EAAe,QAAO;AACxC,UAAM,IAAY,CAAC,GAAU,CAAA;AAE7B,WAAI,EAAU,SAAS,QAAA,KAAa,EAAU,SAAS,QAAA,IAC9C,EAAM,UAAU,YAAY,EAAM,UAAU,SAEjD,EAAU,SAAS,QAAA,KAAa,EAAU,SAAS,QAAA,IAC9C,EAAM,UAAU,YAAY,EAAM,UAAU,SAE9C;AAAA;EAUT,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA,GAC5C,IAAgB,EAAM;AAC5B,IAAA,EAAM,YAAY;AAClB,UAAM,IAAc,KAAK,eAAe,GAAc,CAAA;AAEtD,WAAI,EAAY,OAAO,KAAK,CAAC,EAAY,IAAI,QAAA,IACpC;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA,QAId;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAIrB,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AACjB,UAAM,IAAqC,CAAA,GAErC,IAAiB,EAAkB,EAAU,MAAA;AAEnD,WAAI,EAAQ,SAAS,mBAAmB,CAAC,UAAU,QAAA,EAAU,SAAS,EAAM,KAAA,MAC1E,EAAM,SAAS,EAAM,UAAU,WAAW,SAAS,QAAQ,EAAQ,eAAA,GACnE,EAAM,aACJ,EAAM,UAAU,SAAS,WAAW,UACpC,EAAQ,kBAAkB,CAAA,GAE5B,IAAa,IAEb,EAAgB,KAAK;AAAA,MACnB,UAAU,EAAU;AAAA,MACpB,iBAAiB,EAAM;AAAA,MACvB,aAAa,EAAM;AAAA,MACnB,MAAM,EAAM,UAAU,SAAS,oBAAoB;AAAA,MACnD,YAAY,oBAAI,IAAI,CAAC,CAAC,aAAa,MAAA,CAAO,CAAC;AAAA,KAC5C,IAGI;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACJ,iBAAA;AAAA;;EAIrB,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AAEjB,WAAI,EAAM,SAAS,oBACb,EAAM,UAAU,aAClB,EAAM,SAAS,UAAU,EAAM,WAAA,GAC/B,IAAa,MAEN,EAAM,SAAS,qBACpB,EAAM,UAAU,aAClB,EAAM,SAAS,UAAU,EAAM,WAAA,GAC/B,IAAa,KAIV;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;GClJV,KAAb,cAAmC,EAAqD;AAAA,EACtF,cAAc;AACZ,UAAM,EAAc,KAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,6CAA6C,EAAU,IAAA,EAAA;AAEzE,UAAM,IAAQ,IAAI,GAAW,EAAU,EAAA,GACjC,IAAY,EAAU,OAAO,IAAI,WAAA,KAAgB;AACvD,IAAA,EAAM,SAAS,IAAY,SAAS,OAAO,CAAA;AAC3C,UAAM,IAAa,OAAO,EAAU,OAAO,IAAI,YAAA,CAAa;AAC5D,WAAA,EAAM,aAAa,IAAY,QAAQ,QAAQ,CAAA,GAExC;AAAA;EAGT,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,QAAI,MAAU,EAAY,QAAO;AACjC,UAAM,IAAW,EAAU,YAAY,CAAA,GACjC,IAAgB,EAAU,YAAY,CAAA;AAC5C,QAAI,CAAC,KAAY,CAAC,EAAe,QAAO;AACxC,UAAM,IAAY,CAAC,GAAU,CAAA;AAE7B,WAAI,EAAU,SAAS,KAAA,KAAU,EAAU,SAAS,KAAA,IAC3C,KAGL,EAAU,SAAS,KAAA,KAAU,EAAU,SAAS,QAAA,IACnC,EAAM,UAAU,QAK7B,EAAU,SAAS,KAAA,KAAU,EAAU,SAAS,QAAA,IACnC,EAAM,UAAU,SAI1B;AAAA;EAQT,QAAiB,GAAsB,GAA+C;AAEpF,UAAM,IAAa,OAAO,EAAU,OAAO,IAAI,YAAA,CAAa;AAE5D,WAAA,EAAM,aAAa,EAAM,UAAU,SAAS,QAAQ,QAAQ,IAAa,CAAA,GAElE;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CACf;AAAA,QACE,UAAU,EAAU;AAAA,QACpB,iBAAiB,EAAM;AAAA,QACvB,aAAa,EAAM;AAAA,QACnB,MAAM;AAAA,QACN,YAAY,oBAAI,IAAI,CAAC,CAAC,aAAa,MAAA,CAAO,CAAC;AAAA,OAC5C;AAAA;;EAKP,cACE,GACA,GACA,GACiB;AACjB,QAAI,EAAM,SAAS,OACjB,QAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;AAIrB,UAAM,IAAa,OAAO,EAAU,OAAO,IAAI,YAAA,CAAa;AAC5D,WAAA,EAAM,SAAS,EAAM,UAAU,SAAS,QAAQ,QAAQ,EAAM,WAAA,GAC9D,EAAM,aAAa,EAAM,UAAU,SAAS,QAAQ,QAAQ,EAAM,cAAc,CAAA,GAIzE;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CACf;AAAA,QACE,UAAU,EAAU;AAAA,QACpB,iBAAiB,EAAM;AAAA,QACvB,aAAa,EAAM;AAAA,QACnB,MAAM;AAAA,QACN,YAAY,oBAAI,IAAI,CAAC,CAAC,aAAa,MAAA,CAAO,CAAC;AAAA,OAC5C;AAAA;;GCnHa,IAAtB,cAAqD,EAAuB;AAAA,EAO1E,iBACE,GACA,GACA,GACwB;AAExB,QADmB,EAAU,IAAI,KAAA,EAAQ,WAEvC,QAAO;AAGT,QAAI,IAAa,IACb,IAAsB;AAG1B,WAFsB,EAAM,UAEN,UACpB,EAAM,SAAS,OAAO,CAAA,GACtB,IAAa,IACb,IAAsB,KAGjB;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACS,qBAAA;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAerB,2BACE,GACA,GACA,GACwB;AACxB,QAAI,IAAgB;AAEpB,UAAM,IAAW,KAAK,aAAa;AACnC,eAAW,CAAC,GAAU,CAAA,KAAa,GAAW;AAC5C,UAAI,CAAC,EAAS,IAAI,CAAA,EAAW;AAC7B,YAAM,IAAU,EAAS,IAAI,CAAA;AAC7B,UAAK,KACD,GAAS,YAAY,cAEzB;AAAA,YAAI,EAAS,cAAc,EAAS,YAAY;AAC9C,UAAA,IAAgB;AAChB;AAAA;AAGF,YAAI,CAAC,EAAS,cAAc,CAAC,EAAS,YAAY;AAChD,UAAA,IAAgB;AAChB;AAAA;;;AAIJ,QAAI,CAAC,EACH,QAAO;AAGT,QAAI,IAAa,IACb,IAAsB;AAG1B,WAFsB,EAAM,UAEN,oBACpB,EAAM,SAAS,iBAAiB,CAAA,GAChC,IAAa,IACb,IAAsB,KAGjB;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACS,qBAAA;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAIrB,YACE,GACA,GACA,GACA,GACiB;AAEjB,QAAI,CAAC;AAAA,MAAC;AAAA,MAAO;AAAA,MAAU;AAAA,MAAQ;AAAA,MAAW;AAAA,MAAiB,SAAS,EAAM,KAAA;AACxE,aAAA,EAAM,SAAS,OAAO,CAAA,GACf;AAAA,QACL,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,qBAAqB;AAAA,QACrB,iBAAiB,CAAA;AAAA;AAIrB,UAAM,IAAiB,EAAkB,EAAU,MAAA,GAC7C,IACJ,EAAM,iBAAiB,IAAI,IAAiB,KAAK,IAAI,IAAa,EAAM,WAAW,CAAA;AAErF,QAAI,GAAqB;AACvB,UAAI,EAAM,UAAU,SAAS,EAAM,UAAU,aAAa,EAAM,UAAU;AACxE,eAAA,EAAM,SAAS,UAAU,CAAA,GACzB,EAAM,aAAa,QAAQ,IAAa,CAAA,GACjC;AAAA,UACL,gBAAgB;AAAA,UAChB,YAAY;AAAA,UACZ,qBAAqB;AAAA,UACrB,iBAAiB,CACf;AAAA,YACE,UAAU,EAAU;AAAA,YACpB,iBAAiB,EAAM;AAAA,YACvB,aAAa,EAAM;AAAA,YACnB,MAAM;AAAA,YACN,YAAY;AAAA,WACb;AAAA;AAIP,UAAI,EAAM,UAAU,YAAY,EAAM,UAAU,OAE9C,QAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,qBAAqB;AAAA,QACrB,iBAAiB,CAAA;AAAA;;AAKvB,WAAI,EAAM,UAAU,aAAa,EAAM,UAAU,QAExC;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA,QAGjB,EAAM,UAAU,UAAU,EAAM,UAAU,YAAY,EAAM,UAAU,mBACxE,EAAM,SAAS,WAAW,CAAA,GAC1B,EAAM,aAAa,OAAO,IAAa,CAAA,GAChC;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CACf;AAAA,QACE,UAAU,EAAU;AAAA,QACpB,iBAAiB,EAAM;AAAA,QACvB,aAAa,EAAM;AAAA,QACnB,MAAM;AAAA,QACN,YAAY;AAAA,OACb;AAAA,UAKP,EAAM,SAAS,OAAO,CAAA,GACf;AAAA,MACL,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;EAIrB,kBACE,GACA,GACA,GACA,GACA,GACS;AACT,QAAI,MAAU,EAAY,QAAO;AACjC,UAAM,IAAW,EAAU,YAAY,CAAA,GACjC,IAAgB,EAAU,YAAY,CAAA;AAC5C,QAAI,CAAC,KAAY,CAAC,EAAe,QAAO;AACxC,UAAM,IAAY,CAAC,GAAU,CAAA;AAE7B,WAAI,EAAU,SAAS,KAAA,KAAU,EAAU,SAAS,QAAA,IAC3C,EAAM,UAAU,UAAU,EAAM,UAAU,YAE/C,EAAU,SAAS,KAAA,KAAU,EAAU,SAAS,QAAA,IAC3C,EAAM,UAAU,SAAS,EAAM,UAAU,WAE3C;AAAA;EAGT,cACE,GACA,GACA,GACiB;AACjB,QAAI,IAAa;AAEjB,WAAI,EAAM,SAAS,mBACb,EAAM,UAAU,WAClB,IAAa,IACb,EAAM,SAAS,QAAQ,EAAM,WAAA,KAEtB,EAAM,SAAS,qBACpB,EAAM,UAAU,UAClB,IAAa,IACb,EAAM,SAAS,OAAO,EAAM,WAAA,IAIzB;AAAA,MACL,gBAAgB;AAAA,MACJ,YAAA;AAAA,MACZ,qBAAqB;AAAA,MACrB,iBAAiB,CAAA;AAAA;;GC1NV,KAAb,cAAsC,EAAqD;AAAA,EACzF,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAc,EAAU,IAAI,CAAA;AAAA;EAUzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IAAc,EAAa,IAAI,OAAA,EAAU,YACzC,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAc;AAE1E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GClDtD,KAAb,cAAsC,EAAqD;AAAA,EACzF,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAStB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAc,EAAU,IAAI,CAAA;AAAA;EAOzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IACJ,EAAa,IAAI,QAAA,EAAW,cAAc,EAAa,IAAI,QAAA,EAAW,YAElE,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAgB;AAE5E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GCnDtD,KAAb,cAAuC,EAAqD;AAAA,EAC1F,cAAc;AACZ,UAAM,EAAc,SAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,iDAAiD,EAAU,IAAA,EAAA;AAE7E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAe,EAAU,IAAI,CAAA;AAAA;EAG1C,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IACJ,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,YAExB,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAgB;AAE5E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GC5CtD,KAAb,cAAuC,EAAqD;AAAA,EAC1F,cAAc;AACZ,UAAM,EAAc,SAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,iDAAiD,EAAU,IAAA,EAAA;AAE7E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAe,EAAU,IAAI,CAAA;AAAA;EAG1C,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IACJ,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,YAExB,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAgB;AAE5E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GChDtD,KAAb,cAAqC,EAAqD;AAAA,EACxF,cAAc;AACZ,UAAM,EAAc,OAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,+CAA+C,EAAU,IAAA,EAAA;AAE3E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAa,EAAU,IAAI,CAAA;AAAA;EAOxC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IACJ,EAAa,IAAI,QAAA,EAAW,cAAc,EAAa,IAAI,QAAA,EAAW,YAElE,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAe;AAE3E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GC7CtD,KAAb,cAAsC,EAAqD;AAAA,EACzF,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAc,EAAU,IAAI,CAAA;AAAA;EAGzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IACJ,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,YAExB,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAe;AAE3E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GC5CtD,KAAb,cAAsC,EAAqD;AAAA,EACzF,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAc,EAAU,IAAI,CAAA;AAAA;EAGzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAGT,UAAM,IACJ,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,cAC5B,EAAa,IAAI,QAAA,EAAW,YAExB,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAe;AAE3E,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GChDtD,KAAb,cAAqC,EAAqD;AAAA,EACxF,cAAc;AACZ,UAAM,EAAc,OAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,+CAA+C,EAAU,IAAA,EAAA;AAE3E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAa,EAAU,IAAI,CAAA;AAAA;EAOxC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAKT,UAAM,IAFa,EAAa,IAAI,QAAA,EAAW,eAC5B,EAAa,IAAI,QAAA,EAAW,YAGzC,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAY;AAExE,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GC9CtD,KAAb,cAAsC,EAAqD;AAAA,EACzF,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAc,EAAU,IAAI,CAAA;AAAA;EAGzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAST,UAAM,MALH,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAElB,MAAM,GAE9B,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAY;AAExE,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GC9CtD,KAAb,cAAsC,EAAqD;AAAA,EACzF,cAAc;AACZ,UAAM,EAAc,QAAA;AAAA;EAGtB,mBAAmB,GAAsC;AACvD,QAAI,EAAU,SAAS,KAAK,eAC1B,OAAM,IAAI,MAAM,gDAAgD,EAAU,IAAA,EAAA;AAE5E,UAAM,IAAQ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,SAAS;AAChF,WAAO,IAAI,GAAc,EAAU,IAAI,CAAA;AAAA;EAGzC,aACE,GACA,GACA,GACA,GACiB;AACjB,UAAM,IAAe,KAAK,aAAa,GAAW,CAAA;AAClD,IAAA,EAAM,YAAY;AAElB,UAAM,IAAmB,KAAK,iBAAiB,GAAO,GAAc,CAAA;AACpE,QAAI,EACF,QAAO;AAET,UAAM,IAA6B,KAAK,2BACtC,GACA,GACA,CAAA;AAEF,QAAI,EACF,QAAO;AAaT,UAAM,MATH,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAC7C,EAAa,IAAI,QAAA,EAAW,aAAa,IAAI,MAElB,MAAM,GAE9B,IACJ,EAAU,OAAO,IAAI,iBAAA,MAAuB,aAAa,CAAC,IAAY;AAExE,WAAO,KAAK,YAAY,GAAW,GAAO,GAAqB,CAAA;AAAA;GCzDtD,KAAb,MAAwB;AAAA,EACtB;AAAA,EAKA,cAAc;AACZ,SAAK,OAAO,CAAA;AAAA;EASd,SAAS,GAA8B;AACrC,QAAI,EAAM,cAAc,EAAM,gBAC5B,OAAM,IAAI,WACR,gBAAgB,EAAM,WAAA,uCAAkD,EAAM,eAAA,GAAgB;AAGlG,SAAK,KAAK,KAAK,CAAA,GACf,KAAK,SAAS,KAAK,KAAK,SAAS,CAAA;AAAA;EAWnC,eAAe,GAAwC;AACrD,UAAM,IAA2B,CAAA;AAEjC,WAAO,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,CAAA,EAAI,eAAe,KAAa;AACvE,YAAM,IAAQ,KAAK,WAAA;AACnB,MAAI,KACF,EAAM,KAAK,CAAA;AAAA;AAKf,WAAA,EAAM,KAAA,CAAM,GAAG,MACT,EAAE,gBAAgB,EAAE,cACf,EAAE,kBAAkB,EAAE,kBAExB,EAAE,cAAc,EAAE,cAGpB;AAAA;EAQT,YAAqB;AACnB,WAAO,KAAK,KAAK,SAAS;AAAA;EAM5B,QAAc;AACZ,SAAK,OAAO,CAAA;AAAA;EAWd,aAAa,GAAwC,GAA2C;AAC9F,eAAW,KAAS,EAClB,KAAI,EAAM,cAAc,EAAM,gBAC5B,OAAM,IAAI,WACR,gBAAgB,EAAM,WAAA,uCAAkD,EAAM,eAAA,GAAgB;AAKpG,IAAI,KAAiB,EAAc,OAAO,MACxC,KAAK,OAAO,KAAK,KAAK,OAAA,CAAQ,MAAM,CAAC,EAAc,IAAI,EAAE,QAAA,CAAS;AAGpE,eAAW,KAAS,EAClB,MAAK,KAAK,KAAK,CAAA;AAGjB,KAAI,EAAO,SAAS,KAAM,KAAiB,EAAc,OAAO,MAC9D,KAAK,YAAA;AAAA;EAWT,sBAAsB,GAA0B;AAC9C,UAAM,IAAgB,KAAK,KAAK;AAChC,gBAAK,OAAO,KAAK,KAAK,OAAA,CAAQ,MAAU,EAAM,aAAa,CAAA,GAGvD,KAAK,KAAK,WAAW,KACvB,KAAK,YAAA,GAEA,IAAgB,KAAK,KAAK;AAAA;EAQnC,OAAe;AACb,WAAO,KAAK,KAAK;AAAA;EAGnB,cAA4B;AAC1B,aAAS,IAAI,KAAK,MAAM,KAAK,KAAK,SAAS,CAAA,IAAK,GAAG,KAAK,GAAG,IACzD,MAAK,WAAW,CAAA;AAAA;EAIpB,SAAiB,GAAqB;AACpC,WAAO,IAAQ,KAAG;AAChB,YAAM,IAAc,KAAK,OAAO,IAAQ,KAAK,CAAA;AAC7C,UAAI,KAAK,KAAK,CAAA,EAAQ,cAAc,KAAK,KAAK,CAAA,EAAc;AAC1D,SAAC,KAAK,KAAK,CAAA,GAAQ,KAAK,KAAK,CAAA,CAAA,IAAgB,CAAC,KAAK,KAAK,CAAA,GAAe,KAAK,KAAK,CAAA,CAAA,GACjF,IAAQ;AAAA,UAER;AAAA;;EAKN,WAAmB,GAAqB;AACtC,UAAM,IAAS,KAAK,KAAK;AAEzB,eAAa;AACX,YAAM,IAAY,IAAI,IAAQ,GACxB,IAAa,IAAI,IAAQ;AAC/B,UAAI,IAAW;AAgBf,UAbE,IAAY,KACZ,KAAK,KAAK,CAAA,EAAY,cAAc,KAAK,KAAK,CAAA,EAAW,gBAEzD,IAAW,IAIX,IAAa,KACb,KAAK,KAAK,CAAA,EAAa,cAAc,KAAK,KAAK,CAAA,EAAW,gBAE1D,IAAW,IAGT,MAAa;AACf,SAAC,KAAK,KAAK,CAAA,GAAQ,KAAK,KAAK,CAAA,CAAA,IAAa,CAAC,KAAK,KAAK,CAAA,GAAY,KAAK,KAAK,CAAA,CAAA,GAC3E,IAAQ;AAAA,UAER;AAAA;;EAKN,aAAkD;AAChD,QAAI,KAAK,KAAK,WAAW,EACvB;AAGF,UAAM,IAAM,KAAK,KAAK,CAAA,GAChB,IAAO,KAAK,KAAK,IAAA;AAEvB,WAAI,KAAK,KAAK,SAAS,KAAK,MAC1B,KAAK,KAAK,CAAA,IAAK,GACf,KAAK,WAAW,CAAA,IAGX;AAAA;GC5LE,KAAb,MAA0B;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EAKA,cAAc;AACZ,SAAK,kBAAkB,oBAAI,IAAA,GAC3B,KAAK,aAAa,oBAAI,IAAA,GACtB,KAAK,cAAc,oBAAI,IAAA;AAAA;EAQzB,mBAAmB,GAAyB;AAC1C,SAAK,gBAAgB,IAAI,CAAA;AAAA;EAQ3B,cAAc,GAAoB;AAChC,SAAK,WAAW,IAAI,CAAA;AAAA;EAQtB,eAAe,GAAqB;AAClC,SAAK,YAAY,IAAI,CAAA;AAAA;EAOvB,mBAAmB,GAA+B;AAChD,SAAK,kBAAkB,IAAI,IAAI,CAAA;AAAA;EAOjC,eAAe,GAA2B;AACxC,SAAK,cAAc,IAAI,IAAI,CAAA;AAAA;EAO7B,cAAc,GAA0B;AACtC,SAAK,aAAa,IAAI,IAAI,CAAA;AAAA;EAS5B,mBAAmC;AACjC,UAAM,IAAyB;AAAA,MAC7B,YAAY,IAAI,IAAI,KAAK,eAAA;AAAA,MACzB,OAAO,IAAI,IAAI,KAAK,UAAA;AAAA,MACpB,QAAQ,IAAI,IAAI,KAAK,WAAA;AAAA;AAGvB,gBAAK,MAAA,GAEE;AAAA;EAQT,mBAA4B;AAC1B,WAAO,KAAK,gBAAgB,OAAO,KAAK,KAAK,WAAW,OAAO,KAAK,KAAK,YAAY,OAAO;AAAA;EAM9F,QAAc;AACZ,SAAK,gBAAgB,MAAA,GACrB,KAAK,WAAW,MAAA,GAChB,KAAK,YAAY,MAAA;AAAA;EAQnB,yBAAiC;AAC/B,WAAO,KAAK,gBAAgB;AAAA;EAQ9B,oBAA4B;AAC1B,WAAO,KAAK,WAAW;AAAA;EAQzB,qBAA6B;AAC3B,WAAO,KAAK,YAAY;AAAA;GChIf,KAAb,MAA0B;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAQA,YAAY,IAAyB,IAAO,IAAuB,KAAM;AACvE,QAAI,IAAe,EACjB,OAAM,IAAI,WAAW,wCAAwC,CAAA,GAAa;AAG5E,SAAK,iBAAiB,GACtB,KAAK,eAAe,GACpB,KAAK,eAAe,IAAI,EAAgB,CAAA,GACxC,KAAK,UAAU,CAAA,GACf,KAAK,oBAAoB;AAAA;EAQ3B,kBAAmC;AACjC,WAAO,KAAK;AAAA;EAQd,iBAAyB;AACvB,WAAO,KAAK,aAAa;AAAA;EAS3B,oBAAqC;AACnC,UAAM,IAAW,KAAK,aAAa,OAAO;AAG1C,WAAI,KAAK,kBACP,KAAK,cAAc,KAAK,aAAa,MAAA,CAAO,GAI9C,KAAK,aAAa,OAAO,GAElB,KAAK;AAAA;EAUd,eAAe,GAA2C;AACxD,QAAK,KAAK;AAIV,aAAO,KAAK,QAAQ,KAAA,CAAM,MAAU,EAAM,SAAS,CAAA;AAAA;EASrD,aAA6C;AAC3C,WAAK,KAAK,iBAKH,CAAC,GAAG,KAAK,OAAA,EAAS,KAAA,CAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAA,IAJ1C,CAAA;AAAA;EAYX,gBAAoC;AAClC,QAAI,GAAC,KAAK,kBAAkB,KAAK,QAAQ,WAAW;AAIpD,aAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,IAAA,CAAK,MAAU,EAAM,IAAA,CAAK;AAAA;EAQ5D,0BAA8C;AAC5C,QAAI,GAAC,KAAK,kBAAkB,KAAK,QAAQ,WAAW;AAIpD,aAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,IAAA,CAAK,MAAU,EAAM,IAAA,CAAK;AAAA;EAM5D,eAAqB;AACnB,SAAK,UAAU,CAAA,GACf,KAAK,oBAAoB;AAAA;EAM3B,QAAc;AACZ,SAAK,eAAe,IAAI,EAAgB,CAAA,GACxC,KAAK,aAAA;AAAA;EAQP,mBAA4B;AAC1B,WAAO,KAAK;AAAA;EAQd,kBAA0B;AACxB,WAAO,KAAK;AAAA;EAQd,iBAAyB;AACvB,WAAO,KAAK,QAAQ;AAAA;EAStB,cAAsB,GAA8B;AAClD,IAAI,KAAK,QAAQ,SAAS,KAAK,eAE7B,KAAK,QAAQ,KAAK,CAAA,KAGlB,KAAK,QAAQ,KAAK,iBAAA,IAAqB,GACvC,KAAK,qBAAqB,KAAK,oBAAoB,KAAK,KAAK;AAAA;GCtJtD,KAAb,MAA2B;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EASA,YAAY,GAAkB,GAAoC,IAA0B,CAAA,GAAI;AAC9F,SAAK,UAAU,GACf,KAAK,mBAAmB,GAKxB,KAAK,eAAe,IAAI,GAHF,EAAQ,iBAAiB,IAC1B,EAAQ,gBAAgB,GAAA,GAG7C,KAAK,aAAa,IAAI,GAAA,GACtB,KAAK,WAAW,oBAAI,IAAA,GACpB,KAAK,eAAe,IAAI,GAAA;AAGxB,QAAI;AACF,WAAK,gBAAA;AAAA,aACE,GAAG;AACV,oBAAQ,MAAM,8CAA8C,CAAA,GACtD;AAAA;;EAUV,OAAsB;AACpB,UAAM,IAAsB,KAAK,WAAW,KAAA,GACtC,IAAc,KAAK,aAAa,eAAA,GAGhC,IAAe,KAAK,iBAAiB,IAAc,CAAA,GAGnD,IAAS,KAAK,YAAY,IAAc,CAAA;AAC9C,IAAA,EAAO,kBAAkB,EAAa,QAItC,EAAO,wBADoB,KAAK,gBAAA,EACkB,QAElD,EAAO,sBACL,KAAK,WAAW,KAAA,IAAS,EAAO,kBAAkB;AAGpD,eAAW,KAAe,EACxB,CAAI,EAAY,cACd,KAAK,aAAa,mBAAmB,EAAY,eAAe,WAAA;AAGpE,WAAA,EAAO,uBAAuB,KAAK,aAAa,uBAAA,GAGhD,KAAK,aAAa,kBAAA,GAClB,EAAO,UAAU,KAAK,aAAa,eAAA,GAC5B;AAAA;EAST,MAAM,GAAgC;AACpC,QAAI,IAAQ,EACV,OAAM,IAAI,WAAW,sCAAsC,CAAA,GAAM;AAGnE,UAAM,IAAU,CAAA;AAChB,aAAS,IAAI,GAAG,IAAI,GAAO,IACzB,CAAA,EAAQ,KAAK,KAAK,KAAA,CAAM;AAG1B,WAAO;AAAA;EAOT,QAAc;AACZ,SAAK,aAAa,MAAA,GAClB,KAAK,WAAW,MAAA,GAChB,KAAK,aAAa,MAAA,GAClB,KAAK,gBAAA;AAAA;EAQP,iBAAyB;AACvB,WAAO,KAAK,aAAa,eAAA;AAAA;EAQ3B,kBAAmC;AACjC,WAAO,KAAK,aAAa,gBAAA;AAAA;EAS3B,cAAc,GAAiD;AAC7D,WAAO,KAAK,aAAa,gBAAA,EAAkB,WAAW,IAAI,CAAA;AAAA;EAS5D,aAAa,GAAgD;AAC3D,WAAO,KAAK,aAAa,gBAAA,EAAkB,WAAW,IAAI,CAAA;AAAA;EAS5D,kBAAkB,GAA+C;AAC/D,WAAO,KAAK,aAAa,gBAAA,EAAkB,gBAAgB,IAAI,CAAA;AAAA;EAUjE,eAAe,GAA2C;AACxD,WAAO,KAAK,aAAa,eAAe,CAAA;AAAA;EAS1C,YAAY,GAAgC;AAC1C,WAAO,KAAK,iBAAiB,IAAI,CAAA;AAAA;EAUnC,cAAc,GAAgC;AAC5C,QAAI,CAAC,KAAK,QAAQ,aAAa,EAAQ,QAAA,EACrC,OAAM,MAAM,mDAAmD,EAAQ,QAAA,GAAS;AAElF,WAAI,KAAK,SAAS,IAAI,EAAQ,QAAA,IACrB,MAET,EAAQ,kBAAkB,KAAK,eAAA,GAC/B,KAAK,SAAS,IAAI,EAAQ,UAAU,CAAA,GAC7B;AAAA;EAUT,kBAA6C;AAC3C,UAAM,IAAe,KAAK,aAAa,gBAAA,GAEjC,IAA6B,CAAA,GAC7B,IAAgB,oBAAI,IAAA,GACpB,IAAsC,CAAA;AAE5C,eAAW,KAAW,KAAK,SAAS,OAAA,GAAU;AAC5C,YAAM,IAAY,KAAK,QAAQ,aAAa,EAAQ,QAAA,GAG9C,IAFW,KAAK,iBAAiB,IAAI,EAAU,IAAA,EAE7B,cACtB,GACA,EAAa,gBAAgB,IAAI,EAAU,EAAA,GAC3C,CAAA;AAEF,MAAI,EAAO,uBACT,EAAc,IAAI,EAAU,EAAA;AAE9B,iBAAW,KAAS,EAAO,gBACzB,CAAA,EAAiB,KAAK,CAAA;AAExB,MAAA,EAAQ,KAAK,CAAA,GACT,EAAO,cACT,KAAK,aAAa,mBAAmB,EAAU,EAAA;AAAA;AAInD,gBAAK,WAAW,aAAa,GAAkB,CAAA,GAC/C,KAAK,SAAS,MAAA,GAEP;AAAA;EAUT,uBAA+B,GAAqC;AAClE,UAAM,IAAQ,EAAO,IAAI,qBAAA;AACzB,QAAI,CAAC,KAAS,MAAU,GAAI,QAAO;AACnC,UAAM,IAAS,SAAS,GAAO,EAAA;AAC/B,WAAO,MAAM,CAAA,IAAU,IAAI;AAAA;EAgB7B,kBAAyC;AACvC,UAAM,IAAe,KAAK,aAAa,gBAAA;AAGvC,eAAW,KAAa,KAAK,QAAQ,iBAAA,GAAoB;AACvD,UAAI,EAAU,KAAK,SAAS,EAAG;AAE/B,YAAM,IAAW,KAAK,iBAAiB,IAAI,EAAU,IAAA;AACrD,UAAI,CAAC,EAIH;AAGF,YAAM,IAAe,EAAS,mBAAmB,CAAA;AAChD,MAAA,EAAa,gBAA8C,IAAI,EAAU,IAAI,CAAA,GAG9E,KAAK,aAAa,mBAAmB,EAAU,EAAA;AAAA;AAIjD,eAAW,KAAS,KAAK,QAAQ,aAAA,EAC9B,CAAA,EAAa,WAA+C,IAAI,EAAM,IAAI;AAAA,MACzE,YAAY,EAAM,WAAW,EAAgB;AAAA,MAC7C,YAAY,EAAM,WAAW,EAAgB;AAAA,MAC7C,QAAQ,CAAC,CAAC,EAAM;AAAA,KACjB;AAGH,eAAW,KAAQ,KAAK,QAAQ,YAAA,EAC7B,CAAA,EAAa,WAA+C,IAAI,EAAK,IAAI;AAAA,MACxE,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,QAAQ;AAAA,KACT;AAKH,UAAM,IAAgB,KAAK,QAAQ,iBAAA,GAC7B,IAAoB,oBAAI,IAAA;AAE9B,eAAW,KAAa,GAAe;AACrC,YAAM,IAAQ,KAAK,uBAAuB,EAAU,MAAA,GAC9C,IAAQ,EAAkB,IAAI,CAAA,KAAU,CAAA;AAC9C,MAAA,EAAM,KAAK,CAAA,GACX,EAAkB,IAAI,GAAO,CAAA;AAAA;AAI/B,UAAM,IAAe,MAAM,KAAK,EAAkB,KAAA,CAAM,EAAE,KAAA,CAAM,GAAG,MAAM,IAAI,CAAA;AAG7E,eAAW,KAAS,EACJ,CAAA,EAAkB,IAAI,CAAA,EAC9B,KAAA,CAAM,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAA,CAAG;AAW/C,QAAI,IAAa,IACb,IAAa;AACjB,UAAM,IAAgB;AAEtB,WAAO,KAAc,IAAa,KAAe;AAC/C,MAAA,IAAa,IACb;AAGA,iBAAW,KAAS,GAAc;AAChC,cAAM,IAAQ,EAAkB,IAAI,CAAA;AAGpC,mBAAW,KAAa,GAAO;AAC7B,gBAAM,IAAW,KAAK,iBAAiB,IAAI,EAAU,IAAA;AACrD,cAAI,CAAC,EAAU;AAEf,gBAAM,IAAiB,EAAa,gBAAgB,IAAI,EAAU,EAAA;AAClE,cAAI,CAAC,EAAgB;AAGrB,eAAK,sBAAA;AAIL,gBAAM,IAAsB,EAAS,QAAQ,GAAW,CAAA;AACxD,cAAM,GAAqB;AACxB,YAAA,EAAa,gBAA8C,IAC1D,EAAU,IACV,EAAoB,cAAA,GAElB,EAAoB,uBACtB,KAAK,WAAW,sBAAsB,EAAU,EAAA;AAElD,uBAAW,KAAS,EAAoB,gBACtC,MAAK,WAAW,SAAS,CAAA;AAE3B;AAAA;AAIF,gBAAM,IAAS,EAAS,aACtB,GACA,GACA,EAAa,YACb,CAAA;AAIF,UAAI,EAAO,eACT,IAAa,IACZ,EAAa,gBAA8C,IAC1D,EAAU,IACV,EAAO,cAAA;AAQX,qBAAW,KAAS,EAAO,iBAAiB;AAC1C,kBAAM,IAAc,EAAS,cAAc,GAAW,GAAgB,CAAA;AACtE,YAAI,EAAY,eACd,IAAa,IACZ,EAAa,gBAA8C,IAC1D,EAAU,IACV,EAAY,cAAA;AAAA;;;;AAQxB,UAAM,IAAS,KAAK,YAAY,CAAA;AAGhC,gBAAK,aAAa,mBAChB,oBAAI,IAAI,CAAC,GAAG,KAAK,QAAQ,iBAAA,EAAmB,IAAA,CAAK,MAAM,EAAE,EAAA,CAAG,CAAC,CAAC,GAEhE,KAAK,aAAa,eAAe,oBAAI,IAAI,CAAC,GAAG,KAAK,QAAQ,aAAA,EAAe,IAAA,CAAK,MAAM,EAAE,EAAA,CAAG,CAAC,CAAC,GAC3F,KAAK,aAAa,cAAc,oBAAI,IAAI,CAAC,GAAG,KAAK,QAAQ,YAAA,EAAc,IAAA,CAAK,MAAM,EAAE,EAAA,CAAG,CAAC,CAAC,GAElF;AAAA;EAQT,YAAoB,GAAmC;AACrD,UAAM,IAAe,KAAK,aAAa,gBAAA,GAEjC,EAAE,cAAA,GAAc,cAAA,EAAA,IAAiB,KAAK,sBAAA,GACtC,IAAqB,KAAK,QAAQ,oBAAoB,CAAA,GACtD,IAA6B,CAAA,GAE7B,IAAoB,oBAAI,IAAA;AAG9B,QAAI,IAAqB,MAAM,KAAK,CAAA;AACpC,IAAI,MAAe,MACjB,IAAqB,EAAmB,KAAA,CAAM,GAAK,MAAQ;AACzD,YAAM,IAAQ,KAAK,QAAQ,aAAa,CAAA,GAClC,IAAQ,KAAK,QAAQ,aAAa,CAAA,GAClC,IAAS,KAAK,uBAAuB,EAAM,MAAA,GAC3C,IAAS,KAAK,uBAAuB,EAAM,MAAA;AAGjD,aAAI,MAAW,IACN,IAAS,IAIX,EAAI,cAAc,CAAA;AAAA;AAI7B,UAAM,IAAgB,oBAAI,IAAA,GACpB,IAAsC,CAAA;AAE5C,eAAW,KAAe,GAAoB;AAC5C,YAAM,IAAY,KAAK,QAAQ,aAAa,CAAA,GACtC,IAAW,KAAK,iBAAiB,IAAI,EAAU,IAAA;AACrD,UAAI,CAAC,EAAU;AAEf,YAAM,IAAM,EAAS,aACnB,GACA,EAAa,gBAAgB,IAAI,CAAA,GACjC,EAAa,YACb,CAAA;AAEF,MAAI,EAAI,uBACN,EAAc,IAAI,CAAA,GAEhB,EAAI,eACN,EAAkB,IAAI,CAAA,GACtB,EAAQ,KAAK,CAAA;AAEf,iBAAW,KAAS,EAAI,gBACtB,CAAA,EAAiB,KAAK,CAAA;AAAA;AAI1B,gBAAK,WAAW,aAAa,GAAkB,CAAA,GAE/C,KAAK,aAAa,mBAAmB,CAAA,GACrC,KAAK,aAAa,eAAe,CAAA,GACjC,KAAK,aAAa,cAAc,CAAA,GAEzB;AAAA,MACL,WAAW,KAAK,eAAA;AAAA,MAChB,SAAS,KAAK,eAAA;AAAA,MACd,sBAAsB,EAAkB;AAAA,MACxC,iBAAiB,EAAa;AAAA,MAC9B,iBAAiB,EAAa;AAAA,MAC9B,uBAAuB;AAAA,MACvB,qBAAqB,EAAiB;AAAA,MACtC,iBAAiB;AAAA;;EAUrB,wBAAsF;AACpF,UAAM,IAAe,KAAK,aAAa,gBAAA,GAEjC,IAAA,CACJ,MAIG;AACH,YAAM,IAAe,oBAAI,IAAA,GACnB,IAAe,oBAAI,IAAA,GAEnB,IAAU,KAAK,QAClB,aAAA,EACA,OAAA,CAAQ,MAAS,EAAK,UAAU,CAAA,EAChC,IAAA,CAAK,MAAS,EAAK,EAAA,GAChB,IAAiB,oBAAI,IAAI,CAC7B,GAAG,KAAK,QACL,aAAA,EACA,OAAA,CAAQ,MAAS,CAAC,EAAK,MAAA,EACvB,IAAA,CAAK,MAAS,EAAK,EAAA,CAAG,CAC1B,GACK,IAAiB,oBAAI,IAAI,CAAC,GAAG,KAAK,QAAQ,YAAA,EAAc,IAAA,CAAK,MAAS,EAAK,EAAA,CAAG,CAAC,GAE/E,EAAE,OAAA,GAAO,OAAA,EAAA,IAAU,KAAK,oBAC5B,GACA,GACA,EAAa,eAAA,GAGT,IAAY,KAAQ,EAAgB,UAAU,eAAe;AAEnE,iBAAW,KAAU,GAAO;AAC1B,cAAM,IAAY,EAAa,WAAW,IAAI,CAAA;AAC9C,QAAI,KAAa,CAAC,EAAU,WACrB,EAAU,CAAA,MACb,EAAU,CAAA,IAAa,IACvB,EAAa,IAAI,CAAA,IAEnB,EAAe,OAAO,CAAA;AAAA;AAI1B,iBAAW,KAAU,GAAgB;AACnC,cAAM,IAAY,EAAa,WAAW,IAAI,CAAA;AAC9C,QAAI,KAAa,CAAC,EAAU,UACtB,EAAU,CAAA,MACZ,EAAU,CAAA,IAAa,IACvB,EAAa,IAAI,CAAA;AAAA;AAKvB,iBAAW,KAAU,GAAO;AAC1B,cAAM,IAAY,EAAa,WAAW,IAAI,CAAA;AAC9C,QAAM,MACC,EAAU,CAAA,MACb,EAAU,CAAA,IAAa,IACvB,EAAa,IAAI,CAAA,IAEnB,EAAe,OAAO,CAAA;AAAA;AAI1B,iBAAW,KAAU,GAAgB;AACnC,cAAM,IAAY,EAAa,WAAW,IAAI,CAAA;AAC9C,QAAM,KACA,EAAU,CAAA,MACZ,EAAU,CAAA,IAAa,IACvB,EAAa,IAAI,CAAA;AAAA;AAKvB,aAAO;AAAA,QAAE,cAAA;AAAA,QAAc,cAAA;AAAA;OAGnB,EAAE,cAAc,GAAoB,cAAc,EAAA,IACtD,EAAmB,EAAgB,OAAA,GAC/B,EAAE,cAAc,GAAoB,cAAc,EAAA,IACtD,EAAmB,EAAgB,OAAA;AAErC,WAAO;AAAA,MACL,cAAc,oBAAI,IAAI,CAAC,GAAG,GAAoB,GAAG,CAAA,CAAmB;AAAA,MACpE,cAAc,oBAAI,IAAI,CAAC,GAAG,GAAqB,GAAG,CAAA,CAAoB;AAAA;;EAY1E,oBACE,GACA,GACA,GACqB;AACrB,UAAM,IAAiB,oBAAI,IAAA,GACrB,IAAiB,oBAAI,IAAA,GACrB,IAAmB,CAAA;AAGzB,eAAW,KAAQ;AACjB,MAAA,EAAS,KAAK,CAAA,GACd,EAAe,IAAI,CAAA;AAGrB,WAAO,EAAS,SAAS,KAAG;AAC1B,YAAM,IAAY,EAAS,MAAA;AAG3B,iBAAW,KAAQ,KAAK,QAAQ,eAAe,CAAA,GAAY;AACzD,cAAM,IAAc,EAAK,UAAU,IAAY,EAAK,QAAQ,EAAK;AAEjE,QAAK,EAAe,IAAI,CAAA,MACtB,EAAe,IAAI,CAAA,GACnB,EAAS,KAAK,CAAA,IAEX,EAAe,IAAI,EAAK,EAAA,KAC3B,EAAe,IAAI,EAAK,EAAA;AAAA;AAK5B,YAAM,IAAO,KAAK,QAAQ,SAAS,CAAA;AACnC,UAAI,EAAK,SAAS,EAAU,KAAK;AAC/B,cAAM,IAAY,KAAK,QAAQ,aAAa,EAAK,SAAA,GAC3C,IAAW,KAAK,iBAAiB,IAAI,EAAU,IAAA;AACrD,YAAI,CAAC,EAIH;AAGF,cAAM,IAAQ,EAAgB,IAAI,EAAU,EAAA;AAE5C,mBAAW,KAAc,EAAU;AACjC,UAAI,MAAe,MACf,EAAe,IAAI,CAAA,KAGX,EAAS,kBACnB,GACA,GACA,GACA,GACA,CAAA,MAIA,EAAe,IAAI,CAAA,GACnB,EAAS,KAAK,CAAA;AAAA;;AAMtB,WAAO;AAAA,MAAE,OAAO;AAAA,MAAgB,OAAO;AAAA;;EAYzC,iBAAyB,GAAuC;AAC9D,UAAM,IAAe,KAAK,aAAa,gBAAA,GACjC,IAAc,KAAK,WAAW,eAAe,CAAA,GAE7C,IAA6B,CAAA,GAC7B,IAAgB,oBAAI,IAAA,GACpB,IAAsC,CAAA;AAE5C,eAAW,KAAS,GAAa;AAC/B,YAAM,IAAY,KAAK,QAAQ,aAAa,EAAM,QAAA,GAC5C,IAAW,KAAK,iBAAiB,IAAI,EAAU,IAAA;AACrD,UAAI,CAAC,EAAU;AAEf,YAAM,IAAiB,EAAa,gBAAgB,IAAI,EAAU,EAAA,GAC5D,IAAS,EAAS,cAAc,GAAW,GAAgB,CAAA;AACjE,MAAI,EAAO,uBACT,EAAc,IAAI,EAAU,EAAA;AAE9B,iBAAW,KAAS,EAAO,gBACzB,CAAA,EAAiB,KAAK,CAAA;AAExB,MAAA,EAAQ,KAAK,CAAA;AAAA;AAGf,gBAAK,WAAW,aAAa,GAAkB,CAAA,GACxC;AAAA;;AC7rBX,SAAgB,GAAiC,GAA8C;AAC7F,SAAA,EACG,SAAS,IAAI,GAAA,CAAiB,EAC9B,SAAS,IAAI,GAAA,CAAmB,EAChC,SAAS,IAAI,GAAA,CAAsB,EACnC,SAAS,IAAI,GAAA,CAAe,EAC5B,SAAS,IAAI,GAAA,CAAkB,EAC/B,SAAS,IAAI,GAAA,CAAgB,EAC7B,SAAS,IAAI,GAAA,CAA2B,EACxC,SAAS,IAAI,GAAA,CAAe,GACxB;;AAUT,SAAgB,GAAiC,GAA8C;AAC7F,SAAA,EACG,SAAS,IAAI,GAAA,CAAkB,EAC/B,SAAS,IAAI,GAAA,CAAkB,EAC/B,SAAS,IAAI,GAAA,CAAmB,EAChC,SAAS,IAAI,GAAA,CAAmB,EAChC,SAAS,IAAI,GAAA,CAAiB,EAC9B,SAAS,IAAI,GAAA,CAAkB,EAC/B,SAAS,IAAI,GAAA,CAAkB,EAC/B,SAAS,IAAI,GAAA,CAAiB,EAC9B,SAAS,IAAI,GAAA,CAAkB,EAC/B,SAAS,IAAI,GAAA,CAAkB,GAC3B"}