simple-circuit-engine 0.0.9 → 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,208 +1,58 @@
1
- import { e as T, d as g, P, C as b, c as _, i as C, f as A, b as L, s as E, a as p, T as y } from "../CircuitRunner-FXM_s5ll.js";
2
- import { j as Z, D as j, E as ee, m as te, h as ne, R as ie, l as se, S as oe, k as re, g as ae } from "../CircuitRunner-FXM_s5ll.js";
3
- class w {
4
- /**
5
- * Unique identifier for this ENode.
6
- * @readonly
7
- */
8
- id;
9
- /**
10
- * Type of electrical node (Pin or BranchingPoint).
11
- * @readonly
12
- */
13
- type;
14
- /**
15
- * Parent component UUID (only for pin nodes).
16
- * Undefined for branching point nodes.
17
- * @readonly
18
- */
19
- component;
20
- /**
21
- * Pin label within component (only for pin nodes).
22
- * Undefined for branching point nodes.
23
- * @readonly
24
- */
25
- pinLabel;
26
- /**
27
- * Grid position (only for branching point nodes).
28
- * Undefined for pin nodes (position derived from component).
29
- * @readonly
30
- */
31
- position;
32
- /**
33
- * Set of wire UUIDs connected to this node.
34
- * Mutable to allow wire connections/disconnections.
35
- */
36
- wires;
37
- /**
38
- * Is the ENode a source of voltage or current?
39
- */
40
- source;
41
- /**
42
- * Create a new electrical node.
43
- *
44
- * **Note**: Typically ENodes are created automatically by Circuit.
45
- * This constructor is used internally.
46
- *
47
- * @param type - Node type (Pin or BranchingPoint)
48
- * @param component - Parent component UUID (pin nodes only)
49
- * @param pinLabel - Pin label (pin nodes only)
50
- * @param position - Grid position (branching points only)
51
- * @param source - Source type (Voltage/Current) or undefined
52
- *
53
- * @example
54
- * ```typescript
55
- * // Pin node (internal to Circuit)
56
- * const pinNode = new ENode(
57
- * ENodeType.Pin,
58
- * componentId,
59
- * '0', // first pin
60
- * undefined,
61
- * undefined
62
- * );
63
- *
64
- * // Branching point node
65
- * const branchNode = new ENode(
66
- * ENodeType.BranchingPoint,
67
- * undefined,
68
- * undefined,
69
- * new Position(15, 25),
70
- * undefined
71
- * );
72
- * ```
73
- */
74
- constructor(e, t, i, n, s = void 0) {
75
- this.id = T(), this.type = e, this.component = t, this.pinLabel = i, this.position = n, this.wires = /* @__PURE__ */ new Set(), this.source = s;
76
- }
77
- /**
78
- * Get the position of this electrical node.
79
- *
80
- * **Pin nodes**: Derives position from parent component.
81
- * **Branching nodes**: Returns stored position directly.
82
- *
83
- * @param circuit - Circuit instance (needed to look up component for pin nodes)
84
- * @returns Position on the grid
85
- *
86
- * @example
87
- * ```typescript
88
- * const circuit = new Circuit();
89
- * const component = circuit.addComponent(
90
- * new Position(10, 20),
91
- * new Rotation(0),
92
- * 1
93
- * );
94
- *
95
- * const pinNode = circuit.getENode(component.pins[0]);
96
- * const position = pinNode.getPosition(circuit);
97
- * console.log(position.x); // 10 (derived from component)
98
- * ```
99
- */
100
- getPosition(e) {
101
- if (this.type === g.Pin) {
102
- if (!this.component)
103
- throw new Error("Pin node missing component reference");
104
- const t = e.getComponent(this.component);
105
- if (!t)
106
- throw new Error(`Component ${this.component} not found for pin node ${this.id}`);
107
- return t.position;
108
- }
109
- if (!this.position)
110
- throw new Error("Branching point node missing position");
111
- return this.position;
112
- }
113
- /**
114
- * Update the enode (branching point only)'s position.
115
- *
116
- * @param newPosition - The new position for the enode
117
- *
118
- * @example
119
- * ```typescript
120
- * const component = circuit.getComponent(componentId);
121
- * component.setPosition(new Position(15, 25));
122
- * ```
123
- */
124
- setPosition(e) {
125
- Object.defineProperty(this, "position", {
126
- value: e,
1
+ import { g as M, P as R, D as O, b as E, C as A, c as h, d as G, i as _, h as I, e as m, f as D, s as P, T as S } from "../CircuitRunner-BQQlhwjD.js";
2
+ import { A as Me, m as Re, k as De, E as We, j as ke, a as Fe, R as Xe, S as Je, n as Ue, l as ze } from "../CircuitRunner-BQQlhwjD.js";
3
+ function W(a) {
4
+ let e, t, o;
5
+ return typeof a == "object" ? (e = a.hashFunction, t = a.expiring, o = a.tags) : e = a, (i, n, s) => {
6
+ if (s.value != null)
7
+ s.value = b(s.value, e, t, o);
8
+ else if (s.get != null)
9
+ s.get = b(s.get, e, t, o);
10
+ else
11
+ throw "Only put a Memoize() decorator on a method or get accessor.";
12
+ };
13
+ }
14
+ function be(a, e) {
15
+ return W({
16
+ expiring: a,
17
+ hashFunction: e
18
+ });
19
+ }
20
+ const T = /* @__PURE__ */ new Map();
21
+ function b(a, e, t = 0, o) {
22
+ const i = Symbol("__memoized_map__");
23
+ return function(...n) {
24
+ let s;
25
+ this.hasOwnProperty(i) || Object.defineProperty(this, i, {
26
+ configurable: !1,
27
+ enumerable: !1,
127
28
  writable: !1,
128
- enumerable: !0,
129
- configurable: !0
130
- });
131
- }
132
- /**
133
- * Update the enode's source type.
134
- * @param sourceType
135
- */
136
- setSourceType(e) {
137
- Object.defineProperty(this, "source", {
138
- value: e,
139
- writable: !0,
140
- enumerable: !0,
141
- configurable: !0
29
+ value: /* @__PURE__ */ new Map()
142
30
  });
143
- }
144
- /**
145
- * Serialize ENode to JSON.
146
- *
147
- * @returns Plain object representation
148
- *
149
- * @example
150
- * ```typescript
151
- * const json = enode.toJSON();
152
- * console.log(json);
153
- * // Pin node:
154
- * // {
155
- * // id: "uuid",
156
- * // type: "Pin",
157
- * // component: "component-uuid",
158
- * // pinLabel: "0"
159
- * // }
160
- *
161
- * // Branching node:
162
- * // {
163
- * // id: "uuid",
164
- * // type: "BranchingPoint",
165
- * // position: { x: 15, y: 25 }
166
- * // }
167
- * ```
168
- */
169
- toJSON() {
170
- const e = {
171
- id: this.id,
172
- type: this.type,
173
- source: this.source || null
174
- };
175
- return this.type === g.Pin ? (e.component = this.component || null, e.pinLabel = this.pinLabel || null) : e.position = this.position?.toJSON() || null, e;
176
- }
177
- /**
178
- * Deserialize ENode from JSON.
179
- *
180
- * @param json - ENode data
181
- * @returns ENode instance
182
- *
183
- * @example
184
- * ```typescript
185
- * const json = {
186
- * id: "uuid",
187
- * type: "Pin",
188
- * component: "component-uuid",
189
- * pinLabel: "0"
190
- * };
191
- *
192
- * const enode = ENode.fromJSON(json);
193
- * ```
194
- */
195
- static fromJSON(e) {
196
- const t = e.position ? P.fromJSON(e.position) : void 0, i = new w(e.type, e.component, e.pinLabel, t, e.source);
197
- return Object.defineProperty(i, "id", {
198
- value: e.id,
199
- writable: !1,
200
- enumerable: !0,
201
- configurable: !1
202
- }), i;
203
- }
31
+ let c = this[i];
32
+ if (Array.isArray(o))
33
+ for (const r of o)
34
+ T.has(r) ? T.get(r).push(c) : T.set(r, [c]);
35
+ if (e || n.length > 0 || t > 0) {
36
+ let r;
37
+ e === !0 ? r = n.map((l) => l.toString()).join("!") : e ? r = e.apply(this, n) : r = n[0];
38
+ const u = `${r}__timestamp`;
39
+ let d = !1;
40
+ if (t > 0)
41
+ if (!c.has(u))
42
+ d = !0;
43
+ else {
44
+ let l = c.get(u);
45
+ d = Date.now() - l > t;
46
+ }
47
+ c.has(r) && !d ? s = c.get(r) : (s = a.apply(this, n), c.set(r, s), t > 0 && c.set(u, Date.now()));
48
+ } else {
49
+ const r = this;
50
+ c.has(r) ? s = c.get(r) : (s = a.apply(this, n), c.set(r, s));
51
+ }
52
+ return s;
53
+ };
204
54
  }
205
- class f {
55
+ class w {
206
56
  /**
207
57
  * Unique identifier for this wire.
208
58
  * @readonly
@@ -248,8 +98,8 @@ class f {
248
98
  * );
249
99
  * ```
250
100
  */
251
- constructor(e, t, i = []) {
252
- this.id = T(), this.node1 = e, this.node2 = t, this.intermediatePositions = i;
101
+ constructor(e, t, o = []) {
102
+ this.id = M(), this.node1 = e, this.node2 = t, this.intermediatePositions = o;
253
103
  }
254
104
  /**
255
105
  * Check if this is a straight-line wire.
@@ -312,52 +162,169 @@ class f {
312
162
  * ```
313
163
  */
314
164
  static fromJSON(e) {
315
- const t = e.intermediatePositions.map((n) => P.fromJSON(n)), i = new f(e.node1, e.node2, t);
316
- return Object.defineProperty(i, "id", {
165
+ const t = e.intermediatePositions.map((i) => R.fromJSON(i)), o = new w(e.node1, e.node2, t);
166
+ return Object.defineProperty(o, "id", {
317
167
  value: e.id,
318
168
  writable: !1,
319
169
  enumerable: !0,
320
170
  configurable: !1
321
- }), i;
171
+ }), o;
322
172
  }
323
173
  }
324
- class v {
174
+ class C {
175
+ /**
176
+ * Create new circuit options.
177
+ *
178
+ * @param name - Circuit name (default: Untitled Circuit)
179
+ * @param defaultLogicFamily - Circuit default logic family (default: CMOS1)
180
+ */
181
+ constructor(e = "Untitled Circuit", t = O) {
182
+ this.name = e, this.defaultLogicFamily = t;
183
+ }
184
+ toJSON() {
185
+ return {
186
+ name: this.name,
187
+ defaultLogicFamily: this.defaultLogicFamily
188
+ };
189
+ }
190
+ static fromJSON(e) {
191
+ return new C(e.name, e.defaultLogicFamily);
192
+ }
193
+ }
194
+ class N {
325
195
  /**
326
196
  * Create a new CircuitMetadata holding general information about the Circuit.
327
197
  *
328
- * @param name - Name of the circuit
198
+ * @param version - Circuit version
199
+ * @param options - Circuit options
329
200
  * @param size - Size of the circuit grid
330
201
  * @param divisions - Divisions in the circuit grid
331
202
  * @param cameraOptions - Camera Options at startup
332
203
  * @throws {TypeError} If size or divisions are not integers
333
204
  */
334
- constructor(e, t, i, n) {
335
- if (this.name = e, this.size = t, this.divisions = i, this.cameraOptions = n, !Number.isInteger(t) || !Number.isInteger(i))
205
+ constructor(e, t, o, i, n) {
206
+ if (this.version = e, this.options = t, this.size = o, this.divisions = i, this.cameraOptions = n, !Number.isInteger(o) || !Number.isInteger(i))
336
207
  throw new TypeError(
337
- `Size and divisions must be integers (got size=${t}, divisions=${i})`
208
+ `Size and divisions must be integers (got size=${o}, divisions=${i})`
338
209
  );
339
210
  }
340
211
  toJSON() {
341
212
  return {
342
- name: this.name,
213
+ version: this.version,
214
+ options: this.options.toJSON(),
343
215
  size: this.size,
344
216
  divisions: this.divisions,
345
217
  cameraOptions: this.cameraOptions.toJSON()
346
218
  };
347
219
  }
348
220
  static fromJSON(e) {
349
- return new v(
350
- e.name,
221
+ E !== e.version && console.warn(`This version of the engine supports v${E} circuit version files.
222
+ Unexpected behavior may occurs loading v${e.version}.`);
223
+ const t = e.options ? C.fromJSON(e.options) : new C("Untitled Circuit", O);
224
+ return new N(
225
+ e.version,
226
+ t,
351
227
  e.size,
352
228
  e.divisions,
353
- b.fromJSON(e.cameraOptions)
229
+ A.fromJSON(e.cameraOptions)
354
230
  );
355
231
  }
356
232
  toString() {
357
- return `CircuitMetadata(${this.name}, ${this.size}, ${this.divisions}, ${this.cameraOptions.toString()})`;
233
+ return `CircuitMetadata(${this.version}, ${this.options.name}, ${this.options.defaultLogicFamily}, ${this.size}, ${this.divisions}, ${this.cameraOptions.toString()})`;
234
+ }
235
+ }
236
+ const k = { 2: 1, 4: 1, 8: 2, 16: 2 }, F = { 2: 2, 4: 2, 8: 3, 16: 3 }, X = { 2: 1, 4: 2, 8: 2, 16: 3 }, J = { 2: 2, 4: 3, 8: 3, 16: 4 };
237
+ function U(a) {
238
+ const e = a.config.get("defaultLogicFamily");
239
+ if (!(!e || e === "Sandbox") && z(a.type)) {
240
+ const t = a.config.get("activationLogic") ?? "negative", o = H(a.type, t);
241
+ return o && K(e, o.gateFamily, o.inputCount) || void 0;
242
+ }
243
+ }
244
+ function z(a) {
245
+ return [
246
+ h.Inverter,
247
+ h.NandGate,
248
+ h.Nand4Gate,
249
+ h.Nand8Gate,
250
+ h.NorGate,
251
+ h.Nor4Gate,
252
+ h.Nor8Gate,
253
+ h.XorGate,
254
+ h.Xor4Gate,
255
+ h.Xor8Gate
256
+ ].includes(a);
257
+ }
258
+ function H(a, e) {
259
+ switch (a) {
260
+ case h.Inverter:
261
+ return { gateFamily: e === "negative" ? "NOT" : "Buffer", inputCount: 1 };
262
+ case h.NandGate:
263
+ return { gateFamily: e === "negative" ? "NAND" : "AND", inputCount: 2 };
264
+ case h.Nand4Gate:
265
+ return { gateFamily: e === "negative" ? "NAND" : "AND", inputCount: 4 };
266
+ case h.Nand8Gate:
267
+ return { gateFamily: e === "negative" ? "NAND" : "AND", inputCount: 8 };
268
+ case h.NorGate:
269
+ return { gateFamily: e === "negative" ? "NOR" : "OR", inputCount: 2 };
270
+ case h.Nor4Gate:
271
+ return { gateFamily: e === "negative" ? "NOR" : "OR", inputCount: 4 };
272
+ case h.Nor8Gate:
273
+ return { gateFamily: e === "negative" ? "NOR" : "OR", inputCount: 8 };
274
+ case h.XorGate:
275
+ return { gateFamily: e === "negative" ? "XNOR" : "XOR", inputCount: 2 };
276
+ case h.Xor4Gate:
277
+ return { gateFamily: e === "negative" ? "XNOR" : "XOR", inputCount: 4 };
278
+ case h.Xor8Gate:
279
+ return { gateFamily: e === "negative" ? "XNOR" : "XOR", inputCount: 8 };
280
+ default:
281
+ return null;
282
+ }
283
+ }
284
+ function K(a, e, t) {
285
+ if (a === "Sandbox")
286
+ throw new Error("computeGateDelay must not be called for Sandbox family");
287
+ if (e === "NOT") return 1;
288
+ if (e === "Buffer") return 2;
289
+ if (e === "XOR") return Math.log2(t) * 2;
290
+ if (e === "XNOR") return Math.log2(t) * 2 + 1;
291
+ if (a === "CMOS1") {
292
+ const o = Math.log2(t);
293
+ switch (e) {
294
+ case "NAND":
295
+ return o;
296
+ case "NOR":
297
+ return o;
298
+ case "AND":
299
+ return o + 1;
300
+ case "OR":
301
+ return o + 1;
302
+ }
358
303
  }
304
+ if (a === "TTL1") {
305
+ let o;
306
+ switch (e) {
307
+ case "NAND":
308
+ o = k;
309
+ break;
310
+ case "AND":
311
+ o = F;
312
+ break;
313
+ case "NOR":
314
+ o = X;
315
+ break;
316
+ case "OR":
317
+ o = J;
318
+ break;
319
+ }
320
+ const i = o[t];
321
+ if (i === void 0)
322
+ throw new Error(`Unsupported input count ${t} for TTL1 ${e}`);
323
+ return i;
324
+ }
325
+ throw new Error(`Unsupported logic family: ${a}`);
359
326
  }
360
- class O {
327
+ class x {
361
328
  /**
362
329
  * Circuit metadata holding general information.
363
330
  * @private
@@ -382,16 +349,16 @@ class O {
382
349
  /**
383
350
  * Create a new empty circuit.
384
351
  */
385
- constructor(e = "Untitled Circuit") {
386
- this.metadata = new v(e, 10, 10, new b()), this.components = /* @__PURE__ */ new Map(), this.enodes = /* @__PURE__ */ new Map(), this.wires = /* @__PURE__ */ new Map();
352
+ constructor(e) {
353
+ this.metadata = new N(E, e, 10, 10, new A()), this.components = /* @__PURE__ */ new Map(), this.enodes = /* @__PURE__ */ new Map(), this.wires = /* @__PURE__ */ new Map();
387
354
  }
388
355
  get name() {
389
- return this.metadata.name;
356
+ return this.metadata.options.name;
390
357
  }
391
358
  set name(e) {
392
359
  if (typeof e != "string" || e.trim() === "")
393
360
  throw new TypeError("Circuit name must be a non-empty string");
394
- this.metadata.name = e;
361
+ this.metadata.options.name = e;
395
362
  }
396
363
  /**
397
364
  * Add a new component to the circuit.
@@ -420,27 +387,43 @@ class O {
420
387
  * console.log(lightbulb.position.x); // 10
421
388
  * ```
422
389
  */
423
- addComponent(e, t, i, n) {
424
- const s = _(e), o = new C(e, t, i, []);
425
- n && (o.config = new Map(n));
426
- const a = [];
427
- for (const [r, c] of s.pins) {
428
- const l = new w(
429
- g.Pin,
430
- o.id,
390
+ addComponent(e, t, o, i) {
391
+ const n = G[e], s = new _(e, t, o, []);
392
+ if (i)
393
+ for (const [r, u] of i)
394
+ s.config.set(r, u);
395
+ s.config.has("defaultLogicFamily") && !s.config.get("defaultLogicFamily") && s.config.set("defaultLogicFamily", this.metadata.options.defaultLogicFamily), this.resolveTransitionSpan(s);
396
+ const c = [];
397
+ for (const [r, u] of n.pins) {
398
+ const d = new I(
399
+ m.Pin,
400
+ s.id,
431
401
  r,
432
402
  void 0,
433
- // Pin position derived from component,
434
- c
403
+ // Pin position derived from component
404
+ u.sourceType,
405
+ u.subtype
435
406
  );
436
- this.enodes.set(l.id, l), a.push(l.id);
407
+ this.enodes.set(d.id, d), c.push(d.id);
437
408
  }
438
- return Object.defineProperty(o, "pins", {
439
- value: a,
409
+ return Object.defineProperty(s, "pins", {
410
+ value: c,
440
411
  writable: !1,
441
412
  enumerable: !0,
442
413
  configurable: !1
443
- }), this.components.set(o.id, o), o;
414
+ }), this.components.set(s.id, s), s;
415
+ }
416
+ /**
417
+ * Resolve and update the transitionSpan config for a component
418
+ * if automatic resolution returns undefined nothing is done on the component
419
+ *
420
+ * @param component - Component to resolve transitionSpan for
421
+ */
422
+ resolveTransitionSpan(e) {
423
+ if (!e.config.has("transitionSpan"))
424
+ return;
425
+ const t = U(e);
426
+ t && e.config.set("transitionSpan", String(t));
444
427
  }
445
428
  /**
446
429
  * Remove a component from the circuit.
@@ -463,17 +446,17 @@ class O {
463
446
  const t = this.components.get(e);
464
447
  if (!t)
465
448
  throw new Error(`Component ${e} does not exist`);
466
- const i = [], n = [];
467
- for (const s of t.pins) {
468
- const o = this.enodes.get(s);
469
- if (o) {
470
- const a = Array.from(o.wires);
471
- for (const r of a)
472
- this.removeWire(r), i.push(r);
449
+ const o = [], i = [];
450
+ for (const n of t.pins) {
451
+ const s = this.enodes.get(n);
452
+ if (s) {
453
+ const c = Array.from(s.wires);
454
+ for (const r of c)
455
+ this.removeWire(r), o.push(r);
473
456
  }
474
- this.enodes.delete(s), n.push(s);
457
+ this.enodes.delete(n), i.push(n);
475
458
  }
476
- return this.components.delete(e), { deletedWires: i, deletedENodes: n };
459
+ return this.components.delete(e), { deletedWires: o, deletedENodes: i };
477
460
  }
478
461
  hasComponent(e) {
479
462
  return this.components.has(e);
@@ -517,8 +500,8 @@ class O {
517
500
  }
518
501
  getAllComponentsByType(e) {
519
502
  const t = [];
520
- for (const i of this.components.values())
521
- i.type === e && t.push(i);
503
+ for (const o of this.components.values())
504
+ o.type === e && t.push(o);
522
505
  return t;
523
506
  }
524
507
  getFirstComponentOfType(e) {
@@ -583,14 +566,14 @@ class O {
583
566
  * @returns The created ENode
584
567
  */
585
568
  addBranchingPoint(e, t) {
586
- const i = new w(
587
- g.BranchingPoint,
569
+ const o = new I(
570
+ m.BranchingPoint,
588
571
  void 0,
589
572
  void 0,
590
573
  e,
591
574
  t
592
575
  );
593
- return this.enodes.set(i.id, i), i;
576
+ return this.enodes.set(o.id, o), o;
594
577
  }
595
578
  /**
596
579
  * Remove a branching point electrical node from the circuit.
@@ -604,25 +587,25 @@ class O {
604
587
  const t = this.enodes.get(e);
605
588
  if (!t)
606
589
  throw new Error(`Enode ${e} does not exist`);
607
- if (t.type !== g.BranchingPoint)
590
+ if (t.type !== m.BranchingPoint)
608
591
  throw new Error(
609
592
  `Enode ${e} is not a branching point, it must be removed with its component.`
610
593
  );
611
- const i = {}, n = this.getWiresByNode(e);
612
- if (n.length === 1 || n.length > 2) {
613
- const s = [];
614
- for (const o of n)
615
- this.removeWire(o.id), s.push(o.id);
616
- Object.assign(i, { deletedWires: s });
617
- } else if (n.length === 2) {
618
- const s = n[0], o = n[1], a = s.node1 === e ? s.node2 : s.node1, r = o.node1 === e ? o.node2 : o.node1, c = [];
619
- a === s.node1 ? c.push(...s.intermediatePositions) : a === s.node2 && c.push(...[...s.intermediatePositions].reverse()), c.push(t.getPosition(this)), r === o.node1 ? c.push(...[...o.intermediatePositions].reverse()) : r === o.node2 && c.push(...o.intermediatePositions), this.removeWire(s.id), this.removeWire(o.id);
620
- const l = this.addWire(a, r, c);
621
- if (l instanceof Error)
622
- throw new Error(`Failed to merge wires at branching point ${e}: ${l.message}`);
623
- Object.assign(i, { mergedWires: [s.id, o.id] }), Object.assign(i, { newWire: l });
594
+ const o = {}, i = this.getWiresByNode(e);
595
+ if (i.length === 1 || i.length > 2) {
596
+ const n = [];
597
+ for (const s of i)
598
+ this.removeWire(s.id), n.push(s.id);
599
+ Object.assign(o, { deletedWires: n });
600
+ } else if (i.length === 2) {
601
+ const n = i[0], s = i[1], c = n.node1 === e ? n.node2 : n.node1, r = s.node1 === e ? s.node2 : s.node1, u = [];
602
+ c === n.node1 ? u.push(...n.intermediatePositions) : c === n.node2 && u.push(...[...n.intermediatePositions].reverse()), u.push(t.getPosition(this)), r === s.node1 ? u.push(...[...s.intermediatePositions].reverse()) : r === s.node2 && u.push(...s.intermediatePositions), this.removeWire(n.id), this.removeWire(s.id);
603
+ const d = this.addWire(c, r, u);
604
+ if (d instanceof Error)
605
+ throw new Error(`Failed to merge wires at branching point ${e}: ${d.message}`);
606
+ Object.assign(o, { mergedWires: [n.id, s.id] }), Object.assign(o, { newWire: d });
624
607
  }
625
- return this.enodes.delete(e), i;
608
+ return this.enodes.delete(e), o;
626
609
  }
627
610
  /**
628
611
  * Add a wire connecting two electrical nodes.
@@ -646,16 +629,16 @@ class O {
646
629
  * }
647
630
  * ```
648
631
  */
649
- addWire(e, t, i) {
632
+ addWire(e, t, o) {
650
633
  if (e === t)
651
634
  return new Error("Cannot create wire connecting node to itself");
652
- const n = this.enodes.get(e), s = this.enodes.get(t);
653
- if (!n || !s)
635
+ const i = this.enodes.get(e), n = this.enodes.get(t);
636
+ if (!i || !n)
654
637
  return new Error("Wire requires at least one existing ENode");
655
638
  if (this.hasWireBetween(e, t))
656
639
  return new Error("Duplicate wire between same nodes");
657
- const o = new f(e, t, i || []);
658
- return this.wires.set(o.id, o), n.wires.add(o.id), s.wires.add(o.id), o;
640
+ const s = new w(e, t, o || []);
641
+ return this.wires.set(s.id, s), i.wires.add(s.id), n.wires.add(s.id), s;
659
642
  }
660
643
  /**
661
644
  * Remove a wire from the circuit.
@@ -673,8 +656,8 @@ class O {
673
656
  const t = this.wires.get(e);
674
657
  if (!t)
675
658
  throw new Error(`Wire ${e} does not exist`);
676
- const i = this.enodes.get(t.node1), n = this.enodes.get(t.node2);
677
- i && i.wires.delete(e), n && n.wires.delete(e), this.wires.delete(e);
659
+ const o = this.enodes.get(t.node1), i = this.enodes.get(t.node2);
660
+ o && o.wires.delete(e), i && i.wires.delete(e), this.wires.delete(e);
678
661
  }
679
662
  /**
680
663
  * Split a wire in the circuit.
@@ -705,48 +688,48 @@ class O {
705
688
  * @returns Object containing the new branching point and an array of the two new wires
706
689
  * @throws Error if wireId not found
707
690
  */
708
- splitWire(e, t, i = null) {
709
- const n = this.wires.get(e);
710
- if (!n)
691
+ splitWire(e, t, o = null) {
692
+ const i = this.wires.get(e);
693
+ if (!i)
711
694
  throw new Error(`Wire ${e} does not exist`);
712
- const s = this.enodes.get(n.node1), o = this.enodes.get(n.node2);
713
- if (!s || !o)
695
+ const n = this.enodes.get(i.node1), s = this.enodes.get(i.node2);
696
+ if (!n || !s)
714
697
  throw new Error(`Wire ${e} is connected to non-existent ENodes`);
715
- const a = [
716
- s.getPosition(this),
717
- ...n.intermediatePositions,
718
- o.getPosition(this)
719
- ], r = A(a, t), c = a.slice(1, r), l = a.slice(r, a.length - 1);
720
- this.wires.delete(e), s.wires.delete(e), o.wires.delete(e);
721
- let h;
722
- if (i)
723
- if (this.enodes.get(i))
724
- h = this.enodes.get(i);
698
+ const c = [
699
+ n.getPosition(this),
700
+ ...i.intermediatePositions,
701
+ s.getPosition(this)
702
+ ], r = D(c, t), u = c.slice(1, r), d = c.slice(r, c.length - 1);
703
+ this.wires.delete(e), n.wires.delete(e), s.wires.delete(e);
704
+ let l;
705
+ if (o)
706
+ if (this.enodes.get(o))
707
+ l = this.enodes.get(o);
725
708
  else
726
- throw new Error(`Target ENode ${i} does not exist`);
709
+ throw new Error(`Target ENode ${o} does not exist`);
727
710
  else
728
- h = this.addBranchingPoint(t);
729
- const S = [];
730
- if ((!h.component || s.component !== h.component) && !this.hasWireBetween(s.id, h.id)) {
731
- const u = this.addWire(s.id, h.id, c);
732
- u instanceof f ? (this.simplifyWireIntermediatePositions(u.id), S.push(u)) : console.warn(`Failure to create wire at split : ${u.message}`);
711
+ l = this.addBranchingPoint(t);
712
+ const B = [];
713
+ if ((!l.component || n.component !== l.component) && !this.hasWireBetween(n.id, l.id)) {
714
+ const f = this.addWire(n.id, l.id, u);
715
+ f instanceof w ? (this.simplifyWireIntermediatePositions(f.id), B.push(f)) : console.warn(`Failure to create wire at split : ${f.message}`);
733
716
  }
734
- if ((!h.component || o.component !== h.component) && !this.hasWireBetween(o.id, h.id)) {
735
- const u = this.addWire(h.id, o.id, l);
736
- u instanceof f ? (this.simplifyWireIntermediatePositions(u.id), S.push(u)) : console.warn(`Failure to create wire at split : ${u.message}`);
717
+ if ((!l.component || s.component !== l.component) && !this.hasWireBetween(s.id, l.id)) {
718
+ const f = this.addWire(l.id, s.id, d);
719
+ f instanceof w ? (this.simplifyWireIntermediatePositions(f.id), B.push(f)) : console.warn(`Failure to create wire at split : ${f.message}`);
737
720
  }
738
721
  return {
739
- branchingPoint: h,
740
- wires: S
722
+ branchingPoint: l,
723
+ wires: B
741
724
  };
742
725
  }
743
726
  getWireBetweenNodes(e, t) {
744
- const i = this.enodes.get(e);
745
- if (i)
746
- for (const n of i.wires) {
747
- const s = this.wires.get(n);
748
- if (s && (s.node2 === t || s.node1 === t))
749
- return s;
727
+ const o = this.enodes.get(e);
728
+ if (o)
729
+ for (const i of o.wires) {
730
+ const n = this.wires.get(i);
731
+ if (n && (n.node2 === t || n.node1 === t))
732
+ return n;
750
733
  }
751
734
  }
752
735
  /**
@@ -778,12 +761,12 @@ class O {
778
761
  const t = this.enodes.get(e);
779
762
  if (!t)
780
763
  return [];
781
- const i = [];
782
- for (const n of t.wires) {
783
- const s = this.wires.get(n);
784
- s && i.push(s);
764
+ const o = [];
765
+ for (const i of t.wires) {
766
+ const n = this.wires.get(i);
767
+ n && o.push(n);
785
768
  }
786
- return i;
769
+ return o;
787
770
  }
788
771
  /**
789
772
  * Get all wires connected to a component, e.g to any pin enode of the component.
@@ -795,10 +778,10 @@ class O {
795
778
  const t = this.components.get(e);
796
779
  if (!t)
797
780
  return [];
798
- const i = [];
799
- for (const n of t.pins)
800
- i.push(...this.getWiresByNode(n));
801
- return i;
781
+ const o = [];
782
+ for (const i of t.pins)
783
+ o.push(...this.getWiresByNode(i));
784
+ return o;
802
785
  }
803
786
  /**
804
787
  * Get both ENodes connected by a wire.
@@ -810,9 +793,9 @@ class O {
810
793
  const t = this.wires.get(e);
811
794
  if (!t)
812
795
  return;
813
- const i = this.enodes.get(t.node1), n = this.enodes.get(t.node2);
814
- if (!(!i || !n))
815
- return [i, n];
796
+ const o = this.enodes.get(t.node1), i = this.enodes.get(t.node2);
797
+ if (!(!o || !i))
798
+ return [o, i];
816
799
  }
817
800
  /**
818
801
  * Check if a wire already exists between two nodes.
@@ -824,12 +807,12 @@ class O {
824
807
  * @returns true if wire exists, false otherwise
825
808
  */
826
809
  hasWireBetween(e, t) {
827
- const i = this.enodes.get(e);
828
- if (!i)
810
+ const o = this.enodes.get(e);
811
+ if (!o)
829
812
  return !1;
830
- for (const n of i.wires) {
831
- const s = this.wires.get(n);
832
- if (s && (s.node2 === t || s.node1 === t))
813
+ for (const i of o.wires) {
814
+ const n = this.wires.get(i);
815
+ if (n && (n.node2 === t || n.node1 === t))
833
816
  return !0;
834
817
  }
835
818
  return !1;
@@ -842,9 +825,9 @@ class O {
842
825
  */
843
826
  getComponentsOfPins(e) {
844
827
  const t = /* @__PURE__ */ new Set();
845
- for (const i of e) {
846
- const n = this.enodes.get(i);
847
- n?.component && t.add(n.component);
828
+ for (const o of e) {
829
+ const i = this.enodes.get(o);
830
+ i?.component && t.add(i.component);
848
831
  }
849
832
  return t;
850
833
  }
@@ -854,14 +837,14 @@ class O {
854
837
  * @param pinLabel
855
838
  */
856
839
  getComponentPinByLabel(e, t) {
857
- let i = 0;
858
- const n = L[e.type], s = Array.from(n.pins.keys());
859
- for (const o of e.pins) {
860
- const a = this.enodes.get(o), r = s[i];
840
+ let o = 0;
841
+ const i = G[e.type], n = Array.from(i.pins.keys());
842
+ for (const s of e.pins) {
843
+ const c = this.enodes.get(s), r = n[o];
861
844
  if (r) {
862
- if (a && r === t)
863
- return a;
864
- i++;
845
+ if (c && r === t)
846
+ return c;
847
+ o++;
865
848
  }
866
849
  }
867
850
  }
@@ -875,23 +858,23 @@ class O {
875
858
  * @returns The updated Wire
876
859
  * @throws Error if wireId not found
877
860
  */
878
- updateWireIntermediatePositions(e, t, i = !1) {
879
- const n = this.wires.get(e);
880
- if (!n)
861
+ updateWireIntermediatePositions(e, t, o = !1) {
862
+ const i = this.wires.get(e);
863
+ if (!i)
881
864
  throw new Error(`Wire ${e} does not exist`);
882
- if (i) {
883
- const s = [
884
- this.enodes.get(n.node1).getPosition(this),
865
+ if (o) {
866
+ const n = [
867
+ this.enodes.get(i.node1).getPosition(this),
885
868
  ...t,
886
- this.enodes.get(n.node2).getPosition(this)
887
- ], o = E(s, 10);
888
- n.intermediatePositions = o.slice(
869
+ this.enodes.get(i.node2).getPosition(this)
870
+ ], s = P(n, 10);
871
+ i.intermediatePositions = s.slice(
889
872
  1,
890
- o.length - 1
873
+ s.length - 1
891
874
  );
892
875
  } else
893
- n.intermediatePositions = t;
894
- return n;
876
+ i.intermediatePositions = t;
877
+ return i;
895
878
  }
896
879
  /**
897
880
  * Simplify intermediate positions of a wire.
@@ -904,15 +887,15 @@ class O {
904
887
  const t = this.wires.get(e);
905
888
  if (!t)
906
889
  throw new Error(`Wire ${e} does not exist`);
907
- const i = [
890
+ const o = [
908
891
  this.enodes.get(t.node1).getPosition(this),
909
892
  ...t.intermediatePositions,
910
893
  this.enodes.get(t.node2).getPosition(this)
911
- ], n = E(i, 5);
912
- return t.intermediatePositions = n.slice(
894
+ ], i = P(o, 5);
895
+ return t.intermediatePositions = i.slice(
913
896
  1,
914
- n.length - 1
915
- ), t.intermediatePositions = E(t.intermediatePositions), t;
897
+ i.length - 1
898
+ ), t.intermediatePositions = P(t.intermediatePositions), t;
916
899
  }
917
900
  /**
918
901
  * Update the source type of an ENode (branching point or component pin).
@@ -921,28 +904,29 @@ class O {
921
904
  * @throws Error if enodeId not found
922
905
  */
923
906
  updateENodeSourceType(e, t) {
924
- const i = this.enodes.get(e);
925
- if (!i)
907
+ const o = this.enodes.get(e);
908
+ if (!o)
926
909
  throw new Error(`ENode ${e} does not exist`);
927
- i.source = t || void 0;
910
+ o.source = t || void 0;
928
911
  }
929
912
  /**
930
913
  * iterate through all components, enodes and wires positions to get the size that allows to enclose all elements.
931
914
  * @param margin - optional margin to add to the size
932
915
  * @returns size that allows to enclose all elements plus margin
916
+ * @todo if calls to this method at each build operation ends causes slowness see to optimize by restricting checked elements
933
917
  */
934
918
  getEnclosingSize(e = 0) {
935
919
  let t = 0;
936
- for (const i of this.components.values())
937
- t = Math.max(t, Math.abs(i.position.x), Math.abs(i.position.y));
938
- for (const i of this.enodes.values()) {
939
- if (i.type === g.Pin) continue;
940
- const n = i.position;
941
- n && (t = Math.max(t, Math.abs(n.x), Math.abs(n.y)));
920
+ for (const o of this.components.values())
921
+ t = Math.max(t, Math.abs(o.position.x), Math.abs(o.position.y));
922
+ for (const o of this.enodes.values()) {
923
+ if (o.type === m.Pin) continue;
924
+ const i = o.position;
925
+ i && (t = Math.max(t, Math.abs(i.x), Math.abs(i.y)));
942
926
  }
943
- for (const i of this.wires.values())
944
- for (const n of i.intermediatePositions)
945
- t = Math.max(t, Math.abs(n.x), Math.abs(n.y));
927
+ for (const o of this.wires.values())
928
+ for (const i of o.intermediatePositions)
929
+ t = Math.max(t, Math.abs(i.x), Math.abs(i.y));
946
930
  return Math.ceil(t * 2 + Math.max(e, 0));
947
931
  }
948
932
  /**
@@ -979,115 +963,27 @@ class O {
979
963
  * ```
980
964
  */
981
965
  static fromJSON(e) {
982
- const t = new O();
983
- t.metadata = v.fromJSON(e.metadata);
966
+ const t = N.fromJSON(e.metadata), o = new x(t.options);
967
+ o.metadata = t;
984
968
  for (const i of e.components) {
985
- const n = C.fromJSON(
986
- i
987
- );
988
- t.components.set(n.id, n);
969
+ const n = _.fromJSON(i);
970
+ o.components.set(n.id, n);
989
971
  }
990
972
  for (const i of e.enodes) {
991
- const n = w.fromJSON(
992
- i
993
- );
994
- t.enodes.set(n.id, n);
973
+ const n = I.fromJSON(i);
974
+ o.enodes.set(n.id, n);
995
975
  }
996
976
  if (e.wires)
997
977
  for (const i of e.wires) {
998
- const n = f.fromJSON(
999
- i
1000
- );
1001
- t.wires.set(n.id, n);
1002
- const s = t.enodes.get(n.node1), o = t.enodes.get(n.node2);
1003
- s && s.wires.add(n.id), o && o.wires.add(n.id);
978
+ const n = w.fromJSON(i);
979
+ o.wires.set(n.id, n);
980
+ const s = o.enodes.get(n.node1), c = o.enodes.get(n.node2);
981
+ s && s.wires.add(n.id), c && c.wires.add(n.id);
1004
982
  }
1005
- return t;
1006
- }
1007
- }
1008
- class Q {
1009
- behaviors;
1010
- /**
1011
- * Create a new empty behavior registry.
1012
- */
1013
- constructor() {
1014
- this.behaviors = /* @__PURE__ */ new Map();
1015
- }
1016
- /**
1017
- * Register a behavior for a component type.
1018
- * Overwrites any existing behavior for the same type.
1019
- *
1020
- * @param behavior - The component behavior to register
1021
- * @throws TypeError if behavior is null/undefined or componentType is empty
1022
- * @returns The registry instance for chaining
1023
- */
1024
- register(e) {
1025
- if (!e)
1026
- throw new TypeError("Behavior cannot be null or undefined");
1027
- if (!e.componentType || e.componentType.trim() === "")
1028
- throw new TypeError("Behavior componentType cannot be empty");
1029
- return this.behaviors.set(e.componentType, e), this;
1030
- }
1031
- /**
1032
- * Register multiple behaviors at once.
1033
- * Convenience method for bulk registration.
1034
- *
1035
- * @param behaviors - Array of behaviors to register
1036
- */
1037
- registerAll(e) {
1038
- e.forEach((t) => this.register(t));
1039
- }
1040
- /**
1041
- * Get the behavior for a component type.
1042
- *
1043
- * @param componentType - Type identifier (e.g., "battery", "led")
1044
- * @returns The registered behavior, or undefined if not found
1045
- */
1046
- get(e) {
1047
- return this.behaviors.get(e);
1048
- }
1049
- /**
1050
- * Check if a behavior is registered for a component type.
1051
- *
1052
- * @param componentType - Type identifier to check
1053
- * @returns True if behavior is registered
1054
- */
1055
- has(e) {
1056
- return this.behaviors.has(e);
1057
- }
1058
- /**
1059
- * Unregister a behavior for a component type.
1060
- *
1061
- * @param componentType - Type identifier to unregister
1062
- * @returns True if behavior was found and removed
1063
- */
1064
- unregister(e) {
1065
- return this.behaviors.delete(e);
1066
- }
1067
- /**
1068
- * Clear all registered behaviors.
1069
- */
1070
- clear() {
1071
- this.behaviors.clear();
1072
- }
1073
- /**
1074
- * Get all registered component types.
1075
- *
1076
- * @returns Array of component type identifiers
1077
- */
1078
- getRegisteredTypes() {
1079
- return Array.from(this.behaviors.keys());
1080
- }
1081
- /**
1082
- * Get count of registered behaviors.
1083
- *
1084
- * @returns Number of registered behaviors
1085
- */
1086
- size() {
1087
- return this.behaviors.size;
983
+ return o;
1088
984
  }
1089
985
  }
1090
- class m {
986
+ class v {
1091
987
  /**
1092
988
  * Component UUID this state belongs to.
1093
989
  * @readonly
@@ -1115,7 +1011,7 @@ class m {
1115
1011
  return this.componentId === e.componentId;
1116
1012
  }
1117
1013
  }
1118
- class B extends m {
1014
+ class Y extends v {
1119
1015
  /**
1120
1016
  * Create a new battery state.
1121
1017
  *
@@ -1125,262 +1021,462 @@ class B extends m {
1125
1021
  super(e, "on");
1126
1022
  }
1127
1023
  }
1128
- class k {
1129
- componentType = p.Battery;
1024
+ class q extends v {
1130
1025
  /**
1131
- * Create initial state for a battery.
1026
+ * Create a new Lightbulb state.
1132
1027
  *
1133
- * @param component - The Battery component
1134
- * @returns Battery Initial state (always active and delivering voltage)
1028
+ * @param componentId - UUID of the Lightbulb component
1029
+ * @param initialState - Initial operational state (default: "off")
1135
1030
  */
1136
- createInitialState(e) {
1137
- if (e.type !== p.Battery)
1138
- throw new Error(`Invalid component type for BatteryBehavior: ${e.type}`);
1139
- return new B(e.id);
1140
- }
1141
- allowConductivity(e, t, i, n, s) {
1142
- return !1;
1031
+ constructor(e, t = "off") {
1032
+ super(e, t);
1143
1033
  }
1144
1034
  /**
1145
- * Batteries are always on, and their pins are locked so this is more of a decorative function
1146
- * @param component
1147
- * @param componentState
1148
- * @param nodeStates
1149
- * @param _targetTick
1035
+ * Check if Lightbulb is in lit state (on or going_on)
1150
1036
  */
1151
- onPinsChange(e, t, i, n) {
1152
- const s = /* @__PURE__ */ new Map();
1153
- for (const o in e.pins)
1154
- s.set(e.getPinLabel(o), i.get(o));
1155
- return {
1156
- componentState: t,
1157
- hasChanged: !1,
1158
- scheduledEvents: []
1159
- };
1160
- }
1161
- onUserCommand(e, t, i) {
1162
- return {
1163
- componentState: t,
1164
- hasChanged: !1,
1165
- scheduledEvents: []
1166
- };
1167
- }
1168
- onEventFiring(e, t, i) {
1169
- return {
1170
- componentState: t,
1171
- hasChanged: !1,
1172
- scheduledEvents: []
1173
- };
1037
+ get isLit() {
1038
+ return this.state === "on" || this.state === "goingOn";
1174
1039
  }
1175
1040
  }
1176
- class W extends m {
1041
+ class V extends v {
1177
1042
  /**
1178
- * Create a new Lightbulb state.
1043
+ * Create a new SmallLED state.
1179
1044
  *
1180
- * @param componentId - UUID of the Lightbulb component
1045
+ * @param componentId - UUID of the LED component
1181
1046
  * @param initialState - Initial operational state (default: "off")
1182
1047
  */
1183
1048
  constructor(e, t = "off") {
1184
1049
  super(e, t);
1185
1050
  }
1186
1051
  /**
1187
- * Check if Lightbulb is in lit state (on or going_on)
1052
+ * Check if LED is in lit state (on or going_on)
1188
1053
  */
1189
1054
  get isLit() {
1190
1055
  return this.state === "on" || this.state === "goingOn";
1191
1056
  }
1192
1057
  }
1193
- class x {
1194
- componentType = p.Lightbulb;
1058
+ class Q extends V {
1059
+ }
1060
+ class Z extends v {
1195
1061
  /**
1196
- * Create initial state for a lightbulb.
1062
+ * Create a new Relay state.
1197
1063
  *
1198
- * @param component - The lightbulb component
1199
- * @returns lightbulbInitial state (always active and delivering voltage)
1064
+ * @param componentId - UUID of the Relay component
1065
+ * @param initialState - Initial operational state (default: "open")
1200
1066
  */
1201
- createInitialState(e) {
1202
- if (e.type !== p.Lightbulb)
1203
- throw new Error(`Invalid component type for lightbulbBehavior: ${e.type}`);
1204
- return new W(e.id);
1067
+ constructor(e, t = "open") {
1068
+ super(e, t);
1205
1069
  }
1206
- allowConductivity(e, t, i, n, s) {
1207
- return !0;
1070
+ /**
1071
+ * Check if relay is in opening or closing state
1072
+ */
1073
+ get isInTransition() {
1074
+ return this.state === "closing" || this.state === "opening";
1208
1075
  }
1209
1076
  /**
1210
- * @param component
1211
- * @param state
1212
- * @param nodeStates
1213
- * @param targetTick
1077
+ * Check if relay is in closed or closing state
1214
1078
  */
1215
- onPinsChange(e, t, i, n) {
1216
- const s = /* @__PURE__ */ new Map();
1217
- for (const c of e.pins)
1218
- s.set(e.getPinLabel(c), i.get(c));
1219
- let o = s.get("pin1").hasVoltage && s.get("pin1").hasCurrent || s.get("pin2").hasVoltage && s.get("pin2").hasCurrent || s.get("pin1").hasVoltage && s.get("pin2").hasCurrent || s.get("pin2").hasVoltage && s.get("pin1").hasCurrent, a = !1;
1220
- const r = [];
1221
- return o ? (t.state === "off" || t.state === "goingOff") && (a = !0, t.state = "goingOn", t.startTick = n, r.push({
1222
- targetId: e.id,
1223
- scheduledAtTick: n,
1224
- readyAtTick: n + 1,
1225
- // TODO handle component config later
1226
- type: "GoingOnEnd",
1227
- parameters: void 0
1228
- }), t.state = "goingOn") : (t.state === "on" || t.state === "goingOn") && (a = !0, t.state = "goingOff", t.startTick = n, r.push({
1229
- targetId: e.id,
1230
- scheduledAtTick: n,
1231
- readyAtTick: n + 1,
1232
- // TODO handle component config later
1233
- type: "GoingOffEnd",
1234
- parameters: void 0
1235
- }), t.state = "goingOff"), {
1236
- componentState: t,
1237
- hasChanged: a,
1238
- scheduledEvents: r
1239
- };
1079
+ get isClosed() {
1080
+ return this.state === "closed" || this.state === "closing";
1240
1081
  }
1241
- onUserCommand(e, t, i) {
1242
- return {
1243
- componentState: t,
1244
- hasChanged: !1,
1245
- scheduledEvents: []
1246
- };
1082
+ }
1083
+ class j extends v {
1084
+ /**
1085
+ * Create a new Switch state.
1086
+ *
1087
+ * @param componentId - UUID of the Switch component
1088
+ * @param initialState - Initial operational state (default: "open")
1089
+ */
1090
+ constructor(e, t = "open") {
1091
+ super(e, t);
1247
1092
  }
1248
- onEventFiring(e, t, i) {
1249
- let n = !1;
1250
- return i.type === "GoingOffEnd" ? t.state !== "off" && (n = !0, t.startTick = i.readyAtTick, t.state = "off") : i.type === "GoingOnEnd" && t.state !== "on" && (n = !0, t.startTick = i.readyAtTick, t.state = "on"), {
1251
- componentState: t,
1252
- hasChanged: n,
1253
- scheduledEvents: []
1254
- };
1093
+ /**
1094
+ * Check if switch is in opening or closing state
1095
+ */
1096
+ get isInTransition() {
1097
+ return this.state === "closing" || this.state === "opening";
1098
+ }
1099
+ /**
1100
+ * Check if switch is in closed or closing state
1101
+ */
1102
+ get isClosed() {
1103
+ return this.state === "closed" || this.state === "closing";
1255
1104
  }
1256
1105
  }
1257
- class N extends m {
1106
+ class ee extends v {
1258
1107
  /**
1259
- * Create a new SmallLED state.
1108
+ * Create a new double Switch state.
1260
1109
  *
1261
- * @param componentId - UUID of the LED component
1262
- * @param initialState - Initial operational state (default: "off")
1110
+ * @param componentId - UUID of the double Switch component
1111
+ * @param initialState - Initial operational state (default: "input1")
1263
1112
  */
1264
- constructor(e, t = "off") {
1113
+ constructor(e, t = "input1") {
1265
1114
  super(e, t);
1266
1115
  }
1267
1116
  /**
1268
- * Check if LED is in lit state (on or going_on)
1117
+ * Check if switch is in 1to2 or 2to1 state
1269
1118
  */
1270
- get isLit() {
1271
- return this.state === "on" || this.state === "goingOn";
1119
+ get isInTransition() {
1120
+ return this.state === "1to2" || this.state === "2to1";
1272
1121
  }
1273
1122
  }
1274
- class I {
1275
- componentType = p.SmallLED;
1123
+ class g extends v {
1276
1124
  /**
1277
- * Create initial state for a smallLED.
1125
+ * Create a new Inverter state.
1278
1126
  *
1279
- * @param component - The smallLED component
1280
- * @returns LED Initial state (always active and delivering voltage)
1127
+ * @param componentId - UUID of the Inverter component
1128
+ * @param initialState - Initial operational state (default: "low")
1281
1129
  */
1282
- createInitialState(e) {
1283
- if (e.type !== p.SmallLED)
1284
- throw new Error(`Invalid component type for SmallLEDBehavior: ${e.type}`);
1285
- return new N(e.id);
1130
+ constructor(e, t = "low") {
1131
+ super(e, t);
1286
1132
  }
1287
- allowConductivity(e, t, i, n, s) {
1288
- return !0;
1133
+ /**
1134
+ * Check if output is in a rising or falling transition
1135
+ */
1136
+ get isInTransition() {
1137
+ return this.state === "rising" || this.state === "falling";
1289
1138
  }
1290
1139
  /**
1291
- * only symmetrical behavior of LEDS is handled for now
1292
- * @param component
1293
- * @param state
1294
- * @param nodeStates
1295
- * @param targetTick
1140
+ * Check if output is high
1141
+ */
1142
+ get isHigh() {
1143
+ return this.state === "high";
1144
+ }
1145
+ }
1146
+ class te extends g {
1147
+ /**
1148
+ * Create a new Inverter state.
1149
+ *
1150
+ * @param componentId - UUID of the Inverter component
1151
+ * @param initialState - Initial operational state (default: "low")
1152
+ */
1153
+ constructor(e, t = "low") {
1154
+ super(e, t);
1155
+ }
1156
+ }
1157
+ class ne extends g {
1158
+ /**
1159
+ * Create a new NAND Gate state.
1160
+ *
1161
+ * @param componentId - UUID of the NAND Gate component
1162
+ * @param initialState - Initial operational state (default: "low")
1296
1163
  */
1297
- onPinsChange(e, t, i, n) {
1298
- const s = /* @__PURE__ */ new Map();
1299
- for (const c of e.pins)
1300
- s.set(e.getPinLabel(c), i.get(c));
1301
- let o = s.get("anode").hasVoltage && s.get("anode").hasCurrent || s.get("cathode").hasVoltage && s.get("cathode").hasCurrent || s.get("anode").hasVoltage && s.get("cathode").hasCurrent || s.get("cathode").hasVoltage && s.get("anode").hasCurrent, a = !1;
1302
- const r = [];
1303
- return o ? (t.state === "off" || t.state === "goingOff") && (a = !0, t.state = "goingOn", t.startTick = n, r.push({
1164
+ constructor(e, t = "low") {
1165
+ super(e, t);
1166
+ }
1167
+ }
1168
+ class ie extends g {
1169
+ constructor(e, t = "low") {
1170
+ super(e, t);
1171
+ }
1172
+ }
1173
+ class oe extends g {
1174
+ constructor(e, t = "low") {
1175
+ super(e, t);
1176
+ }
1177
+ }
1178
+ class se extends g {
1179
+ constructor(e, t = "low") {
1180
+ super(e, t);
1181
+ }
1182
+ }
1183
+ class re extends g {
1184
+ constructor(e, t = "low") {
1185
+ super(e, t);
1186
+ }
1187
+ }
1188
+ class ae extends g {
1189
+ constructor(e, t = "low") {
1190
+ super(e, t);
1191
+ }
1192
+ }
1193
+ class ce extends g {
1194
+ constructor(e, t = "low") {
1195
+ super(e, t);
1196
+ }
1197
+ }
1198
+ class ue extends g {
1199
+ constructor(e, t = "low") {
1200
+ super(e, t);
1201
+ }
1202
+ }
1203
+ class he extends g {
1204
+ constructor(e, t = "low") {
1205
+ super(e, t);
1206
+ }
1207
+ }
1208
+ class Oe {
1209
+ behaviors;
1210
+ /**
1211
+ * Create a new empty behavior registry.
1212
+ */
1213
+ constructor() {
1214
+ this.behaviors = /* @__PURE__ */ new Map();
1215
+ }
1216
+ /**
1217
+ * Register a behavior for a component type.
1218
+ * Overwrites any existing behavior for the same type.
1219
+ *
1220
+ * @param behavior - The component behavior to register
1221
+ * @throws TypeError if behavior is null/undefined or componentType is empty
1222
+ * @returns The registry instance for chaining
1223
+ */
1224
+ register(e) {
1225
+ if (!e)
1226
+ throw new TypeError("Behavior cannot be null or undefined");
1227
+ if (!e.componentType || e.componentType.trim() === "")
1228
+ throw new TypeError("Behavior componentType cannot be empty");
1229
+ return this.behaviors.set(e.componentType, e), this;
1230
+ }
1231
+ /**
1232
+ * Register multiple behaviors at once.
1233
+ * Convenience method for bulk registration.
1234
+ *
1235
+ * @param behaviors - Array of behaviors to register
1236
+ */
1237
+ registerAll(e) {
1238
+ e.forEach((t) => this.register(t));
1239
+ }
1240
+ /**
1241
+ * Get the behavior for a component type.
1242
+ *
1243
+ * @param componentType - Type identifier (e.g., "battery", "led")
1244
+ * @returns The registered behavior, or undefined if not found
1245
+ */
1246
+ get(e) {
1247
+ return this.behaviors.get(e);
1248
+ }
1249
+ /**
1250
+ * Check if a behavior is registered for a component type.
1251
+ *
1252
+ * @param componentType - Type identifier to check
1253
+ * @returns True if behavior is registered
1254
+ */
1255
+ has(e) {
1256
+ return this.behaviors.has(e);
1257
+ }
1258
+ /**
1259
+ * Unregister a behavior for a component type.
1260
+ *
1261
+ * @param componentType - Type identifier to unregister
1262
+ * @returns True if behavior was found and removed
1263
+ */
1264
+ unregister(e) {
1265
+ return this.behaviors.delete(e);
1266
+ }
1267
+ /**
1268
+ * Clear all registered behaviors.
1269
+ */
1270
+ clear() {
1271
+ this.behaviors.clear();
1272
+ }
1273
+ /**
1274
+ * Get all registered component types.
1275
+ *
1276
+ * @returns Array of component type identifiers
1277
+ */
1278
+ getRegisteredTypes() {
1279
+ return Array.from(this.behaviors.keys());
1280
+ }
1281
+ /**
1282
+ * Get count of registered behaviors.
1283
+ *
1284
+ * @returns Number of registered behaviors
1285
+ */
1286
+ size() {
1287
+ return this.behaviors.size;
1288
+ }
1289
+ }
1290
+ class y {
1291
+ /**
1292
+ * Component type this behavior handles (e.g., "battery", "led", "switch").
1293
+ * Used as the key in BehaviorRegistry.
1294
+ */
1295
+ _componentType;
1296
+ constructor(e) {
1297
+ this._componentType = e;
1298
+ }
1299
+ get componentType() {
1300
+ return this._componentType;
1301
+ }
1302
+ get typeMetadata() {
1303
+ const e = G[this._componentType];
1304
+ if (!e)
1305
+ throw new Error(`Unknown metadata for Component type ${this._componentType}`);
1306
+ return e;
1307
+ }
1308
+ getPinStates(e, t) {
1309
+ const o = /* @__PURE__ */ new Map();
1310
+ for (const i of e.pins)
1311
+ o.set(e.getPinLabel(i), t.get(i));
1312
+ return o;
1313
+ }
1314
+ /**
1315
+ * Default: nothing happens
1316
+ * @param _component
1317
+ * @param componentState
1318
+ * @param _nodeStates
1319
+ * @param _targetTick
1320
+ */
1321
+ onPinsChange(e, t, o, i) {
1322
+ return {
1323
+ componentState: t,
1324
+ hasChanged: !1,
1325
+ shouldCancelPending: !1,
1326
+ scheduledEvents: []
1327
+ };
1328
+ }
1329
+ /**
1330
+ * Default: no conductivity between pins
1331
+ * @param _component
1332
+ * @param _state
1333
+ * @param _conductivityType
1334
+ * @param _pinId
1335
+ * @param _otherPinId
1336
+ */
1337
+ allowConductivity(e, t, o, i, n) {
1338
+ return !1;
1339
+ }
1340
+ onUserCommand(e, t, o) {
1341
+ return {
1342
+ componentState: t,
1343
+ hasChanged: !1,
1344
+ shouldCancelPending: !1,
1345
+ scheduledEvents: []
1346
+ };
1347
+ }
1348
+ onEventFiring(e, t, o) {
1349
+ return {
1350
+ componentState: t,
1351
+ hasChanged: !1,
1352
+ shouldCancelPending: !1,
1353
+ scheduledEvents: []
1354
+ };
1355
+ }
1356
+ }
1357
+ class de extends y {
1358
+ constructor() {
1359
+ super(h.Battery);
1360
+ }
1361
+ /**
1362
+ * Create initial state for a battery.
1363
+ *
1364
+ * @param component - The Battery component
1365
+ * @returns Battery Initial state (always active and delivering voltage)
1366
+ */
1367
+ createInitialState(e) {
1368
+ if (e.type !== this._componentType)
1369
+ throw new Error(`Invalid component type for BatteryBehavior: ${e.type}`);
1370
+ return new Y(e.id);
1371
+ }
1372
+ }
1373
+ class L extends y {
1374
+ getBehavior(e, t, o, i) {
1375
+ let n = !1;
1376
+ const s = [];
1377
+ return o ? (t.state === "off" || t.state === "goingOff") && (n = !0, t.state = "goingOn", t.startTick = i, s.push({
1304
1378
  targetId: e.id,
1305
- scheduledAtTick: n,
1306
- readyAtTick: n + 1,
1307
- // TODO handle component config later
1379
+ scheduledAtTick: i,
1380
+ readyAtTick: i + 1,
1381
+ // TODO handle component config later ?
1308
1382
  type: "GoingOnEnd",
1309
1383
  parameters: void 0
1310
- })) : (t.state === "on" || t.state === "goingOn") && (a = !0, t.state = "goingOff", t.startTick = n, r.push({
1384
+ }), t.state = "goingOn") : (t.state === "on" || t.state === "goingOn") && (n = !0, t.state = "goingOff", t.startTick = i, s.push({
1311
1385
  targetId: e.id,
1312
- scheduledAtTick: n,
1313
- readyAtTick: n + 1,
1314
- // TODO handle component config later
1386
+ scheduledAtTick: i,
1387
+ readyAtTick: i + 1,
1388
+ // TODO handle component config later ?
1315
1389
  type: "GoingOffEnd",
1316
1390
  parameters: void 0
1317
- })), {
1391
+ }), t.state = "goingOff"), {
1318
1392
  componentState: t,
1319
- hasChanged: a,
1320
- scheduledEvents: r
1393
+ hasChanged: n,
1394
+ shouldCancelPending: !1,
1395
+ scheduledEvents: s
1321
1396
  };
1322
1397
  }
1323
- onUserCommand(e, t, i) {
1324
- return {
1325
- componentState: t,
1326
- hasChanged: !1,
1327
- scheduledEvents: []
1328
- };
1398
+ allowConductivity(e, t, o, i, n) {
1399
+ return !0;
1329
1400
  }
1330
- onEventFiring(e, t, i) {
1331
- let n = !1;
1332
- return i.type === "GoingOffEnd" ? t.state !== "off" && (n = !0, t.startTick = i.readyAtTick, t.state = "off") : i.type === "GoingOnEnd" && t.state !== "on" && (n = !0, t.startTick = i.readyAtTick, t.state = "on"), {
1401
+ onEventFiring(e, t, o) {
1402
+ let i = !1;
1403
+ return o.type === "GoingOffEnd" ? t.state !== "off" && (i = !0, t.startTick = o.readyAtTick, t.state = "off") : o.type === "GoingOnEnd" && t.state !== "on" && (i = !0, t.startTick = o.readyAtTick, t.state = "on"), {
1333
1404
  componentState: t,
1334
- hasChanged: n,
1405
+ hasChanged: i,
1406
+ shouldCancelPending: !1,
1335
1407
  scheduledEvents: []
1336
1408
  };
1337
1409
  }
1338
1410
  }
1339
- class $ extends N {
1411
+ function $(a) {
1412
+ if (!a)
1413
+ return S.TRANSITION_SPAN_TICKS;
1414
+ const e = parseInt(a.get("tickCount") || "", 10);
1415
+ return isNaN(e) || e < 1 ? S.TRANSITION_SPAN_TICKS : e;
1340
1416
  }
1341
- class M extends I {
1342
- componentType = p.RectangleLED;
1417
+ class le extends L {
1418
+ constructor() {
1419
+ super(h.Lightbulb);
1420
+ }
1343
1421
  /**
1344
- * Create initial state for a RectangleLED.
1422
+ * Create initial state for a lightbulb.
1345
1423
  *
1346
- * @param component - The smallLED component
1347
- * @returns LED Initial state (always active and delivering voltage)
1424
+ * @param component - The lightbulb component
1425
+ * @returns lightbulbInitial state (always active and delivering voltage)
1348
1426
  */
1349
1427
  createInitialState(e) {
1350
- if (e.type !== p.RectangleLED)
1351
- throw new Error(`Invalid component type for RectangleLEDBehavior: ${e.type}`);
1352
- return new $(e.id);
1428
+ if (e.type !== this._componentType)
1429
+ throw new Error(`Invalid component type for lightbulbBehavior: ${e.type}`);
1430
+ return new q(e.id);
1353
1431
  }
1354
- }
1355
- class J extends m {
1356
1432
  /**
1357
- * Create a new Relay state.
1358
- *
1359
- * @param componentId - UUID of the Relay component
1360
- * @param initialState - Initial operational state (default: "open")
1433
+ * @param component
1434
+ * @param state
1435
+ * @param nodeStates
1436
+ * @param targetTick
1361
1437
  */
1362
- constructor(e, t = "open") {
1363
- super(e, t);
1438
+ onPinsChange(e, t, o, i) {
1439
+ const n = this.getPinStates(e, o);
1440
+ let s = n.get("pin1").hasVoltage && n.get("pin1").hasCurrent || n.get("pin2").hasVoltage && n.get("pin2").hasCurrent || n.get("pin1").hasVoltage && n.get("pin2").hasCurrent || n.get("pin2").hasVoltage && n.get("pin1").hasCurrent;
1441
+ return this.getBehavior(e, t, s, i);
1442
+ }
1443
+ }
1444
+ class ge extends L {
1445
+ constructor() {
1446
+ super(h.RectangleLED);
1364
1447
  }
1365
1448
  /**
1366
- * Check if relay is in opening or closing state
1449
+ * Create initial state for a RectangleLED.
1450
+ *
1451
+ * @param component - The smallLED component
1452
+ * @returns LED Initial state (always active and delivering voltage)
1367
1453
  */
1368
- get isInTransition() {
1369
- return this.state === "closing" || this.state === "opening";
1454
+ createInitialState(e) {
1455
+ if (e.type !== this._componentType)
1456
+ throw new Error(`Invalid component type for RectangleLEDBehavior: ${e.type}`);
1457
+ return new Q(e.id);
1370
1458
  }
1371
1459
  /**
1372
- * Check if relay is in closed or closing state
1460
+ * only symmetrical behavior of LEDS is handled for now
1461
+ * @param component
1462
+ * @param state
1463
+ * @param nodeStates
1464
+ * @param targetTick
1373
1465
  */
1374
- get isClosed() {
1375
- return this.state === "closed" || this.state === "closing";
1466
+ onPinsChange(e, t, o, i) {
1467
+ const n = this.getPinStates(e, o);
1468
+ let s = n.get("pin2").hasVoltage && n.get("pin2").hasCurrent || n.get("pin1").hasVoltage && n.get("pin1").hasCurrent || n.get("pin2").hasVoltage && n.get("pin1").hasCurrent || n.get("pin1").hasVoltage && n.get("pin2").hasCurrent;
1469
+ return this.getBehavior(e, t, s, i);
1376
1470
  }
1377
1471
  }
1378
- function D(d) {
1379
- const e = parseInt(d.get("transitionSpan") || "", 10);
1380
- return isNaN(e) || e < 1 ? y.TRANSITION_SPAN_TICKS : e;
1472
+ function pe(a) {
1473
+ const e = parseInt(a.get("transitionSpan") || "", 10);
1474
+ return isNaN(e) || e < 1 ? S.TRANSITION_SPAN_TICKS : e;
1381
1475
  }
1382
- class R {
1383
- componentType = p.Relay;
1476
+ class fe extends y {
1477
+ constructor() {
1478
+ super(h.Relay);
1479
+ }
1384
1480
  /**
1385
1481
  * Create initial state for a relay.
1386
1482
  *
@@ -1388,16 +1484,16 @@ class R {
1388
1484
  * @returns Relay Initial state (open by default)
1389
1485
  */
1390
1486
  createInitialState(e) {
1391
- if (e.type !== p.Relay)
1487
+ if (e.type !== this._componentType)
1392
1488
  throw new Error(`Invalid component type for RelayBehavior: ${e.type}`);
1393
1489
  const t = e.config.get("activationLogic") === "negative" ? "closed" : "open";
1394
- return new J(e.id, t);
1490
+ return new Z(e.id, t);
1395
1491
  }
1396
- allowConductivity(e, t, i, n, s) {
1397
- if (n === s) return !0;
1398
- const o = e.getPinLabel(n), a = e.getPinLabel(s);
1399
- if (!o || !a) return !1;
1400
- const r = [o, a];
1492
+ allowConductivity(e, t, o, i, n) {
1493
+ if (i === n) return !0;
1494
+ const s = e.getPinLabel(i), c = e.getPinLabel(n);
1495
+ if (!s || !c) return !1;
1496
+ const r = [s, c];
1401
1497
  return r.includes("cmd_in") && r.includes("cmd_out") ? !0 : r.includes("power_in") && r.includes("power_out") ? t.state === "closed" || t.state === "opening" : !1;
1402
1498
  }
1403
1499
  /**
@@ -1407,101 +1503,71 @@ class R {
1407
1503
  * @param nodeStates
1408
1504
  * @param targetTick
1409
1505
  */
1410
- onPinsChange(e, t, i, n) {
1411
- const s = /* @__PURE__ */ new Map();
1412
- for (const h of e.pins)
1413
- s.set(e.getPinLabel(h), i.get(h));
1414
- const o = s.get("cmd_in").hasVoltage && s.get("cmd_in").hasCurrent || s.get("cmd_out").hasVoltage && s.get("cmd_out").hasCurrent || s.get("cmd_in").hasVoltage && s.get("cmd_out").hasCurrent || s.get("cmd_out").hasVoltage && s.get("cmd_in").hasCurrent, a = e.config.get("activationLogic") === "negative" ? !o : o;
1506
+ onPinsChange(e, t, o, i) {
1507
+ const n = this.getPinStates(e, o), s = n.get("cmd_in").hasVoltage && n.get("cmd_in").hasCurrent || n.get("cmd_out").hasVoltage && n.get("cmd_out").hasCurrent || n.get("cmd_in").hasVoltage && n.get("cmd_out").hasCurrent || n.get("cmd_out").hasVoltage && n.get("cmd_in").hasCurrent, c = e.config.get("activationLogic") === "negative" ? !s : s;
1415
1508
  let r = !1;
1416
- const c = [], l = D(e.config);
1417
- return a ? (t.state === "open" || t.state === "opening") && (r = !0, t.state = "closing", t.startTick = n, c.push({
1509
+ const u = [], d = pe(e.config);
1510
+ return c ? (t.state === "open" || t.state === "opening") && (r = !0, t.state = "closing", t.startTick = i, u.push({
1418
1511
  targetId: e.id,
1419
- scheduledAtTick: n,
1420
- readyAtTick: n + l,
1512
+ scheduledAtTick: i,
1513
+ readyAtTick: i + d,
1421
1514
  type: "ClosingEnd",
1422
1515
  parameters: void 0
1423
- })) : (t.state === "closed" || t.state === "closing") && (r = !0, t.state = "opening", t.startTick = n, c.push({
1516
+ })) : (t.state === "closed" || t.state === "closing") && (r = !0, t.state = "opening", t.startTick = i, u.push({
1424
1517
  targetId: e.id,
1425
- scheduledAtTick: n,
1426
- readyAtTick: n + l,
1518
+ scheduledAtTick: i,
1519
+ readyAtTick: i + d,
1427
1520
  type: "OpeningEnd",
1428
1521
  parameters: void 0
1429
1522
  })), {
1430
1523
  componentState: t,
1431
1524
  hasChanged: r,
1432
- scheduledEvents: c
1433
- };
1434
- }
1435
- onUserCommand(e, t, i) {
1436
- return {
1437
- componentState: t,
1438
- hasChanged: !1,
1439
- scheduledEvents: []
1525
+ shouldCancelPending: !1,
1526
+ scheduledEvents: u
1440
1527
  };
1441
1528
  }
1442
- onEventFiring(e, t, i) {
1443
- let n = !1;
1444
- return i.type === "ClosingEnd" ? t.state !== "closed" && (n = !0, t.startTick = i.readyAtTick, t.state = "closed") : i.type === "OpeningEnd" && t.state !== "open" && (n = !0, t.startTick = i.readyAtTick, t.state = "open"), {
1529
+ onEventFiring(e, t, o) {
1530
+ let i = !1;
1531
+ return o.type === "ClosingEnd" ? t.state !== "closed" && (i = !0, t.startTick = o.readyAtTick, t.state = "closed") : o.type === "OpeningEnd" && t.state !== "open" && (i = !0, t.startTick = o.readyAtTick, t.state = "open"), {
1445
1532
  componentState: t,
1446
- hasChanged: n,
1533
+ hasChanged: i,
1534
+ shouldCancelPending: !1,
1447
1535
  scheduledEvents: []
1448
1536
  };
1449
1537
  }
1450
1538
  }
1451
- class F extends m {
1452
- /**
1453
- * Create a new Switch state.
1454
- *
1455
- * @param componentId - UUID of the Switch component
1456
- * @param initialState - Initial operational state (default: "open")
1457
- */
1458
- constructor(e, t = "open") {
1459
- super(e, t);
1460
- }
1461
- /**
1462
- * Check if switch is in opening or closing state
1463
- */
1464
- get isInTransition() {
1465
- return this.state === "closing" || this.state === "opening";
1466
- }
1467
- /**
1468
- * Check if switch is in closed or closing state
1469
- */
1470
- get isClosed() {
1471
- return this.state === "closed" || this.state === "closing";
1539
+ class ve extends L {
1540
+ constructor() {
1541
+ super(h.SmallLED);
1472
1542
  }
1473
- }
1474
- class V extends m {
1475
1543
  /**
1476
- * Create a new Transistor state.
1544
+ * Create initial state for a smallLED.
1477
1545
  *
1478
- * @param componentId - UUID of the Transistor component
1479
- * @param initialState - Initial operational state (default: "open")
1480
- */
1481
- constructor(e, t = "open") {
1482
- super(e, t);
1483
- }
1484
- /**
1485
- * Check if transistor is in opening or closing state
1546
+ * @param component - The smallLED component
1547
+ * @returns LED Initial state (always active and delivering voltage)
1486
1548
  */
1487
- get isInTransition() {
1488
- return this.state === "closing" || this.state === "opening";
1549
+ createInitialState(e) {
1550
+ if (e.type !== this._componentType)
1551
+ throw new Error(`Invalid component type for SmallLEDBehavior: ${e.type}`);
1552
+ return new V(e.id);
1489
1553
  }
1490
1554
  /**
1491
- * Check if transistor is in closed or closing state
1555
+ * only symmetrical behavior of LEDS is handled for now
1556
+ * @param component
1557
+ * @param state
1558
+ * @param nodeStates
1559
+ * @param targetTick
1492
1560
  */
1493
- get isClosed() {
1494
- return this.state === "closed" || this.state === "closing";
1561
+ onPinsChange(e, t, o, i) {
1562
+ const n = this.getPinStates(e, o);
1563
+ let s = n.get("pin2").hasVoltage && n.get("pin2").hasCurrent || n.get("pin1").hasVoltage && n.get("pin1").hasCurrent || n.get("pin2").hasVoltage && n.get("pin1").hasCurrent || n.get("pin1").hasVoltage && n.get("pin2").hasCurrent;
1564
+ return this.getBehavior(e, t, s, i);
1495
1565
  }
1496
1566
  }
1497
- function U(d) {
1498
- if (!d)
1499
- return y.TRANSITION_SPAN_TICKS;
1500
- const e = parseInt(d.get("tickCount") || "", 10);
1501
- return isNaN(e) || e < 1 ? y.TRANSITION_SPAN_TICKS : e;
1502
- }
1503
- class z {
1504
- componentType = p.Switch;
1567
+ class we extends y {
1568
+ constructor() {
1569
+ super(h.Switch);
1570
+ }
1505
1571
  /**
1506
1572
  * Create initial state for a switch.
1507
1573
  *
@@ -1509,175 +1575,543 @@ class z {
1509
1575
  * @returns Switch Initial state (open by default)
1510
1576
  */
1511
1577
  createInitialState(e) {
1512
- if (e.type !== p.Switch)
1578
+ if (e.type !== this._componentType)
1513
1579
  throw new Error(`Invalid component type for SwitchBehavior: ${e.type}`);
1514
1580
  const t = e.config.get("initialState") || "open";
1515
- return new F(e.id, t);
1581
+ return new j(e.id, t);
1516
1582
  }
1517
- allowConductivity(e, t, i, n, s) {
1583
+ allowConductivity(e, t, o, i, n) {
1518
1584
  return t.state === "closed" || t.state === "opening";
1519
1585
  }
1520
- /**
1521
- * Switches states depend on user interaction, not their pins so this is more of a decorative function
1522
- * @param _component
1523
- * @param componentState
1524
- * @param _nodeStates
1525
- * @param _targetTick
1526
- */
1527
- onPinsChange(e, t, i, n) {
1586
+ onUserCommand(e, t, o) {
1587
+ let i = !1;
1588
+ const n = [];
1589
+ if (o.type === "toggle_switch" && ["open", "closed"].includes(t.state)) {
1590
+ t.state = t.state === "open" ? "closing" : "opening", t.startTick = o.scheduledAtTick + 1, i = !0;
1591
+ const s = $(o.parameters);
1592
+ n.push({
1593
+ targetId: e.id,
1594
+ scheduledAtTick: t.startTick,
1595
+ readyAtTick: t.startTick + s,
1596
+ type: t.state === "closing" ? "ClosingEnd" : "OpeningEnd",
1597
+ parameters: void 0
1598
+ });
1599
+ }
1528
1600
  return {
1529
1601
  componentState: t,
1530
- hasChanged: !1,
1602
+ hasChanged: i,
1603
+ shouldCancelPending: !1,
1604
+ scheduledEvents: n
1605
+ };
1606
+ }
1607
+ onEventFiring(e, t, o) {
1608
+ let i = !1;
1609
+ return o.type === "ClosingEnd" ? t.state !== "closed" && (i = !0, t.startTick = o.readyAtTick, t.state = "closed") : o.type === "OpeningEnd" && t.state !== "open" && (i = !0, t.startTick = o.readyAtTick, t.state = "open"), {
1610
+ componentState: t,
1611
+ hasChanged: i,
1612
+ shouldCancelPending: !1,
1531
1613
  scheduledEvents: []
1532
1614
  };
1533
1615
  }
1534
- onUserCommand(e, t, i) {
1535
- let n = !1;
1536
- const s = [];
1537
- if (i.type === "toggle_switch" && ["open", "closed"].includes(t.state)) {
1538
- t.state = t.state === "open" ? "closing" : "opening", t.startTick = i.scheduledAtTick + 1, n = !0;
1539
- const o = U(i.parameters);
1540
- s.push({
1616
+ }
1617
+ class ye extends y {
1618
+ constructor() {
1619
+ super(h.DoubleThrowSwitch);
1620
+ }
1621
+ /**
1622
+ * Create initial state for a double throw switch (SPDT).
1623
+ *
1624
+ * @param component - The double Switch component
1625
+ * @returns double Switch Initial state (input1 by default)
1626
+ */
1627
+ createInitialState(e) {
1628
+ if (e.type !== this._componentType)
1629
+ throw new Error(`Invalid component type for DoubleThrowSwitchBehavior: ${e.type}`);
1630
+ const t = e.config.get("initialState") || "input1";
1631
+ return new ee(e.id, t);
1632
+ }
1633
+ allowConductivity(e, t, o, i, n) {
1634
+ if (i === n) return !0;
1635
+ const s = e.getPinLabel(i), c = e.getPinLabel(n);
1636
+ if (!s || !c) return !1;
1637
+ const r = [s, c];
1638
+ return r.includes("output") && r.includes("input1") ? t.state === "input1" || t.state === "1to2" : r.includes("output") && r.includes("input2") ? t.state === "input2" || t.state === "2to1" : !1;
1639
+ }
1640
+ onUserCommand(e, t, o) {
1641
+ let i = !1;
1642
+ const n = [];
1643
+ if (o.type === "toggle_switch" && ["input1", "input2"].includes(t.state)) {
1644
+ t.state = t.state === "input1" ? "1to2" : "2to1", t.startTick = o.scheduledAtTick + 1, i = !0;
1645
+ const s = $(o.parameters);
1646
+ n.push({
1541
1647
  targetId: e.id,
1542
1648
  scheduledAtTick: t.startTick,
1543
- readyAtTick: t.startTick + o,
1544
- type: t.state === "closing" ? "ClosingEnd" : "OpeningEnd",
1649
+ readyAtTick: t.startTick + s,
1650
+ type: t.state === "1to2" ? "ContactedInput2" : "ContactedInput1",
1545
1651
  parameters: void 0
1546
1652
  });
1547
1653
  }
1548
1654
  return {
1549
1655
  componentState: t,
1550
- hasChanged: n,
1551
- scheduledEvents: s
1656
+ hasChanged: i,
1657
+ shouldCancelPending: !1,
1658
+ scheduledEvents: n
1552
1659
  };
1553
1660
  }
1554
- onEventFiring(e, t, i) {
1555
- let n = !1;
1556
- return i.type === "ClosingEnd" ? t.state !== "closed" && (n = !0, t.startTick = i.readyAtTick, t.state = "closed") : i.type === "OpeningEnd" && t.state !== "open" && (n = !0, t.startTick = i.readyAtTick, t.state = "open"), {
1661
+ onEventFiring(e, t, o) {
1662
+ let i = !1;
1663
+ return o.type === "ContactedInput2" ? t.state !== "input2" && (i = !0, t.startTick = o.readyAtTick, t.state = "input2") : o.type === "ContactedInput1" && t.state !== "input1" && (i = !0, t.startTick = o.readyAtTick, t.state = "input1"), {
1557
1664
  componentState: t,
1558
- hasChanged: n,
1665
+ hasChanged: i,
1666
+ shouldCancelPending: !1,
1559
1667
  scheduledEvents: []
1560
1668
  };
1561
1669
  }
1562
1670
  }
1563
- function G(d) {
1564
- const e = parseInt(d.get("transitionSpan") || "", 10);
1565
- return isNaN(e) || e < 1 ? y.TRANSITION_SPAN_TICKS : e;
1671
+ function me(a) {
1672
+ const e = parseInt(a.get("transitionSpan") || "", 10);
1673
+ return isNaN(e) || e < 1 ? S.TRANSITION_SPAN_TICKS : e;
1566
1674
  }
1567
- class K {
1568
- componentType = p.Transistor;
1675
+ class p extends y {
1569
1676
  /**
1570
- * Create initial state for a transistor.
1571
- *
1572
- * @param component - The Transistor component
1573
- * @returns Transistor Initial state (open by default)
1574
- */
1575
- createInitialState(e) {
1576
- if (e.type !== p.Transistor)
1577
- throw new Error(`Invalid component type for TransistorBehavior: ${e.type}`);
1578
- const t = e.config.get("activationLogic") === "negative" ? "closed" : "open";
1579
- return new V(e.id, t);
1580
- }
1581
- allowConductivity(e, t, i, n, s) {
1582
- if (n === s) return !0;
1583
- const o = e.getPinLabel(n), a = e.getPinLabel(s);
1584
- if (!o || !a) return !1;
1585
- const r = [o, a];
1586
- return r.includes("collector") && r.includes("emitter") ? t.state === "closed" || t.state === "opening" : !1;
1677
+ * default return for all logic gates when vcc fails -> go low immediately
1678
+ * @param state
1679
+ * @param pinStates
1680
+ * @protected
1681
+ */
1682
+ vccGuardBehavior(e, t, o) {
1683
+ if (t.get("vcc").hasVoltage)
1684
+ return null;
1685
+ e.startTick = e.state === "low" ? e.startTick : o;
1686
+ const n = e.state !== "low", s = e.state !== "low";
1687
+ return e.state = "low", {
1688
+ componentState: e,
1689
+ hasChanged: n,
1690
+ shouldCancelPending: s,
1691
+ scheduledEvents: []
1692
+ };
1587
1693
  }
1588
1694
  /**
1589
- * Transistor Base need to have only voltage so that transistor contactor stays closed
1590
- * @param component
1695
+ * guard scanning all inputs of logic gates to detect if Any has:
1696
+ * - both voltage and ground hence with established flowing current
1697
+ * - neither voltage nor ground
1698
+ * it makes a not well-defined input between LOW and HIGH
1699
+ * in that case gate goes to state indeterminate and output nothing too
1591
1700
  * @param state
1592
- * @param nodeStates
1701
+ * @param pinStates
1593
1702
  * @param targetTick
1594
- */
1595
- onPinsChange(e, t, i, n) {
1596
- const s = /* @__PURE__ */ new Map();
1597
- for (const h of e.pins)
1598
- s.set(e.getPinLabel(h), i.get(h));
1599
- const o = s.get("base").hasVoltage, a = e.config.get("activationLogic") === "negative" ? !o : o;
1600
- let r = !1;
1601
- const c = [], l = G(e.config);
1602
- return a ? (t.state === "open" || t.state === "opening") && (r = !0, t.state = "closing", t.startTick = n, c.push({
1603
- targetId: e.id,
1604
- scheduledAtTick: n,
1605
- readyAtTick: n + l,
1606
- type: "ClosingEnd",
1607
- parameters: void 0
1608
- })) : (t.state === "closed" || t.state === "closing") && (r = !0, t.state = "opening", t.startTick = n, c.push({
1609
- targetId: e.id,
1610
- scheduledAtTick: n,
1611
- readyAtTick: n + l,
1612
- type: "OpeningEnd",
1613
- parameters: void 0
1614
- })), {
1615
- componentState: t,
1616
- hasChanged: r,
1617
- scheduledEvents: c
1703
+ * @protected
1704
+ */
1705
+ nonLogicInputGuardBehavior(e, t, o) {
1706
+ let i = !1;
1707
+ const n = this.typeMetadata.pins;
1708
+ for (const [r, u] of t) {
1709
+ if (!n.has(r)) continue;
1710
+ const d = n.get(r);
1711
+ if (d && d?.subtype === "logicInput") {
1712
+ if (u.hasVoltage && u.hasCurrent) {
1713
+ i = !0;
1714
+ break;
1715
+ }
1716
+ if (!u.hasVoltage && !u.hasCurrent) {
1717
+ i = !0;
1718
+ break;
1719
+ }
1720
+ }
1721
+ }
1722
+ if (!i)
1723
+ return null;
1724
+ e.startTick = e.state === "indeterminate" ? e.startTick : o;
1725
+ const s = e.state !== "indeterminate", c = e.state !== "indeterminate";
1726
+ return e.state = "indeterminate", {
1727
+ componentState: e,
1728
+ hasChanged: s,
1729
+ shouldCancelPending: c,
1730
+ scheduledEvents: []
1618
1731
  };
1619
1732
  }
1620
- onUserCommand(e, t, i) {
1621
- return {
1733
+ getBehavior(e, t, o, i) {
1734
+ const n = me(e.config);
1735
+ return ["low", "rising", "high", "falling", "indeterminate"].includes(t.state) || (t.state = "low"), o ? t.state === "low" || t.state === "indeterminate" ? (t.state = "rising", t.startTick = i, {
1736
+ componentState: t,
1737
+ hasChanged: !0,
1738
+ shouldCancelPending: !1,
1739
+ scheduledEvents: [{
1740
+ targetId: e.id,
1741
+ scheduledAtTick: i,
1742
+ readyAtTick: i + n,
1743
+ type: "RisingComplete",
1744
+ parameters: void 0
1745
+ }]
1746
+ }) : t.state === "rising" || t.state === "high" ? {
1622
1747
  componentState: t,
1623
1748
  hasChanged: !1,
1749
+ shouldCancelPending: !1,
1624
1750
  scheduledEvents: []
1625
- };
1751
+ } : (t.state = "high", {
1752
+ componentState: t,
1753
+ hasChanged: !0,
1754
+ shouldCancelPending: !0,
1755
+ // goes back to high immediately and cancel pending FallingComplete event
1756
+ scheduledEvents: []
1757
+ }) : t.state === "falling" || t.state === "low" ? {
1758
+ componentState: t,
1759
+ hasChanged: !1,
1760
+ shouldCancelPending: !1,
1761
+ scheduledEvents: []
1762
+ } : t.state === "high" ? (t.state = "falling", t.startTick = i, {
1763
+ componentState: t,
1764
+ hasChanged: !0,
1765
+ shouldCancelPending: !1,
1766
+ scheduledEvents: [{
1767
+ targetId: e.id,
1768
+ scheduledAtTick: i,
1769
+ readyAtTick: i + n,
1770
+ type: "FallingComplete",
1771
+ parameters: void 0
1772
+ }]
1773
+ }) : (t.state = "low", {
1774
+ componentState: t,
1775
+ hasChanged: !0,
1776
+ shouldCancelPending: !0,
1777
+ // goes back to low immediately and cancel pending RisingComplete event
1778
+ scheduledEvents: []
1779
+ });
1626
1780
  }
1627
- onEventFiring(e, t, i) {
1628
- let n = !1;
1629
- return i.type === "ClosingEnd" ? t.state !== "closed" && (n = !0, t.startTick = i.readyAtTick, t.state = "closed") : i.type === "OpeningEnd" && t.state !== "open" && (n = !0, t.startTick = i.readyAtTick, t.state = "open"), {
1781
+ allowConductivity(e, t, o, i, n) {
1782
+ if (i === n) return !0;
1783
+ const s = e.getPinLabel(i), c = e.getPinLabel(n);
1784
+ if (!s || !c) return !1;
1785
+ const r = [s, c];
1786
+ return r.includes("vcc") && r.includes("output") ? t.state === "high" || t.state === "falling" : r.includes("gnd") && r.includes("output") ? t.state === "low" || t.state === "rising" : !1;
1787
+ }
1788
+ onEventFiring(e, t, o) {
1789
+ let i = !1;
1790
+ return o.type === "RisingComplete" ? t.state !== "high" && (i = !0, t.startTick = o.readyAtTick, t.state = "high") : o.type === "FallingComplete" && t.state !== "low" && (i = !0, t.startTick = o.readyAtTick, t.state = "low"), {
1630
1791
  componentState: t,
1631
- hasChanged: n,
1792
+ hasChanged: i,
1793
+ shouldCancelPending: !1,
1632
1794
  scheduledEvents: []
1633
1795
  };
1634
1796
  }
1635
1797
  }
1636
- function Y(d) {
1637
- return d.register(new k()).register(new x()).register(new M()).register(new R()).register(new I()).register(new z()).register(new K()), d;
1798
+ class Se extends p {
1799
+ constructor() {
1800
+ super(h.Inverter);
1801
+ }
1802
+ /**
1803
+ * Create initial state for a Inverter.
1804
+ *
1805
+ * @param component - The Inverter component
1806
+ * @returns Inverter Initial state (HIGH if input LOW, LOW if input LOW for positive activation logic)
1807
+ */
1808
+ createInitialState(e) {
1809
+ if (e.type !== this._componentType)
1810
+ throw new Error(`Invalid component type for InverterBehavior: ${e.type}`);
1811
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1812
+ return new te(e.id, t);
1813
+ }
1814
+ /**
1815
+ * Inverter needs LOW on input to drive the output HIGH, and on the contrary Buffer needs HIGH on input to output HIGH
1816
+ * @param component
1817
+ * @param state
1818
+ * @param nodeStates
1819
+ * @param targetTick
1820
+ */
1821
+ onPinsChange(e, t, o, i) {
1822
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1823
+ if (s)
1824
+ return s;
1825
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1826
+ if (c)
1827
+ return c;
1828
+ const r = n.get("input").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1829
+ return this.getBehavior(e, t, u, i);
1830
+ }
1831
+ }
1832
+ class Ce extends p {
1833
+ constructor() {
1834
+ super(h.NandGate);
1835
+ }
1836
+ /**
1837
+ * Create initial state for an NAND Gate.
1838
+ *
1839
+ * @param component - The NAND Gate component
1840
+ * @returns Initial state (low by default, high for negative activation logic)
1841
+ */
1842
+ createInitialState(e) {
1843
+ if (e.type !== this._componentType)
1844
+ throw new Error(`Invalid component type for NandGateBehavior: ${e.type}`);
1845
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1846
+ return new ne(e.id, t);
1847
+ }
1848
+ /**
1849
+ * NAND gate output goes high when ANY inputs LACK voltage.
1850
+ * With positive activationLogic (AND), output goes high when ALL inputs HAS voltage.
1851
+ */
1852
+ onPinsChange(e, t, o, i) {
1853
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1854
+ if (s)
1855
+ return s;
1856
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1857
+ if (c)
1858
+ return c;
1859
+ const r = n.get("input1").hasVoltage && n.get("input2").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1860
+ return this.getBehavior(e, t, u, i);
1861
+ }
1862
+ }
1863
+ class Ne extends p {
1864
+ constructor() {
1865
+ super(h.Nand4Gate);
1866
+ }
1867
+ createInitialState(e) {
1868
+ if (e.type !== this._componentType)
1869
+ throw new Error(`Invalid component type for Nand4GateBehavior: ${e.type}`);
1870
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1871
+ return new ie(e.id, t);
1872
+ }
1873
+ onPinsChange(e, t, o, i) {
1874
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1875
+ if (s)
1876
+ return s;
1877
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1878
+ if (c)
1879
+ return c;
1880
+ const r = n.get("input1").hasVoltage && n.get("input2").hasVoltage && n.get("input3").hasVoltage && n.get("input4").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1881
+ return this.getBehavior(e, t, u, i);
1882
+ }
1883
+ }
1884
+ class Be extends p {
1885
+ constructor() {
1886
+ super(h.Nand8Gate);
1887
+ }
1888
+ createInitialState(e) {
1889
+ if (e.type !== this._componentType)
1890
+ throw new Error(`Invalid component type for Nand8GateBehavior: ${e.type}`);
1891
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1892
+ return new oe(e.id, t);
1893
+ }
1894
+ onPinsChange(e, t, o, i) {
1895
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1896
+ if (s)
1897
+ return s;
1898
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1899
+ if (c)
1900
+ return c;
1901
+ const r = n.get("input1").hasVoltage && n.get("input2").hasVoltage && n.get("input3").hasVoltage && n.get("input4").hasVoltage && n.get("input5").hasVoltage && n.get("input6").hasVoltage && n.get("input7").hasVoltage && n.get("input8").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1902
+ return this.getBehavior(e, t, u, i);
1903
+ }
1904
+ }
1905
+ class Ie extends p {
1906
+ constructor() {
1907
+ super(h.NorGate);
1908
+ }
1909
+ createInitialState(e) {
1910
+ if (e.type !== this._componentType)
1911
+ throw new Error(`Invalid component type for NorGateBehavior: ${e.type}`);
1912
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1913
+ return new se(e.id, t);
1914
+ }
1915
+ /**
1916
+ * NOR gate output goes high when ALL inputs LACK voltage.
1917
+ * With positive activationLogic (OR), output goes high when ANY inputs HAS voltage.
1918
+ */
1919
+ onPinsChange(e, t, o, i) {
1920
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1921
+ if (s)
1922
+ return s;
1923
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1924
+ if (c)
1925
+ return c;
1926
+ const r = n.get("input1").hasVoltage || n.get("input2").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1927
+ return this.getBehavior(e, t, u, i);
1928
+ }
1929
+ }
1930
+ class Pe extends p {
1931
+ constructor() {
1932
+ super(h.Nor4Gate);
1933
+ }
1934
+ createInitialState(e) {
1935
+ if (e.type !== this._componentType)
1936
+ throw new Error(`Invalid component type for Nor4GateBehavior: ${e.type}`);
1937
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1938
+ return new re(e.id, t);
1939
+ }
1940
+ onPinsChange(e, t, o, i) {
1941
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1942
+ if (s)
1943
+ return s;
1944
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1945
+ if (c)
1946
+ return c;
1947
+ const r = n.get("input1").hasVoltage || n.get("input2").hasVoltage || n.get("input3").hasVoltage || n.get("input4").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1948
+ return this.getBehavior(e, t, u, i);
1949
+ }
1950
+ }
1951
+ class Te extends p {
1952
+ constructor() {
1953
+ super(h.Nor8Gate);
1954
+ }
1955
+ createInitialState(e) {
1956
+ if (e.type !== this._componentType)
1957
+ throw new Error(`Invalid component type for Nor8GateBehavior: ${e.type}`);
1958
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1959
+ return new ae(e.id, t);
1960
+ }
1961
+ onPinsChange(e, t, o, i) {
1962
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1963
+ if (s)
1964
+ return s;
1965
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1966
+ if (c)
1967
+ return c;
1968
+ const r = n.get("input1").hasVoltage || n.get("input2").hasVoltage || n.get("input3").hasVoltage || n.get("input4").hasVoltage || n.get("input5").hasVoltage || n.get("input6").hasVoltage || n.get("input7").hasVoltage || n.get("input8").hasVoltage, u = e.config.get("activationLogic") === "negative" ? !r : r;
1969
+ return this.getBehavior(e, t, u, i);
1970
+ }
1971
+ }
1972
+ class Ee extends p {
1973
+ constructor() {
1974
+ super(h.XorGate);
1975
+ }
1976
+ createInitialState(e) {
1977
+ if (e.type !== this._componentType)
1978
+ throw new Error(`Invalid component type for XorGateBehavior: ${e.type}`);
1979
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
1980
+ return new ce(e.id, t);
1981
+ }
1982
+ /**
1983
+ * XOR gate output goes high when inputs differ (odd parity).
1984
+ * With negative activationLogic (XNOR), output goes high when inputs are equal (even parity).
1985
+ */
1986
+ onPinsChange(e, t, o, i) {
1987
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
1988
+ if (s)
1989
+ return s;
1990
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
1991
+ if (c)
1992
+ return c;
1993
+ const r = n.get("input1").hasVoltage, u = n.get("input2").hasVoltage, d = r !== u, l = e.config.get("activationLogic") === "negative" ? !d : d;
1994
+ return this.getBehavior(e, t, l, i);
1995
+ }
1996
+ }
1997
+ class Ge extends p {
1998
+ constructor() {
1999
+ super(h.Xor4Gate);
2000
+ }
2001
+ createInitialState(e) {
2002
+ if (e.type !== this._componentType)
2003
+ throw new Error(`Invalid component type for Xor4GateBehavior: ${e.type}`);
2004
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
2005
+ return new ue(e.id, t);
2006
+ }
2007
+ onPinsChange(e, t, o, i) {
2008
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
2009
+ if (s)
2010
+ return s;
2011
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
2012
+ if (c)
2013
+ return c;
2014
+ const u = ((n.get("input1").hasVoltage ? 1 : 0) + (n.get("input2").hasVoltage ? 1 : 0) + (n.get("input3").hasVoltage ? 1 : 0) + (n.get("input4").hasVoltage ? 1 : 0)) % 2 === 1, d = e.config.get("activationLogic") === "negative" ? !u : u;
2015
+ return this.getBehavior(e, t, d, i);
2016
+ }
2017
+ }
2018
+ class Le extends p {
2019
+ constructor() {
2020
+ super(h.Xor8Gate);
2021
+ }
2022
+ createInitialState(e) {
2023
+ if (e.type !== this._componentType)
2024
+ throw new Error(`Invalid component type for Xor8GateBehavior: ${e.type}`);
2025
+ const t = e.config.get("activationLogic") === "negative" ? "high" : "low";
2026
+ return new he(e.id, t);
2027
+ }
2028
+ onPinsChange(e, t, o, i) {
2029
+ const n = this.getPinStates(e, o), s = this.vccGuardBehavior(t, n, i);
2030
+ if (s)
2031
+ return s;
2032
+ const c = this.nonLogicInputGuardBehavior(t, n, i);
2033
+ if (c)
2034
+ return c;
2035
+ const u = ((n.get("input1").hasVoltage ? 1 : 0) + (n.get("input2").hasVoltage ? 1 : 0) + (n.get("input3").hasVoltage ? 1 : 0) + (n.get("input4").hasVoltage ? 1 : 0) + (n.get("input5").hasVoltage ? 1 : 0) + (n.get("input6").hasVoltage ? 1 : 0) + (n.get("input7").hasVoltage ? 1 : 0) + (n.get("input8").hasVoltage ? 1 : 0)) % 2 === 1, d = e.config.get("activationLogic") === "negative" ? !u : u;
2036
+ return this.getBehavior(e, t, d, i);
2037
+ }
2038
+ }
2039
+ function Ae(a) {
2040
+ return a.register(new de()).register(new le()).register(new ge()).register(new fe()).register(new ve()).register(new we()).register(new ye()), a;
2041
+ }
2042
+ function xe(a) {
2043
+ return a.register(new Se()).register(new Ce()).register(new Ne()).register(new Be()).register(new Ie()).register(new Pe()).register(new Te()).register(new Ee()).register(new Ge()).register(new Le()), a;
1638
2044
  }
1639
2045
  export {
1640
- k as BatteryBehavior,
1641
- B as BatteryState,
1642
- Q as BehaviorRegistry,
1643
- L as COMPONENT_TYPE_METADATA,
1644
- b as CameraOptions,
1645
- O as Circuit,
1646
- v as CircuitMetadata,
1647
- Z as CircuitRunner,
1648
- C as Component,
1649
- m as ComponentState,
1650
- p as ComponentType,
1651
- j as DirtyTracker,
1652
- w as ENode,
1653
- ee as ENodeSourceType,
1654
- g as ENodeType,
1655
- te as EventQueue,
1656
- x as LightbulbBehavior,
1657
- W as LightbulbState,
1658
- P as Position,
1659
- ne as Position3D,
1660
- M as RectangleLEDBehavior,
1661
- $ as RectangleLEDState,
1662
- R as RelayBehavior,
1663
- J as RelayState,
1664
- ie as Rotation,
1665
- se as SIMULATION_SPEED,
1666
- oe as SimulationState,
1667
- I as SmallLEDBehavior,
1668
- N as SmallLEDState,
1669
- re as StateManager,
1670
- z as SwitchBehavior,
1671
- F as SwitchState,
1672
- y as TRANSITION_DEFAULTS,
1673
- K as TransistorBehavior,
1674
- V as TransistorState,
1675
- f as Wire,
1676
- A as findPositionBestIndex,
1677
- T as generateUUID,
1678
- ae as getAllComponentTypes,
1679
- _ as getComponentTypeMetadata,
1680
- Y as registerBasicComponentsBehaviors,
1681
- E as simplifyPositions
2046
+ Me as ALL_LOGIC_FAMILIES,
2047
+ de as BatteryBehavior,
2048
+ Y as BatteryState,
2049
+ Oe as BehaviorRegistry,
2050
+ E as CIRCUIT_FILE_VERSION,
2051
+ G as COMPONENT_TYPE_METADATA,
2052
+ A as CameraOptions,
2053
+ x as Circuit,
2054
+ N as CircuitMetadata,
2055
+ C as CircuitOptions,
2056
+ Re as CircuitRunner,
2057
+ _ as Component,
2058
+ v as ComponentState,
2059
+ h as ComponentType,
2060
+ O as DEFAULT_LOGIC_FAMILY,
2061
+ De as DirtyTracker,
2062
+ ye as DoubleThrowSwitchBehavior,
2063
+ ee as DoubleThrowSwitchState,
2064
+ I as ENode,
2065
+ We as ENodeSourceType,
2066
+ m as ENodeType,
2067
+ ke as EventQueue,
2068
+ Se as InverterBehavior,
2069
+ te as InverterState,
2070
+ le as LightbulbBehavior,
2071
+ q as LightbulbState,
2072
+ W as Memoize,
2073
+ be as MemoizeExpiring,
2074
+ Ne as Nand4GateBehavior,
2075
+ ie as Nand4GateState,
2076
+ Be as Nand8GateBehavior,
2077
+ oe as Nand8GateState,
2078
+ Ce as NandGateBehavior,
2079
+ ne as NandGateState,
2080
+ Pe as Nor4GateBehavior,
2081
+ re as Nor4GateState,
2082
+ Te as Nor8GateBehavior,
2083
+ ae as Nor8GateState,
2084
+ Ie as NorGateBehavior,
2085
+ se as NorGateState,
2086
+ R as Position,
2087
+ Fe as Position3D,
2088
+ ge as RectangleLEDBehavior,
2089
+ Q as RectangleLEDState,
2090
+ fe as RelayBehavior,
2091
+ Z as RelayState,
2092
+ Xe as Rotation,
2093
+ Je as SIMULATION_SPEED,
2094
+ Ue as SimulationState,
2095
+ ve as SmallLEDBehavior,
2096
+ V as SmallLEDState,
2097
+ ze as StateManager,
2098
+ we as SwitchBehavior,
2099
+ j as SwitchState,
2100
+ S as TRANSITION_DEFAULTS,
2101
+ w as Wire,
2102
+ Ge as Xor4GateBehavior,
2103
+ ue as Xor4GateState,
2104
+ Le as Xor8GateBehavior,
2105
+ he as Xor8GateState,
2106
+ Ee as XorGateBehavior,
2107
+ ce as XorGateState,
2108
+ H as classifyGate,
2109
+ K as computeGateDelay,
2110
+ U as computeTransitionSpan,
2111
+ D as findPositionBestIndex,
2112
+ M as generateUUID,
2113
+ Ae as registerBasicComponentsBehaviors,
2114
+ xe as registerGatesComponentsBehaviors,
2115
+ P as simplifyPositions
1682
2116
  };
1683
2117
  //# sourceMappingURL=index.js.map