simple-circuit-engine 0.0.10 → 0.0.11

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.
@@ -1,4 +1,4 @@
1
- class w {
1
+ class m {
2
2
  /**
3
3
  * Create a new 3D position.
4
4
  *
@@ -57,7 +57,7 @@ class w {
57
57
  * ```
58
58
  */
59
59
  static fromJSON(t) {
60
- return new w(t.x, t.y, t.z);
60
+ return new m(t.x, t.y, t.z);
61
61
  }
62
62
  /**
63
63
  * String representation for debugging.
@@ -78,8 +78,8 @@ class M {
78
78
  * @param near - Near clipping plane distance (default: 0.1)
79
79
  * @param far - Far clipping plane distance (default: 1000)
80
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;
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
83
  }
84
84
  /**
85
85
  * Serialize camera options to JSON.
@@ -130,8 +130,8 @@ class M {
130
130
  */
131
131
  static fromJSON(t) {
132
132
  return new M(
133
- w.fromJSON(t.position),
134
- w.fromJSON(t.lookAtPosition),
133
+ m.fromJSON(t.position),
134
+ m.fromJSON(t.lookAtPosition),
135
135
  t.fov,
136
136
  t.near,
137
137
  t.far
@@ -146,266 +146,7 @@ class M {
146
146
  return `CameraOptions(position: ${this.position.toString()}, lookAt: ${this.lookAtPosition.toString()}, fov: ${this.fov}, near: ${this.near}, far: ${this.far})`;
147
147
  }
148
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 {
149
+ class T {
409
150
  /**
410
151
  * Create a new position on the discrete grid.
411
152
  *
@@ -466,7 +207,7 @@ class C {
466
207
  * ```
467
208
  */
468
209
  static fromJSON(t) {
469
- return new C(t.x, t.y);
210
+ return new T(t.x, t.y);
470
211
  }
471
212
  /**
472
213
  * String representation for debugging.
@@ -477,46 +218,46 @@ class C {
477
218
  return `Position(${this.x}, ${this.y})`;
478
219
  }
479
220
  }
480
- function G(r, t, e = 1 / 0) {
481
- if (r.length === 0)
221
+ function R(o, t, e = 1 / 0) {
222
+ if (o.length === 0)
482
223
  return 0;
483
- if (r.length === 1)
224
+ if (o.length === 1)
484
225
  return 1;
485
226
  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);
227
+ for (let n = 0; n < o.length - 1; n++) {
228
+ const r = o[n], a = o[n + 1], c = N(t, r, a);
488
229
  c < e && (e = c, i = n + 1);
489
230
  }
490
231
  return i;
491
232
  }
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);
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);
496
237
  const a = Math.max(
497
238
  0,
498
239
  Math.min(
499
240
  1,
500
- ((r.x - t.x) * i + (r.y - t.y) * n) / s
241
+ ((o.x - t.x) * i + (o.y - t.y) * n) / r
501
242
  )
502
- ), c = t.x + a * i, l = t.y + a * n;
503
- return Math.sqrt((r.x - c) ** 2 + (r.y - l) ** 2);
243
+ ), c = t.x + a * i, h = t.y + a * n;
244
+ return Math.sqrt((o.x - c) ** 2 + (o.y - h) ** 2);
504
245
  }
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;
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;
514
255
  }
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);
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);
517
258
  return Math.abs(n) <= i;
518
259
  }
519
- class k {
260
+ class C {
520
261
  /**
521
262
  * Create a new rotation with the specified angle.
522
263
  *
@@ -556,7 +297,7 @@ class k {
556
297
  * ```
557
298
  */
558
299
  static fromJSON(t) {
559
- return new k(t);
300
+ return new C(t);
560
301
  }
561
302
  /**
562
303
  * Check if this rotation equals another rotation.
@@ -586,196 +327,413 @@ class k {
586
327
  return `Rotation(${this.angle}°)`;
587
328
  }
588
329
  }
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
- );
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];
660
339
  }
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;
340
+ e.push(h);
776
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("");
777
346
  }
778
- class N {
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 {
779
737
  /**
780
738
  * Unique identifier for this ENode.
781
739
  * @readonly
@@ -813,6 +771,11 @@ class N {
813
771
  * Is the ENode a source of voltage or current?
814
772
  */
815
773
  source;
774
+ /**
775
+ * Pin role classification: free, mainVcc, vcc, mainGnd, gnd, logicInput, logicOutput.
776
+ * @readonly
777
+ */
778
+ subtype;
816
779
  /**
817
780
  * Create a new electrical node.
818
781
  *
@@ -825,6 +788,7 @@ class N {
825
788
  * @param position - Grid position (branching points only)
826
789
  * @param source - Source type (Voltage/Current) or undefined
827
790
  *
791
+ * @param subtype
828
792
  * @example
829
793
  * ```typescript
830
794
  * // Pin node (internal to Circuit)
@@ -846,8 +810,8 @@ class N {
846
810
  * );
847
811
  * ```
848
812
  */
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;
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;
851
815
  }
852
816
  /**
853
817
  * Get the position of this electrical node.
@@ -945,7 +909,8 @@ class N {
945
909
  const t = {
946
910
  id: this.id,
947
911
  type: this.type,
948
- source: this.source || null
912
+ source: this.source || null,
913
+ subtype: this.subtype
949
914
  };
950
915
  return this.type === S.Pin ? (t.component = this.component || null, t.pinLabel = this.pinLabel || null) : t.position = this.position?.toJSON() || null, t;
951
916
  }
@@ -968,7 +933,14 @@ class N {
968
933
  * ```
969
934
  */
970
935
  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);
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
+ );
972
944
  return Object.defineProperty(i, "id", {
973
945
  value: t.id,
974
946
  writable: !1,
@@ -977,207 +949,289 @@ class N {
977
949
  }), i;
978
950
  }
979
951
  }
980
- class b {
952
+ class E {
981
953
  /**
982
- * Current simulation step number (starts at 0).
954
+ * Unique identifier for this component.
983
955
  * @readonly
984
956
  */
985
- tick;
957
+ id;
986
958
  /**
987
- * Electrical state for each ENode (component pins and branching points).
988
- * Key: ENode UUID, Value: NodeElectricalState
959
+ * Component type (Battery, Switch, LED, etc.).
989
960
  * @readonly
990
961
  */
991
- nodeStates;
962
+ type;
992
963
  /**
993
- * Electrical state for each Wire connecting ENodes.
994
- * Key: Wire UUID, Value: NodeElectricalState
964
+ * Position on the 2D discrete grid.
995
965
  * @readonly
996
966
  */
997
- wireStates;
967
+ position;
998
968
  /**
999
- * Component-specific state for each component.
1000
- * Key: Component UUID, Value: ComponentState subclass
969
+ * Orientation angle in degrees.
1001
970
  * @readonly
1002
971
  */
1003
- componentStates;
972
+ rotation;
1004
973
  /**
1005
- * Create a new simulation state snapshot.
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.
1006
984
  *
1007
- * @param tick - Current simulation step number
1008
985
  */
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
- }
986
+ config;
1017
987
  /**
1018
- * Create a deep copy of this state for historical storage.
988
+ * allow to flag a component as non editable (feature to implement)
989
+ */
990
+ editable;
991
+ /**
992
+ * Create a new component.
1019
993
  *
1020
- * @returns Cloned SimulationState
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
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)
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(", ")}`
1034
1027
  );
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;
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);
1051
1043
  }
1052
- }
1053
- class z {
1054
- currentState;
1055
- history;
1056
- historyEnabled;
1057
- historyLimit;
1058
- historyWriteIndex;
1059
1044
  /**
1060
- * Create a new state controllerType.
1045
+ * Update the component's position.
1061
1046
  *
1062
- * @param enableHistory - Whether to store state history (default: false)
1063
- * @param historyLimit - Maximum number of historical states to keep (default: 1000)
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
+ * ```
1064
1054
  */
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;
1055
+ setPosition(t) {
1056
+ Object.defineProperty(this, "position", {
1057
+ value: t,
1058
+ writable: !1,
1059
+ enumerable: !0,
1060
+ configurable: !0
1061
+ });
1069
1062
  }
1070
1063
  /**
1071
- * Get the current simulation state.
1064
+ * Update the component's rotation.
1072
1065
  *
1073
- * @returns Current state (mutable for simulation controller use)
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
+ * ```
1074
1073
  */
1075
- getCurrentState() {
1076
- return this.currentState;
1074
+ setRotation(t) {
1075
+ Object.defineProperty(this, "rotation", {
1076
+ value: t,
1077
+ writable: !1,
1078
+ enumerable: !0,
1079
+ configurable: !0
1080
+ });
1077
1081
  }
1078
1082
  /**
1079
- * Get current tick number.
1083
+ * Serialize component to JSON.
1080
1084
  *
1081
- * @returns Current simulation tick
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
+ * ```
1082
1099
  */
1083
- getCurrentTick() {
1084
- return this.currentState.tick;
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
+ };
1085
1110
  }
1086
1111
  /**
1087
- * Advance to next tick, optionally saving current state to history.
1088
- * Creates a new SimulationState for the next tick.
1112
+ * Deserialize component from JSON.
1113
+ *
1114
+ * @param json - Component data
1115
+ * @returns Component instance
1089
1116
  *
1090
- * @returns New current state for the next tick
1091
1117
  */
1092
- advanceToNextTick() {
1093
- const t = this.currentState.tick + 1;
1094
- return this.historyEnabled && this.saveToHistory(this.currentState.clone()), this.currentState.tick = t, this.currentState;
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;
1095
1132
  }
1133
+ }
1134
+ const F = {
1096
1135
  /**
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
1136
+ * Minimum simulation speed in ticks per second
1102
1137
  */
1103
- getStateAtTick(t) {
1104
- if (this.historyEnabled)
1105
- return this.history.find((e) => e.tick === t);
1106
- }
1138
+ MIN_TPS: 1,
1107
1139
  /**
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)
1140
+ * Maximum simulation speed in ticks per second
1112
1141
  */
1113
- getHistory() {
1114
- return this.historyEnabled ? [...this.history].sort((t, e) => t.tick - e.tick) : [];
1115
- }
1142
+ MAX_TPS: 50,
1116
1143
  /**
1117
- * Get the oldest tick number available in history.
1118
- *
1119
- * @returns Oldest tick number, or undefined if no history
1144
+ * Default simulation speed in ticks per second
1120
1145
  */
1121
- getOldestTick() {
1122
- if (!(!this.historyEnabled || this.history.length === 0))
1123
- return Math.min(...this.history.map((t) => t.tick));
1124
- }
1146
+ DEFAULT_TPS: 3,
1125
1147
  /**
1126
- * Get the newest tick number in history (not including current tick).
1127
- *
1128
- * @returns Newest historical tick, or undefined if no history
1148
+ * Default tick interval in milliseconds (1000 / DEFAULT_TPS)
1129
1149
  */
1130
- getNewestHistoricalTick() {
1131
- if (!(!this.historyEnabled || this.history.length === 0))
1132
- return Math.max(...this.history.map((t) => t.tick));
1133
- }
1150
+ DEFAULT_INTERVAL_MS: 500
1151
+ }, $ = {
1134
1152
  /**
1135
- * Clear all history.
1153
+ * Default transitionSpan for relays and transistors in ticks (instant transition)
1136
1154
  */
1137
- clearHistory() {
1138
- this.history = [], this.historyWriteIndex = 0;
1139
- }
1155
+ TRANSITION_SPAN_TICKS: 1,
1140
1156
  /**
1141
- * Reset to tick 0, clearing current state and all history.
1157
+ * Default transitionUserSpan for switches in milliseconds
1142
1158
  */
1143
- reset() {
1144
- this.currentState = new b(0), this.clearHistory();
1145
- }
1159
+ TRANSITION_USER_SPAN_MS: 200
1160
+ };
1161
+ class w {
1146
1162
  /**
1147
- * Check if history tracking is enabled.
1148
- *
1149
- * @returns True if history is enabled
1163
+ * Current simulation step number (starts at 0).
1164
+ * @readonly
1150
1165
  */
1151
- isHistoryEnabled() {
1152
- return this.historyEnabled;
1153
- }
1166
+ tick;
1154
1167
  /**
1155
- * Get the configured history limit.
1156
- *
1157
- * @returns Maximum number of historical states
1168
+ * Electrical state for each ENode (component pins and branching points).
1169
+ * Key: ENode UUID, Value: INodeElectricalState
1170
+ * @readonly
1158
1171
  */
1159
- getHistoryLimit() {
1160
- return this.historyLimit;
1161
- }
1172
+ nodeStates;
1162
1173
  /**
1163
- * Get current history size.
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.
1164
1187
  *
1165
- * @returns Number of states in history
1188
+ * @param tick - Current simulation step number
1166
1189
  */
1167
- getHistorySize() {
1168
- return this.history.length;
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;
1169
1197
  }
1170
1198
  /**
1171
- * Save a state to history using circular buffer.
1172
- * Private helper for advanceToNextTick.
1199
+ * Create a deep copy of this state for historical storage.
1173
1200
  *
1174
- * @param state - State to save
1201
+ * @returns Cloned SimulationState
1175
1202
  */
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);
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;
1178
1232
  }
1179
1233
  }
