simple-circuit-engine 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/AGENTS.md +10 -7
  2. package/CLAUDE.md +4 -6
  3. package/README.md +5 -2
  4. package/dist/core/index.d.ts +0 -1
  5. package/dist/core/index.js +74 -2114
  6. package/dist/core/setup.d.ts +17 -0
  7. package/dist/core/simulation/CircuitRunner.d.ts +176 -0
  8. package/dist/core/simulation/DirtyTracker.d.ts +87 -0
  9. package/dist/core/simulation/EventQueue.d.ts +68 -0
  10. package/dist/core/simulation/StateManager.d.ts +100 -0
  11. package/dist/core/simulation/behaviors/BehaviorRegistry.d.ts +70 -0
  12. package/dist/core/simulation/behaviors/ComponentBehavior.d.ts +53 -0
  13. package/dist/core/simulation/behaviors/basic/BatteryBehavior.d.ts +14 -0
  14. package/dist/core/simulation/behaviors/basic/ClockBehavior.d.ts +24 -0
  15. package/dist/core/simulation/behaviors/basic/DoubleThrowSwitchBehavior.d.ts +33 -0
  16. package/dist/core/simulation/behaviors/basic/LightbulbBehavior.d.ts +23 -0
  17. package/dist/core/simulation/behaviors/basic/RectangleLEDBehavior.d.ts +24 -0
  18. package/dist/core/simulation/behaviors/basic/RelayBehavior.d.ts +33 -0
  19. package/dist/core/simulation/behaviors/basic/SmallLEDBehavior.d.ts +24 -0
  20. package/dist/core/simulation/behaviors/basic/SwitchBehavior.d.ts +33 -0
  21. package/dist/core/simulation/behaviors/basic/index.d.ts +20 -0
  22. package/dist/core/simulation/behaviors/gates/InverterBehavior.d.ts +29 -0
  23. package/dist/core/simulation/behaviors/gates/Nand4GateBehavior.d.ts +18 -0
  24. package/dist/core/simulation/behaviors/gates/Nand8GateBehavior.d.ts +18 -0
  25. package/dist/core/simulation/behaviors/gates/NandGateBehavior.d.ts +28 -0
  26. package/dist/core/simulation/behaviors/gates/Nor4GateBehavior.d.ts +18 -0
  27. package/dist/core/simulation/behaviors/gates/Nor8GateBehavior.d.ts +18 -0
  28. package/dist/core/simulation/behaviors/gates/NorGateBehavior.d.ts +22 -0
  29. package/dist/core/simulation/behaviors/gates/Xor4GateBehavior.d.ts +18 -0
  30. package/dist/core/simulation/behaviors/gates/Xor8GateBehavior.d.ts +18 -0
  31. package/dist/core/simulation/behaviors/gates/XorGateBehavior.d.ts +22 -0
  32. package/dist/core/simulation/behaviors/gates/index.d.ts +34 -0
  33. package/dist/core/simulation/behaviors/index.d.ts +24 -0
  34. package/dist/core/simulation/behaviors/types.d.ts +101 -0
  35. package/dist/core/simulation/index.d.ts +18 -0
  36. package/dist/core/simulation/states/ComponentState.d.ts +57 -0
  37. package/dist/core/simulation/states/SimulationState.d.ts +46 -0
  38. package/dist/core/simulation/states/basic/BatteryState.d.ts +16 -0
  39. package/dist/core/simulation/states/basic/ClockState.d.ts +16 -0
  40. package/dist/core/simulation/states/basic/DoubleThrowSwitchState.d.ts +21 -0
  41. package/dist/core/simulation/states/basic/LightbulbState.d.ts +21 -0
  42. package/dist/core/simulation/states/basic/RectangleLEDState.d.ts +9 -0
  43. package/dist/core/simulation/states/basic/RelayState.d.ts +25 -0
  44. package/dist/core/simulation/states/basic/SmallLEDState.d.ts +21 -0
  45. package/dist/core/simulation/states/basic/SwitchState.d.ts +25 -0
  46. package/dist/core/simulation/states/gates/InverterState.d.ts +17 -0
  47. package/dist/core/simulation/states/gates/Nand4GateState.d.ts +10 -0
  48. package/dist/core/simulation/states/gates/Nand8GateState.d.ts +10 -0
  49. package/dist/core/simulation/states/gates/NandGateState.d.ts +16 -0
  50. package/dist/core/simulation/states/gates/Nor4GateState.d.ts +10 -0
  51. package/dist/core/simulation/states/gates/Nor8GateState.d.ts +10 -0
  52. package/dist/core/simulation/states/gates/NorGateState.d.ts +10 -0
  53. package/dist/core/simulation/states/gates/Xor4GateState.d.ts +10 -0
  54. package/dist/core/simulation/states/gates/Xor8GateState.d.ts +10 -0
  55. package/dist/core/simulation/states/gates/XorGateState.d.ts +10 -0
  56. package/dist/core/simulation/states/gates/index.d.ts +25 -0
  57. package/dist/core/simulation/states/index.d.ts +26 -0
  58. package/dist/core/simulation/states/types.d.ts +32 -0
  59. package/dist/core/simulation/types.d.ts +155 -0
  60. package/dist/core/topology/Circuit.d.ts +420 -0
  61. package/dist/core/topology/CircuitMetadata.d.ts +24 -0
  62. package/dist/core/topology/CircuitOptions.d.ts +14 -0
  63. package/dist/core/topology/Component.d.ts +152 -0
  64. package/dist/core/topology/ENode.d.ts +200 -0
  65. package/dist/core/topology/Wire.d.ts +130 -0
  66. package/dist/core/topology/delays.d.ts +52 -0
  67. package/dist/core/topology/index.d.ts +14 -0
  68. package/dist/core/topology/types.d.ts +175 -0
  69. package/dist/core/utils/CameraOptions.d.ts +83 -0
  70. package/dist/core/utils/MemoizeDecorator.d.ts +9 -0
  71. package/dist/core/utils/Position.d.ts +166 -0
  72. package/dist/core/utils/Position3D.d.ts +77 -0
  73. package/dist/core/utils/Rotation.d.ts +82 -0
  74. package/dist/core/utils/index.d.ts +24 -0
  75. package/dist/core/utils/types.d.ts +35 -0
  76. package/dist/core-Bjta9Y7_.js +2707 -0
  77. package/dist/core-Bjta9Y7_.js.map +1 -0
  78. package/dist/index.d.ts +13 -6306
  79. package/dist/index.js +117 -110
  80. package/dist/scene/CircuitEngine.d.ts +270 -0
  81. package/dist/scene/index.d.ts +0 -1
  82. package/dist/scene/index.js +43 -39
  83. package/dist/scene/setup.d.ts +18 -0
  84. package/dist/scene/shared/AbstractCircuitController.d.ts +211 -0
  85. package/dist/scene/shared/BranchingPointVisualFactory.d.ts +70 -0
  86. package/dist/scene/shared/EventEmitter.d.ts +92 -0
  87. package/dist/scene/shared/HoverManager.d.ts +151 -0
  88. package/dist/scene/shared/SelectionManager.d.ts +159 -0
  89. package/dist/scene/shared/WireVisualManager.d.ts +242 -0
  90. package/dist/scene/shared/components/ComponentVisualFactory.d.ts +438 -0
  91. package/dist/scene/shared/components/DefaultVisualFactory.d.ts +51 -0
  92. package/dist/scene/shared/components/FactoryRegistry.d.ts +84 -0
  93. package/dist/scene/shared/components/GroupedFactoryRegistry.d.ts +153 -0
  94. package/dist/scene/shared/components/basic/BatteryVisualFactory.d.ts +13 -0
  95. package/dist/scene/shared/components/basic/ClockVisualFactory.d.ts +79 -0
  96. package/dist/scene/shared/components/basic/DoubleThrowSwitchVisualFactory.d.ts +87 -0
  97. package/dist/scene/shared/components/basic/LabelVisualFactory.d.ts +148 -0
  98. package/dist/scene/shared/components/basic/LightbulbVisualFactory.d.ts +72 -0
  99. package/dist/scene/shared/components/basic/RectangleLEDVisualFactory.d.ts +86 -0
  100. package/dist/scene/shared/components/basic/RelayVisualFactory.d.ts +92 -0
  101. package/dist/scene/shared/components/basic/SmallLEDVisualFactory.d.ts +86 -0
  102. package/dist/scene/shared/components/basic/SwitchVisualFactory.d.ts +85 -0
  103. package/dist/scene/shared/components/gates/InverterVisualFactory.d.ts +104 -0
  104. package/dist/scene/shared/components/gates/Nand4GateVisualFactory.d.ts +27 -0
  105. package/dist/scene/shared/components/gates/Nand8GateVisualFactory.d.ts +27 -0
  106. package/dist/scene/shared/components/gates/NandGateVisualFactory.d.ts +101 -0
  107. package/dist/scene/shared/components/gates/Nor4GateVisualFactory.d.ts +27 -0
  108. package/dist/scene/shared/components/gates/Nor8GateVisualFactory.d.ts +27 -0
  109. package/dist/scene/shared/components/gates/NorGateVisualFactory.d.ts +101 -0
  110. package/dist/scene/shared/components/gates/Xor4GateVisualFactory.d.ts +29 -0
  111. package/dist/scene/shared/components/gates/Xor8GateVisualFactory.d.ts +29 -0
  112. package/dist/scene/shared/components/gates/XorGateVisualFactory.d.ts +103 -0
  113. package/dist/scene/shared/components/index.d.ts +29 -0
  114. package/dist/scene/shared/components/types.d.ts +43 -0
  115. package/dist/scene/shared/types.d.ts +476 -0
  116. package/dist/scene/shared/utils/CameraUtils.d.ts +23 -0
  117. package/dist/scene/shared/utils/ColorUtils.d.ts +26 -0
  118. package/dist/scene/shared/utils/ControlsUtils.d.ts +8 -0
  119. package/dist/scene/shared/utils/GeometryUtils.d.ts +261 -0
  120. package/dist/scene/shared/utils/LayerConstants.d.ts +40 -0
  121. package/dist/scene/shared/utils/LightingUtils.d.ts +31 -0
  122. package/dist/scene/shared/utils/MaterialUtils.d.ts +73 -0
  123. package/dist/scene/shared/utils/Options.d.ts +16 -0
  124. package/dist/scene/simulation/CircuitRunnerController.d.ts +227 -0
  125. package/dist/scene/static/CircuitController.d.ts +227 -0
  126. package/dist/scene/static/CircuitWriter.d.ts +146 -0
  127. package/dist/scene/static/PinTooltipWidget.d.ts +26 -0
  128. package/dist/scene/static/tools/BuildTool.d.ts +286 -0
  129. package/dist/scene/static/tools/ComponentPickerWidget.d.ts +82 -0
  130. package/dist/scene/static/tools/ConfigPanelWidget.d.ts +93 -0
  131. package/dist/scene/static/tools/MultiSelectTool.d.ts +265 -0
  132. package/dist/scene-CVsDdySt.js +7357 -0
  133. package/dist/scene-CVsDdySt.js.map +1 -0
  134. package/package.json +24 -25
  135. package/dist/CircuitRunner-BQQlhwjD.js +0 -1981
  136. package/dist/CircuitRunner-BQQlhwjD.js.map +0 -1
  137. package/dist/core/index.js.map +0 -1
  138. package/dist/index.js.map +0 -1
  139. package/dist/scene/index.js.map +0 -1
  140. package/dist/setup-CIq_kgaw.js +0 -10230
  141. package/dist/setup-CIq_kgaw.js.map +0 -1
