simple-circuit-engine 0.0.8 → 0.0.10
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.
- package/AGENTS.md +19 -11
- package/CLAUDE.md +4 -3
- package/README.md +4 -4
- package/dist/{CircuitRunner-FXM_s5ll.js → CircuitRunner-DEb7JdNf.js} +543 -211
- package/dist/CircuitRunner-DEb7JdNf.js.map +1 -0
- package/dist/core/index.js +923 -604
- package/dist/core/index.js.map +1 -1
- package/dist/index.d.ts +779 -140
- package/dist/index.js +96 -68
- package/dist/scene/index.d.ts +3 -2
- package/dist/scene/index.js +37 -26
- package/dist/{setup-aoI3UTB5.js → setup-AB1vFiis.js} +3176 -1571
- package/dist/setup-AB1vFiis.js.map +1 -0
- package/package.json +1 -1
- package/dist/CircuitRunner-FXM_s5ll.js.map +0 -1
- package/dist/setup-aoI3UTB5.js.map +0 -1
|
@@ -6,8 +6,8 @@ class w {
|
|
|
6
6
|
* @param y - Y coordinate
|
|
7
7
|
* @param z - Z coordinate
|
|
8
8
|
*/
|
|
9
|
-
constructor(t, e,
|
|
10
|
-
this.x = t, this.y = e, this.z =
|
|
9
|
+
constructor(t, e, i) {
|
|
10
|
+
this.x = t, this.y = e, this.z = i;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Check if this position equals another position.
|
|
@@ -68,7 +68,7 @@ class w {
|
|
|
68
68
|
return `Position(${this.x}, ${this.y}, ${this.z})`;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
class
|
|
71
|
+
class M {
|
|
72
72
|
/**
|
|
73
73
|
* Create new camera options.
|
|
74
74
|
*
|
|
@@ -78,8 +78,8 @@ class k {
|
|
|
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),
|
|
82
|
-
this.position = t, this.lookAtPosition = e, this.fov =
|
|
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
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Serialize camera options to JSON.
|
|
@@ -129,7 +129,7 @@ class k {
|
|
|
129
129
|
* ```
|
|
130
130
|
*/
|
|
131
131
|
static fromJSON(t) {
|
|
132
|
-
return new
|
|
132
|
+
return new M(
|
|
133
133
|
w.fromJSON(t.position),
|
|
134
134
|
w.fromJSON(t.lookAtPosition),
|
|
135
135
|
t.fov,
|
|
@@ -146,8 +146,8 @@ class k {
|
|
|
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
|
|
150
|
-
const
|
|
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
151
|
switch: {
|
|
152
152
|
id: "switch",
|
|
153
153
|
name: "Switch",
|
|
@@ -164,8 +164,8 @@ const E = {
|
|
|
164
164
|
id: "battery",
|
|
165
165
|
name: "Battery",
|
|
166
166
|
pins: /* @__PURE__ */ new Map([
|
|
167
|
-
["cathode",
|
|
168
|
-
["anode",
|
|
167
|
+
["cathode", v.Voltage],
|
|
168
|
+
["anode", v.Current]
|
|
169
169
|
]),
|
|
170
170
|
config: /* @__PURE__ */ new Map([])
|
|
171
171
|
},
|
|
@@ -205,6 +205,19 @@ const E = {
|
|
|
205
205
|
["initializationOrder", ""]
|
|
206
206
|
])
|
|
207
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
|
+
},
|
|
208
221
|
smallLED: {
|
|
209
222
|
id: "smallLED",
|
|
210
223
|
name: "SmallLED",
|
|
@@ -250,33 +263,149 @@ const E = {
|
|
|
250
263
|
["text", "Label"],
|
|
251
264
|
["size", "1"]
|
|
252
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
|
+
])
|
|
253
382
|
}
|
|
254
383
|
};
|
|
255
|
-
function
|
|
256
|
-
return Object.values(
|
|
384
|
+
function x() {
|
|
385
|
+
return Object.values(E);
|
|
257
386
|
}
|
|
258
|
-
function
|
|
259
|
-
return
|
|
387
|
+
function I(r) {
|
|
388
|
+
return O[r];
|
|
260
389
|
}
|
|
261
|
-
var
|
|
262
|
-
function
|
|
390
|
+
var S = /* @__PURE__ */ ((r) => (r.Pin = "Pin", r.BranchingPoint = "BranchingPoint", r))(S || {});
|
|
391
|
+
function T() {
|
|
263
392
|
if (typeof crypto < "u" && crypto.randomUUID)
|
|
264
393
|
return crypto.randomUUID();
|
|
265
|
-
const
|
|
394
|
+
const r = "0123456789abcdef", t = [8, 4, 4, 4, 12], e = [];
|
|
266
395
|
for (const c of t) {
|
|
267
396
|
let l = "";
|
|
268
|
-
for (let
|
|
397
|
+
for (let o = 0; o < c; o++) {
|
|
269
398
|
const h = Math.floor(Math.random() * 16);
|
|
270
|
-
l +=
|
|
399
|
+
l += r[h];
|
|
271
400
|
}
|
|
272
401
|
e.push(l);
|
|
273
402
|
}
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
const a = parseInt(
|
|
277
|
-
return
|
|
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("");
|
|
278
407
|
}
|
|
279
|
-
class
|
|
408
|
+
class C {
|
|
280
409
|
/**
|
|
281
410
|
* Create a new position on the discrete grid.
|
|
282
411
|
*
|
|
@@ -337,7 +466,7 @@ class v {
|
|
|
337
466
|
* ```
|
|
338
467
|
*/
|
|
339
468
|
static fromJSON(t) {
|
|
340
|
-
return new
|
|
469
|
+
return new C(t.x, t.y);
|
|
341
470
|
}
|
|
342
471
|
/**
|
|
343
472
|
* String representation for debugging.
|
|
@@ -348,46 +477,46 @@ class v {
|
|
|
348
477
|
return `Position(${this.x}, ${this.y})`;
|
|
349
478
|
}
|
|
350
479
|
}
|
|
351
|
-
function
|
|
352
|
-
if (
|
|
480
|
+
function G(r, t, e = 1 / 0) {
|
|
481
|
+
if (r.length === 0)
|
|
353
482
|
return 0;
|
|
354
|
-
if (
|
|
483
|
+
if (r.length === 1)
|
|
355
484
|
return 1;
|
|
356
|
-
let
|
|
357
|
-
for (let
|
|
358
|
-
const
|
|
359
|
-
c < e && (e = c,
|
|
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);
|
|
360
489
|
}
|
|
361
|
-
return
|
|
490
|
+
return i;
|
|
362
491
|
}
|
|
363
|
-
function
|
|
364
|
-
const
|
|
365
|
-
if (
|
|
366
|
-
return Math.sqrt((
|
|
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);
|
|
367
496
|
const a = Math.max(
|
|
368
497
|
0,
|
|
369
498
|
Math.min(
|
|
370
499
|
1,
|
|
371
|
-
((
|
|
500
|
+
((r.x - t.x) * i + (r.y - t.y) * n) / s
|
|
372
501
|
)
|
|
373
|
-
), c = t.x + a *
|
|
374
|
-
return Math.sqrt((
|
|
502
|
+
), c = t.x + a * i, l = t.y + a * n;
|
|
503
|
+
return Math.sqrt((r.x - c) ** 2 + (r.y - l) ** 2);
|
|
375
504
|
}
|
|
376
|
-
function
|
|
377
|
-
if (
|
|
378
|
-
return [...
|
|
379
|
-
const e = [
|
|
380
|
-
for (let
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
return e.push(
|
|
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;
|
|
385
514
|
}
|
|
386
|
-
function
|
|
387
|
-
const
|
|
388
|
-
return Math.abs(
|
|
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;
|
|
389
518
|
}
|
|
390
|
-
class
|
|
519
|
+
class k {
|
|
391
520
|
/**
|
|
392
521
|
* Create a new rotation with the specified angle.
|
|
393
522
|
*
|
|
@@ -427,7 +556,7 @@ class C {
|
|
|
427
556
|
* ```
|
|
428
557
|
*/
|
|
429
558
|
static fromJSON(t) {
|
|
430
|
-
return new
|
|
559
|
+
return new k(t);
|
|
431
560
|
}
|
|
432
561
|
/**
|
|
433
562
|
* Check if this rotation equals another rotation.
|
|
@@ -522,21 +651,21 @@ class A {
|
|
|
522
651
|
* );
|
|
523
652
|
* ```
|
|
524
653
|
*/
|
|
525
|
-
constructor(t, e,
|
|
526
|
-
if (this.id =
|
|
527
|
-
const
|
|
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);
|
|
528
657
|
throw new Error(
|
|
529
|
-
`Duplicate pin names are not allowed: ${[...new Set(
|
|
658
|
+
`Duplicate pin names are not allowed: ${[...new Set(s)].join(", ")}`
|
|
530
659
|
);
|
|
531
660
|
}
|
|
532
|
-
this.pins =
|
|
661
|
+
this.pins = n, this.config = new Map(O[t].config);
|
|
533
662
|
}
|
|
534
663
|
getPinLabel(t) {
|
|
535
664
|
const e = this.pins.indexOf(t);
|
|
536
665
|
if (e === -1)
|
|
537
666
|
return;
|
|
538
|
-
const
|
|
539
|
-
return Array.from(
|
|
667
|
+
const i = I(this.type).pins.keys();
|
|
668
|
+
return Array.from(i)[e] || void 0;
|
|
540
669
|
}
|
|
541
670
|
setAllParameters(t) {
|
|
542
671
|
this.config = new Map(t);
|
|
@@ -634,8 +763,8 @@ class A {
|
|
|
634
763
|
static fromJSON(t) {
|
|
635
764
|
const e = new A(
|
|
636
765
|
t.type,
|
|
637
|
-
|
|
638
|
-
|
|
766
|
+
C.fromJSON(t.position),
|
|
767
|
+
k.fromJSON(t.rotation),
|
|
639
768
|
t.pins
|
|
640
769
|
);
|
|
641
770
|
return e.config = new Map(Object.entries(t.config)), Object.defineProperty(e, "id", {
|
|
@@ -646,6 +775,208 @@ class A {
|
|
|
646
775
|
}), e;
|
|
647
776
|
}
|
|
648
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
|
+
}
|
|
649
980
|
class b {
|
|
650
981
|
/**
|
|
651
982
|
* Current simulation step number (starts at 0).
|
|
@@ -690,15 +1021,15 @@ class b {
|
|
|
690
1021
|
*/
|
|
691
1022
|
clone() {
|
|
692
1023
|
const t = new b(this.tick), e = /* @__PURE__ */ new Map();
|
|
693
|
-
for (const [
|
|
694
|
-
e.set(
|
|
695
|
-
const r = /* @__PURE__ */ new Map();
|
|
696
|
-
for (const [o, a] of this.wireStates.entries())
|
|
697
|
-
r.set(o, { ...a });
|
|
1024
|
+
for (const [s, a] of this.nodeStates.entries())
|
|
1025
|
+
e.set(s, { ...a });
|
|
698
1026
|
const i = /* @__PURE__ */ new Map();
|
|
699
|
-
for (const [
|
|
700
|
-
i.set(
|
|
701
|
-
|
|
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,
|
|
702
1033
|
Object.assign(Object.create(Object.getPrototypeOf(a)), a)
|
|
703
1034
|
);
|
|
704
1035
|
return Object.defineProperty(t, "nodeStates", {
|
|
@@ -707,19 +1038,19 @@ class b {
|
|
|
707
1038
|
configurable: !1,
|
|
708
1039
|
enumerable: !0
|
|
709
1040
|
}), Object.defineProperty(t, "wireStates", {
|
|
710
|
-
value:
|
|
1041
|
+
value: i,
|
|
711
1042
|
writable: !1,
|
|
712
1043
|
configurable: !1,
|
|
713
1044
|
enumerable: !0
|
|
714
1045
|
}), Object.defineProperty(t, "componentStates", {
|
|
715
|
-
value:
|
|
1046
|
+
value: n,
|
|
716
1047
|
writable: !1,
|
|
717
1048
|
configurable: !1,
|
|
718
1049
|
enumerable: !0
|
|
719
1050
|
}), t;
|
|
720
1051
|
}
|
|
721
1052
|
}
|
|
722
|
-
class
|
|
1053
|
+
class z {
|
|
723
1054
|
currentState;
|
|
724
1055
|
history;
|
|
725
1056
|
historyEnabled;
|
|
@@ -846,7 +1177,7 @@ class R {
|
|
|
846
1177
|
this.history.length < this.historyLimit ? this.history.push(t) : (this.history[this.historyWriteIndex] = t, this.historyWriteIndex = (this.historyWriteIndex + 1) % this.historyLimit);
|
|
847
1178
|
}
|
|
848
1179
|
}
|
|
849
|
-
class
|
|
1180
|
+
class L {
|
|
850
1181
|
heap;
|
|
851
1182
|
/**
|
|
852
1183
|
* Create a new empty event queue.
|
|
@@ -878,10 +1209,10 @@ class x {
|
|
|
878
1209
|
getReadyEvents(t) {
|
|
879
1210
|
const e = [];
|
|
880
1211
|
for (; this.heap.length > 0 && this.heap[0].readyAtTick <= t; ) {
|
|
881
|
-
const
|
|
882
|
-
|
|
1212
|
+
const i = this.extractMin();
|
|
1213
|
+
i && e.push(i);
|
|
883
1214
|
}
|
|
884
|
-
return e.sort((
|
|
1215
|
+
return e.sort((i, n) => i.readyAtTick === n.readyAtTick ? i.scheduledAtTick - n.scheduledAtTick : i.readyAtTick - n.readyAtTick), e;
|
|
885
1216
|
}
|
|
886
1217
|
/**
|
|
887
1218
|
* Check if any events are pending.
|
|
@@ -917,10 +1248,10 @@ class x {
|
|
|
917
1248
|
bubbleDown(t) {
|
|
918
1249
|
const e = this.heap.length;
|
|
919
1250
|
for (; ; ) {
|
|
920
|
-
const
|
|
921
|
-
let
|
|
922
|
-
if (
|
|
923
|
-
[this.heap[t], this.heap[
|
|
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;
|
|
924
1255
|
else
|
|
925
1256
|
break;
|
|
926
1257
|
}
|
|
@@ -932,7 +1263,7 @@ class x {
|
|
|
932
1263
|
return this.heap.length > 0 && e && (this.heap[0] = e, this.bubbleDown(0)), t;
|
|
933
1264
|
}
|
|
934
1265
|
}
|
|
935
|
-
class
|
|
1266
|
+
class R {
|
|
936
1267
|
dirtyComponents;
|
|
937
1268
|
dirtyWires;
|
|
938
1269
|
dirtyEnodes;
|
|
@@ -1040,7 +1371,7 @@ class P {
|
|
|
1040
1371
|
return this.dirtyEnodes.size;
|
|
1041
1372
|
}
|
|
1042
1373
|
}
|
|
1043
|
-
const
|
|
1374
|
+
const $ = {
|
|
1044
1375
|
/**
|
|
1045
1376
|
* Minimum simulation speed in ticks per second
|
|
1046
1377
|
*/
|
|
@@ -1057,7 +1388,7 @@ const U = {
|
|
|
1057
1388
|
* Default tick interval in milliseconds (1000 / DEFAULT_TPS)
|
|
1058
1389
|
*/
|
|
1059
1390
|
DEFAULT_INTERVAL_MS: 500
|
|
1060
|
-
},
|
|
1391
|
+
}, J = {
|
|
1061
1392
|
/**
|
|
1062
1393
|
* Default transitionSpan for relays and transistors in ticks (instant transition)
|
|
1063
1394
|
*/
|
|
@@ -1067,7 +1398,7 @@ const U = {
|
|
|
1067
1398
|
*/
|
|
1068
1399
|
TRANSITION_USER_SPAN_MS: 200
|
|
1069
1400
|
};
|
|
1070
|
-
class
|
|
1401
|
+
class U {
|
|
1071
1402
|
circuit;
|
|
1072
1403
|
stateManager;
|
|
1073
1404
|
eventQueue;
|
|
@@ -1081,10 +1412,10 @@ class J {
|
|
|
1081
1412
|
* @param behaviorRegistry - Registry of component behaviors
|
|
1082
1413
|
* @param options - Simulation options (history settings)
|
|
1083
1414
|
*/
|
|
1084
|
-
constructor(t, e,
|
|
1415
|
+
constructor(t, e, i = {}) {
|
|
1085
1416
|
this.circuit = t, this.behaviorRegistry = e;
|
|
1086
|
-
const
|
|
1087
|
-
this.stateManager = new
|
|
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();
|
|
1088
1419
|
try {
|
|
1089
1420
|
this.initializeState();
|
|
1090
1421
|
} catch (a) {
|
|
@@ -1098,13 +1429,13 @@ class J {
|
|
|
1098
1429
|
* @returns the result of the tick execution
|
|
1099
1430
|
*/
|
|
1100
1431
|
tick() {
|
|
1101
|
-
const t = this.eventQueue.size(), e = this.stateManager.getCurrentTick(),
|
|
1102
|
-
|
|
1103
|
-
const
|
|
1104
|
-
|
|
1105
|
-
for (const a of
|
|
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)
|
|
1106
1437
|
a.hasChanged && this.dirtyTracker.markComponentDirty(a.componentState.componentId);
|
|
1107
|
-
return
|
|
1438
|
+
return n.componentUpdateCount = this.dirtyTracker.getDirtyComponentCount(), this.stateManager.advanceToNextTick(), n.endTick = this.stateManager.getCurrentTick(), n;
|
|
1108
1439
|
}
|
|
1109
1440
|
/**
|
|
1110
1441
|
* Execute multiple simulation ticks.
|
|
@@ -1116,7 +1447,7 @@ class J {
|
|
|
1116
1447
|
if (t < 1)
|
|
1117
1448
|
throw new RangeError(`Tick count must be at least 1 (got ${t})`);
|
|
1118
1449
|
const e = [];
|
|
1119
|
-
for (let
|
|
1450
|
+
for (let i = 0; i < t; i++)
|
|
1120
1451
|
e.push(this.tick());
|
|
1121
1452
|
return e;
|
|
1122
1453
|
}
|
|
@@ -1210,15 +1541,15 @@ class J {
|
|
|
1210
1541
|
*/
|
|
1211
1542
|
processCommands() {
|
|
1212
1543
|
const t = this.stateManager.getCurrentState(), e = [];
|
|
1213
|
-
for (const
|
|
1214
|
-
const
|
|
1215
|
-
|
|
1216
|
-
t.componentStates.get(
|
|
1217
|
-
|
|
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
|
|
1218
1549
|
);
|
|
1219
1550
|
for (const c of a.scheduledEvents)
|
|
1220
1551
|
this.eventQueue.schedule(c);
|
|
1221
|
-
e.push(a), a.hasChanged && this.dirtyTracker.markComponentDirty(
|
|
1552
|
+
e.push(a), a.hasChanged && this.dirtyTracker.markComponentDirty(n.id);
|
|
1222
1553
|
}
|
|
1223
1554
|
return this.commands.clear(), e;
|
|
1224
1555
|
}
|
|
@@ -1232,8 +1563,8 @@ class J {
|
|
|
1232
1563
|
getInitializationOrder(t) {
|
|
1233
1564
|
const e = t.get("initializationOrder");
|
|
1234
1565
|
if (!e || e === "") return 0;
|
|
1235
|
-
const
|
|
1236
|
-
return isNaN(
|
|
1566
|
+
const i = parseInt(e, 10);
|
|
1567
|
+
return isNaN(i) ? 0 : i;
|
|
1237
1568
|
}
|
|
1238
1569
|
/**
|
|
1239
1570
|
* Initialize simulation state for all components.
|
|
@@ -1250,59 +1581,59 @@ class J {
|
|
|
1250
1581
|
*/
|
|
1251
1582
|
initializeState() {
|
|
1252
1583
|
const t = this.stateManager.getCurrentState();
|
|
1253
|
-
for (const
|
|
1254
|
-
if (
|
|
1255
|
-
const h = this.behaviorRegistry.get(
|
|
1584
|
+
for (const o of this.circuit.getAllComponents()) {
|
|
1585
|
+
if (o.pins.length < 1) continue;
|
|
1586
|
+
const h = this.behaviorRegistry.get(o.type);
|
|
1256
1587
|
if (!h)
|
|
1257
1588
|
continue;
|
|
1258
|
-
const u = h.createInitialState(
|
|
1259
|
-
t.componentStates.set(
|
|
1589
|
+
const u = h.createInitialState(o);
|
|
1590
|
+
t.componentStates.set(o.id, u), this.dirtyTracker.markComponentDirty(o.id);
|
|
1260
1591
|
}
|
|
1261
|
-
for (const
|
|
1262
|
-
t.nodeStates.set(
|
|
1263
|
-
hasVoltage:
|
|
1264
|
-
hasCurrent:
|
|
1265
|
-
locked: !!
|
|
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
|
|
1266
1597
|
});
|
|
1267
|
-
for (const
|
|
1268
|
-
t.wireStates.set(
|
|
1598
|
+
for (const o of this.circuit.getAllWires())
|
|
1599
|
+
t.wireStates.set(o.id, {
|
|
1269
1600
|
hasVoltage: !1,
|
|
1270
1601
|
hasCurrent: !1,
|
|
1271
1602
|
locked: !1
|
|
1272
1603
|
});
|
|
1273
|
-
const e = this.circuit.getAllComponents(),
|
|
1274
|
-
for (const
|
|
1275
|
-
const h = this.getInitializationOrder(
|
|
1276
|
-
u.push(
|
|
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);
|
|
1277
1608
|
}
|
|
1278
|
-
const
|
|
1279
|
-
for (const
|
|
1280
|
-
|
|
1281
|
-
let
|
|
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;
|
|
1282
1613
|
const c = 100;
|
|
1283
|
-
for (;
|
|
1284
|
-
|
|
1285
|
-
for (const
|
|
1286
|
-
const h =
|
|
1614
|
+
for (; s && a < c; ) {
|
|
1615
|
+
s = !1, a++;
|
|
1616
|
+
for (const o of n) {
|
|
1617
|
+
const h = i.get(o);
|
|
1287
1618
|
for (const u of h) {
|
|
1288
|
-
const
|
|
1619
|
+
const p = this.behaviorRegistry.get(u.type);
|
|
1620
|
+
if (!p) continue;
|
|
1621
|
+
const g = t.componentStates.get(u.id);
|
|
1289
1622
|
if (!g) continue;
|
|
1290
|
-
const f = t.componentStates.get(u.id);
|
|
1291
|
-
if (!f) continue;
|
|
1292
1623
|
this.propagateConductivity();
|
|
1293
|
-
const m =
|
|
1624
|
+
const m = p.onPinsChange(
|
|
1294
1625
|
u,
|
|
1295
|
-
|
|
1626
|
+
g,
|
|
1296
1627
|
t.nodeStates,
|
|
1297
1628
|
0
|
|
1298
1629
|
);
|
|
1299
|
-
m.hasChanged && (
|
|
1630
|
+
m.hasChanged && (s = !0, t.componentStates.set(
|
|
1300
1631
|
u.id,
|
|
1301
1632
|
m.componentState
|
|
1302
1633
|
));
|
|
1303
1634
|
for (const y of m.scheduledEvents) {
|
|
1304
|
-
const d =
|
|
1305
|
-
d.hasChanged && (
|
|
1635
|
+
const d = p.onEventFiring(u, g, y);
|
|
1636
|
+
d.hasChanged && (s = !0, t.componentStates.set(
|
|
1306
1637
|
u.id,
|
|
1307
1638
|
d.componentState
|
|
1308
1639
|
));
|
|
@@ -1312,8 +1643,8 @@ class J {
|
|
|
1312
1643
|
}
|
|
1313
1644
|
const l = this.updateState(0);
|
|
1314
1645
|
return this.dirtyTracker.setDirtyComponents(
|
|
1315
|
-
/* @__PURE__ */ new Set([...this.circuit.getAllComponents().map((
|
|
1316
|
-
), this.dirtyTracker.setDirtyEnodes(/* @__PURE__ */ new Set([...this.circuit.getAllENodes().map((
|
|
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;
|
|
1317
1648
|
}
|
|
1318
1649
|
/**
|
|
1319
1650
|
* Core method that orchestrates nodes, wires and components state updates
|
|
@@ -1321,32 +1652,32 @@ class J {
|
|
|
1321
1652
|
* @param targetTick - Tick at which to perform the update
|
|
1322
1653
|
*/
|
|
1323
1654
|
updateState(t) {
|
|
1324
|
-
const e = this.stateManager.getCurrentState(), { updatedNodes:
|
|
1325
|
-
let c = 0, l = Array.from(
|
|
1326
|
-
t === 0 && (l = l.sort((
|
|
1327
|
-
const u = this.circuit.getComponent(
|
|
1328
|
-
return
|
|
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);
|
|
1329
1660
|
}));
|
|
1330
|
-
for (const
|
|
1331
|
-
const h = this.circuit.getComponent(
|
|
1661
|
+
for (const o of l) {
|
|
1662
|
+
const h = this.circuit.getComponent(o), u = this.behaviorRegistry.get(h.type);
|
|
1332
1663
|
if (!u)
|
|
1333
1664
|
continue;
|
|
1334
|
-
const
|
|
1665
|
+
const p = u.onPinsChange(
|
|
1335
1666
|
h,
|
|
1336
|
-
e.componentStates.get(
|
|
1667
|
+
e.componentStates.get(o),
|
|
1337
1668
|
e.nodeStates,
|
|
1338
1669
|
t
|
|
1339
1670
|
);
|
|
1340
|
-
|
|
1341
|
-
for (const
|
|
1342
|
-
this.eventQueue.schedule(
|
|
1671
|
+
p.hasChanged && a.add(o);
|
|
1672
|
+
for (const g of p.scheduledEvents)
|
|
1673
|
+
this.eventQueue.schedule(g), c++;
|
|
1343
1674
|
}
|
|
1344
|
-
return this.dirtyTracker.setDirtyComponents(a), this.dirtyTracker.setDirtyEnodes(
|
|
1675
|
+
return this.dirtyTracker.setDirtyComponents(a), this.dirtyTracker.setDirtyEnodes(i), this.dirtyTracker.setDirtyWires(n), {
|
|
1345
1676
|
startTick: this.getCurrentTick(),
|
|
1346
1677
|
endTick: this.getCurrentTick(),
|
|
1347
1678
|
componentUpdateCount: a.size,
|
|
1348
|
-
nodeUpdateCount:
|
|
1349
|
-
wireUpdateCount:
|
|
1679
|
+
nodeUpdateCount: i.size,
|
|
1680
|
+
wireUpdateCount: n.size,
|
|
1350
1681
|
processedCommandCount: 0,
|
|
1351
1682
|
scheduledEventCount: c,
|
|
1352
1683
|
firedEventCount: 0
|
|
@@ -1360,34 +1691,34 @@ class J {
|
|
|
1360
1691
|
*/
|
|
1361
1692
|
propagateConductivity() {
|
|
1362
1693
|
const t = this.stateManager.getCurrentState(), e = (c) => {
|
|
1363
|
-
const l = /* @__PURE__ */ new Set(),
|
|
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([
|
|
1364
1695
|
...this.circuit.getAllENodes().filter((d) => !d.source).map((d) => d.id)
|
|
1365
|
-
]),
|
|
1696
|
+
]), p = /* @__PURE__ */ new Set([...this.circuit.getAllWires().map((d) => d.id)]), { nodes: g, wires: m } = this.computeReachability(
|
|
1366
1697
|
c,
|
|
1367
1698
|
h,
|
|
1368
1699
|
t.componentStates
|
|
1369
|
-
), y = c ==
|
|
1370
|
-
for (const d of
|
|
1371
|
-
const
|
|
1372
|
-
|
|
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));
|
|
1373
1704
|
}
|
|
1374
1705
|
for (const d of u) {
|
|
1375
|
-
const
|
|
1376
|
-
|
|
1706
|
+
const f = t.nodeStates.get(d);
|
|
1707
|
+
f && !f.locked && f[y] && (f[y] = !1, l.add(d));
|
|
1377
1708
|
}
|
|
1378
1709
|
for (const d of m) {
|
|
1379
|
-
const
|
|
1380
|
-
|
|
1710
|
+
const f = t.wireStates.get(d);
|
|
1711
|
+
f && (f[y] || (f[y] = !0, o.add(d)), p.delete(d));
|
|
1381
1712
|
}
|
|
1382
|
-
for (const d of
|
|
1383
|
-
const
|
|
1384
|
-
|
|
1713
|
+
for (const d of p) {
|
|
1714
|
+
const f = t.wireStates.get(d);
|
|
1715
|
+
f && f[y] && (f[y] = !1, o.add(d));
|
|
1385
1716
|
}
|
|
1386
|
-
return { updatedNodes: l, updatedWires:
|
|
1387
|
-
}, { updatedNodes:
|
|
1717
|
+
return { updatedNodes: l, updatedWires: o };
|
|
1718
|
+
}, { updatedNodes: i, updatedWires: n } = e(v.Voltage), { updatedNodes: s, updatedWires: a } = e(v.Current);
|
|
1388
1719
|
return {
|
|
1389
|
-
updatedNodes: /* @__PURE__ */ new Set([...
|
|
1390
|
-
updatedWires: /* @__PURE__ */ new Set([...
|
|
1720
|
+
updatedNodes: /* @__PURE__ */ new Set([...i, ...s]),
|
|
1721
|
+
updatedWires: /* @__PURE__ */ new Set([...n, ...a])
|
|
1391
1722
|
};
|
|
1392
1723
|
}
|
|
1393
1724
|
/**
|
|
@@ -1398,35 +1729,35 @@ class J {
|
|
|
1398
1729
|
* @param seeds
|
|
1399
1730
|
* @param componentStates
|
|
1400
1731
|
*/
|
|
1401
|
-
computeReachability(t, e,
|
|
1402
|
-
const
|
|
1732
|
+
computeReachability(t, e, i) {
|
|
1733
|
+
const n = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), a = [];
|
|
1403
1734
|
for (const c of e)
|
|
1404
|
-
a.push(c),
|
|
1735
|
+
a.push(c), n.add(c);
|
|
1405
1736
|
for (; a.length > 0; ) {
|
|
1406
1737
|
const c = a.shift();
|
|
1407
|
-
for (const
|
|
1408
|
-
const h =
|
|
1409
|
-
|
|
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);
|
|
1410
1741
|
}
|
|
1411
1742
|
const l = this.circuit.getENode(c);
|
|
1412
|
-
if (l.type ===
|
|
1413
|
-
const
|
|
1743
|
+
if (l.type === S.Pin) {
|
|
1744
|
+
const o = this.circuit.getComponent(l.component), h = this.behaviorRegistry.get(o.type);
|
|
1414
1745
|
if (!h)
|
|
1415
1746
|
continue;
|
|
1416
|
-
const u =
|
|
1417
|
-
for (const
|
|
1418
|
-
if (
|
|
1747
|
+
const u = i.get(o.id);
|
|
1748
|
+
for (const p of o.pins) {
|
|
1749
|
+
if (p === c || n.has(p)) continue;
|
|
1419
1750
|
h.allowConductivity(
|
|
1420
|
-
|
|
1751
|
+
o,
|
|
1421
1752
|
u,
|
|
1422
1753
|
t,
|
|
1423
1754
|
c,
|
|
1424
|
-
|
|
1425
|
-
) && (
|
|
1755
|
+
p
|
|
1756
|
+
) && (n.add(p), a.push(p));
|
|
1426
1757
|
}
|
|
1427
1758
|
}
|
|
1428
1759
|
}
|
|
1429
|
-
return { nodes:
|
|
1760
|
+
return { nodes: n, wires: s };
|
|
1430
1761
|
}
|
|
1431
1762
|
/**
|
|
1432
1763
|
* Fire ready events and update current state accordingly
|
|
@@ -1438,40 +1769,41 @@ class J {
|
|
|
1438
1769
|
* @param targetTick - Target tick for event processing
|
|
1439
1770
|
*/
|
|
1440
1771
|
applyReadyEvents(t) {
|
|
1441
|
-
const e = this.stateManager.getCurrentState(),
|
|
1442
|
-
for (const
|
|
1443
|
-
const a = this.circuit.getComponent(
|
|
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);
|
|
1444
1775
|
if (!c)
|
|
1445
1776
|
continue;
|
|
1446
|
-
const l = e.componentStates.get(a.id),
|
|
1447
|
-
for (const h of
|
|
1777
|
+
const l = e.componentStates.get(a.id), o = c.onEventFiring(a, l, s);
|
|
1778
|
+
for (const h of o.scheduledEvents)
|
|
1448
1779
|
this.eventQueue.schedule(h);
|
|
1449
|
-
|
|
1780
|
+
n.push(o);
|
|
1450
1781
|
}
|
|
1451
|
-
return
|
|
1782
|
+
return n;
|
|
1452
1783
|
}
|
|
1453
1784
|
}
|
|
1454
1785
|
export {
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1786
|
+
M as C,
|
|
1787
|
+
R as D,
|
|
1788
|
+
v as E,
|
|
1789
|
+
C as P,
|
|
1790
|
+
k as R,
|
|
1460
1791
|
b as S,
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
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,
|
|
1469
1800
|
w as h,
|
|
1470
1801
|
A as i,
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
L as
|
|
1802
|
+
N as j,
|
|
1803
|
+
U as k,
|
|
1804
|
+
z as l,
|
|
1805
|
+
$ as m,
|
|
1806
|
+
L as n,
|
|
1807
|
+
W as s
|
|
1476
1808
|
};
|
|
1477
|
-
//# sourceMappingURL=CircuitRunner-
|
|
1809
|
+
//# sourceMappingURL=CircuitRunner-DEb7JdNf.js.map
|