1180
- class L {
1234
+ class D {
1181
1235
  heap;
1182
1236
  /**
1183
1237
  * Create a new empty event queue.
@@ -1228,6 +1282,17 @@ class L {
1228
1282
  clear() {
1229
1283
  this.heap = [];
1230
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
+ }
1231
1296
  /**
1232
1297
  * Get number of pending events.
1233
1298
  *
@@ -1236,6 +1301,10 @@ class L {
1236
1301
  size() {
1237
1302
  return this.heap.length;
1238
1303
  }
1304
+ rebuildHeap() {
1305
+ for (let t = Math.floor(this.heap.length / 2) - 1; t >= 0; t--)
1306
+ this.bubbleDown(t);
1307
+ }
1239
1308
  bubbleUp(t) {
1240
1309
  for (; t > 0; ) {
1241
1310
  const e = Math.floor((t - 1) / 2);
@@ -1249,9 +1318,9 @@ class L {
1249
1318
  const e = this.heap.length;
1250
1319
  for (; ; ) {
1251
1320
  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;
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;
1255
1324
  else
1256
1325
  break;
1257
1326
  }
@@ -1263,7 +1332,7 @@ class L {
1263
1332
  return this.heap.length > 0 && e && (this.heap[0] = e, this.bubbleDown(0)), t;
1264
1333
  }
1265
1334
  }
1266
- class R {
1335
+ class P {
1267
1336
  dirtyComponents;
1268
1337
  dirtyWires;
1269
1338
  dirtyEnodes;
@@ -1371,34 +1440,134 @@ class R {
1371
1440
  return this.dirtyEnodes.size;
1372
1441
  }
1373
1442
  }
1374
- const $ = {
1443
+ class x {
1444
+ currentState;
1445
+ history;
1446
+ historyEnabled;
1447
+ historyLimit;
1448
+ historyWriteIndex;
1375
1449
  /**
1376
- * Minimum simulation speed in ticks per second
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)
1377
1454
  */
1378
- MIN_TPS: 1,
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
+ }
1379
1460
  /**
1380
- * Maximum simulation speed in ticks per second
1461
+ * Get the current simulation state.
1462
+ *
1463
+ * @returns Current state (mutable for simulation controller use)
1381
1464
  */
1382
- MAX_TPS: 50,
1465
+ getCurrentState() {
1466
+ return this.currentState;
1467
+ }
1383
1468
  /**
1384
- * Default simulation speed in ticks per second
1469
+ * Get current tick number.
1470
+ *
1471
+ * @returns Current simulation tick
1385
1472
  */
1386
- DEFAULT_TPS: 3,
1473
+ getCurrentTick() {
1474
+ return this.currentState.tick;
1475
+ }
1387
1476
  /**
1388
- * Default tick interval in milliseconds (1000 / DEFAULT_TPS)
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
1389
1481
  */
1390
- DEFAULT_INTERVAL_MS: 500
1391
- }, J = {
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
+ }
1392
1486
  /**
1393
- * Default transitionSpan for relays and transistors in ticks (instant transition)
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
1394
1492
  */