@@ -1,1981 +0,0 @@
1
- class m {
2
- /**
3
- * Create a new 3D position.
4
- *
5
- * @param x - X coordinate
6
- * @param y - Y coordinate
7
- * @param z - Z coordinate
8
- */
9
- constructor(t, e, i) {
10
- this.x = t, this.y = e, this.z = i;
11
- }
12
- /**
13
- * Check if this position equals another position.
14
- *
15
- * @param other - Position to compare with
16
- * @returns true if x,y and z coordinates are equal
17
- *
18
- * @example
19
- * ```typescript
20
- * const p1 = new Position(10, 20, 40);
21
- * const p2 = new Position(10, 20, 40);
22
- * const p3 = new Position(15, 20, 40);
23
- *
24
- * console.log(p1.equals(p2)); // true
25
- * console.log(p1.equals(p3)); // false
26
- * ```
27
- */
28
- equals(t) {
29
- return this.x === t.x && this.y === t.y && this.z === t.z;
30
- }
31
- /**
32
- * Serialize position to JSON.
33
- *
34
- * @returns Plain object with x, y and z properties
35
- *
36
- * @example
37
- * ```typescript
38
- * const pos = new Position(10, 20, 40);
39
- * const json = pos.toJSON();
40
- * console.log(json); // { x: 10, y: 20, z: 40 }
41
- * ```
42
- */
43
- toJSON() {
44
- return { x: this.x, y: this.y, z: this.z };
45
- }
46
- /**
47
- * Deserialize position from JSON.
48
- *
49
- * @param json - Plain object with x, y and z properties
50
- * @returns Position instance
51
- *
52
- * @example
53
- * ```typescript
54
- * const json = { x: 10, y: 20, z: 40 };
55
- * const pos = Position.fromJSON(json);
56
- * console.log(pos.x); // 10
57
- * ```
58
- */
59
- static fromJSON(t) {
60
- return new m(t.x, t.y, t.z);
61
- }
62
- /**
63
- * String representation for debugging.
64
- *
65
- * @returns String in format "Position(x, y, z)"
66
- */
67
- toString() {
68
- return `Position(${this.x}, ${this.y}, ${this.z})`;
69
- }
70
- }
71
- class M {
72
- /**
73
- * Create new camera options.
74
- *
75
- * @param position - Camera position (default: 0, 15, 15)
76
- * @param lookAtPosition - Camera look-at target position (default: 0, 0, 0)
77
- * @param fov - Field of view in degrees (default: 75)
78
- * @param near - Near clipping plane distance (default: 0.1)
79
- * @param far - Far clipping plane distance (default: 1000)
80
- */
81
- constructor(t = new m(0, 15, 15), e = new m(0, 0, 0), i = 75, n = 0.1, r = 1e3) {
82
- this.position = t, this.lookAtPosition = e, this.fov = i, this.near = n, this.far = r;
83
- }
84
- /**
85
- * Serialize camera options to JSON.
86
- *
87
- * @returns Plain object with camera configuration
88
- *
89
- * @example
90
- * ```typescript
91
- * const opts = new CameraOptions();
92
- * const json = opts.toJSON();
93
- * console.log(json);
94
- * // {
95
- * // position: { x: 0, y: 15, z: 0 },
96
- * // lookAtPosition: { x: 0, y: 0, z: 0 },
97
- * // fov: 75,
98
- * // near: 0.1,
99
- * // far: 1000
100
- * // }
101
- * ```
102
- */
103
- toJSON() {
104
- return {
105
- position: this.position.toJSON(),
106
- lookAtPosition: this.lookAtPosition.toJSON(),
107
- fov: this.fov,
108
- near: this.near,
109
- far: this.far
110
- };
111
- }
112
- /**
113
- * Deserialize camera options from JSON.
114
- *
115
- * @param json - Plain object with camera configuration
116
- * @returns CameraOptions instance
117
- *
118
- * @example
119
- * ```typescript
120
- * const json = {
121
- * position: { x: 0, y: 20, z: 10 },
122
- * lookAtPosition: { x: 5, y: 0, z: 0 },
123
- * fov: 60,
124
- * near: 0.5,
125
- * far: 2000
126
- * };
127
- * const opts = CameraOptions.fromJSON(json);
128
- * console.log(opts.position.y); // 20
129
- * ```
130
- */
131
- static fromJSON(t) {
132
- return new M(
133
- m.fromJSON(t.position),
134
- m.fromJSON(t.lookAtPosition),
135
- t.fov,
136
- t.near,
137
- t.far
138
- );
139
- }
140
- /**
141
- * String representation for debugging.
142
- *
143
- * @returns String with camera configuration details
144
- */
145
- toString() {
146
- return `CameraOptions(position: ${this.position.toString()}, lookAt: ${this.lookAtPosition.toString()}, fov: ${this.fov}, near: ${this.near}, far: ${this.far})`;
147
- }
148
- }
149
- class T {
150
- /**
151
- * Create a new position on the discrete grid.
152
- *
153
- * @param x - X coordinate (must be integer)
154
- * @param y - Y coordinate (must be integer)
155
- * @throws {TypeError} If x or y are not integers
156
- */
157
- constructor(t, e) {
158
- if (this.x = t, this.y = e, !Number.isInteger(t) || !Number.isInteger(e))
159
- throw new TypeError(`Position coordinates must be integers (got x=${t}, y=${e})`);
160
- }
161
- /**
162
- * Check if this position equals another position.
163
- *
164
- * @param other - Position to compare with
165
- * @returns true if both x and y coordinates are equal
166
- *
167
- * @example
168
- * ```typescript
169
- * const p1 = new Position(10, 20);
170
- * const p2 = new Position(10, 20);
171
- * const p3 = new Position(15, 20);
172
- *
173
- * console.log(p1.equals(p2)); // true
174
- * console.log(p1.equals(p3)); // false
175
- * ```
176
- */
177
- equals(t) {
178
- return this.x === t.x && this.y === t.y;
179
- }
180
- /**
181
- * Serialize position to JSON.
182
- *
183
- * @returns Plain object with x and y properties
184
- *
185
- * @example
186
- * ```typescript
187
- * const pos = new Position(10, 20);
188
- * const json = pos.toJSON();
189
- * console.log(json); // { x: 10, y: 20 }
190
- * ```
191
- */
192
- toJSON() {
193
- return { x: this.x, y: this.y };
194
- }
195
- /**
196
- * Deserialize position from JSON.
197
- *
198
- * @param json - Plain object with x and y properties
199
- * @returns Position instance
200
- * @throws {TypeError} If coordinates are not integers
201
- *
202
- * @example
203
- * ```typescript
204
- * const json = { x: 10, y: 20 };
205
- * const pos = Position.fromJSON(json);
206
- * console.log(pos.x); // 10
207
- * ```
208
- */
209
- static fromJSON(t) {
210
- return new T(t.x, t.y);
211
- }
212
- /**
213
- * String representation for debugging.
214
- *
215
- * @returns String in format "Position(x, y)"
216
- */
217
- toString() {
218
- return `Position(${this.x}, ${this.y})`;
219
- }
220
- }
221
- function R(o, t, e = 1 / 0) {
222
- if (o.length === 0)
223
- return 0;
224
- if (o.length === 1)
225
- return 1;
226
- let i = 1;
227
- for (let n = 0; n < o.length - 1; n++) {
228
- const r = o[n], a = o[n + 1], c = N(t, r, a);
229
- c < e && (e = c, i = n + 1);
230
- }
231
- return i;
232
- }
233
- function N(o, t, e) {
234
- const i = e.x - t.x, n = e.y - t.y, r = i * i + n * n;
235
- if (r === 0)
236
- return Math.sqrt((o.x - t.x) ** 2 + (o.y - t.y) ** 2);
237
- const a = Math.max(
238
- 0,
239
- Math.min(
240
- 1,
241
- ((o.x - t.x) * i + (o.y - t.y) * n) / r
242
- )
243
- ), c = t.x + a * i, h = t.y + a * n;
244
- return Math.sqrt((o.x - c) ** 2 + (o.y - h) ** 2);
245
- }
246
- function z(o, t = 5) {
247
- if (o.length <= 2)
248
- return [...o];
249
- const e = [o[0]];
250
- for (let i = 1; i < o.length - 1; i++) {
251
- const n = e[e.length - 1], r = o[i], a = o[i + 1];
252
- A(n, r, a, t) || e.push(r);
253
- }
254
- return e.push(o[o.length - 1]), e;
255
- }
256
- function A(o, t, e, i = 5) {
257
- const n = (t.x - o.x) * (e.y - o.y) - (t.y - o.y) * (e.x - o.x);
258
- return Math.abs(n) <= i;
259
- }
260
- class C {
261
- /**
262
- * Create a new rotation with the specified angle.
263
- *
264
- * @param angle - Rotation angle in degrees (must be integer)
265
- * @throws {TypeError} If angle is not an integer
266
- */
267
- constructor(t) {
268
- if (this.angle = t, !Number.isInteger(t))
269
- throw new TypeError(`Rotation angle must be an integer (got ${t})`);
270
- }
271
- /**
272
- * Serialize rotation to JSON.
273
- *
274
- * @returns The angle value as a number
275
- *
276
- * @example
277
- * ```typescript
278
- * const rotation = new Rotation(90);
279
- * const json = rotation.toJSON();
280
- * console.log(json); // 90
281
- * ```
282
- */
283
- toJSON() {
284
- return this.angle;
285
- }
286
- /**
287
- * Deserialize rotation from JSON.
288
- *
289
- * @param angle - Angle value
290
- * @returns Rotation instance
291
- * @throws {TypeError} If angle is not an integer
292
- *
293
- * @example
294
- * ```typescript
295
- * const rotation = Rotation.fromJSON(90);
296
- * console.log(rotation.angle); // 90
297
- * ```
298
- */
299
- static fromJSON(t) {
300
- return new C(t);
301
- }
302
- /**
303
- * Check if this rotation equals another rotation.
304
- *
305
- * @param other - Rotation to compare with
306
- * @returns true if angles are equal
307
- *
308
- * @example
309
- * ```typescript
310
- * const r1 = new Rotation(90);
311
- * const r2 = new Rotation(90);
312
- * const r3 = new Rotation(180);
313
- *
314
- * console.log(r1.equals(r2)); // true
315
- * console.log(r1.equals(r3)); // false
316
- * ```
317
- */
318
- equals(t) {
319
- return this.angle === t.angle;
320
- }
321
- /**
322
- * String representation for debugging.
323
- *
324
- * @returns String in format "Rotation(angle°)"
325
- */
326
- toString() {
327
- return `Rotation(${this.angle}°)`;
328
- }
329
- }
330
- function O() {
331
- if (typeof crypto < "u" && crypto.randomUUID)
332
- return crypto.randomUUID();
333
- const o = "0123456789abcdef", t = [8, 4, 4, 4, 12], e = [];
334
- for (const c of t) {
335
- let h = "";
336
- for (let s = 0; s < c; s++) {
337
- const u = Math.floor(Math.random() * 16);
338
- h += o[u];
339
- }
340
- e.push(h);
341
- }
342
- const n = e.join("-").split("");
343
- n[14] = "4";
344
- const a = parseInt(n[19] ?? "0", 16) & 3 | 8;
345
- return n[19] = o[a] ?? "0", n.join("");
346
- }
347
- const G = "0.0.11";
348
- var v = /* @__PURE__ */ ((o) => (o.Voltage = "Voltage", o.Current = "Current", o))(v || {}), S = /* @__PURE__ */ ((o) => (o.Pin = "Pin", o.BranchingPoint = "BranchingPoint", o))(S || {});
349
- const W = ["CMOS1", "TTL1", "Sandbox"], U = "CMOS1";
350
- var L = /* @__PURE__ */ ((o) => (o.Cube = "cube", o.Label = "label", o.Battery = "battery", o.Switch = "switch", o.DoubleThrowSwitch = "doubleThrowSwitch", o.Lightbulb = "lightbulb", o.Relay = "relay", o.SmallLED = "smallLED", o.RectangleLED = "rectangleLED", o.Inverter = "inverter", o.NandGate = "nandGate", o.Nand4Gate = "nand4Gate", o.Nand8Gate = "nand8Gate", o.NorGate = "norGate", o.Nor4Gate = "nor4Gate", o.Nor8Gate = "nor8Gate", o.XorGate = "xorGate", o.Xor4Gate = "xor4Gate", o.Xor8Gate = "xor8Gate", o))(L || {});
351
- const I = {
352
- switch: {
353
- id: "switch",
354
- name: "Switch",
355
- pins: /* @__PURE__ */ new Map([
356
- ["input", { subtype: "free", sourceType: void 0 }],
357
- ["output", { subtype: "free", sourceType: void 0 }]
358
- ]),
359
- config: /* @__PURE__ */ new Map([
360
- ["initialState", "open"],
361
- ["size", "1"]
362
- ])
363
- },
364
- doubleThrowSwitch: {
365
- id: "doubleThrowSwitch",
366
- // SPDT (Single-Pole Double-Throw) Switch
367
- name: "DoubleThrowSwitch",
368
- pins: /* @__PURE__ */ new Map([
369
- ["input1", { subtype: "free", sourceType: void 0 }],
370
- ["input2", { subtype: "free", sourceType: void 0 }],
371
- ["output", { subtype: "free", sourceType: void 0 }]
372
- ]),
373
- config: /* @__PURE__ */ new Map([
374
- ["initialState", "input1"],
375
- ["size", "1"]
376
- ])
377
- },
378
- battery: {
379
- id: "battery",
380
- name: "Battery",
381
- pins: /* @__PURE__ */ new Map([
382
- ["cathode", {
383
- subtype: "mainVcc",
384
- sourceType: "Voltage"
385
- /* Voltage */
386
- }],
387
- ["anode", {
388
- subtype: "mainGnd",
389
- sourceType: "Current"
390
- /* Current */
391
- }]
392
- ]),
393
- config: /* @__PURE__ */ new Map([])
394
- },
395
- lightbulb: {
396
- id: "lightbulb",
397
- name: "Lightbulb",
398
- pins: /* @__PURE__ */ new Map([
399
- ["pin1", { subtype: "free", sourceType: void 0 }],
400
- ["pin2", { subtype: "free", sourceType: void 0 }]
401
- ]),
402
- config: /* @__PURE__ */ new Map([["size", "1"]])
403
- },
404
- relay: {
405
- id: "relay",
406
- name: "Relay",
407
- pins: /* @__PURE__ */ new Map([
408
- ["cmd_in", { subtype: "free", sourceType: void 0 }],
409
- ["cmd_out", { subtype: "free", sourceType: void 0 }],
410
- ["power_in", { subtype: "free", sourceType: void 0 }],
411
- ["power_out", { subtype: "free", sourceType: void 0 }]
412
- ]),
413
- config: /* @__PURE__ */ new Map([
414
- ["activationLogic", "positive"],
415
- ["initializationOrder", ""]
416
- ])
417
- },
418
- smallLED: {
419
- id: "smallLED",
420
- name: "SmallLED",
421
- pins: /* @__PURE__ */ new Map([
422
- ["pin1", { subtype: "free", sourceType: void 0 }],
423
- ["pin2", { subtype: "free", sourceType: void 0 }]
424
- ]),
425
- config: /* @__PURE__ */ new Map([
426
- ["idleColor", "white"],
427
- ["activeColor", "#ffff00"],
428
- ["size", "1"],
429
- ["ywRatio", "1"]
430
- ])
431
- },
432
- rectangleLED: {
433
- id: "rectangleLED",
434
- name: "RectangleLED",
435
- pins: /* @__PURE__ */ new Map([
436
- ["pin1", { subtype: "free", sourceType: void 0 }],
437
- ["pin2", { subtype: "free", sourceType: void 0 }]
438
- ]),
439
- config: /* @__PURE__ */ new Map([
440
- ["idleColor", "white"],
441
- ["activeColor", "#ffff00"],
442
- ["size", "1"],
443
- ["hwRatio", "1"],
444
- ["ywRatio", "1"]
445
- ])
446
- },
447
- cube: {
448
- id: "cube",
449
- name: "Cube",
450
- pins: /* @__PURE__ */ new Map([]),
451
- config: /* @__PURE__ */ new Map([["color", "red"]])
452
- },
453
- label: {
454
- id: "label",
455
- name: "Label",
456
- pins: /* @__PURE__ */ new Map([]),
457
- config: /* @__PURE__ */ new Map([
458
- ["text", "Label"],
459
- ["size", "1"]
460
- ])
461
- },
462
- inverter: {
463
- id: "inverter",
464
- name: "Inverter",
465
- pins: /* @__PURE__ */ new Map([
466
- ["vcc", {
467
- subtype: "vcc",
468
- sourceType: "Voltage"
469
- /* Voltage */
470
- }],
471
- ["input", { subtype: "logicInput", sourceType: void 0 }],
472
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
473
- ["gnd", {
474
- subtype: "gnd",
475
- sourceType: "Current"
476
- /* Current */
477
- }]
478
- ]),
479
- config: /* @__PURE__ */ new Map([
480
- ["defaultLogicFamily", "CMOS1"],
481
- ["activationLogic", "negative"],
482
- ["transitionSpan", "1"],
483
- ["initializationOrder", ""]
484
- ])
485
- },
486
- nandGate: {
487
- id: "nandGate",
488
- name: "NAND Gate",
489
- pins: /* @__PURE__ */ new Map([
490
- ["vcc", {
491
- subtype: "vcc",
492
- sourceType: "Voltage"
493
- /* Voltage */
494
- }],
495
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
496
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
497
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
498
- ["gnd", {
499
- subtype: "gnd",
500
- sourceType: "Current"
501
- /* Current */
502
- }]
503
- ]),
504
- config: /* @__PURE__ */ new Map([
505
- ["defaultLogicFamily", "CMOS1"],
506
- ["activationLogic", "negative"],
507
- ["transitionSpan", "1"],
508
- ["initializationOrder", ""]
509
- ])
510
- },
511
- nand4Gate: {
512
- id: "nand4Gate",
513
- name: "NAND4 Gate",
514
- pins: /* @__PURE__ */ new Map([
515
- ["vcc", {
516
- subtype: "vcc",
517
- sourceType: "Voltage"
518
- /* Voltage */
519
- }],
520
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
521
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
522
- ["input3", { subtype: "logicInput", sourceType: void 0 }],
523
- ["input4", { subtype: "logicInput", sourceType: void 0 }],
524
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
525
- ["gnd", {
526
- subtype: "gnd",
527
- sourceType: "Current"
528
- /* Current */
529
- }]
530
- ]),
531
- config: /* @__PURE__ */ new Map([
532
- ["defaultLogicFamily", "CMOS1"],
533
- ["activationLogic", "negative"],
534
- ["transitionSpan", "2"],
535
- ["initializationOrder", ""]
536
- ])
537
- },
538
- nand8Gate: {
539
- id: "nand8Gate",
540
- name: "NAND8 Gate",
541
- pins: /* @__PURE__ */ new Map([
542
- ["vcc", {
543
- subtype: "vcc",
544
- sourceType: "Voltage"
545
- /* Voltage */
546
- }],
547
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
548
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
549
- ["input3", { subtype: "logicInput", sourceType: void 0 }],
550
- ["input4", { subtype: "logicInput", sourceType: void 0 }],
551
- ["input5", { subtype: "logicInput", sourceType: void 0 }],
552
- ["input6", { subtype: "logicInput", sourceType: void 0 }],
553
- ["input7", { subtype: "logicInput", sourceType: void 0 }],
554
- ["input8", { subtype: "logicInput", sourceType: void 0 }],
555
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
556
- ["gnd", {
557
- subtype: "gnd",
558
- sourceType: "Current"
559
- /* Current */
560
- }]
561
- ]),
562
- config: /* @__PURE__ */ new Map([
563
- ["defaultLogicFamily", "CMOS1"],
564
- ["activationLogic", "negative"],
565
- ["transitionSpan", "3"],
566
- ["initializationOrder", ""]
567
- ])
568
- },
569
- norGate: {
570
- id: "norGate",
571
- name: "NOR Gate",
572
- pins: /* @__PURE__ */ new Map([
573
- ["vcc", {
574
- subtype: "vcc",
575
- sourceType: "Voltage"
576
- /* Voltage */
577
- }],
578
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
579
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
580
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
581
- ["gnd", {
582
- subtype: "gnd",
583
- sourceType: "Current"
584
- /* Current */
585
- }]
586
- ]),
587
- config: /* @__PURE__ */ new Map([
588
- ["defaultLogicFamily", "CMOS1"],
589
- ["activationLogic", "negative"],
590
- ["transitionSpan", "1"],
591
- ["initializationOrder", ""]
592
- ])
593
- },
594
- nor4Gate: {
595
- id: "nor4Gate",
596
- name: "NOR4 Gate",
597
- pins: /* @__PURE__ */ new Map([
598
- ["vcc", {
599
- subtype: "vcc",
600
- sourceType: "Voltage"
601
- /* Voltage */
602
- }],
603
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
604
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
605
- ["input3", { subtype: "logicInput", sourceType: void 0 }],
606
- ["input4", { subtype: "logicInput", sourceType: void 0 }],
607
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
608
- ["gnd", {
609
- subtype: "gnd",
610
- sourceType: "Current"
611
- /* Current */
612
- }]
613
- ]),
614
- config: /* @__PURE__ */ new Map([
615
- ["defaultLogicFamily", "CMOS1"],
616
- ["activationLogic", "negative"],
617
- ["transitionSpan", "2"],
618
- ["initializationOrder", ""]
619
- ])
620
- },
621
- nor8Gate: {
622
- id: "nor8Gate",
623
- name: "NOR8 Gate",
624
- pins: /* @__PURE__ */ new Map([
625
- ["vcc", {
626
- subtype: "vcc",
627
- sourceType: "Voltage"
628
- /* Voltage */
629
- }],
630
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
631
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
632
- ["input3", { subtype: "logicInput", sourceType: void 0 }],
633
- ["input4", { subtype: "logicInput", sourceType: void 0 }],
634
- ["input5", { subtype: "logicInput", sourceType: void 0 }],
635
- ["input6", { subtype: "logicInput", sourceType: void 0 }],
636
- ["input7", { subtype: "logicInput", sourceType: void 0 }],
637
- ["input8", { subtype: "logicInput", sourceType: void 0 }],
638
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
639
- ["gnd", {
640
- subtype: "gnd",
641
- sourceType: "Current"
642
- /* Current */
643
- }]
644
- ]),
645
- config: /* @__PURE__ */ new Map([
646
- ["defaultLogicFamily", "CMOS1"],
647
- ["activationLogic", "negative"],
648
- ["transitionSpan", "3"],
649
- ["initializationOrder", ""]
650
- ])
651
- },
652
- xorGate: {
653
- id: "xorGate",
654
- name: "XOR Gate",
655
- pins: /* @__PURE__ */ new Map([
656
- ["vcc", {
657
- subtype: "vcc",
658
- sourceType: "Voltage"
659
- /* Voltage */
660
- }],
661
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
662
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
663
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
664
- ["gnd", {
665
- subtype: "gnd",
666
- sourceType: "Current"
667
- /* Current */
668
- }]
669
- ]),
670
- config: /* @__PURE__ */ new Map([
671
- ["defaultLogicFamily", "CMOS1"],
672
- ["activationLogic", "positive"],
673
- ["transitionSpan", "2"],
674
- ["initializationOrder", ""]
675
- ])
676
- },
677
- xor4Gate: {
678
- id: "xor4Gate",
679
- name: "XOR4 Gate",
680
- pins: /* @__PURE__ */ new Map([
681
- ["vcc", {
682
- subtype: "vcc",
683
- sourceType: "Voltage"
684
- /* Voltage */
685
- }],
686
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
687
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
688
- ["input3", { subtype: "logicInput", sourceType: void 0 }],
689
- ["input4", { subtype: "logicInput", sourceType: void 0 }],
690
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
691
- ["gnd", {
692
- subtype: "gnd",
693
- sourceType: "Current"
694
- /* Current */
695
- }]
696
- ]),
697
- config: /* @__PURE__ */ new Map([
698
- ["defaultLogicFamily", "CMOS1"],
699
- ["activationLogic", "positive"],
700
- ["transitionSpan", "4"],
701
- ["initializationOrder", ""]
702
- ])
703
- },
704
- xor8Gate: {
705
- id: "xor8Gate",
706
- name: "XOR8 Gate",
707
- pins: /* @__PURE__ */ new Map([
708
- ["vcc", {
709
- subtype: "vcc",
710
- sourceType: "Voltage"
711
- /* Voltage */
712
- }],
713
- ["input1", { subtype: "logicInput", sourceType: void 0 }],
714
- ["input2", { subtype: "logicInput", sourceType: void 0 }],
715
- ["input3", { subtype: "logicInput", sourceType: void 0 }],
716
- ["input4", { subtype: "logicInput", sourceType: void 0 }],
717
- ["input5", { subtype: "logicInput", sourceType: void 0 }],
718
- ["input6", { subtype: "logicInput", sourceType: void 0 }],
719
- ["input7", { subtype: "logicInput", sourceType: void 0 }],
720
- ["input8", { subtype: "logicInput", sourceType: void 0 }],
721
- ["output", { subtype: "logicOutput", sourceType: void 0 }],
722
- ["gnd", {
723
- subtype: "gnd",
724
- sourceType: "Current"
725
- /* Current */
726
- }]
727
- ]),
728
- config: /* @__PURE__ */ new Map([
729
- ["defaultLogicFamily", "CMOS1"],
730
- ["activationLogic", "positive"],
731
- ["transitionSpan", "6"],
732
- ["initializationOrder", ""]
733
- ])
734
- }
735
- };
736
- class k {
737
- /**
738
- * Unique identifier for this ENode.
739
- * @readonly
740
- */
741
- id;
742
- /**
743
- * Type of electrical node (Pin or BranchingPoint).
744
- * @readonly
745
- */
746
- type;
747
- /**
748
- * Parent component UUID (only for pin nodes).
749
- * Undefined for branching point nodes.
750
- * @readonly
751
- */
752
- component;
753
- /**
754
- * Pin label within component (only for pin nodes).
755
- * Undefined for branching point nodes.
756
- * @readonly
757
- */
758
- pinLabel;
759
- /**
760
- * Grid position (only for branching point nodes).
761
- * Undefined for pin nodes (position derived from component).
762
- * @readonly
763
- */
764
- position;
765
- /**
766
- * Set of wire UUIDs connected to this node.
767
- * Mutable to allow wire connections/disconnections.
768
- */
769
- wires;
770
- /**
771
- * Is the ENode a source of voltage or current?
772
- */
773
- source;
774
- /**
775
- * Pin role classification: free, mainVcc, vcc, mainGnd, gnd, logicInput, logicOutput.
776
- * @readonly
777
- */
778
- subtype;
779
- /**
780
- * Create a new electrical node.
781
- *
782
- * **Note**: Typically ENodes are created automatically by Circuit.
783
- * This constructor is used internally.
784
- *
785
- * @param type - Node type (Pin or BranchingPoint)
786
- * @param component - Parent component UUID (pin nodes only)
787
- * @param pinLabel - Pin label (pin nodes only)
788
- * @param position - Grid position (branching points only)
789
- * @param source - Source type (Voltage/Current) or undefined
790
- *
791
- * @param subtype
792
- * @example
793
- * ```typescript
794
- * // Pin node (internal to Circuit)
795
- * const pinNode = new ENode(
796
- * ENodeType.Pin,
797
- * componentId,
798
- * '0', // first pin
799
- * undefined,
800
- * undefined
801
- * );
802
- *
803
- * // Branching point node
804
- * const branchNode = new ENode(
805
- * ENodeType.BranchingPoint,
806
- * undefined,
807
- * undefined,
808
- * new Position(15, 25),
809
- * undefined
810
- * );
811
- * ```
812
- */
813
- constructor(t, e, i, n, r = void 0, a = "free") {
814
- this.id = O(), this.type = t, this.component = e, this.pinLabel = i, this.position = n, this.wires = /* @__PURE__ */ new Set(), this.source = r, this.subtype = a;
815
- }
816
- /**
817
- * Get the position of this electrical node.
818
- *
819
- * **Pin nodes**: Derives position from parent component.
820
- * **Branching nodes**: Returns stored position directly.
821
- *
822
- * @param circuit - Circuit instance (needed to look up component for pin nodes)
823
- * @returns Position on the grid
824
- *
825
- * @example
826
- * ```typescript
827
- * const circuit = new Circuit();
828
- * const component = circuit.addComponent(
829
- * new Position(10, 20),
830
- * new Rotation(0),
831
- * 1
832
- * );
833
- *
834
- * const pinNode = circuit.getENode(component.pins[0]);
835
- * const position = pinNode.getPosition(circuit);
836
- * console.log(position.x); // 10 (derived from component)
837
- * ```
838
- */
839
- getPosition(t) {
840
- if (this.type === S.Pin) {
841
- if (!this.component)
842
- throw new Error("Pin node missing component reference");
843
- const e = t.getComponent(this.component);
844
- if (!e)
845
- throw new Error(`Component ${this.component} not found for pin node ${this.id}`);
846
- return e.position;
847
- }
848
- if (!this.position)
849
- throw new Error("Branching point node missing position");
850
- return this.position;
851
- }
852
- /**
853
- * Update the enode (branching point only)'s position.
854
- *
855
- * @param newPosition - The new position for the enode
856
- *
857
- * @example
858
- * ```typescript
859
- * const component = circuit.getComponent(componentId);
860
- * component.setPosition(new Position(15, 25));
861
- * ```
862
- */
863
- setPosition(t) {
864
- Object.defineProperty(this, "position", {
865
- value: t,
866
- writable: !1,
867
- enumerable: !0,
868
- configurable: !0
869
- });
870
- }
871
- /**
872
- * Update the enode's source type.
873
- * @param sourceType
874
- */
875
- setSourceType(t) {
876
- Object.defineProperty(this, "source", {
877
- value: t,
878
- writable: !0,
879
- enumerable: !0,
880
- configurable: !0
881
- });
882
- }
883
- /**
884
- * Serialize ENode to JSON.
885
- *
886
- * @returns Plain object representation
887
- *
888
- * @example
889
- * ```typescript
890
- * const json = enode.toJSON();
891
- * console.log(json);
892
- * // Pin node:
893
- * // {
894
- * // id: "uuid",
895
- * // type: "Pin",
896
- * // component: "component-uuid",
897
- * // pinLabel: "0"
898
- * // }
899
- *
900
- * // Branching node:
901
- * // {
902
- * // id: "uuid",
903
- * // type: "BranchingPoint",
904
- * // position: { x: 15, y: 25 }
905
- * // }
906
- * ```
907
- */
908
- toJSON() {
909
- const t = {
910
- id: this.id,
911
- type: this.type,
912
- source: this.source || null,
913
- subtype: this.subtype
914
- };
915
- return this.type === S.Pin ? (t.component = this.component || null, t.pinLabel = this.pinLabel || null) : t.position = this.position?.toJSON() || null, t;
916
- }
917
- /**
918
- * Deserialize ENode from JSON.
919
- *
920
- * @param json - ENode data
921
- * @returns ENode instance
922
- *
923
- * @example
924
- * ```typescript
925
- * const json = {
926
- * id: "uuid",
927
- * type: "Pin",
928
- * component: "component-uuid",
929
- * pinLabel: "0"
930
- * };
931
- *
932
- * const enode = ENode.fromJSON(json);
933
- * ```
934
- */
935
- static fromJSON(t) {
936
- const e = t.position ? T.fromJSON(t.position) : void 0, i = new k(
937
- t.type,
938
- t.component || void 0,
939
- t.pinLabel || void 0,
940
- e,
941
- t.source || void 0,
942
- t.subtype ?? "free"
943
- );
944
- return Object.defineProperty(i, "id", {
945
- value: t.id,
946
- writable: !1,
947
- enumerable: !0,
948
- configurable: !1
949
- }), i;
950
- }
951
- }
952
- class E {
953
- /**
954
- * Unique identifier for this component.
955
- * @readonly
956
- */
957
- id;
958
- /**
959
- * Component type (Battery, Switch, LED, etc.).
960
- * @readonly
961
- */
962
- type;
963
- /**
964
- * Position on the 2D discrete grid.
965
- * @readonly
966
- */
967
- position;
968
- /**
969
- * Orientation angle in degrees.
970
- * @readonly
971
- */
972
- rotation;
973
- /**
974
- * Array of pin ENode UUIDs.
975
- * Pin order is significant (index 0 is first pin, etc.).
976
- * @readonly
977
- */
978
- pins;
979
- /**
980
- * Configuration parameters for this component instance.
981
- *
982
- * This map holds key-value pairs representing configurable settings
983
- * The available configuration keys depend on the component type see IComponentTypeMetadata for details.
984
- *
985
- */
986
- config;
987
- /**
988
- * allow to flag a component as non editable (feature to implement)
989
- */
990
- editable;
991
- /**
992
- * Create a new component.
993
- *
994
- * **Note**: Typically components are created via `Circuit.addComponent()`
995
- * which handles pin ENode creation automatically. This constructor is used
996
- * internally by Circuit.
997
- *
998
- * @param type - Component type (Battery, Switch, LED, etc.)
999
- * @param position - Grid position (integer x, y)
1000
- * @param rotation - Orientation angle (integer degrees)
1001
- * @param pins - Array of pin ENode UUIDs
1002
- *
1003
- * @param editable
1004
- * @example
1005
- * ```typescript
1006
- * // Usually created via Circuit:
1007
- * const component = circuit.addComponent(
1008
- * new Position(10, 20),
1009
- * new Rotation(90),
1010
- * ComponentType.Battery
1011
- * );
1012
- *
1013
- * // Direct construction (for deserialization):
1014
- * const component = new Component(
1015
- * ComponentType.Battery,
1016
- * new Position(10, 20),
1017
- * new Rotation(90),
1018
- * ['pin-id-1', 'pin-id-2']
1019
- * );
1020
- * ```
1021
- */
1022
- constructor(t, e, i, n, r = !0) {
1023
- if (this.id = O(), this.type = t, this.position = e, this.rotation = i, new Set(n).size !== n.length) {
1024
- const a = n.filter((c, h) => n.indexOf(c) !== h);
1025
- throw new Error(
1026
- `Duplicate pin names are not allowed: ${[...new Set(a)].join(", ")}`
1027
- );
1028
- }
1029
- this.pins = n, this.config = new Map(I[t].config), this.editable = r;
1030
- }
1031
- getPinLabel(t) {
1032
- const e = this.pins.indexOf(t);
1033
- if (e === -1)
1034
- return;
1035
- const i = I[this.type].pins.keys();
1036
- return Array.from(i)[e] || void 0;
1037
- }
1038
- setAllParameters(t) {
1039
- this.config = new Map(t);
1040
- }
1041
- setParameter(t, e) {
1042
- this.config.set(t, e);
1043
- }
1044
- /**
1045
- * Update the component's position.
1046
- *
1047
- * @param newPosition - The new position for the component
1048
- *
1049
- * @example
1050
- * ```typescript
1051
- * const component = circuit.getComponent(componentId);
1052
- * component.setPosition(new Position(15, 25));
1053
- * ```
1054
- */
1055
- setPosition(t) {
1056
- Object.defineProperty(this, "position", {
1057
- value: t,
1058
- writable: !1,
1059
- enumerable: !0,
1060
- configurable: !0
1061
- });
1062
- }
1063
- /**
1064
- * Update the component's rotation.
1065
- *
1066
- * @param newRotation - The new rotation for the component
1067
- *
1068
- * @example
1069
- * ```typescript
1070
- * const component = circuit.getComponent(componentId);
1071
- * component.setRotation(new Rotation(90));
1072
- * ```
1073
- */
1074
- setRotation(t) {
1075
- Object.defineProperty(this, "rotation", {
1076
- value: t,
1077
- writable: !1,
1078
- enumerable: !0,
1079
- configurable: !0
1080
- });
1081
- }
1082
- /**
1083
- * Serialize component to JSON.
1084
- *
1085
- * @returns Plain object representation
1086
- *
1087
- * @example
1088
- * ```typescript
1089
- * const json = component.toJSON();
1090
- * console.log(json);
1091
- * // {
1092
- * // id: "550e8400-...",
1093
- * // type: "battery",
1094
- * // position: { x: 10, y: 20 },
1095
- * // rotation: 90,
1096
- * // pins: ['pin-uuid-1', 'pin-uuid-2']
1097
- * // }
1098
- * ```
1099
- */
1100
- toJSON() {
1101
- return {
1102
- id: this.id,
1103
- type: this.type,
1104
- position: this.position.toJSON(),
1105
- rotation: this.rotation.toJSON(),
1106
- pins: [...this.pins],
1107
- config: Object.fromEntries(this.config),
1108
- editable: this.editable
1109
- };
1110
- }
1111
- /**
1112
- * Deserialize component from JSON.
1113
- *
1114
- * @param json - Component data
1115
- * @returns Component instance
1116
- *
1117
- */
1118
- static fromJSON(t) {
1119
- const e = new E(
1120
- t.type,
1121
- T.fromJSON(t.position),
1122
- C.fromJSON(t.rotation),
1123
- t.pins,
1124
- t.editable
1125
- );
1126
- return e.config = new Map(Object.entries(t.config)), Object.defineProperty(e, "id", {
1127
- value: t.id,
1128
- writable: !1,
1129
- enumerable: !0,
1130
- configurable: !1
1131
- }), e;
1132
- }
1133
- }
1134
- const F = {
1135
- /**
1136
- * Minimum simulation speed in ticks per second
1137
- */
1138
- MIN_TPS: 1,
1139
- /**
1140
- * Maximum simulation speed in ticks per second
1141
- */
1142
- MAX_TPS: 50,
1143
- /**
1144
- * Default simulation speed in ticks per second
1145
- */
1146
- DEFAULT_TPS: 3,
1147
- /**
1148
- * Default tick interval in milliseconds (1000 / DEFAULT_TPS)
1149
- */
1150
- DEFAULT_INTERVAL_MS: 500
1151
- }, $ = {
1152
- /**
1153
- * Default transitionSpan for relays and transistors in ticks (instant transition)
1154
- */
1155
- TRANSITION_SPAN_TICKS: 1,
1156
- /**
1157
- * Default transitionUserSpan for switches in milliseconds
1158
- */
1159
- TRANSITION_USER_SPAN_MS: 200
1160
- };
1161
- class w {
1162
- /**
1163
- * Current simulation step number (starts at 0).
1164
- * @readonly
1165
- */
1166
- tick;
1167
- /**
1168
- * Electrical state for each ENode (component pins and branching points).
1169
- * Key: ENode UUID, Value: INodeElectricalState
1170
- * @readonly
1171
- */
1172
- nodeStates;
1173
- /**
1174
- * Electrical state for each Wire connecting ENodes.
1175
- * Key: Wire UUID, Value: INodeElectricalState
1176
- * @readonly
1177
- */
1178
- wireStates;
1179
- /**
1180
- * Component-specific state for each component.
1181
- * Key: Component UUID, Value: ComponentState subclass
1182
- * @readonly
1183
- */
1184
- componentStates;
1185
- /**
1186
- * Create a new simulation state snapshot.
1187
- *
1188
- * @param tick - Current simulation step number
1189
- */
1190
- constructor(t) {
1191
- if (t < 0 || !Number.isInteger(t))
1192
- throw new RangeError(`Tick must be a non-negative integer (got ${t})`);
1193
- this.tick = t, this.nodeStates = /* @__PURE__ */ new Map(), this.wireStates = /* @__PURE__ */ new Map(), this.componentStates = /* @__PURE__ */ new Map();
1194
- }
1195
- setTick(t) {
1196
- this.tick = t;
1197
- }
1198
- /**
1199
- * Create a deep copy of this state for historical storage.
1200
- *
1201
- * @returns Cloned SimulationState
1202
- */
1203
- clone() {
1204
- const t = new w(this.tick), e = /* @__PURE__ */ new Map();
1205
- for (const [r, a] of this.nodeStates.entries())
1206
- e.set(r, { ...a });
1207
- const i = /* @__PURE__ */ new Map();
1208
- for (const [r, a] of this.wireStates.entries())
1209
- i.set(r, { ...a });
1210
- const n = /* @__PURE__ */ new Map();
1211
- for (const [r, a] of this.componentStates.entries())
1212
- n.set(
1213
- r,
1214
- Object.assign(Object.create(Object.getPrototypeOf(a)), a)
1215
- );
1216
- return Object.defineProperty(t, "nodeStates", {
1217
- value: e,
1218
- writable: !1,
1219
- configurable: !1,
1220
- enumerable: !0
1221
- }), Object.defineProperty(t, "wireStates", {
1222
- value: i,
1223
- writable: !1,
1224
- configurable: !1,
1225
- enumerable: !0
1226
- }), Object.defineProperty(t, "componentStates", {
1227
- value: n,
1228
- writable: !1,
1229
- configurable: !1,
1230
- enumerable: !0
1231
- }), t;
1232
- }
1233
- }
1234
- class D {
1235
- heap;
1236
- /**
1237
- * Create a new empty event queue.
1238
- */
1239
- constructor() {
1240
- this.heap = [];
1241
- }
1242
- /**
1243
- * Schedule a future event.
1244
- * Inserted with O(log N) complexity using heap operations.
1245
- *
1246
- * @param event - Event to schedule
1247
- */
1248
- schedule(t) {
1249
- if (t.readyAtTick < t.scheduledAtTick)
1250
- throw new RangeError(
1251
- `readyAtTick (${t.readyAtTick}) cannot be before scheduledAtTick (${t.scheduledAtTick})`
1252
- );
1253
- this.heap.push(t), this.bubbleUp(this.heap.length - 1);
1254
- }
1255
- /**
1256
- * Get all events ready to fire at or before current tick.
1257
- * Returns events in FIFO order for same readyAtTick.
1258
- * Removes returned events from the queue.
1259
- *
1260
- * @param currentTick - Current simulation tick
1261
- * @returns Array of ready events (removed from queue)
1262
- */
1263
- getReadyEvents(t) {
1264
- const e = [];
1265
- for (; this.heap.length > 0 && this.heap[0].readyAtTick <= t; ) {
1266
- const i = this.extractMin();
1267
- i && e.push(i);
1268
- }
1269
- return e.sort((i, n) => i.readyAtTick === n.readyAtTick ? i.scheduledAtTick - n.scheduledAtTick : i.readyAtTick - n.readyAtTick), e;
1270
- }
1271
- /**
1272
- * Check if any events are pending.
1273
- *
1274
- * @returns True if queue contains events
1275
- */
1276
- hasEvents() {
1277
- return this.heap.length > 0;
1278
- }
1279
- /**
1280
- * Clear all pending events.
1281
- */
1282
- clear() {
1283
- this.heap = [];
1284
- }
1285
- /**
1286
- * Remove all pending events targeting a specific component.
1287
- * Used when a behavior signals shouldCancelPending (e.g., Vcc loss, input change during transition).
1288
- *
1289
- * @param targetId - UUID of the component whose events should be removed
1290
- * @returns Number of events removed
1291
- */
1292
- removeEventsForTarget(t) {
1293
- const e = this.heap.length;
1294
- return this.heap = this.heap.filter((i) => i.targetId !== t), this.heap.length !== e && this.rebuildHeap(), e - this.heap.length;
1295
- }
1296
- /**
1297
- * Get number of pending events.
1298
- *
1299
- * @returns Event count
1300
- */
1301
- size() {
1302
- return this.heap.length;
1303
- }
1304
- rebuildHeap() {
1305
- for (let t = Math.floor(this.heap.length / 2) - 1; t >= 0; t--)
1306
- this.bubbleDown(t);
1307
- }
1308
- bubbleUp(t) {
1309
- for (; t > 0; ) {
1310
- const e = Math.floor((t - 1) / 2);
1311
- if (this.heap[t].readyAtTick < this.heap[e].readyAtTick)
1312
- [this.heap[t], this.heap[e]] = [this.heap[e], this.heap[t]], t = e;
1313
- else
1314
- break;
1315
- }
1316
- }
1317
- bubbleDown(t) {
1318
- const e = this.heap.length;
1319
- for (; ; ) {
1320
- const i = 2 * t + 1, n = 2 * t + 2;
1321
- let r = t;
1322
- if (i < e && this.heap[i].readyAtTick < this.heap[r].readyAtTick && (r = i), n < e && this.heap[n].readyAtTick < this.heap[r].readyAtTick && (r = n), r !== t)
1323
- [this.heap[t], this.heap[r]] = [this.heap[r], this.heap[t]], t = r;
1324
- else
1325
- break;
1326
- }
1327
- }
1328
- extractMin() {
1329
- if (this.heap.length === 0)
1330
- return;
1331
- const t = this.heap[0], e = this.heap.pop();
1332
- return this.heap.length > 0 && e && (this.heap[0] = e, this.bubbleDown(0)), t;
1333
- }
1334
- }
1335
- class P {
1336
- dirtyComponents;
1337
- dirtyWires;
1338
- dirtyEnodes;
1339
- /**
1340
- * Create a new dirty tracker with no marked elements.
1341
- */
1342
- constructor() {
1343
- this.dirtyComponents = /* @__PURE__ */ new Set(), this.dirtyWires = /* @__PURE__ */ new Set(), this.dirtyEnodes = /* @__PURE__ */ new Set();
1344
- }
1345
- /**
1346
- * Mark a component as having changed state this tick.
1347
- *
1348
- * @param componentId - UUID of the component
1349
- */
1350
- markComponentDirty(t) {
1351
- this.dirtyComponents.add(t);
1352
- }
1353
- /**
1354
- * Mark a wire as having changed electrical state this tick.
1355
- *
1356
- * @param wireId - UUID of the wire
1357
- */
1358
- markWireDirty(t) {
1359
- this.dirtyWires.add(t);
1360
- }
1361
- /**
1362
- * Mark an ENode as having changed electrical state this tick.
1363
- *
1364
- * @param enodeId - UUID of the ENode
1365
- */
1366
- markEnodeDirty(t) {
1367
- this.dirtyEnodes.add(t);
1368
- }
1369
- /**
1370
- * Set the entire set of dirty components. Should be only used at CircuitRunner initialization.
1371
- * @param componentIds
1372
- */
1373
- setDirtyComponents(t) {
1374
- this.dirtyComponents = new Set(t);
1375
- }
1376
- /**
1377
- * Set the entire set of dirty components. Should be only used at CircuitRunner initialization.
1378
- * @param enodeIds
1379
- */
1380
- setDirtyEnodes(t) {
1381
- this.dirtyEnodes = new Set(t);
1382
- }
1383
- /**
1384
- * Set the entire set of dirty components. Should be only used at CircuitRunner initialization.
1385
- * @param wireIds
1386
- */
1387
- setDirtyWires(t) {
1388
- this.dirtyWires = new Set(t);
1389
- }
1390
- /**
1391
- * Get all dirty elements and clear the tracker.
1392
- * This is typically called at the end of a tick to collect changes.
1393
- *
1394
- * @returns Object containing sets of dirty component/wire/enode UUIDs
1395
- */
1396
- getDirtyElements() {
1397
- const t = {
1398
- components: new Set(this.dirtyComponents),
1399
- wires: new Set(this.dirtyWires),
1400
- enodes: new Set(this.dirtyEnodes)
1401
- };
1402
- return this.clear(), t;
1403
- }
1404
- /**
1405
- * Check if any elements are marked dirty.
1406
- *
1407
- * @returns True if at least one element is dirty
1408
- */
1409
- hasDirtyElements() {
1410
- return this.dirtyComponents.size > 0 || this.dirtyWires.size > 0 || this.dirtyEnodes.size > 0;
1411
- }
1412
- /**
1413
- * Clear all dirty markers without returning them.
1414
- */
1415
- clear() {
1416
- this.dirtyComponents.clear(), this.dirtyWires.clear(), this.dirtyEnodes.clear();
1417
- }
1418
- /**
1419
- * Get current count of dirty components (for debugging/metrics).
1420
- *
1421
- * @returns Number of dirty components
1422
- */
1423
- getDirtyComponentCount() {
1424
- return this.dirtyComponents.size;
1425
- }
1426
- /**
1427
- * Get current count of dirty wires (for debugging/metrics).
1428
- *
1429
- * @returns Number of dirty wires
1430
- */
1431
- getDirtyWireCount() {
1432
- return this.dirtyWires.size;
1433
- }
1434
- /**
1435
- * Get current count of dirty enodes (for debugging/metrics).
1436
- *
1437
- * @returns Number of dirty enodes
1438
- */
1439
- getDirtyEnodeCount() {
1440
- return this.dirtyEnodes.size;
1441
- }
1442
- }
1443
- class x {
1444
- currentState;
1445
- history;
1446
- historyEnabled;
1447
- historyLimit;
1448
- historyWriteIndex;
1449
- /**
1450
- * Create a new state controllerType.
1451
- *
1452
- * @param enableHistory - Whether to store state history (default: false)
1453
- * @param historyLimit - Maximum number of historical states to keep (default: 1000)
1454
- */
1455
- constructor(t = !1, e = 1e3) {
1456
- if (e < 1)
1457
- throw new RangeError(`historyLimit must be at least 1 (got ${e})`);
1458
- this.historyEnabled = t, this.historyLimit = e, this.currentState = new w(0), this.history = [], this.historyWriteIndex = 0;
1459
- }
1460
- /**
1461
- * Get the current simulation state.
1462
- *
1463
- * @returns Current state (mutable for simulation controller use)
1464
- */
1465
- getCurrentState() {
1466
- return this.currentState;
1467
- }
1468
- /**
1469
- * Get current tick number.
1470
- *
1471
- * @returns Current simulation tick
1472
- */
1473
- getCurrentTick() {
1474
- return this.currentState.tick;
1475
- }
1476
- /**
1477
- * Advance to next tick, optionally saving current state to history.
1478
- * Creates a new SimulationState for the next tick.
1479
- *
1480
- * @returns New current state for the next tick
1481
- */
1482
- advanceToNextTick() {
1483
- const t = this.currentState.tick + 1;
1484
- return this.historyEnabled && this.saveToHistory(this.currentState.clone()), this.currentState.tick = t, this.currentState;
1485
- }
1486
- /**
1487
- * Get a historical state by tick number.
1488
- * Only works if history is enabled.
1489
- *
1490
- * @param tick - Tick number to retrieve
1491
- * @returns State at that tick, or undefined if not available
1492
- */
1493
- getStateAtTick(t) {
1494
- if (this.historyEnabled)
1495
- return this.history.find((e) => e.tick === t);
1496
- }
1497
- /**
1498
- * Get all available historical states.
1499
- * Returns empty array if history is disabled.
1500
- *
1501
- * @returns Array of historical states, sorted by tick (oldest first)
1502
- */
1503
- getHistory() {
1504
- return this.historyEnabled ? [...this.history].sort((t, e) => t.tick - e.tick) : [];
1505
- }
1506
- /**
1507
- * Get the oldest tick number available in history.
1508
- *
1509
- * @returns Oldest tick number, or undefined if no history
1510
- */
1511
- getOldestTick() {
1512
- if (!(!this.historyEnabled || this.history.length === 0))
1513
- return Math.min(...this.history.map((t) => t.tick));
1514
- }
1515
- /**
1516
- * Get the newest tick number in history (not including current tick).
1517
- *
1518
- * @returns Newest historical tick, or undefined if no history
1519
- */
1520
- getNewestHistoricalTick() {
1521
- if (!(!this.historyEnabled || this.history.length === 0))
1522
- return Math.max(...this.history.map((t) => t.tick));
1523
- }
1524
- /**
1525
- * Clear all history.
1526
- */
1527
- clearHistory() {
1528
- this.history = [], this.historyWriteIndex = 0;
1529
- }
1530
- /**
1531
- * Reset to tick 0, clearing current state and all history.
1532
- */
1533
- reset() {
1534
- this.currentState = new w(0), this.clearHistory();
1535
- }
1536
- /**
1537
- * Check if history tracking is enabled.
1538
- *
1539
- * @returns True if history is enabled
1540
- */
1541
- isHistoryEnabled() {
1542
- return this.historyEnabled;
1543
- }
1544
- /**
1545
- * Get the configured history limit.
1546
- *
1547
- * @returns Maximum number of historical states
1548
- */
1549
- getHistoryLimit() {
1550
- return this.historyLimit;
1551
- }
1552
- /**
1553
- * Get current history size.
1554
- *
1555
- * @returns Number of states in history
1556
- */
1557
- getHistorySize() {
1558
- return this.history.length;
1559
- }
1560
- /**
1561
- * Save a state to history using circular buffer.
1562
- * Private helper for advanceToNextTick.
1563
- *
1564
- * @param state - State to save
1565
- */
1566
- saveToHistory(t) {
1567
- this.history.length < this.historyLimit ? this.history.push(t) : (this.history[this.historyWriteIndex] = t, this.historyWriteIndex = (this.historyWriteIndex + 1) % this.historyLimit);
1568
- }
1569
- }
1570
- class J {
1571
- circuit;
1572
- stateManager;
1573
- eventQueue;
1574
- commands;
1575
- dirtyTracker;
1576
- behaviorRegistry;
1577
- /**
1578
- * Create a new circuit simulation runner.
1579
- *
1580
- * @param circuit - The circuit topology to simulate
1581
- * @param behaviorRegistry - Registry of component behaviors
1582
- * @param options - Simulation options (history settings)
1583
- */
1584
- constructor(t, e, i = {}) {
1585
- this.circuit = t, this.behaviorRegistry = e;
1586
- const n = i.enableHistory ?? !1, r = i.historyLimit ?? 1e3;
1587
- this.stateManager = new x(n, r), this.eventQueue = new D(), this.commands = /* @__PURE__ */ new Map(), this.dirtyTracker = new P();
1588
- try {
1589
- this.initializeState();
1590
- } catch (a) {
1591
- throw console.error("Error during CircuitRunner initialization:", a), a;
1592
- }
1593
- }
1594
- /**
1595
- * Execute one simulation tick.
1596
- * Process scheduled events, update state (electrical propagation), process user commands and advance tick.
1597
- *
1598
- * @returns the result of the tick execution
1599
- */
1600
- tick() {
1601
- const t = this.eventQueue.size(), e = this.stateManager.getCurrentTick(), i = this.applyReadyEvents(e + 1), n = this.updateState(e + 1);
1602
- n.firedEventCount = i.length;
1603
- const r = this.processCommands();
1604
- n.processedCommandCount = r.length, n.scheduledEventCount = this.eventQueue.size() + n.firedEventCount - t;
1605
- for (const a of i)
1606
- a.hasChanged && this.dirtyTracker.markComponentDirty(a.componentState.componentId);
1607
- return n.componentUpdateCount = this.dirtyTracker.getDirtyComponentCount(), this.stateManager.advanceToNextTick(), n.endTick = this.stateManager.getCurrentTick(), n;
1608
- }
1609
- /**
1610
- * Execute multiple simulation ticks.
1611
- *
1612
- * @param count - Number of ticks to execute
1613
- * @returns an array of IRunnerResult for each tick executed
1614
- */
1615
- tickN(t) {
1616
- if (t < 1)
1617
- throw new RangeError(`Tick count must be at least 1 (got ${t})`);
1618
- const e = [];
1619
- for (let i = 0; i < t; i++)
1620
- e.push(this.tick());
1621
- return e;
1622
- }
1623
- /**
1624
- * Reset simulation to tick 0.
1625
- * Clears all state, history, and scheduled events.
1626
- */
1627
- reset() {
1628
- this.stateManager.reset(), this.eventQueue.clear(), this.dirtyTracker.clear(), this.initializeState();
1629
- }
1630
- /**
1631
- * Get current simulation tick number.
1632
- *
1633
- * @returns Current tick
1634
- */
1635
- getCurrentTick() {
1636
- return this.stateManager.getCurrentTick();
1637
- }
1638
- /**
1639
- * Get current simulation state snapshot.
1640
- *
1641
- * @returns Current state (readonly)
1642
- */
1643
- getCurrentState() {
1644
- return this.stateManager.getCurrentState();
1645
- }
1646
- /**
1647
- * Get electrical state of a specific ENode.
1648
- *
1649
- * @param enodeId - UUID of the ENode
1650
- * @returns Electrical state, or undefined if not found
1651
- */
1652
- getEnodeState(t) {
1653
- return this.stateManager.getCurrentState().nodeStates.get(t);
1654
- }
1655
- /**
1656
- * Get electrical state of a specific Wire.
1657
- *
1658
- * @param wireId - UUID of the Wire
1659
- * @returns Electrical state, or undefined if not found
1660
- */
1661
- getWireState(t) {
1662
- return this.stateManager.getCurrentState().wireStates.get(t);
1663
- }
1664
- /**
1665
- * Get component state for a specific component.
1666
- *
1667
- * @param componentId - UUID of the component
1668
- * @returns Component state, or undefined if not found
1669
- */
1670
- getComponentState(t) {
1671
- return this.stateManager.getCurrentState().componentStates.get(t);
1672
- }
1673
- /**
1674
- * Get historical state at a specific tick.
1675
- * Only works if history is enabled.
1676
- *
1677
- * @param tick - Tick number to retrieve
1678
- * @returns Historical state, or undefined if not available
1679
- */
1680
- getStateAtTick(t) {
1681
- return this.stateManager.getStateAtTick(t);
1682
- }
1683
- /**
1684
- * Check if a component is registered in behavior registry.
1685
- *
1686
- * @param componentType - Component type to check
1687
- * @returns True if behavior is registered
1688
- */
1689
- hasBehavior(t) {
1690
- return this.behaviorRegistry.has(t);
1691
- }
1692
- /**
1693
- * Submit a user command to execute at the next tick.
1694
- * only one command per component per tick is allowed.
1695
- * Subsequent commands for the same component at this tick will be discarded.
1696
- *
1697
- * @param command - User command to submit
1698
- */
1699
- submitCommand(t) {
1700
- if (!this.circuit.hasComponent(t.targetId))
1701
- throw Error(`Cannot submit command for unknown component ID '${t.targetId}'`);
1702
- return this.commands.has(t.targetId) ? !1 : (t.scheduledAtTick = this.getCurrentTick(), this.commands.set(t.targetId, t), !0);
1703
- }
1704
- /**
1705
- * Process all scheduled user commands.
1706
- * Mark changed components as Dirty and enqueue consequent scheduled events
1707
- * Finally clears command queue after processing.
1708
- *
1709
- * @returns Array of IBehaviorResult for each processed command
1710
- */
1711
- processCommands() {
1712
- const t = this.stateManager.getCurrentState(), e = [];
1713
- for (const i of this.commands.values()) {
1714
- const n = this.circuit.getComponent(i.targetId), a = this.behaviorRegistry.get(n.type).onUserCommand(
1715
- n,
1716
- t.componentStates.get(n.id),
1717
- i
1718
- );
1719
- a.shouldCancelPending && this.eventQueue.removeEventsForTarget(n.id);
1720
- for (const c of a.scheduledEvents)
1721
- this.eventQueue.schedule(c);
1722
- e.push(a), a.hasChanged && this.dirtyTracker.markComponentDirty(n.id);
1723
- }
1724
- return this.commands.clear(), e;
1725
- }
1726
- /**
1727
- * Helper function to extract initializationOrder from component config.
1728
- * Returns numeric order value, with empty string or null defaulting to 0.
1729
- *
1730
- * @param config - Component configuration map
1731
- * @returns Order value (lower = processed first)
1732
- */
1733
- getInitializationOrder(t) {
1734
- const e = t.get("initializationOrder");
1735
- if (!e || e === "") return 0;
1736
- const i = parseInt(e, 10);
1737
- return isNaN(i) ? 0 : i;
1738
- }
1739
- /**
1740
- * Initialize simulation state for all components.
1741
- * Called on construction and reset.
1742
- *
1743
- * Uses order-based initialization to resolve feedback loops:
1744
- * 1. Components are grouped by initializationOrder (higher = processed LAST)
1745
- * 2. Within each group, components are sorted by UUID (ascending) for determinism
1746
- * 3. Conductivity is propagated after each component
1747
- *
1748
- * In feedback circuits, the component processed LAST "wins" because earlier
1749
- * components react to the initial symmetric state and open, while later
1750
- * components see the updated (asymmetric) state and stay closed.
1751
- */
1752
- initializeState() {
1753
- const t = this.stateManager.getCurrentState();
1754
- for (const s of this.circuit.getAllComponents()) {
1755
- if (s.pins.length < 1) continue;
1756
- const u = this.behaviorRegistry.get(s.type);
1757
- if (!u)
1758
- continue;
1759
- const d = u.createInitialState(s);
1760
- t.componentStates.set(s.id, d), this.dirtyTracker.markComponentDirty(s.id);
1761
- }
1762
- for (const s of this.circuit.getAllENodes())
1763
- t.nodeStates.set(s.id, {
1764
- hasVoltage: s.source === v.Voltage,
1765
- hasCurrent: s.source === v.Current,
1766
- locked: !!s.source
1767
- });
1768
- for (const s of this.circuit.getAllWires())
1769
- t.wireStates.set(s.id, {
1770
- hasVoltage: !1,
1771
- hasCurrent: !1,
1772
- locked: !1
1773
- });
1774
- const e = this.circuit.getAllComponents(), i = /* @__PURE__ */ new Map();
1775
- for (const s of e) {
1776
- const u = this.getInitializationOrder(s.config), d = i.get(u) ?? [];
1777
- d.push(s), i.set(u, d);
1778
- }
1779
- const n = Array.from(i.keys()).sort((s, u) => s - u);
1780
- for (const s of n)
1781
- i.get(s).sort((d, l) => d.id.localeCompare(l.id));
1782
- let r = !0, a = 0;
1783
- const c = 100;
1784
- for (; r && a < c; ) {
1785
- r = !1, a++;
1786
- for (const s of n) {
1787
- const u = i.get(s);
1788
- for (const d of u) {
1789
- const l = this.behaviorRegistry.get(d.type);
1790
- if (!l) continue;
1791
- const g = t.componentStates.get(d.id);
1792
- if (!g) continue;
1793
- this.propagateConductivity();
1794
- const b = l.onPinsChange(
1795
- d,
1796
- g,
1797
- t.nodeStates,
1798
- 0
1799
- );
1800
- b.hasChanged && (r = !0, t.componentStates.set(
1801
- d.id,
1802
- b.componentState
1803
- ));
1804
- for (const f of b.scheduledEvents) {
1805
- const p = l.onEventFiring(d, g, f);
1806
- p.hasChanged && (r = !0, t.componentStates.set(
1807
- d.id,
1808
- p.componentState
1809
- ));
1810
- }
1811
- }
1812
- }
1813
- }
1814
- const h = this.updateState(0);
1815
- return this.dirtyTracker.setDirtyComponents(
1816
- /* @__PURE__ */ new Set([...this.circuit.getAllComponents().map((s) => s.id)])
1817
- ), this.dirtyTracker.setDirtyEnodes(/* @__PURE__ */ new Set([...this.circuit.getAllENodes().map((s) => s.id)])), this.dirtyTracker.setDirtyWires(/* @__PURE__ */ new Set([...this.circuit.getAllWires().map((s) => s.id)])), h;
1818
- }
1819
- /**
1820
- * Core method that orchestrates nodes, wires and components state updates
1821
- * enqueue resulting events and update dirty tracker accordingly
1822
- * @param targetTick - Tick at which to perform the update
1823
- */
1824
- updateState(t) {
1825
- const e = this.stateManager.getCurrentState(), { updatedNodes: i, updatedWires: n } = this.propagateConductivity(), r = this.circuit.getComponentsOfPins(i), a = /* @__PURE__ */ new Set();
1826
- let c = 0, h = Array.from(r);
1827
- t === 0 && (h = h.sort((s, u) => {
1828
- const d = this.circuit.getComponent(s), l = this.circuit.getComponent(u), g = this.getInitializationOrder(d.config), b = this.getInitializationOrder(l.config);
1829
- return g !== b ? g - b : s.localeCompare(u);
1830
- }));
1831
- for (const s of h) {
1832
- const u = this.circuit.getComponent(s), d = this.behaviorRegistry.get(u.type);
1833
- if (!d)
1834
- continue;
1835
- const l = d.onPinsChange(
1836
- u,
1837
- e.componentStates.get(s),
1838
- e.nodeStates,
1839
- t
1840
- );
1841
- l.shouldCancelPending && this.eventQueue.removeEventsForTarget(s), l.hasChanged && a.add(s);
1842
- for (const g of l.scheduledEvents)
1843
- this.eventQueue.schedule(g), c++;
1844
- }
1845
- return this.dirtyTracker.setDirtyComponents(a), this.dirtyTracker.setDirtyEnodes(i), this.dirtyTracker.setDirtyWires(n), {
1846
- startTick: this.getCurrentTick(),
1847
- endTick: this.getCurrentTick(),
1848
- componentUpdateCount: a.size,
1849
- nodeUpdateCount: i.size,
1850
- wireUpdateCount: n.size,
1851
- processedCommandCount: 0,
1852
- scheduledEventCount: c,
1853
- firedEventCount: 0
1854
- };
1855
- }
1856
- /**
1857
- * runs BFS (Breadth First Search) on voltage and current conductivity
1858
- * to propagate voltage/current conductivity
1859
- * and update enodes/wires electrical states throughout the circuit
1860
- * update is performed in place and updated nodes and wires returned
1861
- */
1862
- propagateConductivity() {
1863
- const t = this.stateManager.getCurrentState(), e = (c) => {
1864
- const h = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), u = this.circuit.getAllENodes().filter((p) => p.source == c).map((p) => p.id), d = /* @__PURE__ */ new Set([
1865
- ...this.circuit.getAllENodes().filter((p) => !p.source).map((p) => p.id)
1866
- ]), l = /* @__PURE__ */ new Set([...this.circuit.getAllWires().map((p) => p.id)]), { nodes: g, wires: b } = this.computeReachability(
1867
- c,
1868
- u,
1869
- t.componentStates
1870
- ), f = c == v.Voltage ? "hasVoltage" : "hasCurrent";
1871
- for (const p of g) {
1872
- const y = t.nodeStates.get(p);
1873
- y && !y.locked && (y[f] || (y[f] = !0, h.add(p)), d.delete(p));
1874
- }
1875
- for (const p of d) {
1876
- const y = t.nodeStates.get(p);
1877
- y && !y.locked && y[f] && (y[f] = !1, h.add(p));
1878
- }
1879
- for (const p of b) {
1880
- const y = t.wireStates.get(p);
1881
- y && (y[f] || (y[f] = !0, s.add(p)), l.delete(p));
1882
- }
1883
- for (const p of l) {
1884
- const y = t.wireStates.get(p);
1885
- y && y[f] && (y[f] = !1, s.add(p));
1886
- }
1887
- return { updatedNodes: h, updatedWires: s };
1888
- }, { updatedNodes: i, updatedWires: n } = e(v.Voltage), { updatedNodes: r, updatedWires: a } = e(v.Current);
1889
- return {
1890
- updatedNodes: /* @__PURE__ */ new Set([...i, ...r]),
1891
- updatedWires: /* @__PURE__ */ new Set([...n, ...a])
1892
- };
1893
- }
1894
- /**
1895
- * given a conductivity conductivityType and a set of seed nodes, compute all reachable nodes and wires
1896
- * depends on componentStates to determine if conductivity is allowed through components
1897
- * this method doesn't mutate any state, it's a pure function
1898
- * @param conductivityType
1899
- * @param seeds
1900
- * @param componentStates
1901
- */
1902
- computeReachability(t, e, i) {
1903
- const n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), a = [];
1904
- for (const c of e)
1905
- a.push(c), n.add(c);
1906
- for (; a.length > 0; ) {
1907
- const c = a.shift();
1908
- for (const s of this.circuit.getWiresByNode(c)) {
1909
- const u = s.node1 === c ? s.node2 : s.node1;
1910
- n.has(u) || (n.add(u), a.push(u)), r.has(s.id) || r.add(s.id);
1911
- }
1912
- const h = this.circuit.getENode(c);
1913
- if (h.type === S.Pin) {
1914
- const s = this.circuit.getComponent(h.component), u = this.behaviorRegistry.get(s.type);
1915
- if (!u)
1916
- continue;
1917
- const d = i.get(s.id);
1918
- for (const l of s.pins) {
1919
- if (l === c || n.has(l)) continue;
1920
- u.allowConductivity(
1921
- s,
1922
- d,
1923
- t,
1924
- c,
1925
- l
1926
- ) && (n.add(l), a.push(l));
1927
- }
1928
- }
1929
- }
1930
- return { nodes: n, wires: r };
1931
- }
1932
- /**
1933
- * Fire ready events and update current state accordingly
1934
- * eventual subsequent events are enqueued
1935
- *
1936
- * @param targetTick - Tick at which to process events
1937
- * @param events - Events to apply
1938
- * @param state - Current simulation state
1939
- * @param targetTick - Target tick for event processing
1940
- */
1941
- applyReadyEvents(t) {
1942
- const e = this.stateManager.getCurrentState(), i = this.eventQueue.getReadyEvents(t), n = [];
1943
- for (const r of i) {
1944
- const a = this.circuit.getComponent(r.targetId), c = this.behaviorRegistry.get(a.type);
1945
- if (!c)
1946
- continue;
1947
- const h = e.componentStates.get(a.id), s = c.onEventFiring(a, h, r);
1948
- s.shouldCancelPending && this.eventQueue.removeEventsForTarget(a.id);
1949
- for (const u of s.scheduledEvents)
1950
- this.eventQueue.schedule(u);
1951
- n.push(s);
1952
- }
1953
- return n;
1954
- }
1955
- }
1956
- export {
1957
- W as A,
1958
- M as C,
1959
- U as D,
1960
- v as E,
1961
- T as P,
1962
- C as R,
1963
- F as S,
1964
- $ as T,
1965
- m as a,
1966
- G as b,
1967
- L as c,
1968
- I as d,
1969
- S as e,
1970
- R as f,
1971
- O as g,
1972
- k as h,
1973
- E as i,
1974
- D as j,
1975
- P as k,
1976
- x as l,
1977
- J as m,
1978
- w as n,
1979
- z as s
1980
- };
1981
- //# sourceMappingURL=CircuitRunner-BQQlhwjD.js.map