simple-circuit-engine 0.0.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/core/ENode.ts","../../src/core/Wire.ts","../../src/core/Circuit.ts","../../src/core/simulation/behaviors/BehaviorRegistry.ts","../../src/core/simulation/states/ComponentState.ts","../../src/core/simulation/states/BatteryState.ts","../../src/core/simulation/behaviors/BatteryBehavior.ts","../../src/core/simulation/states/LightbulbState.ts","../../src/core/simulation/behaviors/LightbulbBehavior.ts","../../src/core/simulation/states/SmallLEDState.ts","../../src/core/simulation/behaviors/SmallLEDBehavior.ts","../../src/core/simulation/states/RectangleLEDState.ts","../../src/core/simulation/behaviors/RectangleLEDBehavior.ts","../../src/core/simulation/states/RelayState.ts","../../src/core/simulation/behaviors/RelayBehavior.ts","../../src/core/simulation/states/SwitchState.ts","../../src/core/simulation/states/TransistorState.ts","../../src/core/simulation/behaviors/SwitchBehavior.ts","../../src/core/simulation/behaviors/TransistorBehavior.ts","../../src/core/setup.ts"],"sourcesContent":["/**\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/ENode\n */\n\nimport type { UUID } from './types/Identifier.js';\nimport { generateUUID } from './types/Identifier.js';\nimport { ENodeType } from './types/ENodeType.js';\nimport { Position } from './types/Position.js';\nimport type { Circuit } from './Circuit.js';\nimport type { ENodeSourceType } from './types/ENodeSourceType';\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 * 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 * @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 ) {\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 }\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(): {\n id: UUID;\n type: ENodeType;\n component?: UUID | null;\n pinLabel?: string | null;\n position?: { x: number; y: number } | null;\n source?: ENodeSourceType | null;\n } {\n const json: {\n id: UUID;\n type: ENodeType;\n component?: UUID | null;\n pinLabel?: string | null;\n position?: { x: number; y: number } | null;\n source?: ENodeSourceType | null;\n } = {\n id: this.id,\n type: this.type,\n source: this.source || null,\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: {\n id: UUID;\n type: ENodeType;\n component?: UUID;\n pinLabel?: string;\n position?: { x: number; y: number };\n source?: ENodeSourceType;\n }): ENode {\n const position = json.position ? Position.fromJSON(json.position) : undefined;\n\n const enode = new ENode(json.type, json.component, json.pinLabel, position, json.source);\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/Wire\n */\n\nimport type { UUID } from './types/Identifier.js';\nimport { generateUUID } from './types/Identifier.js';\nimport { Position } from './types/Position.js';\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(): {\n id: UUID;\n node1: UUID;\n node2: UUID;\n intermediatePositions: { x: number; y: number }[];\n } {\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: {\n id: UUID;\n node1: UUID;\n node2: UUID;\n intermediatePositions: { x: number; y: number }[];\n }): 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 * Circuit Class\n *\n * Main container managing all circuit elements with automatic lifecycle.\n * Provides the primary API for creating and manipulating circuit topology.\n *\n * @module core/Circuit\n */\n\nimport type { UUID } from './types/Identifier.js';\nimport { findPositionBestIndex, Position, simplifyPositions } from './types/Position.js';\nimport { Rotation } from './types/Rotation.js';\nimport { Component } from './Component.js';\nimport { ENode } from './ENode.js';\nimport { ENodeType } from './types/ENodeType.js';\nimport { Wire } from './Wire.js';\nimport { COMPONENT_TYPE_METADATA, type ComponentType } from './types/ComponentType.js';\nimport { getComponentTypeMetadata } from './types/ComponentType.js';\nimport type { ENodeSourceType } from './types/ENodeSourceType';\nimport { CameraOptions, type ICameraOptions } from './types/CameraOptions';\n\nexport type ICircuitMetadata = {\n name: string;\n size: number;\n divisions: number;\n cameraOptions: ICameraOptions;\n};\n\n/**\n * Circuit metadata placeholder\n */\nexport class CircuitMetadata {\n /**\n * Create a new CircuitMetadata holding general information about the Circuit.\n *\n * @param name - Name of the circuit\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 name: string,\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(): {\n name: string;\n size: number;\n divisions: number;\n cameraOptions: ICameraOptions;\n } {\n return {\n name: this.name,\n size: this.size,\n divisions: this.divisions,\n cameraOptions: this.cameraOptions.toJSON(),\n };\n }\n\n static fromJSON(json: {\n name: string;\n size: number;\n divisions: number;\n cameraOptions: ICameraOptions;\n }): CircuitMetadata {\n return new CircuitMetadata(\n json.name,\n json.size,\n json.divisions,\n CameraOptions.fromJSON(json.cameraOptions)\n );\n }\n\n toString(): string {\n return `CircuitMetadata(${this.name}, ${this.size}, ${this.divisions}, ${this.cameraOptions.toString()})`;\n }\n}\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(name: string = 'Untitled Circuit') {\n this.metadata = new CircuitMetadata(name, 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.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.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 = getComponentTypeMetadata(type);\n\n // Create component first (to get its ID)\n const component = new Component(type, position, rotation, []);\n if (config) {\n component.config = new Map(config);\n }\n\n // Create pin ENodes for the component using metadata pin labels\n const pins: UUID[] = [];\n for (const [pinLabel, source] of metadata.pins) {\n const pinNode = new ENode(\n ENodeType.Pin,\n component.id,\n pinLabel,\n undefined, // Pin position derived from component,\n source\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 * 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 */\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(): {\n metadata: object;\n components: object[];\n enodes: object[];\n wires: object[];\n } {\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: {\n metadata: ICircuitMetadata;\n components: object[];\n enodes: object[];\n wires?: object[];\n }): Circuit {\n const circuit = new Circuit();\n circuit.metadata = CircuitMetadata.fromJSON(json.metadata);\n\n // Restore components\n for (const compData of json.components) {\n const component = Component.fromJSON(\n compData as {\n id: UUID;\n type: ComponentType;\n position: { x: number; y: number };\n rotation: number;\n pins: UUID[];\n config: { [key: string]: string };\n }\n );\n\n circuit.components.set(component.id, component);\n }\n\n // Restore ENodes\n for (const enodeData of json.enodes) {\n const enode = ENode.fromJSON(\n enodeData as {\n id: UUID;\n type: ENodeType;\n component?: UUID;\n pinLabel?: string;\n position?: { x: number; y: number };\n source?: ENodeSourceType;\n }\n );\n\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(\n wireData as {\n id: UUID;\n node1: UUID;\n node2: UUID;\n intermediatePositions: { x: number; y: number }[];\n }\n );\n\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 * Registry for component behavior implementations\n * @module core/simulation/behaviors\n */\n\nimport type { ComponentBehavior } from './ComponentBehavior.js';\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, ComponentBehavior>;\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: ComponentBehavior): 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: ComponentBehavior[]): 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): ComponentBehavior | 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 * Base state for all component types\n * @module core/simulation/states\n */\n\nimport type { UUID } from '../../types/Identifier.js';\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 state: string;\n\n /**\n * Tick when this state started.\n */\n startTick: number;\n\n /**\n * Create a new component state.\n *\n * @param componentId - UUID of the component\n * @param initialState - Initial operational state\n */\n constructor(componentId: UUID, initialState: string) {\n this.componentId = componentId;\n this.state = initialState;\n this.startTick = 0;\n }\n\n hasSameComponent(other: ComponentState): boolean {\n return this.componentId === other.componentId;\n }\n}\n","/**\n * Battery component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from './ComponentState.js';\nimport type { UUID } from '../../types/Identifier.js';\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 * Battery component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport type { NodeElectricalState } from '../states/NodeElectricalState.js';\nimport type { ScheduledEvent, UserCommand } from '../types';\nimport { Component } from '../../Component.js';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { ENodeSourceType } from '../../types/ENodeSourceType.js';\nimport type { ComponentBehavior, BehaviorResult } from './ComponentBehavior.js';\nimport { BatteryState } from '../states/BatteryState.js';\nimport type { ComponentState } from '../states/ComponentState.js';\n\nexport class BatteryBehavior implements ComponentBehavior {\n readonly componentType = ComponentType.Battery;\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 !== ComponentType.Battery) {\n throw new Error(`Invalid component type for BatteryBehavior: ${component.type}`);\n }\n return new BatteryState(component.id);\n }\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 /**\n * Batteries are always on, and their pins are locked so this is more of a decorative function\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, NodeElectricalState>,\n _targetTick: number\n ): BehaviorResult {\n const pinStates: Map<string, NodeElectricalState> = new Map();\n\n for (const pinId in component.pins) {\n pinStates.set(component.getPinLabel(pinId)!, nodeStates.get(pinId as UUID)!);\n }\n\n return {\n componentState: componentState,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onUserCommand(\n _component: Component,\n state: ComponentState,\n _command: UserCommand\n ): BehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n _event: ScheduledEvent\n ): BehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * Lightbulb component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from './ComponentState.js';\nimport type { UUID } from '../../types/Identifier.js';\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 * lightbulb behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport type { Component } from '../../Component.js';\nimport type { ENodeSourceType } from '../../types/ENodeSourceType.js';\nimport type { NodeElectricalState } from '../states/NodeElectricalState.js';\nimport type { ComponentState } from '../states/ComponentState.js';\nimport type { ScheduledEvent, UserCommand } from '../types';\nimport type { ComponentBehavior, BehaviorResult } from './ComponentBehavior.js';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { LightbulbState } from '../states/LightbulbState';\n\n\nexport class LightbulbBehavior implements ComponentBehavior {\n readonly componentType = ComponentType.Lightbulb;\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 !== ComponentType.Lightbulb) {\n throw new Error(`Invalid component type for lightbulbBehavior: ${component.type}`);\n }\n return new LightbulbState(component.id);\n }\n\n allowConductivity(\n _component: Component,\n _state: ComponentState,\n _conductivityType: ENodeSourceType,\n _pinId: string,\n _otherPinId: string\n ): boolean {\n return true; // lightbulb always allows conductivity\n }\n\n /**\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, NodeElectricalState>,\n targetTick: number\n ): BehaviorResult {\n const pinStates: Map<string, NodeElectricalState> = new Map();\n\n for (const pinId of component.pins) {\n pinStates.set(component.getPinLabel(pinId)!, nodeStates.get(pinId as UUID)!);\n }\n\n let activationCondition =\n (pinStates.get('pin1')!.hasVoltage && pinStates.get('pin1')!.hasCurrent) ||\n (pinStates.get('pin2')!.hasVoltage && pinStates.get('pin2')!.hasCurrent) ||\n (pinStates.get('pin1')!.hasVoltage && pinStates.get('pin2')!.hasCurrent) ||\n (pinStates.get('pin2')!.hasVoltage && pinStates.get('pin1')!.hasCurrent);\n\n let hasChanged = false;\n const scheduledEvents: ScheduledEvent[] = [];\n\n if (activationCondition) {\n if (state.state === 'off' || state.state === 'goingOff') {\n hasChanged = true;\n state.state = 'goingOn';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + 1, // TODO handle component config later\n type: 'GoingOnEnd',\n parameters: undefined,\n });\n state.state = 'goingOn';\n }\n } else {\n if (state.state === 'on' || state.state === 'goingOn') {\n hasChanged = true;\n state.state = 'goingOff';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + 1, // TODO handle component config later\n type: 'GoingOffEnd',\n parameters: undefined,\n });\n state.state = 'goingOff';\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: scheduledEvents,\n };\n }\n\n onUserCommand(\n _component: Component,\n state: ComponentState,\n _command: UserCommand\n ): BehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n event: ScheduledEvent\n ): BehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'GoingOffEnd') {\n if (state.state !== 'off') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'off';\n }\n } else if (event.type === 'GoingOnEnd') {\n if (state.state !== 'on') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'on';\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * LED component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from './ComponentState.js';\nimport type { UUID } from '../../types/Identifier.js';\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","/**\n * LED component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport type { Component } from '../../Component.js';\nimport type { ENodeSourceType } from '../../types/ENodeSourceType.js';\nimport type { NodeElectricalState } from '../states/NodeElectricalState.js';\nimport type { ScheduledEvent, UserCommand } from '../types';\nimport type { ComponentBehavior, BehaviorResult } from './ComponentBehavior.js';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { SmallLEDState } from '../states/SmallLEDState';\nimport type { ComponentState } from '../states/ComponentState.js';\n\n\nexport class SmallLEDBehavior implements ComponentBehavior {\n componentType = ComponentType.SmallLED;\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 !== ComponentType.SmallLED) {\n throw new Error(`Invalid component type for SmallLEDBehavior: ${component.type}`);\n }\n return new SmallLEDState(component.id);\n }\n\n allowConductivity(\n _component: Component,\n _state: ComponentState,\n _conductivityType: ENodeSourceType,\n _pinId: string,\n _otherPinId: string\n ): boolean {\n return true;\n // TODO: implement asymmetric conductivity later\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 onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, NodeElectricalState>,\n targetTick: number\n ): BehaviorResult {\n const pinStates: Map<string, NodeElectricalState> = new Map();\n\n for (const pinId of component.pins) {\n pinStates.set(component.getPinLabel(pinId)!, nodeStates.get(pinId as UUID)!);\n }\n\n let activationCondition =\n (pinStates.get('anode')!.hasVoltage && pinStates.get('anode')!.hasCurrent) ||\n (pinStates.get('cathode')!.hasVoltage && pinStates.get('cathode')!.hasCurrent) ||\n (pinStates.get('anode')!.hasVoltage && pinStates.get('cathode')!.hasCurrent) ||\n (pinStates.get('cathode')!.hasVoltage && pinStates.get('anode')!.hasCurrent);\n\n let hasChanged = false;\n const scheduledEvents: ScheduledEvent[] = [];\n\n if (activationCondition) {\n if (state.state === 'off' || state.state === 'goingOff') {\n hasChanged = true;\n state.state = 'goingOn';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + 1, // TODO handle component config later\n type: 'GoingOnEnd',\n parameters: undefined,\n });\n }\n } else {\n if (state.state === 'on' || state.state === 'goingOn') {\n hasChanged = true;\n state.state = 'goingOff';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + 1, // TODO handle component config later\n type: 'GoingOffEnd',\n parameters: undefined,\n });\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: scheduledEvents,\n };\n }\n\n onUserCommand(\n _component: Component,\n state: ComponentState,\n _command: UserCommand\n ): BehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n event: ScheduledEvent\n ): BehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'GoingOffEnd') {\n if (state.state !== 'off') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'off';\n }\n } else if (event.type === 'GoingOnEnd') {\n if (state.state !== 'on') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'on';\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: [],\n };\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 * RectangleLED component behavior implementation (just an extension of SmallLEDBehavior)\n * @module core/simulation/behaviors\n */\n\nimport type { Component } from '../../Component.js';\nimport type { ComponentState } from '../states/ComponentState.js';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { SmallLEDBehavior } from './SmallLEDBehavior.js';\nimport { RectangleLEDState } from '../states/RectangleLEDState';\n\nexport class RectangleLEDBehavior extends SmallLEDBehavior {\n override readonly componentType = ComponentType.RectangleLED;\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 override createInitialState(component: Component): ComponentState {\n if (component.type !== ComponentType.RectangleLED) {\n throw new Error(`Invalid component type for RectangleLEDBehavior: ${component.type}`);\n }\n return new RectangleLEDState(component.id);\n }\n}\n","/**\n * Relay component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from './ComponentState.js';\nimport type { UUID } from '../../types/Identifier.js';\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 * relay component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport type { Component } from '../../Component.js';\nimport type { ENodeSourceType } from '../../types/ENodeSourceType.js';\nimport type { NodeElectricalState } from '../states/NodeElectricalState.js';\nimport type { ComponentState } from '../states/ComponentState.js';\nimport type { ScheduledEvent, UserCommand } from '../types';\nimport type { ComponentBehavior, BehaviorResult } from './ComponentBehavior.js';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { RelayState } from '../states/RelayState';\n\nimport { TRANSITION_DEFAULTS } from '../types/SimulationConstants';\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 implements ComponentBehavior {\n readonly componentType = ComponentType.Relay;\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 !== ComponentType.Relay) {\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 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 onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, NodeElectricalState>,\n targetTick: number\n ): BehaviorResult {\n const pinStates: Map<string, NodeElectricalState> = new Map();\n\n for (const pinId of component.pins) {\n pinStates.set(component.getPinLabel(pinId)!, nodeStates.get(pinId as UUID)!);\n }\n\n const isCommanded =\n (pinStates.get('cmd_in')!.hasVoltage && pinStates.get('cmd_in')!.hasCurrent) ||\n (pinStates.get('cmd_out')!.hasVoltage && pinStates.get('cmd_out')!.hasCurrent) ||\n (pinStates.get('cmd_in')!.hasVoltage && pinStates.get('cmd_out')!.hasCurrent) ||\n (pinStates.get('cmd_out')!.hasVoltage && pinStates.get('cmd_in')!.hasCurrent);\n\n const shouldBeClosed =\n component.config.get('activationLogic') === 'negative' ? !isCommanded : isCommanded;\n\n let hasChanged = false;\n const scheduledEvents: ScheduledEvent[] = [];\n const transitionSpan = getTransitionSpan(component.config);\n\n if (shouldBeClosed) {\n if (state.state === 'open' || state.state === 'opening') {\n hasChanged = true;\n state.state = 'closing';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + transitionSpan,\n type: 'ClosingEnd',\n parameters: undefined,\n });\n }\n } else {\n if (state.state === 'closed' || state.state === 'closing') {\n hasChanged = true;\n state.state = 'opening';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + transitionSpan,\n type: 'OpeningEnd',\n parameters: undefined,\n });\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: scheduledEvents,\n };\n }\n\n onUserCommand(\n _component: Component,\n state: ComponentState,\n _command: UserCommand\n ): BehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n event: ScheduledEvent\n ): BehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'ClosingEnd') {\n if (state.state !== 'closed') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'closed';\n }\n } else if (event.type === 'OpeningEnd') {\n if (state.state !== 'open') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'open';\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * Switch component simulation state\n * @module core/simulation/states\n */\n\nimport { ComponentState } from './ComponentState.js';\nimport type { UUID } from '../../types/Identifier.js';\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 * Transistor component simulation state\n * @module core/simulation/states\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport { ComponentState } from './ComponentState.js';\n\n/**\n * Simulation state for Transistor components (NPN open if no base voltage).\n * Transistors can be \"open\", \"closing\", \"closed\", or \"opening\".\n *\n * @public\n */\nexport class TransistorState extends ComponentState {\n /**\n * Create a new Transistor state.\n *\n * @param componentId - UUID of the Transistor 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 transistor 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 transistor 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 behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport type { Component } from '../../Component.js';\nimport type { ENodeSourceType } from '../../types/ENodeSourceType.js';\nimport type { NodeElectricalState, ComponentState } from '../states';\nimport { SwitchState } from '../states';\nimport type { ScheduledEvent, UserCommand } from '../types';\nimport type { ComponentBehavior, BehaviorResult } from './ComponentBehavior.js';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { TRANSITION_DEFAULTS } from '../types';\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 */\nfunction 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/**\n * Behavior implementation for switches components.\n *\n * @public\n */\nexport class SwitchBehavior implements ComponentBehavior {\n readonly componentType = ComponentType.Switch;\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 !== ComponentType.Switch) {\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 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 * Switches states depend on user interaction, not their pins so this is more of a decorative function\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, NodeElectricalState>,\n _targetTick: number\n ): BehaviorResult {\n return {\n componentState: componentState,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onUserCommand(component: Component, state: ComponentState, command: UserCommand): BehaviorResult {\n let hasChanged = false;\n const scheduledEvents: ScheduledEvent[] = [];\n\n if (command.type === 'toggle_switch' && ['open', 'closed'].includes(state.state)) {\n state.state = state.state === 'open' ? 'closing' : 'opening';\n state.startTick = command.scheduledAtTick + 1;\n hasChanged = true;\n\n const tickCount = getTickCount(command.parameters);\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: state.startTick,\n readyAtTick: state.startTick + tickCount,\n type: state.state === 'closing' ? 'ClosingEnd' : 'OpeningEnd',\n parameters: undefined,\n });\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: scheduledEvents,\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n event: ScheduledEvent\n ): BehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'ClosingEnd') {\n if (state.state !== 'closed') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'closed';\n }\n } else if (event.type === 'OpeningEnd') {\n if (state.state !== 'open') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'open';\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: [],\n };\n }\n}\n","/**\n * transistor component behavior implementation\n * @module core/simulation/behaviors\n */\n\nimport type { UUID } from '../../types/Identifier.js';\nimport type { Component } from '../../Component.js';\nimport type { ENodeSourceType } from '../../types/ENodeSourceType.js';\nimport type { NodeElectricalState } from '../states/NodeElectricalState.js';\nimport type { ComponentState } from '../states/ComponentState.js';\nimport type { ScheduledEvent, UserCommand } from '../types';\nimport type { ComponentBehavior, BehaviorResult } from './ComponentBehavior.js';\nimport { TransistorState } from '../states/TransistorState';\nimport { ComponentType } from '../../types/ComponentType.js';\nimport { TRANSITION_DEFAULTS } from '../types/SimulationConstants';\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 transistors components.\n *\n * @public\n */\nexport class TransistorBehavior implements ComponentBehavior {\n readonly componentType = ComponentType.Transistor;\n\n /**\n * Create initial state for a transistor.\n *\n * @param component - The Transistor component\n * @returns Transistor Initial state (open by default)\n */\n createInitialState(component: Component): ComponentState {\n if (component.type !== ComponentType.Transistor) {\n throw new Error(`Invalid component type for TransistorBehavior: ${component.type}`);\n }\n const state = component.config.get('activationLogic') === 'negative' ? 'closed' : 'open';\n return new TransistorState(component.id, state);\n }\n\n 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('collector') && pinLabels.includes('emitter')) {\n return state.state === 'closed' || state.state === 'opening';\n }\n return false;\n }\n\n /**\n * Transistor Base need to have only voltage so that transistor contactor stays closed\n * @param component\n * @param state\n * @param nodeStates\n * @param targetTick\n */\n onPinsChange(\n component: Component,\n state: ComponentState,\n nodeStates: ReadonlyMap<UUID, NodeElectricalState>,\n targetTick: number\n ): BehaviorResult {\n const pinStates: Map<string, NodeElectricalState> = new Map();\n\n for (const pinId of component.pins) {\n pinStates.set(component.getPinLabel(pinId)!, nodeStates.get(pinId as UUID)!);\n }\n\n const isCommanded = pinStates.get('base')!.hasVoltage;\n\n const shouldConduct =\n component.config.get('activationLogic') === 'negative' ? !isCommanded : isCommanded;\n\n let hasChanged = false;\n const scheduledEvents: ScheduledEvent[] = [];\n const transitionSpan = getTransitionSpan(component.config);\n\n if (shouldConduct) {\n if (state.state === 'open' || state.state === 'opening') {\n hasChanged = true;\n state.state = 'closing';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + transitionSpan,\n type: 'ClosingEnd',\n parameters: undefined,\n });\n }\n } else {\n if (state.state === 'closed' || state.state === 'closing') {\n hasChanged = true;\n state.state = 'opening';\n state.startTick = targetTick;\n scheduledEvents.push({\n targetId: component.id,\n scheduledAtTick: targetTick,\n readyAtTick: targetTick + transitionSpan,\n type: 'OpeningEnd',\n parameters: undefined,\n });\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: scheduledEvents,\n };\n }\n\n onUserCommand(\n _component: Component,\n state: ComponentState,\n _command: UserCommand\n ): BehaviorResult {\n return {\n componentState: state,\n hasChanged: false,\n scheduledEvents: [],\n };\n }\n\n onEventFiring(\n _component: Component,\n state: ComponentState,\n event: ScheduledEvent\n ): BehaviorResult {\n let hasChanged = false;\n\n if (event.type === 'ClosingEnd') {\n if (state.state !== 'closed') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'closed';\n }\n } else if (event.type === 'OpeningEnd') {\n if (state.state !== 'open') {\n hasChanged = true;\n state.startTick = event.readyAtTick;\n state.state = 'open';\n }\n }\n\n return {\n componentState: state,\n hasChanged: hasChanged,\n scheduledEvents: [],\n };\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 TransistorBehavior\n} from './simulation/behaviors';\n\n/**\n * Register all basic component behaviors in the given registry\n * Basic components are : Battery, Lightbulb, RectangleLED, Relay, SmallLED, Switch, Transistor\n * @public\n * @param registry\n */\nexport function registerBasicComponentsBehaviors (registry: BehaviorRegistry): void {\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 TransistorBehavior());\n}"],"names":["ENode","type","component","pinLabel","position","source","generateUUID","circuit","ENodeType","newPosition","sourceType","json","Position","enode","Wire","node1","node2","intermediatePositions","p","positions","wire","CircuitMetadata","name","size","divisions","cameraOptions","CameraOptions","Circuit","value","rotation","config","metadata","getComponentTypeMetadata","Component","pins","pinNode","id","deletedWires","deletedENodes","pinId","wireIds","wireId","result","branchingPoint","wires","wire1","wire2","otherNode1","otherNode2","newWire","enode1","enode2","targetEnodeId","fullPositions","index","findPositionBestIndex","positionsWire1","positionsWire2","eNode","newWires","nodeId","componentId","pinIds","componentIds","enodeId","pinIndex","typeMetadata","COMPONENT_TYPE_METADATA","pinLabels","label","simplify","simplifiedFullPositions","simplifyPositions","margin","maxPos","pos","c","w","compData","enodeData","wireData","BehaviorRegistry","behavior","behaviors","componentType","ComponentState","initialState","other","BatteryState","BatteryBehavior","ComponentType","_component","_state","_conductivityType","_pinId","_otherPinId","componentState","nodeStates","_targetTick","pinStates","state","_command","_event","LightbulbState","LightbulbBehavior","targetTick","activationCondition","hasChanged","scheduledEvents","event","SmallLEDState","SmallLEDBehavior","RectangleLEDState","RectangleLEDBehavior","RelayState","getTransitionSpan","TRANSITION_DEFAULTS","RelayBehavior","otherPinId","otherPinLabel","isCommanded","shouldBeClosed","transitionSpan","SwitchState","TransistorState","getTickCount","parameters","SwitchBehavior","_nodeStates","command","tickCount","TransistorBehavior","shouldConduct","registerBasicComponentsBehaviors","registry"],"mappings":"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"}