1395
- TRANSITION_SPAN_TICKS: 1,
1493
+ getStateAtTick(t) {
1494
+ if (this.historyEnabled)
1495
+ return this.history.find((e) => e.tick === t);
1496
+ }
1396
1497
  /**
1397
- * Default transitionUserSpan for switches in milliseconds
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)
1398
1502
  */
1399
- TRANSITION_USER_SPAN_MS: 200
1400
- };
1401
- class U {
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 {
1402
1571
  circuit;
1403
1572
  stateManager;
1404
1573
  eventQueue;
@@ -1414,8 +1583,8 @@ class U {
1414
1583
  */
1415
1584
  constructor(t, e, i = {}) {
1416
1585
  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();
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();
1419
1588
  try {
1420
1589
  this.initializeState();
1421
1590
  } catch (a) {
@@ -1431,8 +1600,8 @@ class U {
1431
1600
  tick() {
1432
1601
  const t = this.eventQueue.size(), e = this.stateManager.getCurrentTick(), i = this.applyReadyEvents(e + 1), n = this.updateState(e + 1);
1433
1602
  n.firedEventCount = i.length;
1434
- const s = this.processCommands();
1435
- n.processedCommandCount = s.length, n.scheduledEventCount = this.eventQueue.size() + n.firedEventCount - t;
1603
+ const r = this.processCommands();
1604
+ n.processedCommandCount = r.length, n.scheduledEventCount = this.eventQueue.size() + n.firedEventCount - t;
1436
1605
  for (const a of i)
1437
1606
  a.hasChanged && this.dirtyTracker.markComponentDirty(a.componentState.componentId);
1438
1607
  return n.componentUpdateCount = this.dirtyTracker.getDirtyComponentCount(), this.stateManager.advanceToNextTick(), n.endTick = this.stateManager.getCurrentTick(), n;
@@ -1441,7 +1610,7 @@ class U {
1441
1610
  * Execute multiple simulation ticks.
1442
1611
  *
1443
1612
  * @param count - Number of ticks to execute
1444
- * @returns an array of RunnerResult for each tick executed
1613
+ * @returns an array of IRunnerResult for each tick executed
1445
1614
  */
1446
1615
  tickN(t) {
1447
1616
  if (t < 1)
@@ -1537,7 +1706,7 @@ class U {
1537
1706
  * Mark changed components as Dirty and enqueue consequent scheduled events
1538
1707
  * Finally clears command queue after processing.
1539
1708
  *
1540
- * @returns Array of BehaviorResult for each processed command
1709
+ * @returns Array of IBehaviorResult for each processed command
1541
1710
  */
1542
1711
  processCommands() {
1543
1712
  const t = this.stateManager.getCurrentState(), e = [];
@@ -1547,6 +1716,7 @@ class U {
1547
1716
  t.componentStates.get(n.id),
1548
1717
  i
1549
1718
  );
1719
+ a.shouldCancelPending && this.eventQueue.removeEventsForTarget(n.id);
1550
1720
  for (const c of a.scheduledEvents)
1551
1721
  this.eventQueue.schedule(c);
1552
1722
  e.push(a), a.hasChanged && this.dirtyTracker.markComponentDirty(n.id);
@@ -1581,70 +1751,70 @@ class U {
1581
1751
  */
1582
1752
  initializeState() {
1583
1753
  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)
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)
1588
1758
  continue;
1589
- const u = h.createInitialState(o);
1590
- t.componentStates.set(o.id, u), this.dirtyTracker.markComponentDirty(o.id);
1759
+ const d = u.createInitialState(s);
1760
+ t.componentStates.set(s.id, d), this.dirtyTracker.markComponentDirty(s.id);
1591
1761
  }
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
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
1597
1767
  });
1598
- for (const o of this.circuit.getAllWires())
1599
- t.wireStates.set(o.id, {
1768
+ for (const s of this.circuit.getAllWires())
1769
+ t.wireStates.set(s.id, {
1600
1770
  hasVoltage: !1,
1601
1771
  hasCurrent: !1,
1602
1772
  locked: !1
1603
1773
  });
1604
1774
  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);
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);
1608
1778
  }
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;
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;
1613
1783
  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);
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);
1622
1792
  if (!g) continue;
1623
1793
  this.propagateConductivity();
1624
- const m = p.onPinsChange(
1625
- u,
1794
+ const b = l.onPinsChange(
1795
+ d,
1626
1796
  g,
1627
1797
  t.nodeStates,
1628
1798
  0
1629
1799
  );
1630
- m.hasChanged && (s = !0, t.componentStates.set(
1631
- u.id,
1632
- m.componentState
1800
+ b.hasChanged && (r = !0, t.componentStates.set(
1801
+ d.id,
1802
+ b.componentState
1633
1803
  ));
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
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
1639
1809
  ));
1640
1810
  }
1641
1811
  }
1642
1812
  }
1643
1813
  }
1644
- const l = this.updateState(0);
1814
+ const h = this.updateState(0);
1645
1815
  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;
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;
1648
1818
  }
1649
1819
  /**
1650
1820
  * Core method that orchestrates nodes, wires and components state updates
@@ -1652,24 +1822,24 @@ class U {
1652
1822
  * @param targetTick - Tick at which to perform the update
1653
1823
  */
1654
1824
  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);
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);
1660
1830
  }));
