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