simple-circuit-engine 0.0.10 → 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 +13 -7
  2. package/CLAUDE.md +16 -103
  3. package/README.md +8 -5
  4. package/dist/core/index.d.ts +2 -23
  5. package/dist/core/index.js +75 -2000
  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 -6286
  79. package/dist/index.js +120 -100
  80. package/dist/scene/CircuitEngine.d.ts +270 -0
  81. package/dist/scene/index.d.ts +1 -2
  82. package/dist/scene/index.js +44 -38
  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-DEb7JdNf.js +0 -1809
  136. package/dist/CircuitRunner-DEb7JdNf.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-AB1vFiis.js +0 -9918
  141. package/dist/setup-AB1vFiis.js.map +0 -1
@@ -1,2002 +1,77 @@
1
- import { e as O, P as k, C as b, c as B, i as P, j as S, d as y, f as G, b as V, s as C, a as h, T as f } from "../CircuitRunner-DEb7JdNf.js";
2
- import { k as me, D as we, E as ye, n as ve, h as Se, R as Ce, m as Te, S as Ee, l as Ie, g as Ae } from "../CircuitRunner-DEb7JdNf.js";
3
- class w {
4
- /**
5
- * Unique identifier for this wire.
6
- * @readonly
7
- */
8
- id;
9
- /**
10
- * First connected ENode UUID.
11
- * @readonly
12
- */
13
- node1;
14
- /**
15
- * Second connected ENode UUID.
16
- * @readonly
17
- */
18
- node2;
19
- /**
20
- * Optional intermediate positions for wire routing.
21
- * Empty array indicates straight-line connection.
22
- * @readonly
23
- */
24
- intermediatePositions;
25
- /**
26
- * Create a new wire.
27
- *
28
- * **Note**: Typically wires are created via `Circuit.addWire()` which
29
- * handles validation and bidirectional reference updates. This constructor
30
- * is used internally by Circuit.
31
- *
32
- * @param node1 - First ENode UUID
33
- * @param node2 - Second ENode UUID
34
- * @param intermediatePositions - Optional waypoints for rendering
35
- *
36
- * @example
37
- * ```typescript
38
- * // Usually created via Circuit:
39
- * const wire = circuit.addWire(nodeId1, nodeId2);
40
- *
41
- * // With intermediate positions:
42
- * const wire = circuit.addWire(
43
- * nodeId1,
44
- * nodeId2,
45
- * [new Position(5, 10), new Position(15, 10)]
46
- * );
47
- * ```
48
- */
49
- constructor(t, e, i = []) {
50
- this.id = O(), this.node1 = t, this.node2 = e, this.intermediatePositions = i;
51
- }
52
- /**
53
- * Check if this is a straight-line wire.
54
- *
55
- * @returns true if no intermediate positions, false otherwise
56
- *
57
- * @example
58
- * ```typescript
59
- * const straightWire = new Wire(node1, node2);
60
- * console.log(straightWire.isStraightLine()); // true
61
- *
62
- * const curvedWire = new Wire(node1, node2, [new Position(5, 5)]);
63
- * console.log(curvedWire.isStraightLine()); // false
64
- * ```
65
- */
66
- isStraightLine() {
67
- return this.intermediatePositions.length === 0;
68
- }
69
- /**
70
- * Serialize wire to JSON.
71
- *
72
- * @returns Plain object representation
73
- *
74
- * @example
75
- * ```typescript
76
- * const json = wire.toJSON();
77
- * console.log(json);
78
- * // {
79
- * // id: "uuid",
80
- * // node1: "node-uuid-1",
81
- * // node2: "node-uuid-2",
82
- * // intermediatePositions: [{ x: 5, y: 10 }]
83
- * // }
84
- * ```
85
- */
86
- toJSON() {
87
- return {
88
- id: this.id,
89
- node1: this.node1,
90
- node2: this.node2,
91
- intermediatePositions: this.intermediatePositions.map((t) => t.toJSON())
92
- };
93
- }
94
- /**
95
- * Deserialize wire from JSON.
96
- *
97
- * @param json - Wire data
98
- * @returns Wire instance
99
- *
100
- * @example
101
- * ```typescript
102
- * const json = {
103
- * id: "uuid",
104
- * node1: "node-uuid-1",
105
- * node2: "node-uuid-2",
106
- * intermediatePositions: [{ x: 5, y: 10 }]
107
- * };
108
- *
109
- * const wire = Wire.fromJSON(json);
110
- * ```
111
- */
112
- static fromJSON(t) {
113
- const e = t.intermediatePositions.map((n) => k.fromJSON(n)), i = new w(t.node1, t.node2, e);
114
- return Object.defineProperty(i, "id", {
115
- value: t.id,
116
- writable: !1,
117
- enumerable: !0,
118
- configurable: !1
119
- }), i;
120
- }
121
- }
122
- class v {
123
- /**
124
- * Create a new CircuitMetadata holding general information about the Circuit.
125
- *
126
- * @param name - Name of the circuit
127
- * @param size - Size of the circuit grid
128
- * @param divisions - Divisions in the circuit grid
129
- * @param cameraOptions - Camera Options at startup
130
- * @throws {TypeError} If size or divisions are not integers
131
- */
132
- constructor(t, e, i, n) {
133
- if (this.name = t, this.size = e, this.divisions = i, this.cameraOptions = n, !Number.isInteger(e) || !Number.isInteger(i))
134
- throw new TypeError(
135
- `Size and divisions must be integers (got size=${e}, divisions=${i})`
136
- );
137
- }
138
- toJSON() {
139
- return {
140
- name: this.name,
141
- size: this.size,
142
- divisions: this.divisions,
143
- cameraOptions: this.cameraOptions.toJSON()
144
- };
145
- }
146
- static fromJSON(t) {
147
- return new v(
148
- t.name,
149
- t.size,
150
- t.divisions,
151
- b.fromJSON(t.cameraOptions)
152
- );
153
- }
154
- toString() {
155
- return `CircuitMetadata(${this.name}, ${this.size}, ${this.divisions}, ${this.cameraOptions.toString()})`;
156
- }
157
- }
158
- class _ {
159
- /**
160
- * Circuit metadata holding general information.
161
- * @private
162
- */
163
- metadata;
164
- /**
165
- * Map of all components in the circuit (UUID → Component).
166
- * @private
167
- */
168
- components;
169
- /**
170
- * Map of all electrical nodes in the circuit (UUID → ENode).
171
- * Includes both pin nodes and branching point nodes.
172
- * @private
173
- */
174
- enodes;
175
- /**
176
- * Map of all wires in the circuit (UUID → Wire).
177
- * @private
178
- */
179
- wires;
180
- /**
181
- * Create a new empty circuit.
182
- */
183
- constructor(t = "Untitled Circuit") {
184
- this.metadata = new v(t, 10, 10, new b()), this.components = /* @__PURE__ */ new Map(), this.enodes = /* @__PURE__ */ new Map(), this.wires = /* @__PURE__ */ new Map();
185
- }
186
- get name() {
187
- return this.metadata.name;
188
- }
189
- set name(t) {
190
- if (typeof t != "string" || t.trim() === "")
191
- throw new TypeError("Circuit name must be a non-empty string");
192
- this.metadata.name = t;
193
- }
194
- /**
195
- * Add a new component to the circuit.
196
- *
197
- * Automatically creates pin ENodes for the component and links them
198
- * bidirectionally. Pin ENode UUIDs are stored in the component's pins array.
199
- * Pin labels are derived from the ComponentType metadata.
200
- *
201
- * @param type - Component type (Battery, Switch, LED, etc.)
202
- * @param position - Grid position (x, y integers)
203
- * @param rotation - Orientation angle (integer degrees)
204
- * @param config - Optional configuration map for component-specific settings
205
- * @returns The created Component
206
- * @throws {TypeError} If position/rotation coordinates are not integers
207
- *
208
- * @example
209
- * ```typescript
210
- * const lightbulb = circuit.addComponent(
211
- * new Position(10, 20),
212
- * new Rotation(90),
213
- * ComponentType.Lightbulb
214
- * );
215
- *
216
- * console.log(lightbulb.type); // ComponentType.Lightbulb
217
- * console.log(lightbulb.pins.length); // 2
218
- * console.log(lightbulb.position.x); // 10
219
- * ```
220
- */
221
- addComponent(t, e, i, n) {
222
- const s = B(t), o = new P(t, e, i, []);
223
- n && (o.config = new Map(n));
224
- const a = [];
225
- for (const [r, d] of s.pins) {
226
- const g = new S(
227
- y.Pin,
228
- o.id,
229
- r,
230
- void 0,
231
- // Pin position derived from component,
232
- d
233
- );
234
- this.enodes.set(g.id, g), a.push(g.id);
235
- }
236
- return Object.defineProperty(o, "pins", {
237
- value: a,
238
- writable: !1,
239
- enumerable: !0,
240
- configurable: !1
241
- }), this.components.set(o.id, o), o;
242
- }
243
- /**
244
- * Remove a component from the circuit.
245
- *
246
- * **Cascade deletion** removes:
247
- * - All pin ENodes belonging to the component
248
- * - All Wires connected to those pins
249
- *
250
- * @param id - Component UUID
251
- * @throws {Error} If component does not exist
252
- * @returns Object containing arrays of deleted Wires and ENodes IDs
253
- *
254
- * @example
255
- * ```typescript
256
- * circuit.removeComponent(componentId);
257
- * // Component, its pins, and connected wires are all removed
258
- * ```
259
- */
260
- removeComponent(t) {
261
- const e = this.components.get(t);
262
- if (!e)
263
- throw new Error(`Component ${t} does not exist`);
264
- const i = [], n = [];
265
- for (const s of e.pins) {
266
- const o = this.enodes.get(s);
267
- if (o) {
268
- const a = Array.from(o.wires);
269
- for (const r of a)
270
- this.removeWire(r), i.push(r);
271
- }
272
- this.enodes.delete(s), n.push(s);
273
- }
274
- return this.components.delete(t), { deletedWires: i, deletedENodes: n };
275
- }
276
- hasComponent(t) {
277
- return this.components.has(t);
278
- }
279
- /**
280
- * Get a component by ID.
281
- *
282
- * @param id - Component UUID
283
- * @returns The Component or undefined if not found
284
- *
285
- * @example
286
- * ```typescript
287
- * const component = circuit.getComponent(componentId);
288
- * if (component) {
289
- * console.log(component.position);
290
- * }
291
- * ```
292
- */
293
- getComponent(t) {
294
- return this.components.get(t);
295
- }
296
- /**
297
- * Get all components in the circuit.
298
- *
299
- * Returns a new array on each call (defensive copy).
300
- *
301
- * @returns Array of all Components
302
- *
303
- * @example
304
- * ```typescript
305
- * const components = circuit.getAllComponents();
306
- * console.log(`Circuit has ${components.length} components`);
307
- *
308
- * for (const comp of components) {
309
- * console.log(comp.id, comp.position);
310
- * }
311
- * ```
312
- */
313
- getAllComponents() {
314
- return Array.from(this.components.values());
315
- }
316
- getAllComponentsByType(t) {
317
- const e = [];
318
- for (const i of this.components.values())
319
- i.type === t && e.push(i);
320
- return e;
321
- }
322
- getFirstComponentOfType(t) {
323
- for (const e of this.components.values())
324
- if (e.type === t)
325
- return e;
326
- }
327
- /**
328
- * Get an electrical node by ID.
329
- *
330
- * Note: ENodes are automatically managed and not directly created
331
- * or removed by users.
332
- *
333
- * @param id - ENode UUID
334
- * @returns The ENode or undefined if not found
335
- *
336
- * @example
337
- * ```typescript
338
- * const component = circuit.addComponent(
339
- * new Position(10, 20),
340
- * new Rotation(0),
341
- * 2
342
- * );
343
- *
344
- * const pinId = component.pins[0];
345
- * const enode = circuit.getENode(pinId);
346
- * console.log(enode.type); // ENodeType.Pin
347
- * ```
348
- */
349
- getENode(t) {
350
- return this.enodes.get(t);
351
- }
352
- /**
353
- * Get all electrical nodes in the circuit.
354
- *
355
- * Includes both pin nodes (from components) and branching point nodes
356
- * (from wire splits).
357
- *
358
- * Returns a new array on each call (defensive copy).
359
- *
360
- * @returns Array of all ENodes
361
- *
362
- * @example
363
- * ```typescript
364
- * const enodes = circuit.getAllENodes();
365
- * console.log(`Circuit has ${enodes.length} electrical nodes`);
366
- *
367
- * for (const enode of enodes) {
368
- * console.log(enode.id, enode.type);
369
- * }
370
- * ```
371
- */
372
- getAllENodes() {
373
- return Array.from(this.enodes.values());
374
- }
375
- /**
376
- * Add a branching point electrical node at a specific position.
377
- *
378
- * Branching points are used to split wires and create junctions.
379
- * @param position - Grid position for the branching point
380
- * @param sourceType - Optional source type (voltage/current)
381
- * @returns The created ENode
382
- */
383
- addBranchingPoint(t, e) {
384
- const i = new S(
385
- y.BranchingPoint,
386
- void 0,
387
- void 0,
388
- t,
389
- e
390
- );
391
- return this.enodes.set(i.id, i), i;
392
- }
393
- /**
394
- * Remove a branching point electrical node from the circuit.
395
- * Also removes all wires connected to this branching point if there are ony one or more than 2.
396
- * In the case there are exactly two wires, they will be merged before removing the branching point.
397
- *
398
- * @param id - Branching point ENode UUID
399
- * @throws {Error} If ENode does not exist or is not a branching point
400
- */
401
- removeBranchingPoint(t) {
402
- const e = this.enodes.get(t);
403
- if (!e)
404
- throw new Error(`Enode ${t} does not exist`);
405
- if (e.type !== y.BranchingPoint)
406
- throw new Error(
407
- `Enode ${t} is not a branching point, it must be removed with its component.`
408
- );
409
- const i = {}, n = this.getWiresByNode(t);
410
- if (n.length === 1 || n.length > 2) {
411
- const s = [];
412
- for (const o of n)
413
- this.removeWire(o.id), s.push(o.id);
414
- Object.assign(i, { deletedWires: s });
415
- } else if (n.length === 2) {
416
- const s = n[0], o = n[1], a = s.node1 === t ? s.node2 : s.node1, r = o.node1 === t ? o.node2 : o.node1, d = [];
417
- a === s.node1 ? d.push(...s.intermediatePositions) : a === s.node2 && d.push(...[...s.intermediatePositions].reverse()), d.push(e.getPosition(this)), r === o.node1 ? d.push(...[...o.intermediatePositions].reverse()) : r === o.node2 && d.push(...o.intermediatePositions), this.removeWire(s.id), this.removeWire(o.id);
418
- const g = this.addWire(a, r, d);
419
- if (g instanceof Error)
420
- throw new Error(`Failed to merge wires at branching point ${t}: ${g.message}`);
421
- Object.assign(i, { mergedWires: [s.id, o.id] }), Object.assign(i, { newWire: g });
422
- }
423
- return this.enodes.delete(t), i;
424
- }
425
- /**
426
- * Add a wire connecting two electrical nodes.
427
- *
428
- * Validates that both nodes exist, not a self-connection, and no duplicate.
429
- * Updates bidirectional references (Wire ↔ ENodes).
430
- *
431
- * @param node1 - First ENode UUID
432
- * @param node2 - Second ENode UUID
433
- * @param intermediatePositions - Optional path waypoints for rendering
434
- * @returns The created Wire, or Error if validation fails
435
- *
436
- * @example
437
- * ```typescript
438
- * const comp1 = circuit.addComponent(new Position(0, 0), new Rotation(0), 1);
439
- * const comp2 = circuit.addComponent(new Position(10, 10), new Rotation(0), 1);
440
- *
441
- * const wire = circuit.addWire(comp1.pins[0], comp2.pins[0]);
442
- * if (wire instanceof Error) {
443
- * console.error('Failed:', wire.message);
444
- * }
445
- * ```
446
- */
447
- addWire(t, e, i) {
448
- if (t === e)
449
- return new Error("Cannot create wire connecting node to itself");
450
- const n = this.enodes.get(t), s = this.enodes.get(e);
451
- if (!n || !s)
452
- return new Error("Wire requires at least one existing ENode");
453
- if (this.hasWireBetween(t, e))
454
- return new Error("Duplicate wire between same nodes");
455
- const o = new w(t, e, i || []);
456
- return this.wires.set(o.id, o), n.wires.add(o.id), s.wires.add(o.id), o;
457
- }
458
- /**
459
- * Remove a wire from the circuit.
460
- *
461
- * @param id - Wire UUID
462
- * @throws {Error} If wire does not exist
463
- *
464
- * @example
465
- * ```typescript
466
- * circuit.removeWire(wireId);
467
- * // Wire is removed
468
- * ```
469
- */
470
- removeWire(t) {
471
- const e = this.wires.get(t);
472
- if (!e)
473
- throw new Error(`Wire ${t} does not exist`);
474
- const i = this.enodes.get(e.node1), n = this.enodes.get(e.node2);
475
- i && i.wires.delete(t), n && n.wires.delete(t), this.wires.delete(t);
476
- }
477
- /**
478
- * Split a wire in the circuit.
479
- *
480
- * It creates two new wires connected by either the target enode or a new branching point ENode at the specified position.
481
- * Returns 2 UUIDS of the new wires.
482
- *
483
- * @param id - Wire UUID
484
- * @param position
485
- * @throws {Error} If wire does not exist
486
- *
487
- * @example
488
- * ```typescript
489
- * circuit.splitWire(wireId);
490
- * // Wire and any orphaned branching points are removed
491
- * ```
492
- */
493
- /**
494
- * Split an existing wire at a position, creating a branching point.
495
- * The original wire is removed and replaced with two new wires
496
- * connecting through the new branching point.
497
- * NB : in the special case where targetEnode belongs to a component where the wire is already connected
498
- * only one new wire will be created as this method don't allow a wire directly connecting two pins of the same component.
499
- *
500
- * @param wireId - Wire to split
501
- * @param position - Position for the new branching point : no effect if targetEnodeId provided
502
- * @param targetEnodeId - if provided, the existing enode to split the wire at
503
- * @returns Object containing the new branching point and an array of the two new wires
504
- * @throws Error if wireId not found
505
- */
506
- splitWire(t, e, i = null) {
507
- const n = this.wires.get(t);
508
- if (!n)
509
- throw new Error(`Wire ${t} does not exist`);
510
- const s = this.enodes.get(n.node1), o = this.enodes.get(n.node2);
511
- if (!s || !o)
512
- throw new Error(`Wire ${t} is connected to non-existent ENodes`);
513
- const a = [
514
- s.getPosition(this),
515
- ...n.intermediatePositions,
516
- o.getPosition(this)
517
- ], r = G(a, e), d = a.slice(1, r), g = a.slice(r, a.length - 1);
518
- this.wires.delete(t), s.wires.delete(t), o.wires.delete(t);
519
- let l;
520
- if (i)
521
- if (this.enodes.get(i))
522
- l = this.enodes.get(i);
523
- else
524
- throw new Error(`Target ENode ${i} does not exist`);
525
- else
526
- l = this.addBranchingPoint(e);
527
- const m = [];
528
- if ((!l.component || s.component !== l.component) && !this.hasWireBetween(s.id, l.id)) {
529
- const u = this.addWire(s.id, l.id, d);
530
- u instanceof w ? (this.simplifyWireIntermediatePositions(u.id), m.push(u)) : console.warn(`Failure to create wire at split : ${u.message}`);
531
- }
532
- if ((!l.component || o.component !== l.component) && !this.hasWireBetween(o.id, l.id)) {
533
- const u = this.addWire(l.id, o.id, g);
534
- u instanceof w ? (this.simplifyWireIntermediatePositions(u.id), m.push(u)) : console.warn(`Failure to create wire at split : ${u.message}`);
535
- }
536
- return {
537
- branchingPoint: l,
538
- wires: m
539
- };
540
- }
541
- getWireBetweenNodes(t, e) {
542
- const i = this.enodes.get(t);
543
- if (i)
544
- for (const n of i.wires) {
545
- const s = this.wires.get(n);
546
- if (s && (s.node2 === e || s.node1 === e))
547
- return s;
548
- }
549
- }
550
- /**
551
- * Get a wire by ID.
552
- *
553
- * @param id - Wire UUID
554
- * @returns The Wire or undefined if not found
555
- */
556
- getWire(t) {
557
- return this.wires.get(t);
558
- }
559
- /**
560
- * Get all wires in the circuit.
561
- *
562
- * Returns a new array on each call (defensive copy).
563
- *
564
- * @returns Array of all Wires
565
- */
566
- getAllWires() {
567
- return Array.from(this.wires.values());
568
- }
569
- /**
570
- * Get all wires connected to a specific ENode.
571
- *
572
- * @param nodeId - ENode UUID
573
- * @returns Array of connected Wires, or empty array if node not found
574
- */
575
- getWiresByNode(t) {
576
- const e = this.enodes.get(t);
577
- if (!e)
578
- return [];
579
- const i = [];
580
- for (const n of e.wires) {
581
- const s = this.wires.get(n);
582
- s && i.push(s);
583
- }
584
- return i;
585
- }
586
- /**
587
- * Get all wires connected to a component, e.g to any pin enode of the component.
588
- *
589
- * @param componentId - Component UUID
590
- * @returns Array of connected Wires, or empty array if component not found
591
- */
592
- getWiresByComponent(t) {
593
- const e = this.components.get(t);
594
- if (!e)
595
- return [];
596
- const i = [];
597
- for (const n of e.pins)
598
- i.push(...this.getWiresByNode(n));
599
- return i;
600
- }
601
- /**
602
- * Get both ENodes connected by a wire.
603
- *
604
- * @param wireId - Wire UUID
605
- * @returns Tuple [node1, node2] or undefined if wire not found
606
- */
607
- getNodesByWire(t) {
608
- const e = this.wires.get(t);
609
- if (!e)
610
- return;
611
- const i = this.enodes.get(e.node1), n = this.enodes.get(e.node2);
612
- if (!(!i || !n))
613
- return [i, n];
614
- }
615
- /**
616
- * Check if a wire already exists between two nodes.
617
- *
618
- * Order-independent: returns true for (A, B) or (B, A).
619
- *
620
- * @param node1 - First ENode UUID
621
- * @param node2 - Second ENode UUID
622
- * @returns true if wire exists, false otherwise
623
- */
624
- hasWireBetween(t, e) {
625
- const i = this.enodes.get(t);
626
- if (!i)
627
- return !1;
628
- for (const n of i.wires) {
629
- const s = this.wires.get(n);
630
- if (s && (s.node2 === e || s.node1 === e))
631
- return !0;
632
- }
633
- return !1;
634
- }
635
- /**
636
- * Find all components with pins among the provided enode IDs set.
637
- *
638
- * @param pinIds - Set of pins UUIDs
639
- * @returns Set of components UUIDs
640
- */
641
- getComponentsOfPins(t) {
642
- const e = /* @__PURE__ */ new Set();
643
- for (const i of t) {
644
- const n = this.enodes.get(i);
645
- n?.component && e.add(n.component);
646
- }
647
- return e;
648
- }
649
- /**
650
- * Get a component's pin ENode by its label.
651
- * @param component
652
- * @param pinLabel
653
- */
654
- getComponentPinByLabel(t, e) {
655
- let i = 0;
656
- const n = V[t.type], s = Array.from(n.pins.keys());
657
- for (const o of t.pins) {
658
- const a = this.enodes.get(o), r = s[i];
659
- if (r) {
660
- if (a && r === e)
661
- return a;
662
- i++;
663
- }
664
- }
665
- }
666
- /**
667
- * Update the intermediate positions of a wire.
668
- * Update the wire in place.
669
- *
670
- * @param wireId - Wire to update
671
- * @param intermediatePositions - New intermediate positions
672
- * @param simplify - Whether to simplify positions by removing collinear points : useful when finalizing wire routing
673
- * @returns The updated Wire
674
- * @throws Error if wireId not found
675
- */
676
- updateWireIntermediatePositions(t, e, i = !1) {
677
- const n = this.wires.get(t);
678
- if (!n)
679
- throw new Error(`Wire ${t} does not exist`);
680
- if (i) {
681
- const s = [
682
- this.enodes.get(n.node1).getPosition(this),
683
- ...e,
684
- this.enodes.get(n.node2).getPosition(this)
685
- ], o = C(s, 10);
686
- n.intermediatePositions = o.slice(
687
- 1,
688
- o.length - 1
689
- );
690
- } else
691
- n.intermediatePositions = e;
692
- return n;
693
- }
694
- /**
695
- * Simplify intermediate positions of a wire.
696
- * Update the wire in place.
697
- * @param wireId - Wire to simplify
698
- * @returns The updated Wire
699
- * @throws Error if wireId not found
700
- */
701
- simplifyWireIntermediatePositions(t) {
702
- const e = this.wires.get(t);
703
- if (!e)
704
- throw new Error(`Wire ${t} does not exist`);
705
- const i = [
706
- this.enodes.get(e.node1).getPosition(this),
707
- ...e.intermediatePositions,
708
- this.enodes.get(e.node2).getPosition(this)
709
- ], n = C(i, 5);
710
- return e.intermediatePositions = n.slice(
711
- 1,
712
- n.length - 1
713
- ), e.intermediatePositions = C(e.intermediatePositions), e;
714
- }
715
- /**
716
- * Update the source type of an ENode (branching point or component pin).
717
- * @param enodeId - ENode to update
718
- * @param sourceType - New source type (null to clear)
719
- * @throws Error if enodeId not found
720
- */
721
- updateENodeSourceType(t, e) {
722
- const i = this.enodes.get(t);
723
- if (!i)
724
- throw new Error(`ENode ${t} does not exist`);
725
- i.source = e || void 0;
726
- }
727
- /**
728
- * iterate through all components, enodes and wires positions to get the size that allows to enclose all elements.
729
- * @param margin - optional margin to add to the size
730
- * @returns size that allows to enclose all elements plus margin
731
- * @todo if calls to this method at each build operation ends causes slowness see to optimize by restricting checked elements
732
- */
733
- getEnclosingSize(t = 0) {
734
- let e = 0;
735
- for (const i of this.components.values())
736
- e = Math.max(e, Math.abs(i.position.x), Math.abs(i.position.y));
737
- for (const i of this.enodes.values()) {
738
- if (i.type === y.Pin) continue;
739
- const n = i.position;
740
- n && (e = Math.max(e, Math.abs(n.x), Math.abs(n.y)));
741
- }
742
- for (const i of this.wires.values())
743
- for (const n of i.intermediatePositions)
744
- e = Math.max(e, Math.abs(n.x), Math.abs(n.y));
745
- return Math.ceil(e * 2 + Math.max(t, 0));
746
- }
747
- /**
748
- * Serialize circuit to JSON.
749
- *
750
- * @returns JSON-serializable object containing all components, enodes, and wires
751
- *
752
- * @example
753
- * ```typescript
754
- * const json = circuit.toJSON();
755
- * localStorage.setItem('my-circuit', JSON.stringify(json));
756
- * ```
757
- */
758
- toJSON() {
759
- return {
760
- metadata: this.metadata.toJSON(),
761
- components: this.getAllComponents().map((t) => t.toJSON()),
762
- enodes: this.getAllENodes().map((t) => t.toJSON()),
763
- wires: this.getAllWires().map((t) => t.toJSON())
764
- };
765
- }
766
- /**
767
- * Deserialize circuit from JSON.
768
- *
769
- * @param json - Circuit data
770
- * @returns Circuit instance
771
- * @throws {Error} If JSON is invalid or violates invariants
772
- *
773
- * @example
774
- * ```typescript
775
- * const jsonStr = localStorage.getItem('my-circuit');
776
- * const json = JSON.parse(jsonStr);
777
- * const circuit = Circuit.fromJSON(json);
778
- * ```
779
- */
780
- static fromJSON(t) {
781
- const e = new _();
782
- e.metadata = v.fromJSON(t.metadata);
783
- for (const i of t.components) {
784
- const n = P.fromJSON(
785
- i
786
- );
787
- e.components.set(n.id, n);
788
- }
789
- for (const i of t.enodes) {
790
- const n = S.fromJSON(
791
- i
792
- );
793
- e.enodes.set(n.id, n);
794
- }
795
- if (t.wires)
796
- for (const i of t.wires) {
797
- const n = w.fromJSON(
798
- i
799
- );
800
- e.wires.set(n.id, n);
801
- const s = e.enodes.get(n.node1), o = e.enodes.get(n.node2);
802
- s && s.wires.add(n.id), o && o.wires.add(n.id);
803
- }
804
- return e;
805
- }
806
- }
807
- class ge {
808
- behaviors;
809
- /**
810
- * Create a new empty behavior registry.
811
- */
812
- constructor() {
813
- this.behaviors = /* @__PURE__ */ new Map();
814
- }
815
- /**
816
- * Register a behavior for a component type.
817
- * Overwrites any existing behavior for the same type.
818
- *
819
- * @param behavior - The component behavior to register
820
- * @throws TypeError if behavior is null/undefined or componentType is empty
821
- * @returns The registry instance for chaining
822
- */
823
- register(t) {
824
- if (!t)
825
- throw new TypeError("Behavior cannot be null or undefined");
826
- if (!t.componentType || t.componentType.trim() === "")
827
- throw new TypeError("Behavior componentType cannot be empty");
828
- return this.behaviors.set(t.componentType, t), this;
829
- }
830
- /**
831
- * Register multiple behaviors at once.
832
- * Convenience method for bulk registration.
833
- *
834
- * @param behaviors - Array of behaviors to register
835
- */
836
- registerAll(t) {
837
- t.forEach((e) => this.register(e));
838
- }
839
- /**
840
- * Get the behavior for a component type.
841
- *
842
- * @param componentType - Type identifier (e.g., "battery", "led")
843
- * @returns The registered behavior, or undefined if not found
844
- */
845
- get(t) {
846
- return this.behaviors.get(t);
847
- }
848
- /**
849
- * Check if a behavior is registered for a component type.
850
- *
851
- * @param componentType - Type identifier to check
852
- * @returns True if behavior is registered
853
- */
854
- has(t) {
855
- return this.behaviors.has(t);
856
- }
857
- /**
858
- * Unregister a behavior for a component type.
859
- *
860
- * @param componentType - Type identifier to unregister
861
- * @returns True if behavior was found and removed
862
- */
863
- unregister(t) {
864
- return this.behaviors.delete(t);
865
- }
866
- /**
867
- * Clear all registered behaviors.
868
- */
869
- clear() {
870
- this.behaviors.clear();
871
- }
872
- /**
873
- * Get all registered component types.
874
- *
875
- * @returns Array of component type identifiers
876
- */
877
- getRegisteredTypes() {
878
- return Array.from(this.behaviors.keys());
879
- }
880
- /**
881
- * Get count of registered behaviors.
882
- *
883
- * @returns Number of registered behaviors
884
- */
885
- size() {
886
- return this.behaviors.size;
887
- }
888
- }
889
- class p {
890
- /**
891
- * Component UUID this state belongs to.
892
- * @readonly
893
- */
894
- componentId;
895
- /**
896
- * Current operational state (varies by component type).
897
- * Examples: "on", "off", "open", "closed", "activating", "active"
898
- */
899
- state;
900
- /**
901
- * Tick when this state started.
902
- */
903
- startTick;
904
- /**
905
- * Create a new component state.
906
- *
907
- * @param componentId - UUID of the component
908
- * @param initialState - Initial operational state
909
- */
910
- constructor(t, e) {
911
- this.componentId = t, this.state = e, this.startTick = 0;
912
- }
913
- hasSameComponent(t) {
914
- return this.componentId === t.componentId;
915
- }
916
- }
917
- class x extends p {
918
- /**
919
- * Create a new battery state.
920
- *
921
- * @param componentId - UUID of the battery component
922
- */
923
- constructor(t) {
924
- super(t, "on");
925
- }
926
- }
927
- class W {
928
- componentType = h.Battery;
929
- /**
930
- * Create initial state for a battery.
931
- *
932
- * @param component - The Battery component
933
- * @returns Battery Initial state (always active and delivering voltage)
934
- */
935
- createInitialState(t) {
936
- if (t.type !== h.Battery)
937
- throw new Error(`Invalid component type for BatteryBehavior: ${t.type}`);
938
- return new x(t.id);
939
- }
940
- allowConductivity(t, e, i, n, s) {
941
- return !1;
942
- }
943
- /**
944
- * Batteries are always on, and their pins are locked so this is more of a decorative function
945
- * @param component
946
- * @param componentState
947
- * @param nodeStates
948
- * @param _targetTick
949
- */
950
- onPinsChange(t, e, i, n) {
951
- const s = /* @__PURE__ */ new Map();
952
- for (const o in t.pins)
953
- s.set(t.getPinLabel(o), i.get(o));
954
- return {
955
- componentState: e,
956
- hasChanged: !1,
957
- scheduledEvents: []
958
- };
959
- }
960
- onUserCommand(t, e, i) {
961
- return {
962
- componentState: e,
963
- hasChanged: !1,
964
- scheduledEvents: []
965
- };
966
- }
967
- onEventFiring(t, e, i) {
968
- return {
969
- componentState: e,
970
- hasChanged: !1,
971
- scheduledEvents: []
972
- };
973
- }
974
- }
975
- class $ extends p {
976
- /**
977
- * Create a new Lightbulb state.
978
- *
979
- * @param componentId - UUID of the Lightbulb component
980
- * @param initialState - Initial operational state (default: "off")
981
- */
982
- constructor(t, e = "off") {
983
- super(t, e);
984
- }
985
- /**
986
- * Check if Lightbulb is in lit state (on or going_on)
987
- */
988
- get isLit() {
989
- return this.state === "on" || this.state === "goingOn";
990
- }
991
- }
992
- class M {
993
- componentType = h.Lightbulb;
994
- /**
995
- * Create initial state for a lightbulb.
996
- *
997
- * @param component - The lightbulb component
998
- * @returns lightbulbInitial state (always active and delivering voltage)
999
- */
1000
- createInitialState(t) {
1001
- if (t.type !== h.Lightbulb)
1002
- throw new Error(`Invalid component type for lightbulbBehavior: ${t.type}`);
1003
- return new $(t.id);
1004
- }
1005
- allowConductivity(t, e, i, n, s) {
1006
- return !0;
1007
- }
1008
- /**
1009
- * @param component
1010
- * @param state
1011
- * @param nodeStates
1012
- * @param targetTick
1013
- */
1014
- onPinsChange(t, e, i, n) {
1015
- const s = /* @__PURE__ */ new Map();
1016
- for (const d of t.pins)
1017
- s.set(t.getPinLabel(d), i.get(d));
1018
- let o = s.get("pin1").hasVoltage && s.get("pin1").hasCurrent || s.get("pin2").hasVoltage && s.get("pin2").hasCurrent || s.get("pin1").hasVoltage && s.get("pin2").hasCurrent || s.get("pin2").hasVoltage && s.get("pin1").hasCurrent, a = !1;
1019
- const r = [];
1020
- return o ? (e.state === "off" || e.state === "goingOff") && (a = !0, e.state = "goingOn", e.startTick = n, r.push({
1021
- targetId: t.id,
1022
- scheduledAtTick: n,
1023
- readyAtTick: n + 1,
1024
- // TODO handle component config later
1025
- type: "GoingOnEnd",
1026
- parameters: void 0
1027
- }), e.state = "goingOn") : (e.state === "on" || e.state === "goingOn") && (a = !0, e.state = "goingOff", e.startTick = n, r.push({
1028
- targetId: t.id,
1029
- scheduledAtTick: n,
1030
- readyAtTick: n + 1,
1031
- // TODO handle component config later
1032
- type: "GoingOffEnd",
1033
- parameters: void 0
1034
- }), e.state = "goingOff"), {
1035
- componentState: e,
1036
- hasChanged: a,
1037
- scheduledEvents: r
1038
- };
1039
- }
1040
- onUserCommand(t, e, i) {
1041
- return {
1042
- componentState: e,
1043
- hasChanged: !1,
1044
- scheduledEvents: []
1045
- };
1046
- }
1047
- onEventFiring(t, e, i) {
1048
- let n = !1;
1049
- return i.type === "GoingOffEnd" ? e.state !== "off" && (n = !0, e.startTick = i.readyAtTick, e.state = "off") : i.type === "GoingOnEnd" && e.state !== "on" && (n = !0, e.startTick = i.readyAtTick, e.state = "on"), {
1050
- componentState: e,
1051
- hasChanged: n,
1052
- scheduledEvents: []
1053
- };
1054
- }
1055
- }
1056
- class L extends p {
1057
- /**
1058
- * Create a new SmallLED state.
1059
- *
1060
- * @param componentId - UUID of the LED component
1061
- * @param initialState - Initial operational state (default: "off")
1062
- */
1063
- constructor(t, e = "off") {
1064
- super(t, e);
1065
- }
1066
- /**
1067
- * Check if LED is in lit state (on or going_on)
1068
- */
1069
- get isLit() {
1070
- return this.state === "on" || this.state === "goingOn";
1071
- }
1072
- }
1073
- class N {
1074
- componentType = h.SmallLED;
1075
- /**
1076
- * Create initial state for a smallLED.
1077
- *
1078
- * @param component - The smallLED component
1079
- * @returns LED Initial state (always active and delivering voltage)
1080
- */
1081
- createInitialState(t) {
1082
- if (t.type !== h.SmallLED)
1083
- throw new Error(`Invalid component type for SmallLEDBehavior: ${t.type}`);
1084
- return new L(t.id);
1085
- }
1086
- allowConductivity(t, e, i, n, s) {
1087
- return !0;
1088
- }
1089
- /**
1090
- * only symmetrical behavior of LEDS is handled for now
1091
- * @param component
1092
- * @param state
1093
- * @param nodeStates
1094
- * @param targetTick
1095
- */
1096
- onPinsChange(t, e, i, n) {
1097
- const s = /* @__PURE__ */ new Map();
1098
- for (const d of t.pins)
1099
- s.set(t.getPinLabel(d), i.get(d));
1100
- let o = s.get("anode").hasVoltage && s.get("anode").hasCurrent || s.get("cathode").hasVoltage && s.get("cathode").hasCurrent || s.get("anode").hasVoltage && s.get("cathode").hasCurrent || s.get("cathode").hasVoltage && s.get("anode").hasCurrent, a = !1;
1101
- const r = [];
1102
- return o ? (e.state === "off" || e.state === "goingOff") && (a = !0, e.state = "goingOn", e.startTick = n, r.push({
1103
- targetId: t.id,
1104
- scheduledAtTick: n,
1105
- readyAtTick: n + 1,
1106
- // TODO handle component config later
1107
- type: "GoingOnEnd",
1108
- parameters: void 0
1109
- })) : (e.state === "on" || e.state === "goingOn") && (a = !0, e.state = "goingOff", e.startTick = n, r.push({
1110
- targetId: t.id,
1111
- scheduledAtTick: n,
1112
- readyAtTick: n + 1,
1113
- // TODO handle component config later
1114
- type: "GoingOffEnd",
1115
- parameters: void 0
1116
- })), {
1117
- componentState: e,
1118
- hasChanged: a,
1119
- scheduledEvents: r
1120
- };
1121
- }
1122
- onUserCommand(t, e, i) {
1123
- return {
1124
- componentState: e,
1125
- hasChanged: !1,
1126
- scheduledEvents: []
1127
- };
1128
- }
1129
- onEventFiring(t, e, i) {
1130
- let n = !1;
1131
- return i.type === "GoingOffEnd" ? e.state !== "off" && (n = !0, e.startTick = i.readyAtTick, e.state = "off") : i.type === "GoingOnEnd" && e.state !== "on" && (n = !0, e.startTick = i.readyAtTick, e.state = "on"), {
1132
- componentState: e,
1133
- hasChanged: n,
1134
- scheduledEvents: []
1135
- };
1136
- }
1137
- }
1138
- class R extends L {
1139
- }
1140
- class F extends N {
1141
- componentType = h.RectangleLED;
1142
- /**
1143
- * Create initial state for a RectangleLED.
1144
- *
1145
- * @param component - The smallLED component
1146
- * @returns LED Initial state (always active and delivering voltage)
1147
- */
1148
- createInitialState(t) {
1149
- if (t.type !== h.RectangleLED)
1150
- throw new Error(`Invalid component type for RectangleLEDBehavior: ${t.type}`);
1151
- return new R(t.id);
1152
- }
1153
- }
1154
- class D extends p {
1155
- /**
1156
- * Create a new Relay state.
1157
- *
1158
- * @param componentId - UUID of the Relay component
1159
- * @param initialState - Initial operational state (default: "open")
1160
- */
1161
- constructor(t, e = "open") {
1162
- super(t, e);
1163
- }
1164
- /**
1165
- * Check if relay is in opening or closing state
1166
- */
1167
- get isInTransition() {
1168
- return this.state === "closing" || this.state === "opening";
1169
- }
1170
- /**
1171
- * Check if relay is in closed or closing state
1172
- */
1173
- get isClosed() {
1174
- return this.state === "closed" || this.state === "closing";
1175
- }
1176
- }
1177
- function J(c) {
1178
- const t = parseInt(c.get("transitionSpan") || "", 10);
1179
- return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
1180
- }
1181
- class U {
1182
- componentType = h.Relay;
1183
- /**
1184
- * Create initial state for a relay.
1185
- *
1186
- * @param component - The Relay component
1187
- * @returns Relay Initial state (open by default)
1188
- */
1189
- createInitialState(t) {
1190
- if (t.type !== h.Relay)
1191
- throw new Error(`Invalid component type for RelayBehavior: ${t.type}`);
1192
- const e = t.config.get("activationLogic") === "negative" ? "closed" : "open";
1193
- return new D(t.id, e);
1194
- }
1195
- allowConductivity(t, e, i, n, s) {
1196
- if (n === s) return !0;
1197
- const o = t.getPinLabel(n), a = t.getPinLabel(s);
1198
- if (!o || !a) return !1;
1199
- const r = [o, a];
1200
- return r.includes("cmd_in") && r.includes("cmd_out") ? !0 : r.includes("power_in") && r.includes("power_out") ? e.state === "closed" || e.state === "opening" : !1;
1201
- }
1202
- /**
1203
- * Relay cmd pins need to have voltage and current so that relay contactor stays closed
1204
- * @param component
1205
- * @param state
1206
- * @param nodeStates
1207
- * @param targetTick
1208
- */
1209
- onPinsChange(t, e, i, n) {
1210
- const s = /* @__PURE__ */ new Map();
1211
- for (const l of t.pins)
1212
- s.set(t.getPinLabel(l), i.get(l));
1213
- const o = s.get("cmd_in").hasVoltage && s.get("cmd_in").hasCurrent || s.get("cmd_out").hasVoltage && s.get("cmd_out").hasCurrent || s.get("cmd_in").hasVoltage && s.get("cmd_out").hasCurrent || s.get("cmd_out").hasVoltage && s.get("cmd_in").hasCurrent, a = t.config.get("activationLogic") === "negative" ? !o : o;
1214
- let r = !1;
1215
- const d = [], g = J(t.config);
1216
- return a ? (e.state === "open" || e.state === "opening") && (r = !0, e.state = "closing", e.startTick = n, d.push({
1217
- targetId: t.id,
1218
- scheduledAtTick: n,
1219
- readyAtTick: n + g,
1220
- type: "ClosingEnd",
1221
- parameters: void 0
1222
- })) : (e.state === "closed" || e.state === "closing") && (r = !0, e.state = "opening", e.startTick = n, d.push({
1223
- targetId: t.id,
1224
- scheduledAtTick: n,
1225
- readyAtTick: n + g,
1226
- type: "OpeningEnd",
1227
- parameters: void 0
1228
- })), {
1229
- componentState: e,
1230
- hasChanged: r,
1231
- scheduledEvents: d
1232
- };
1233
- }
1234
- onUserCommand(t, e, i) {
1235
- return {
1236
- componentState: e,
1237
- hasChanged: !1,
1238
- scheduledEvents: []
1239
- };
1240
- }
1241
- onEventFiring(t, e, i) {
1242
- let n = !1;
1243
- return i.type === "ClosingEnd" ? e.state !== "closed" && (n = !0, e.startTick = i.readyAtTick, e.state = "closed") : i.type === "OpeningEnd" && e.state !== "open" && (n = !0, e.startTick = i.readyAtTick, e.state = "open"), {
1244
- componentState: e,
1245
- hasChanged: n,
1246
- scheduledEvents: []
1247
- };
1248
- }
1249
- }
1250
- class H extends p {
1251
- /**
1252
- * Create a new Switch state.
1253
- *
1254
- * @param componentId - UUID of the Switch component
1255
- * @param initialState - Initial operational state (default: "open")
1256
- */
1257
- constructor(t, e = "open") {
1258
- super(t, e);
1259
- }
1260
- /**
1261
- * Check if switch is in opening or closing state
1262
- */
1263
- get isInTransition() {
1264
- return this.state === "closing" || this.state === "opening";
1265
- }
1266
- /**
1267
- * Check if switch is in closed or closing state
1268
- */
1269
- get isClosed() {
1270
- return this.state === "closed" || this.state === "closing";
1271
- }
1272
- }
1273
- class z extends p {
1274
- /**
1275
- * Create a new Transistor state.
1276
- *
1277
- * @param componentId - UUID of the Transistor component
1278
- * @param initialState - Initial operational state (default: "open")
1279
- */
1280
- constructor(t, e = "open") {
1281
- super(t, e);
1282
- }
1283
- /**
1284
- * Check if transistor is in opening or closing state
1285
- */
1286
- get isInTransition() {
1287
- return this.state === "closing" || this.state === "opening";
1288
- }
1289
- /**
1290
- * Check if transistor is in closed or closing state
1291
- */
1292
- get isClosed() {
1293
- return this.state === "closed" || this.state === "closing";
1294
- }
1295
- }
1296
- class K extends p {
1297
- /**
1298
- * Create a new Buffer state.
1299
- *
1300
- * @param componentId - UUID of the Buffer component
1301
- * @param initialState - Initial operational state (default: "low")
1302
- */
1303
- constructor(t, e = "low") {
1304
- super(t, e);
1305
- }
1306
- /**
1307
- * Check if output is in a rising or falling transition
1308
- */
1309
- get isInTransition() {
1310
- return this.state === "rising" || this.state === "falling";
1311
- }
1312
- /**
1313
- * Check if output is high
1314
- */
1315
- get isHigh() {
1316
- return this.state === "high";
1317
- }
1318
- }
1319
- class T extends p {
1320
- /**
1321
- * Create a new AND Gate state.
1322
- *
1323
- * @param componentId - UUID of the AND Gate component
1324
- * @param initialState - Initial operational state (default: "low")
1325
- */
1326
- constructor(t, e = "low") {
1327
- super(t, e);
1328
- }
1329
- /**
1330
- * Check if output is in a rising or falling transition
1331
- */
1332
- get isInTransition() {
1333
- return this.state === "rising" || this.state === "falling";
1334
- }
1335
- /**
1336
- * Check if output is high
1337
- */
1338
- get isHigh() {
1339
- return this.state === "high";
1340
- }
1341
- }
1342
- class X extends T {
1343
- constructor(t, e = "low") {
1344
- super(t, e);
1345
- }
1346
- }
1347
- class q extends T {
1348
- constructor(t, e = "low") {
1349
- super(t, e);
1350
- }
1351
- }
1352
- class E extends p {
1353
- constructor(t, e = "low") {
1354
- super(t, e);
1355
- }
1356
- get isInTransition() {
1357
- return this.state === "rising" || this.state === "falling";
1358
- }
1359
- get isHigh() {
1360
- return this.state === "high";
1361
- }
1362
- }
1363
- class Q extends E {
1364
- constructor(t, e = "low") {
1365
- super(t, e);
1366
- }
1367
- }
1368
- class Y extends E {
1369
- constructor(t, e = "low") {
1370
- super(t, e);
1371
- }
1372
- }
1373
- class Z extends p {
1374
- constructor(t, e = "low") {
1375
- super(t, e);
1376
- }
1377
- get isInTransition() {
1378
- return this.state === "rising" || this.state === "falling";
1379
- }
1380
- get isHigh() {
1381
- return this.state === "high";
1382
- }
1383
- }
1384
- function j(c) {
1385
- if (!c)
1386
- return f.TRANSITION_SPAN_TICKS;
1387
- const t = parseInt(c.get("tickCount") || "", 10);
1388
- return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
1389
- }
1390
- class ee {
1391
- componentType = h.Switch;
1392
- /**
1393
- * Create initial state for a switch.
1394
- *
1395
- * @param component - The Switch component
1396
- * @returns Switch Initial state (open by default)
1397
- */
1398
- createInitialState(t) {
1399
- if (t.type !== h.Switch)
1400
- throw new Error(`Invalid component type for SwitchBehavior: ${t.type}`);
1401
- const e = t.config.get("initialState") || "open";
1402
- return new H(t.id, e);
1403
- }
1404
- allowConductivity(t, e, i, n, s) {
1405
- return e.state === "closed" || e.state === "opening";
1406
- }
1407
- /**
1408
- * Switches states depend on user interaction, not their pins so this is more of a decorative function
1409
- * @param _component
1410
- * @param componentState
1411
- * @param _nodeStates
1412
- * @param _targetTick
1413
- */
1414
- onPinsChange(t, e, i, n) {
1415
- return {
1416
- componentState: e,
1417
- hasChanged: !1,
1418
- scheduledEvents: []
1419
- };
1420
- }
1421
- onUserCommand(t, e, i) {
1422
- let n = !1;
1423
- const s = [];
1424
- if (i.type === "toggle_switch" && ["open", "closed"].includes(e.state)) {
1425
- e.state = e.state === "open" ? "closing" : "opening", e.startTick = i.scheduledAtTick + 1, n = !0;
1426
- const o = j(i.parameters);
1427
- s.push({
1428
- targetId: t.id,
1429
- scheduledAtTick: e.startTick,
1430
- readyAtTick: e.startTick + o,
1431
- type: e.state === "closing" ? "ClosingEnd" : "OpeningEnd",
1432
- parameters: void 0
1433
- });
1434
- }
1435
- return {
1436
- componentState: e,
1437
- hasChanged: n,
1438
- scheduledEvents: s
1439
- };
1440
- }
1441
- onEventFiring(t, e, i) {
1442
- let n = !1;
1443
- return i.type === "ClosingEnd" ? e.state !== "closed" && (n = !0, e.startTick = i.readyAtTick, e.state = "closed") : i.type === "OpeningEnd" && e.state !== "open" && (n = !0, e.startTick = i.readyAtTick, e.state = "open"), {
1444
- componentState: e,
1445
- hasChanged: n,
1446
- scheduledEvents: []
1447
- };
1448
- }
1449
- }
1450
- function te(c) {
1451
- const t = parseInt(c.get("transitionSpan") || "", 10);
1452
- return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
1453
- }
1454
- class ne {
1455
- componentType = h.Transistor;
1456
- /**
1457
- * Create initial state for a transistor.
1458
- *
1459
- * @param component - The Transistor component
1460
- * @returns Transistor Initial state (open by default)
1461
- */
1462
- createInitialState(t) {
1463
- if (t.type !== h.Transistor)
1464
- throw new Error(`Invalid component type for TransistorBehavior: ${t.type}`);
1465
- const e = t.config.get("activationLogic") === "negative" ? "closed" : "open";
1466
- return new z(t.id, e);
1467
- }
1468
- allowConductivity(t, e, i, n, s) {
1469
- if (n === s) return !0;
1470
- const o = t.getPinLabel(n), a = t.getPinLabel(s);
1471
- if (!o || !a) return !1;
1472
- const r = [o, a];
1473
- return r.includes("collector") && r.includes("emitter") ? e.state === "closed" || e.state === "opening" : !1;
1474
- }
1475
- /**
1476
- * Transistor Base need to have only voltage so that transistor contactor stays closed
1477
- * @param component
1478
- * @param state
1479
- * @param nodeStates
1480
- * @param targetTick
1481
- */
1482
- onPinsChange(t, e, i, n) {
1483
- const s = /* @__PURE__ */ new Map();
1484
- for (const l of t.pins)
1485
- s.set(t.getPinLabel(l), i.get(l));
1486
- const o = s.get("base").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1487
- let r = !1;
1488
- const d = [], g = te(t.config);
1489
- return a ? (e.state === "open" || e.state === "opening") && (r = !0, e.state = "closing", e.startTick = n, d.push({
1490
- targetId: t.id,
1491
- scheduledAtTick: n,
1492
- readyAtTick: n + g,
1493
- type: "ClosingEnd",
1494
- parameters: void 0
1495
- })) : (e.state === "closed" || e.state === "closing") && (r = !0, e.state = "opening", e.startTick = n, d.push({
1496
- targetId: t.id,
1497
- scheduledAtTick: n,
1498
- readyAtTick: n + g,
1499
- type: "OpeningEnd",
1500
- parameters: void 0
1501
- })), {
1502
- componentState: e,
1503
- hasChanged: r,
1504
- scheduledEvents: d
1505
- };
1506
- }
1507
- onUserCommand(t, e, i) {
1508
- return {
1509
- componentState: e,
1510
- hasChanged: !1,
1511
- scheduledEvents: []
1512
- };
1513
- }
1514
- onEventFiring(t, e, i) {
1515
- let n = !1;
1516
- return i.type === "ClosingEnd" ? e.state !== "closed" && (n = !0, e.startTick = i.readyAtTick, e.state = "closed") : i.type === "OpeningEnd" && e.state !== "open" && (n = !0, e.startTick = i.readyAtTick, e.state = "open"), {
1517
- componentState: e,
1518
- hasChanged: n,
1519
- scheduledEvents: []
1520
- };
1521
- }
1522
- }
1523
- function ie(c) {
1524
- const t = parseInt(c.get("transitionSpan") || "", 10);
1525
- return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
1526
- }
1527
- class se {
1528
- componentType = h.Buffer;
1529
- /**
1530
- * Create initial state for a Buffer.
1531
- *
1532
- * @param component - The Buffer component
1533
- * @returns Buffer Initial state (low by default, high for negative activation logic)
1534
- */
1535
- createInitialState(t) {
1536
- if (t.type !== h.Buffer)
1537
- throw new Error(`Invalid component type for BufferBehavior: ${t.type}`);
1538
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1539
- return new K(t.id, e);
1540
- }
1541
- allowConductivity(t, e, i, n, s) {
1542
- if (n === s) return !0;
1543
- const o = t.getPinLabel(n), a = t.getPinLabel(s);
1544
- if (!o || !a) return !1;
1545
- const r = [o, a];
1546
- return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
1547
- }
1548
- /**
1549
- * Relayer needs voltage on input to drive the output high, and on the contrary Inverter needs no voltage on input
1550
- * @param component
1551
- * @param state
1552
- * @param nodeStates
1553
- * @param targetTick
1554
- */
1555
- onPinsChange(t, e, i, n) {
1556
- const s = /* @__PURE__ */ new Map();
1557
- for (const l of t.pins)
1558
- s.set(t.getPinLabel(l), i.get(l));
1559
- const o = s.get("input").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1560
- let r = !1;
1561
- const d = [], g = ie(t.config);
1562
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1563
- targetId: t.id,
1564
- scheduledAtTick: n,
1565
- readyAtTick: n + g,
1566
- type: "RisingComplete",
1567
- parameters: void 0
1568
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1569
- targetId: t.id,
1570
- scheduledAtTick: n,
1571
- readyAtTick: n + g,
1572
- type: "FallingComplete",
1573
- parameters: void 0
1574
- })), {
1575
- componentState: e,
1576
- hasChanged: r,
1577
- scheduledEvents: d
1578
- };
1579
- }
1580
- onUserCommand(t, e, i) {
1581
- return {
1582
- componentState: e,
1583
- hasChanged: !1,
1584
- scheduledEvents: []
1585
- };
1586
- }
1587
- onEventFiring(t, e, i) {
1588
- let n = !1;
1589
- return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
1590
- componentState: e,
1591
- hasChanged: n,
1592
- scheduledEvents: []
1593
- };
1594
- }
1595
- }
1596
- class I {
1597
- componentType = h.AndGate;
1598
- /**
1599
- * Create initial state for an AND Gate.
1600
- *
1601
- * @param component - The AND Gate component
1602
- * @returns Initial state (low by default, high for negative activation logic)
1603
- */
1604
- createInitialState(t) {
1605
- if (t.type !== h.AndGate)
1606
- throw new Error(`Invalid component type for AndGateBehavior: ${t.type}`);
1607
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1608
- return new T(t.id, e);
1609
- }
1610
- allowConductivity(t, e, i, n, s) {
1611
- if (n === s) return !0;
1612
- const o = t.getPinLabel(n), a = t.getPinLabel(s);
1613
- if (!o || !a) return !1;
1614
- const r = [o, a];
1615
- return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
1616
- }
1617
- /**
1618
- * Get the transition span from component config.
1619
- * @param config - Component config map
1620
- * @returns Number of ticks for transition (minimum 1)
1621
- */
1622
- getTransitionSpan(t) {
1623
- const e = parseInt(t.get("transitionSpan") || "", 10);
1624
- return isNaN(e) || e < 1 ? f.TRANSITION_SPAN_TICKS : e;
1625
- }
1626
- /**
1627
- * AND gate output goes high when ALL inputs have voltage.
1628
- * With negative activationLogic (NAND), output goes high when ANY input lacks voltage.
1629
- */
1630
- onPinsChange(t, e, i, n) {
1631
- const s = /* @__PURE__ */ new Map();
1632
- for (const l of t.pins)
1633
- s.set(t.getPinLabel(l), i.get(l));
1634
- const o = s.get("input1").hasVoltage && s.get("input2").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1635
- let r = !1;
1636
- const d = [], g = this.getTransitionSpan(t.config);
1637
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1638
- targetId: t.id,
1639
- scheduledAtTick: n,
1640
- readyAtTick: n + g,
1641
- type: "RisingComplete",
1642
- parameters: void 0
1643
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1644
- targetId: t.id,
1645
- scheduledAtTick: n,
1646
- readyAtTick: n + g,
1647
- type: "FallingComplete",
1648
- parameters: void 0
1649
- })), {
1650
- componentState: e,
1651
- hasChanged: r,
1652
- scheduledEvents: d
1653
- };
1654
- }
1655
- onUserCommand(t, e, i) {
1656
- return {
1657
- componentState: e,
1658
- hasChanged: !1,
1659
- scheduledEvents: []
1660
- };
1661
- }
1662
- onEventFiring(t, e, i) {
1663
- let n = !1;
1664
- return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
1665
- componentState: e,
1666
- hasChanged: n,
1667
- scheduledEvents: []
1668
- };
1669
- }
1670
- }
1671
- class oe extends I {
1672
- componentType = h.And4Gate;
1673
- createInitialState(t) {
1674
- if (t.type !== h.And4Gate)
1675
- throw new Error(`Invalid component type for And4GateBehavior: ${t.type}`);
1676
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1677
- return new X(t.id, e);
1678
- }
1679
- onPinsChange(t, e, i, n) {
1680
- const s = /* @__PURE__ */ new Map();
1681
- for (const l of t.pins)
1682
- s.set(t.getPinLabel(l), i.get(l));
1683
- const o = s.get("input1").hasVoltage && s.get("input2").hasVoltage && s.get("input3").hasVoltage && s.get("input4").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1684
- let r = !1;
1685
- const d = [], g = this.getTransitionSpan(t.config);
1686
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1687
- targetId: t.id,
1688
- scheduledAtTick: n,
1689
- readyAtTick: n + g,
1690
- type: "RisingComplete",
1691
- parameters: void 0
1692
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1693
- targetId: t.id,
1694
- scheduledAtTick: n,
1695
- readyAtTick: n + g,
1696
- type: "FallingComplete",
1697
- parameters: void 0
1698
- })), {
1699
- componentState: e,
1700
- hasChanged: r,
1701
- scheduledEvents: d
1702
- };
1703
- }
1704
- }
1705
- class re extends I {
1706
- componentType = h.And8Gate;
1707
- createInitialState(t) {
1708
- if (t.type !== h.And8Gate)
1709
- throw new Error(`Invalid component type for And8GateBehavior: ${t.type}`);
1710
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1711
- return new q(t.id, e);
1712
- }
1713
- onPinsChange(t, e, i, n) {
1714
- const s = /* @__PURE__ */ new Map();
1715
- for (const l of t.pins)
1716
- s.set(t.getPinLabel(l), i.get(l));
1717
- const o = s.get("input1").hasVoltage && s.get("input2").hasVoltage && s.get("input3").hasVoltage && s.get("input4").hasVoltage && s.get("input5").hasVoltage && s.get("input6").hasVoltage && s.get("input7").hasVoltage && s.get("input8").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1718
- let r = !1;
1719
- const d = [], g = this.getTransitionSpan(t.config);
1720
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1721
- targetId: t.id,
1722
- scheduledAtTick: n,
1723
- readyAtTick: n + g,
1724
- type: "RisingComplete",
1725
- parameters: void 0
1726
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1727
- targetId: t.id,
1728
- scheduledAtTick: n,
1729
- readyAtTick: n + g,
1730
- type: "FallingComplete",
1731
- parameters: void 0
1732
- })), {
1733
- componentState: e,
1734
- hasChanged: r,
1735
- scheduledEvents: d
1736
- };
1737
- }
1738
- }
1739
- class A {
1740
- componentType = h.OrGate;
1741
- createInitialState(t) {
1742
- if (t.type !== h.OrGate)
1743
- throw new Error(`Invalid component type for OrGateBehavior: ${t.type}`);
1744
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1745
- return new E(t.id, e);
1746
- }
1747
- allowConductivity(t, e, i, n, s) {
1748
- if (n === s) return !0;
1749
- const o = t.getPinLabel(n), a = t.getPinLabel(s);
1750
- if (!o || !a) return !1;
1751
- const r = [o, a];
1752
- return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
1753
- }
1754
- getTransitionSpan(t) {
1755
- const e = parseInt(t.get("transitionSpan") || "", 10);
1756
- return isNaN(e) || e < 1 ? f.TRANSITION_SPAN_TICKS : e;
1757
- }
1758
- /**
1759
- * OR gate output goes high when ANY input has voltage.
1760
- * With negative activationLogic (NOR), output goes high when ALL inputs lack voltage.
1761
- */
1762
- onPinsChange(t, e, i, n) {
1763
- const s = /* @__PURE__ */ new Map();
1764
- for (const l of t.pins)
1765
- s.set(t.getPinLabel(l), i.get(l));
1766
- const o = s.get("input1").hasVoltage || s.get("input2").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1767
- let r = !1;
1768
- const d = [], g = this.getTransitionSpan(t.config);
1769
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1770
- targetId: t.id,
1771
- scheduledAtTick: n,
1772
- readyAtTick: n + g,
1773
- type: "RisingComplete",
1774
- parameters: void 0
1775
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1776
- targetId: t.id,
1777
- scheduledAtTick: n,
1778
- readyAtTick: n + g,
1779
- type: "FallingComplete",
1780
- parameters: void 0
1781
- })), {
1782
- componentState: e,
1783
- hasChanged: r,
1784
- scheduledEvents: d
1785
- };
1786
- }
1787
- onUserCommand(t, e, i) {
1788
- return {
1789
- componentState: e,
1790
- hasChanged: !1,
1791
- scheduledEvents: []
1792
- };
1793
- }
1794
- onEventFiring(t, e, i) {
1795
- let n = !1;
1796
- return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
1797
- componentState: e,
1798
- hasChanged: n,
1799
- scheduledEvents: []
1800
- };
1801
- }
1802
- }
1803
- class ae extends A {
1804
- componentType = h.Or4Gate;
1805
- createInitialState(t) {
1806
- if (t.type !== h.Or4Gate)
1807
- throw new Error(`Invalid component type for Or4GateBehavior: ${t.type}`);
1808
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1809
- return new Q(t.id, e);
1810
- }
1811
- onPinsChange(t, e, i, n) {
1812
- const s = /* @__PURE__ */ new Map();
1813
- for (const l of t.pins)
1814
- s.set(t.getPinLabel(l), i.get(l));
1815
- const o = s.get("input1").hasVoltage || s.get("input2").hasVoltage || s.get("input3").hasVoltage || s.get("input4").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1816
- let r = !1;
1817
- const d = [], g = this.getTransitionSpan(t.config);
1818
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1819
- targetId: t.id,
1820
- scheduledAtTick: n,
1821
- readyAtTick: n + g,
1822
- type: "RisingComplete",
1823
- parameters: void 0
1824
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1825
- targetId: t.id,
1826
- scheduledAtTick: n,
1827
- readyAtTick: n + g,
1828
- type: "FallingComplete",
1829
- parameters: void 0
1830
- })), {
1831
- componentState: e,
1832
- hasChanged: r,
1833
- scheduledEvents: d
1834
- };
1835
- }
1836
- }
1837
- class de extends A {
1838
- componentType = h.Or8Gate;
1839
- createInitialState(t) {
1840
- if (t.type !== h.Or8Gate)
1841
- throw new Error(`Invalid component type for Or8GateBehavior: ${t.type}`);
1842
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1843
- return new Y(t.id, e);
1844
- }
1845
- onPinsChange(t, e, i, n) {
1846
- const s = /* @__PURE__ */ new Map();
1847
- for (const l of t.pins)
1848
- s.set(t.getPinLabel(l), i.get(l));
1849
- const o = s.get("input1").hasVoltage || s.get("input2").hasVoltage || s.get("input3").hasVoltage || s.get("input4").hasVoltage || s.get("input5").hasVoltage || s.get("input6").hasVoltage || s.get("input7").hasVoltage || s.get("input8").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
1850
- let r = !1;
1851
- const d = [], g = this.getTransitionSpan(t.config);
1852
- return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
1853
- targetId: t.id,
1854
- scheduledAtTick: n,
1855
- readyAtTick: n + g,
1856
- type: "RisingComplete",
1857
- parameters: void 0
1858
- })) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
1859
- targetId: t.id,
1860
- scheduledAtTick: n,
1861
- readyAtTick: n + g,
1862
- type: "FallingComplete",
1863
- parameters: void 0
1864
- })), {
1865
- componentState: e,
1866
- hasChanged: r,
1867
- scheduledEvents: d
1868
- };
1869
- }
1870
- }
1871
- class ce {
1872
- componentType = h.XorGate;
1873
- createInitialState(t) {
1874
- if (t.type !== h.XorGate)
1875
- throw new Error(`Invalid component type for XorGateBehavior: ${t.type}`);
1876
- const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
1877
- return new Z(t.id, e);
1878
- }
1879
- allowConductivity(t, e, i, n, s) {
1880
- if (n === s) return !0;
1881
- const o = t.getPinLabel(n), a = t.getPinLabel(s);
1882
- if (!o || !a) return !1;
1883
- const r = [o, a];
1884
- return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
1885
- }
1886
- getTransitionSpan(t) {
1887
- const e = parseInt(t.get("transitionSpan") || "", 10);
1888
- return isNaN(e) || e < 1 ? f.TRANSITION_SPAN_TICKS : e;
1889
- }
1890
- /**
1891
- * XOR gate output goes high when inputs differ (one high, one low).
1892
- * With negative activationLogic (XNOR), output goes high when inputs are equal.
1893
- */
1894
- onPinsChange(t, e, i, n) {
1895
- const s = /* @__PURE__ */ new Map();
1896
- for (const u of t.pins)
1897
- s.set(t.getPinLabel(u), i.get(u));
1898
- const o = s.get("input1").hasVoltage, a = s.get("input2").hasVoltage, r = o !== a, d = t.config.get("activationLogic") === "negative" ? !r : r;
1899
- let g = !1;
1900
- const l = [], m = this.getTransitionSpan(t.config);
1901
- return d ? (e.state === "low" || e.state === "falling") && (g = !0, e.state = "rising", e.startTick = n, l.push({
1902
- targetId: t.id,
1903
- scheduledAtTick: n,
1904
- readyAtTick: n + m,
1905
- type: "RisingComplete",
1906
- parameters: void 0
1907
- })) : (e.state === "high" || e.state === "rising") && (g = !0, e.state = "falling", e.startTick = n, l.push({
1908
- targetId: t.id,
1909
- scheduledAtTick: n,
1910
- readyAtTick: n + m,
1911
- type: "FallingComplete",
1912
- parameters: void 0
1913
- })), {
1914
- componentState: e,
1915
- hasChanged: g,
1916
- scheduledEvents: l
1917
- };
1918
- }
1919
- onUserCommand(t, e, i) {
1920
- return {
1921
- componentState: e,
1922
- hasChanged: !1,
1923
- scheduledEvents: []
1924
- };
1925
- }
1926
- onEventFiring(t, e, i) {
1927
- let n = !1;
1928
- return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
1929
- componentState: e,
1930
- hasChanged: n,
1931
- scheduledEvents: []
1932
- };
1933
- }
1934
- }
1935
- function he(c) {
1936
- return c.register(new W()).register(new M()).register(new F()).register(new U()).register(new N()).register(new ee()).register(new ne()).register(new se()), c;
1937
- }
1938
- function ue(c) {
1939
- return c.register(new I()).register(new oe()).register(new re()).register(new A()).register(new ae()).register(new de()).register(new ce()), c;
1940
- }
1
+ import { $ as t, A as e, B as s, C as o, D as i, E as r, F as n, G as S, H as h, I as v, J as B, K as G, L as c, M as l, N, O as E, P as p, Q as T, R as m, S as u, T as C, U as I, V as L, W as D, X as d, Y as y, Z as g, _, _t as A, a as R, at as M, b as O, bt as b, c as P, ct as w, d as U, dt as X, et as f, f as F, ft as k, g as x, gt as z, h as Y, ht as Q, i as V, it as W, j, k as q, l as H, lt as J, m as K, mt as Z, n as $, nt as aa, o as ta, ot as ea, p as sa, pt as oa, q as ia, r as ra, rt as na, s as Sa, st as ha, t as va, tt as Ba, u as Ga, ut as ca, v as la, vt as Na, w as Ea, x as pa, y as Ta, yt as ma, z as ua } from "../core-Bjta9Y7_.js";
1941
2
  export {
1942
- oe as And4GateBehavior,
1943
- X as And4GateState,
1944
- re as And8GateBehavior,
1945
- q as And8GateState,
1946
- I as AndGateBehavior,
1947
- T as AndGateState,
1948
- W as BatteryBehavior,
1949
- x as BatteryState,
1950
- ge as BehaviorRegistry,
1951
- se as BufferBehavior,
1952
- K as BufferState,
1953
- V as COMPONENT_TYPE_METADATA,
1954
- b as CameraOptions,
1955
- _ as Circuit,
1956
- v as CircuitMetadata,
1957
- me as CircuitRunner,
1958
- P as Component,
1959
- p as ComponentState,
1960
- h as ComponentType,
1961
- we as DirtyTracker,
1962
- S as ENode,
1963
- ye as ENodeSourceType,
1964
- y as ENodeType,
1965
- ve as EventQueue,
1966
- M as LightbulbBehavior,
1967
- $ as LightbulbState,
1968
- ae as Or4GateBehavior,
1969
- Q as Or4GateState,
1970
- de as Or8GateBehavior,
1971
- Y as Or8GateState,
1972
- A as OrGateBehavior,
1973
- E as OrGateState,
1974
- k as Position,
1975
- Se as Position3D,
1976
- F as RectangleLEDBehavior,
1977
- R as RectangleLEDState,
1978
- U as RelayBehavior,
1979
- D as RelayState,
1980
- Ce as Rotation,
1981
- Te as SIMULATION_SPEED,
1982
- Ee as SimulationState,
1983
- N as SmallLEDBehavior,
1984
- L as SmallLEDState,
1985
- Ie as StateManager,
1986
- ee as SwitchBehavior,
1987
- H as SwitchState,
1988
- f as TRANSITION_DEFAULTS,
1989
- ne as TransistorBehavior,
1990
- z as TransistorState,
1991
- w as Wire,
1992
- ce as XorGateBehavior,
1993
- Z as XorGateState,
1994
- G as findPositionBestIndex,
1995
- O as generateUUID,
1996
- Ae as getAllComponentTypes,
1997
- B as getComponentTypeMetadata,
1998
- he as registerBasicComponentsBehaviors,
1999
- ue as registerGatesComponentsBehaviors,
2000
- C as simplifyPositions
3
+ M as ALL_LOGIC_FAMILIES,
4
+ Ea as BatteryBehavior,
5
+ D as BatteryState,
6
+ r as BehaviorRegistry,
7
+ ea as CIRCUIT_FILE_VERSION,
8
+ ha as COMPONENT_TYPE_METADATA,
9
+ A as CameraOptions,
10
+ d as Circuit,
11
+ f as CircuitMetadata,
12
+ Ba as CircuitOptions,
13
+ ra as CircuitRunner,
14
+ _ as ClockBehavior,
15
+ c as ClockState,
16
+ aa as Component,
17
+ S as ComponentState,
18
+ w as ComponentType,
19
+ J as DEFAULT_LOGIC_FAMILY,
20
+ R as DirtyTracker,
21
+ la as DoubleThrowSwitchBehavior,
22
+ m as DoubleThrowSwitchState,
23
+ W as ENode,
24
+ ca as ENodeSourceType,
25
+ X as ENodeType,
26
+ ta as EventQueue,
27
+ x as InverterBehavior,
28
+ v as InverterState,
29
+ o as LightbulbBehavior,
30
+ I as LightbulbState,
31
+ ma as Memoize,
32
+ b as MemoizeExpiring,
33
+ K as Nand4GateBehavior,
34
+ p as Nand4GateState,
35
+ sa as Nand8GateBehavior,
36
+ N as Nand8GateState,
37
+ Y as NandGateBehavior,
38
+ n as NandGateState,
39
+ U as Nor4GateBehavior,
40
+ j as Nor4GateState,
41
+ Ga as Nor8GateBehavior,
42
+ e as Nor8GateState,
43
+ F as NorGateBehavior,
44
+ l as NorGateState,
45
+ Z as Position,
46
+ Na as Position3D,
47
+ u as RectangleLEDBehavior,
48
+ L as RectangleLEDState,
49
+ pa as RelayBehavior,
50
+ s as RelayState,
51
+ oa as Rotation,
52
+ B as SIMULATION_SPEED,
53
+ G as SimulationState,
54
+ O as SmallLEDBehavior,
55
+ h as SmallLEDState,
56
+ V as StateManager,
57
+ Ta as SwitchBehavior,
58
+ ua as SwitchState,
59
+ y as TRANSITION_DEFAULTS,
60
+ na as Wire,
61
+ P as Xor4GateBehavior,
62
+ E as Xor4GateState,
63
+ Sa as Xor8GateBehavior,
64
+ i as Xor8GateState,
65
+ H as XorGateBehavior,
66
+ q as XorGateState,
67
+ g as classifyGate,
68
+ T as computeGateDelay,
69
+ t as computeTransitionSpan,
70
+ Q as findPositionBestIndex,
71
+ k as generateUUID,
72
+ C as getTransitionSpan,
73
+ va as registerBasicComponentsBehaviors,
74
+ $ as registerGatesComponentsBehaviors,
75
+ z as simplifyPositions,
76
+ ia as unionElectricalStates
2001
77
  };
2002
- //# sourceMappingURL=index.js.map