1661
- for (const o of l) {
1662
- const h = this.circuit.getComponent(o), u = this.behaviorRegistry.get(h.type);
1663
- if (!u)
1831
+ for (const s of h) {
1832
+ const u = this.circuit.getComponent(s), d = this.behaviorRegistry.get(u.type);
1833
+ if (!d)
1664
1834
  continue;
1665
- const p = u.onPinsChange(
1666
- h,
1667
- e.componentStates.get(o),
1835
+ const l = d.onPinsChange(
1836
+ u,
1837
+ e.componentStates.get(s),
1668
1838
  e.nodeStates,
1669
1839
  t
1670
1840
  );
1671
- p.hasChanged && a.add(o);
1672
- for (const g of p.scheduledEvents)
1841
+ l.shouldCancelPending && this.eventQueue.removeEventsForTarget(s), l.hasChanged && a.add(s);
1842
+ for (const g of l.scheduledEvents)
1673
1843
  this.eventQueue.schedule(g), c++;
1674
1844
  }
1675
1845
  return this.dirtyTracker.setDirtyComponents(a), this.dirtyTracker.setDirtyEnodes(i), this.dirtyTracker.setDirtyWires(n), {
@@ -1691,33 +1861,33 @@ class U {
1691
1861
  */
1692
1862
  propagateConductivity() {
1693
1863
  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(
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(
1697
1867
  c,
1698
- h,
1868
+ u,
1699
1869
  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));
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));
1704
1874
  }
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));
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));
1708
1878
  }
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));
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));
1712
1882
  }
1713
- for (const d of p) {
1714
- const f = t.wireStates.get(d);
1715
- f && f[y] && (f[y] = !1, o.add(d));
1883
+ for (const p of l) {
1884
+ const y = t.wireStates.get(p);
1885
+ y && y[f] && (y[f] = !1, s.add(p));
1716
1886
  }
1717
- return { updatedNodes: l, updatedWires: o };
1718
- }, { updatedNodes: i, updatedWires: n } = e(v.Voltage), { updatedNodes: s, updatedWires: a } = e(v.Current);
1887
+ return { updatedNodes: h, updatedWires: s };
1888
+ }, { updatedNodes: i, updatedWires: n } = e(v.Voltage), { updatedNodes: r, updatedWires: a } = e(v.Current);
1719
1889
  return {
1720
- updatedNodes: /* @__PURE__ */ new Set([...i, ...s]),
1890
+ updatedNodes: /* @__PURE__ */ new Set([...i, ...r]),
1721
1891
  updatedWires: /* @__PURE__ */ new Set([...n, ...a])
1722
1892
  };
1723
1893
  }
@@ -1730,34 +1900,34 @@ class U {
1730
1900
  * @param componentStates
1731
1901
  */
1732
1902
  computeReachability(t, e, i) {
1733
- const n = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), a = [];
1903
+ const n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), a = [];
1734
1904
  for (const c of e)
1735
1905
  a.push(c), n.add(c);
1736
1906
  for (; a.length > 0; ) {
1737
1907
  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);
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);
1741
1911
  }
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)
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)
1746
1916
  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,
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,
1753
1923
  t,
1754
1924
  c,
1755
- p
1756
- ) && (n.add(p), a.push(p));
1925
+ l
1926
+ ) && (n.add(l), a.push(l));
1757
1927
  }
1758
1928
  }
1759
1929
  }
1760
- return { nodes: n, wires: s };
1930
+ return { nodes: n, wires: r };
1761
1931
  }
1762
1932
  /**
1763
1933
  * Fire ready events and update current state accordingly
@@ -1770,40 +1940,42 @@ class U {
1770
1940
  */
1771
1941
  applyReadyEvents(t) {
1772
1942
  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);
1943
+ for (const r of i) {
1944
+ const a = this.circuit.getComponent(r.targetId), c = this.behaviorRegistry.get(a.type);
1775
1945
  if (!c)
1776
1946
  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);
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);
1781
1952
  }
1782
1953
  return n;
1783
1954
  }
1784
1955
  }
1785
1956
  export {
1957
+ W as A,
1786
1958
  M as C,
1787
- R as D,
1959
+ U as D,
1788
1960
  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
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
1808
1980
  };
1809
- //# sourceMappingURL=CircuitRunner-DEb7JdNf.js.map
1981
+ //# sourceMappingURL=CircuitRunner-BQQlhwjD.js.map