simple-circuit-engine 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +13 -7
- package/CLAUDE.md +16 -103
- package/README.md +8 -5
- package/dist/core/index.d.ts +2 -23
- package/dist/core/index.js +75 -2000
- package/dist/core/setup.d.ts +17 -0
- package/dist/core/simulation/CircuitRunner.d.ts +176 -0
- package/dist/core/simulation/DirtyTracker.d.ts +87 -0
- package/dist/core/simulation/EventQueue.d.ts +68 -0
- package/dist/core/simulation/StateManager.d.ts +100 -0
- package/dist/core/simulation/behaviors/BehaviorRegistry.d.ts +70 -0
- package/dist/core/simulation/behaviors/ComponentBehavior.d.ts +53 -0
- package/dist/core/simulation/behaviors/basic/BatteryBehavior.d.ts +14 -0
- package/dist/core/simulation/behaviors/basic/ClockBehavior.d.ts +24 -0
- package/dist/core/simulation/behaviors/basic/DoubleThrowSwitchBehavior.d.ts +33 -0
- package/dist/core/simulation/behaviors/basic/LightbulbBehavior.d.ts +23 -0
- package/dist/core/simulation/behaviors/basic/RectangleLEDBehavior.d.ts +24 -0
- package/dist/core/simulation/behaviors/basic/RelayBehavior.d.ts +33 -0
- package/dist/core/simulation/behaviors/basic/SmallLEDBehavior.d.ts +24 -0
- package/dist/core/simulation/behaviors/basic/SwitchBehavior.d.ts +33 -0
- package/dist/core/simulation/behaviors/basic/index.d.ts +20 -0
- package/dist/core/simulation/behaviors/gates/InverterBehavior.d.ts +29 -0
- package/dist/core/simulation/behaviors/gates/Nand4GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/Nand8GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/NandGateBehavior.d.ts +28 -0
- package/dist/core/simulation/behaviors/gates/Nor4GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/Nor8GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/NorGateBehavior.d.ts +22 -0
- package/dist/core/simulation/behaviors/gates/Xor4GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/Xor8GateBehavior.d.ts +18 -0
- package/dist/core/simulation/behaviors/gates/XorGateBehavior.d.ts +22 -0
- package/dist/core/simulation/behaviors/gates/index.d.ts +34 -0
- package/dist/core/simulation/behaviors/index.d.ts +24 -0
- package/dist/core/simulation/behaviors/types.d.ts +101 -0
- package/dist/core/simulation/index.d.ts +18 -0
- package/dist/core/simulation/states/ComponentState.d.ts +57 -0
- package/dist/core/simulation/states/SimulationState.d.ts +46 -0
- package/dist/core/simulation/states/basic/BatteryState.d.ts +16 -0
- package/dist/core/simulation/states/basic/ClockState.d.ts +16 -0
- package/dist/core/simulation/states/basic/DoubleThrowSwitchState.d.ts +21 -0
- package/dist/core/simulation/states/basic/LightbulbState.d.ts +21 -0
- package/dist/core/simulation/states/basic/RectangleLEDState.d.ts +9 -0
- package/dist/core/simulation/states/basic/RelayState.d.ts +25 -0
- package/dist/core/simulation/states/basic/SmallLEDState.d.ts +21 -0
- package/dist/core/simulation/states/basic/SwitchState.d.ts +25 -0
- package/dist/core/simulation/states/gates/InverterState.d.ts +17 -0
- package/dist/core/simulation/states/gates/Nand4GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Nand8GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/NandGateState.d.ts +16 -0
- package/dist/core/simulation/states/gates/Nor4GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Nor8GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/NorGateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Xor4GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/Xor8GateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/XorGateState.d.ts +10 -0
- package/dist/core/simulation/states/gates/index.d.ts +25 -0
- package/dist/core/simulation/states/index.d.ts +26 -0
- package/dist/core/simulation/states/types.d.ts +32 -0
- package/dist/core/simulation/types.d.ts +155 -0
- package/dist/core/topology/Circuit.d.ts +420 -0
- package/dist/core/topology/CircuitMetadata.d.ts +24 -0
- package/dist/core/topology/CircuitOptions.d.ts +14 -0
- package/dist/core/topology/Component.d.ts +152 -0
- package/dist/core/topology/ENode.d.ts +200 -0
- package/dist/core/topology/Wire.d.ts +130 -0
- package/dist/core/topology/delays.d.ts +52 -0
- package/dist/core/topology/index.d.ts +14 -0
- package/dist/core/topology/types.d.ts +175 -0
- package/dist/core/utils/CameraOptions.d.ts +83 -0
- package/dist/core/utils/MemoizeDecorator.d.ts +9 -0
- package/dist/core/utils/Position.d.ts +166 -0
- package/dist/core/utils/Position3D.d.ts +77 -0
- package/dist/core/utils/Rotation.d.ts +82 -0
- package/dist/core/utils/index.d.ts +24 -0
- package/dist/core/utils/types.d.ts +35 -0
- package/dist/core-Bjta9Y7_.js +2707 -0
- package/dist/core-Bjta9Y7_.js.map +1 -0
- package/dist/index.d.ts +13 -6286
- package/dist/index.js +120 -100
- package/dist/scene/CircuitEngine.d.ts +270 -0
- package/dist/scene/index.d.ts +1 -2
- package/dist/scene/index.js +44 -38
- package/dist/scene/setup.d.ts +18 -0
- package/dist/scene/shared/AbstractCircuitController.d.ts +211 -0
- package/dist/scene/shared/BranchingPointVisualFactory.d.ts +70 -0
- package/dist/scene/shared/EventEmitter.d.ts +92 -0
- package/dist/scene/shared/HoverManager.d.ts +151 -0
- package/dist/scene/shared/SelectionManager.d.ts +159 -0
- package/dist/scene/shared/WireVisualManager.d.ts +242 -0
- package/dist/scene/shared/components/ComponentVisualFactory.d.ts +438 -0
- package/dist/scene/shared/components/DefaultVisualFactory.d.ts +51 -0
- package/dist/scene/shared/components/FactoryRegistry.d.ts +84 -0
- package/dist/scene/shared/components/GroupedFactoryRegistry.d.ts +153 -0
- package/dist/scene/shared/components/basic/BatteryVisualFactory.d.ts +13 -0
- package/dist/scene/shared/components/basic/ClockVisualFactory.d.ts +79 -0
- package/dist/scene/shared/components/basic/DoubleThrowSwitchVisualFactory.d.ts +87 -0
- package/dist/scene/shared/components/basic/LabelVisualFactory.d.ts +148 -0
- package/dist/scene/shared/components/basic/LightbulbVisualFactory.d.ts +72 -0
- package/dist/scene/shared/components/basic/RectangleLEDVisualFactory.d.ts +86 -0
- package/dist/scene/shared/components/basic/RelayVisualFactory.d.ts +92 -0
- package/dist/scene/shared/components/basic/SmallLEDVisualFactory.d.ts +86 -0
- package/dist/scene/shared/components/basic/SwitchVisualFactory.d.ts +85 -0
- package/dist/scene/shared/components/gates/InverterVisualFactory.d.ts +104 -0
- package/dist/scene/shared/components/gates/Nand4GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/Nand8GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/NandGateVisualFactory.d.ts +101 -0
- package/dist/scene/shared/components/gates/Nor4GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/Nor8GateVisualFactory.d.ts +27 -0
- package/dist/scene/shared/components/gates/NorGateVisualFactory.d.ts +101 -0
- package/dist/scene/shared/components/gates/Xor4GateVisualFactory.d.ts +29 -0
- package/dist/scene/shared/components/gates/Xor8GateVisualFactory.d.ts +29 -0
- package/dist/scene/shared/components/gates/XorGateVisualFactory.d.ts +103 -0
- package/dist/scene/shared/components/index.d.ts +29 -0
- package/dist/scene/shared/components/types.d.ts +43 -0
- package/dist/scene/shared/types.d.ts +476 -0
- package/dist/scene/shared/utils/CameraUtils.d.ts +23 -0
- package/dist/scene/shared/utils/ColorUtils.d.ts +26 -0
- package/dist/scene/shared/utils/ControlsUtils.d.ts +8 -0
- package/dist/scene/shared/utils/GeometryUtils.d.ts +261 -0
- package/dist/scene/shared/utils/LayerConstants.d.ts +40 -0
- package/dist/scene/shared/utils/LightingUtils.d.ts +31 -0
- package/dist/scene/shared/utils/MaterialUtils.d.ts +73 -0
- package/dist/scene/shared/utils/Options.d.ts +16 -0
- package/dist/scene/simulation/CircuitRunnerController.d.ts +227 -0
- package/dist/scene/static/CircuitController.d.ts +227 -0
- package/dist/scene/static/CircuitWriter.d.ts +146 -0
- package/dist/scene/static/PinTooltipWidget.d.ts +26 -0
- package/dist/scene/static/tools/BuildTool.d.ts +286 -0
- package/dist/scene/static/tools/ComponentPickerWidget.d.ts +82 -0
- package/dist/scene/static/tools/ConfigPanelWidget.d.ts +93 -0
- package/dist/scene/static/tools/MultiSelectTool.d.ts +265 -0
- package/dist/scene-CVsDdySt.js +7357 -0
- package/dist/scene-CVsDdySt.js.map +1 -0
- package/package.json +24 -25
- package/dist/CircuitRunner-DEb7JdNf.js +0 -1809
- package/dist/CircuitRunner-DEb7JdNf.js.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/scene/index.js.map +0 -1
- package/dist/setup-AB1vFiis.js +0 -9918
- package/dist/setup-AB1vFiis.js.map +0 -1
package/dist/core/index.js
CHANGED
|
@@ -1,2002 +1,77 @@
|
|
|
1
|
-
import { e as O, P as
|
|
2
|
-
import { k as me, D as we, E as ye, n as ve, h as Se, R as Ce, m as Te, S as Ee, l as Ie, g as Ae } from "../CircuitRunner-DEb7JdNf.js";
|
|
3
|
-
class w {
|
|
4
|
-
/**
|
|
5
|
-
* Unique identifier for this wire.
|
|
6
|
-
* @readonly
|
|
7
|
-
*/
|
|
8
|
-
id;
|
|
9
|
-
/**
|
|
10
|
-
* First connected ENode UUID.
|
|
11
|
-
* @readonly
|
|
12
|
-
*/
|
|
13
|
-
node1;
|
|
14
|
-
/**
|
|
15
|
-
* Second connected ENode UUID.
|
|
16
|
-
* @readonly
|
|
17
|
-
*/
|
|
18
|
-
node2;
|
|
19
|
-
/**
|
|
20
|
-
* Optional intermediate positions for wire routing.
|
|
21
|
-
* Empty array indicates straight-line connection.
|
|
22
|
-
* @readonly
|
|
23
|
-
*/
|
|
24
|
-
intermediatePositions;
|
|
25
|
-
/**
|
|
26
|
-
* Create a new wire.
|
|
27
|
-
*
|
|
28
|
-
* **Note**: Typically wires are created via `Circuit.addWire()` which
|
|
29
|
-
* handles validation and bidirectional reference updates. This constructor
|
|
30
|
-
* is used internally by Circuit.
|
|
31
|
-
*
|
|
32
|
-
* @param node1 - First ENode UUID
|
|
33
|
-
* @param node2 - Second ENode UUID
|
|
34
|
-
* @param intermediatePositions - Optional waypoints for rendering
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```typescript
|
|
38
|
-
* // Usually created via Circuit:
|
|
39
|
-
* const wire = circuit.addWire(nodeId1, nodeId2);
|
|
40
|
-
*
|
|
41
|
-
* // With intermediate positions:
|
|
42
|
-
* const wire = circuit.addWire(
|
|
43
|
-
* nodeId1,
|
|
44
|
-
* nodeId2,
|
|
45
|
-
* [new Position(5, 10), new Position(15, 10)]
|
|
46
|
-
* );
|
|
47
|
-
* ```
|
|
48
|
-
*/
|
|
49
|
-
constructor(t, e, i = []) {
|
|
50
|
-
this.id = O(), this.node1 = t, this.node2 = e, this.intermediatePositions = i;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Check if this is a straight-line wire.
|
|
54
|
-
*
|
|
55
|
-
* @returns true if no intermediate positions, false otherwise
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```typescript
|
|
59
|
-
* const straightWire = new Wire(node1, node2);
|
|
60
|
-
* console.log(straightWire.isStraightLine()); // true
|
|
61
|
-
*
|
|
62
|
-
* const curvedWire = new Wire(node1, node2, [new Position(5, 5)]);
|
|
63
|
-
* console.log(curvedWire.isStraightLine()); // false
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
isStraightLine() {
|
|
67
|
-
return this.intermediatePositions.length === 0;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Serialize wire to JSON.
|
|
71
|
-
*
|
|
72
|
-
* @returns Plain object representation
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* const json = wire.toJSON();
|
|
77
|
-
* console.log(json);
|
|
78
|
-
* // {
|
|
79
|
-
* // id: "uuid",
|
|
80
|
-
* // node1: "node-uuid-1",
|
|
81
|
-
* // node2: "node-uuid-2",
|
|
82
|
-
* // intermediatePositions: [{ x: 5, y: 10 }]
|
|
83
|
-
* // }
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
toJSON() {
|
|
87
|
-
return {
|
|
88
|
-
id: this.id,
|
|
89
|
-
node1: this.node1,
|
|
90
|
-
node2: this.node2,
|
|
91
|
-
intermediatePositions: this.intermediatePositions.map((t) => t.toJSON())
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Deserialize wire from JSON.
|
|
96
|
-
*
|
|
97
|
-
* @param json - Wire data
|
|
98
|
-
* @returns Wire instance
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* const json = {
|
|
103
|
-
* id: "uuid",
|
|
104
|
-
* node1: "node-uuid-1",
|
|
105
|
-
* node2: "node-uuid-2",
|
|
106
|
-
* intermediatePositions: [{ x: 5, y: 10 }]
|
|
107
|
-
* };
|
|
108
|
-
*
|
|
109
|
-
* const wire = Wire.fromJSON(json);
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
|
-
static fromJSON(t) {
|
|
113
|
-
const e = t.intermediatePositions.map((n) => k.fromJSON(n)), i = new w(t.node1, t.node2, e);
|
|
114
|
-
return Object.defineProperty(i, "id", {
|
|
115
|
-
value: t.id,
|
|
116
|
-
writable: !1,
|
|
117
|
-
enumerable: !0,
|
|
118
|
-
configurable: !1
|
|
119
|
-
}), i;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
class v {
|
|
123
|
-
/**
|
|
124
|
-
* Create a new CircuitMetadata holding general information about the Circuit.
|
|
125
|
-
*
|
|
126
|
-
* @param name - Name of the circuit
|
|
127
|
-
* @param size - Size of the circuit grid
|
|
128
|
-
* @param divisions - Divisions in the circuit grid
|
|
129
|
-
* @param cameraOptions - Camera Options at startup
|
|
130
|
-
* @throws {TypeError} If size or divisions are not integers
|
|
131
|
-
*/
|
|
132
|
-
constructor(t, e, i, n) {
|
|
133
|
-
if (this.name = t, this.size = e, this.divisions = i, this.cameraOptions = n, !Number.isInteger(e) || !Number.isInteger(i))
|
|
134
|
-
throw new TypeError(
|
|
135
|
-
`Size and divisions must be integers (got size=${e}, divisions=${i})`
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
toJSON() {
|
|
139
|
-
return {
|
|
140
|
-
name: this.name,
|
|
141
|
-
size: this.size,
|
|
142
|
-
divisions: this.divisions,
|
|
143
|
-
cameraOptions: this.cameraOptions.toJSON()
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
static fromJSON(t) {
|
|
147
|
-
return new v(
|
|
148
|
-
t.name,
|
|
149
|
-
t.size,
|
|
150
|
-
t.divisions,
|
|
151
|
-
b.fromJSON(t.cameraOptions)
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
toString() {
|
|
155
|
-
return `CircuitMetadata(${this.name}, ${this.size}, ${this.divisions}, ${this.cameraOptions.toString()})`;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
class _ {
|
|
159
|
-
/**
|
|
160
|
-
* Circuit metadata holding general information.
|
|
161
|
-
* @private
|
|
162
|
-
*/
|
|
163
|
-
metadata;
|
|
164
|
-
/**
|
|
165
|
-
* Map of all components in the circuit (UUID → Component).
|
|
166
|
-
* @private
|
|
167
|
-
*/
|
|
168
|
-
components;
|
|
169
|
-
/**
|
|
170
|
-
* Map of all electrical nodes in the circuit (UUID → ENode).
|
|
171
|
-
* Includes both pin nodes and branching point nodes.
|
|
172
|
-
* @private
|
|
173
|
-
*/
|
|
174
|
-
enodes;
|
|
175
|
-
/**
|
|
176
|
-
* Map of all wires in the circuit (UUID → Wire).
|
|
177
|
-
* @private
|
|
178
|
-
*/
|
|
179
|
-
wires;
|
|
180
|
-
/**
|
|
181
|
-
* Create a new empty circuit.
|
|
182
|
-
*/
|
|
183
|
-
constructor(t = "Untitled Circuit") {
|
|
184
|
-
this.metadata = new v(t, 10, 10, new b()), this.components = /* @__PURE__ */ new Map(), this.enodes = /* @__PURE__ */ new Map(), this.wires = /* @__PURE__ */ new Map();
|
|
185
|
-
}
|
|
186
|
-
get name() {
|
|
187
|
-
return this.metadata.name;
|
|
188
|
-
}
|
|
189
|
-
set name(t) {
|
|
190
|
-
if (typeof t != "string" || t.trim() === "")
|
|
191
|
-
throw new TypeError("Circuit name must be a non-empty string");
|
|
192
|
-
this.metadata.name = t;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Add a new component to the circuit.
|
|
196
|
-
*
|
|
197
|
-
* Automatically creates pin ENodes for the component and links them
|
|
198
|
-
* bidirectionally. Pin ENode UUIDs are stored in the component's pins array.
|
|
199
|
-
* Pin labels are derived from the ComponentType metadata.
|
|
200
|
-
*
|
|
201
|
-
* @param type - Component type (Battery, Switch, LED, etc.)
|
|
202
|
-
* @param position - Grid position (x, y integers)
|
|
203
|
-
* @param rotation - Orientation angle (integer degrees)
|
|
204
|
-
* @param config - Optional configuration map for component-specific settings
|
|
205
|
-
* @returns The created Component
|
|
206
|
-
* @throws {TypeError} If position/rotation coordinates are not integers
|
|
207
|
-
*
|
|
208
|
-
* @example
|
|
209
|
-
* ```typescript
|
|
210
|
-
* const lightbulb = circuit.addComponent(
|
|
211
|
-
* new Position(10, 20),
|
|
212
|
-
* new Rotation(90),
|
|
213
|
-
* ComponentType.Lightbulb
|
|
214
|
-
* );
|
|
215
|
-
*
|
|
216
|
-
* console.log(lightbulb.type); // ComponentType.Lightbulb
|
|
217
|
-
* console.log(lightbulb.pins.length); // 2
|
|
218
|
-
* console.log(lightbulb.position.x); // 10
|
|
219
|
-
* ```
|
|
220
|
-
*/
|
|
221
|
-
addComponent(t, e, i, n) {
|
|
222
|
-
const s = B(t), o = new P(t, e, i, []);
|
|
223
|
-
n && (o.config = new Map(n));
|
|
224
|
-
const a = [];
|
|
225
|
-
for (const [r, d] of s.pins) {
|
|
226
|
-
const g = new S(
|
|
227
|
-
y.Pin,
|
|
228
|
-
o.id,
|
|
229
|
-
r,
|
|
230
|
-
void 0,
|
|
231
|
-
// Pin position derived from component,
|
|
232
|
-
d
|
|
233
|
-
);
|
|
234
|
-
this.enodes.set(g.id, g), a.push(g.id);
|
|
235
|
-
}
|
|
236
|
-
return Object.defineProperty(o, "pins", {
|
|
237
|
-
value: a,
|
|
238
|
-
writable: !1,
|
|
239
|
-
enumerable: !0,
|
|
240
|
-
configurable: !1
|
|
241
|
-
}), this.components.set(o.id, o), o;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Remove a component from the circuit.
|
|
245
|
-
*
|
|
246
|
-
* **Cascade deletion** removes:
|
|
247
|
-
* - All pin ENodes belonging to the component
|
|
248
|
-
* - All Wires connected to those pins
|
|
249
|
-
*
|
|
250
|
-
* @param id - Component UUID
|
|
251
|
-
* @throws {Error} If component does not exist
|
|
252
|
-
* @returns Object containing arrays of deleted Wires and ENodes IDs
|
|
253
|
-
*
|
|
254
|
-
* @example
|
|
255
|
-
* ```typescript
|
|
256
|
-
* circuit.removeComponent(componentId);
|
|
257
|
-
* // Component, its pins, and connected wires are all removed
|
|
258
|
-
* ```
|
|
259
|
-
*/
|
|
260
|
-
removeComponent(t) {
|
|
261
|
-
const e = this.components.get(t);
|
|
262
|
-
if (!e)
|
|
263
|
-
throw new Error(`Component ${t} does not exist`);
|
|
264
|
-
const i = [], n = [];
|
|
265
|
-
for (const s of e.pins) {
|
|
266
|
-
const o = this.enodes.get(s);
|
|
267
|
-
if (o) {
|
|
268
|
-
const a = Array.from(o.wires);
|
|
269
|
-
for (const r of a)
|
|
270
|
-
this.removeWire(r), i.push(r);
|
|
271
|
-
}
|
|
272
|
-
this.enodes.delete(s), n.push(s);
|
|
273
|
-
}
|
|
274
|
-
return this.components.delete(t), { deletedWires: i, deletedENodes: n };
|
|
275
|
-
}
|
|
276
|
-
hasComponent(t) {
|
|
277
|
-
return this.components.has(t);
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Get a component by ID.
|
|
281
|
-
*
|
|
282
|
-
* @param id - Component UUID
|
|
283
|
-
* @returns The Component or undefined if not found
|
|
284
|
-
*
|
|
285
|
-
* @example
|
|
286
|
-
* ```typescript
|
|
287
|
-
* const component = circuit.getComponent(componentId);
|
|
288
|
-
* if (component) {
|
|
289
|
-
* console.log(component.position);
|
|
290
|
-
* }
|
|
291
|
-
* ```
|
|
292
|
-
*/
|
|
293
|
-
getComponent(t) {
|
|
294
|
-
return this.components.get(t);
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Get all components in the circuit.
|
|
298
|
-
*
|
|
299
|
-
* Returns a new array on each call (defensive copy).
|
|
300
|
-
*
|
|
301
|
-
* @returns Array of all Components
|
|
302
|
-
*
|
|
303
|
-
* @example
|
|
304
|
-
* ```typescript
|
|
305
|
-
* const components = circuit.getAllComponents();
|
|
306
|
-
* console.log(`Circuit has ${components.length} components`);
|
|
307
|
-
*
|
|
308
|
-
* for (const comp of components) {
|
|
309
|
-
* console.log(comp.id, comp.position);
|
|
310
|
-
* }
|
|
311
|
-
* ```
|
|
312
|
-
*/
|
|
313
|
-
getAllComponents() {
|
|
314
|
-
return Array.from(this.components.values());
|
|
315
|
-
}
|
|
316
|
-
getAllComponentsByType(t) {
|
|
317
|
-
const e = [];
|
|
318
|
-
for (const i of this.components.values())
|
|
319
|
-
i.type === t && e.push(i);
|
|
320
|
-
return e;
|
|
321
|
-
}
|
|
322
|
-
getFirstComponentOfType(t) {
|
|
323
|
-
for (const e of this.components.values())
|
|
324
|
-
if (e.type === t)
|
|
325
|
-
return e;
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Get an electrical node by ID.
|
|
329
|
-
*
|
|
330
|
-
* Note: ENodes are automatically managed and not directly created
|
|
331
|
-
* or removed by users.
|
|
332
|
-
*
|
|
333
|
-
* @param id - ENode UUID
|
|
334
|
-
* @returns The ENode or undefined if not found
|
|
335
|
-
*
|
|
336
|
-
* @example
|
|
337
|
-
* ```typescript
|
|
338
|
-
* const component = circuit.addComponent(
|
|
339
|
-
* new Position(10, 20),
|
|
340
|
-
* new Rotation(0),
|
|
341
|
-
* 2
|
|
342
|
-
* );
|
|
343
|
-
*
|
|
344
|
-
* const pinId = component.pins[0];
|
|
345
|
-
* const enode = circuit.getENode(pinId);
|
|
346
|
-
* console.log(enode.type); // ENodeType.Pin
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
|
-
getENode(t) {
|
|
350
|
-
return this.enodes.get(t);
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Get all electrical nodes in the circuit.
|
|
354
|
-
*
|
|
355
|
-
* Includes both pin nodes (from components) and branching point nodes
|
|
356
|
-
* (from wire splits).
|
|
357
|
-
*
|
|
358
|
-
* Returns a new array on each call (defensive copy).
|
|
359
|
-
*
|
|
360
|
-
* @returns Array of all ENodes
|
|
361
|
-
*
|
|
362
|
-
* @example
|
|
363
|
-
* ```typescript
|
|
364
|
-
* const enodes = circuit.getAllENodes();
|
|
365
|
-
* console.log(`Circuit has ${enodes.length} electrical nodes`);
|
|
366
|
-
*
|
|
367
|
-
* for (const enode of enodes) {
|
|
368
|
-
* console.log(enode.id, enode.type);
|
|
369
|
-
* }
|
|
370
|
-
* ```
|
|
371
|
-
*/
|
|
372
|
-
getAllENodes() {
|
|
373
|
-
return Array.from(this.enodes.values());
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Add a branching point electrical node at a specific position.
|
|
377
|
-
*
|
|
378
|
-
* Branching points are used to split wires and create junctions.
|
|
379
|
-
* @param position - Grid position for the branching point
|
|
380
|
-
* @param sourceType - Optional source type (voltage/current)
|
|
381
|
-
* @returns The created ENode
|
|
382
|
-
*/
|
|
383
|
-
addBranchingPoint(t, e) {
|
|
384
|
-
const i = new S(
|
|
385
|
-
y.BranchingPoint,
|
|
386
|
-
void 0,
|
|
387
|
-
void 0,
|
|
388
|
-
t,
|
|
389
|
-
e
|
|
390
|
-
);
|
|
391
|
-
return this.enodes.set(i.id, i), i;
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Remove a branching point electrical node from the circuit.
|
|
395
|
-
* Also removes all wires connected to this branching point if there are ony one or more than 2.
|
|
396
|
-
* In the case there are exactly two wires, they will be merged before removing the branching point.
|
|
397
|
-
*
|
|
398
|
-
* @param id - Branching point ENode UUID
|
|
399
|
-
* @throws {Error} If ENode does not exist or is not a branching point
|
|
400
|
-
*/
|
|
401
|
-
removeBranchingPoint(t) {
|
|
402
|
-
const e = this.enodes.get(t);
|
|
403
|
-
if (!e)
|
|
404
|
-
throw new Error(`Enode ${t} does not exist`);
|
|
405
|
-
if (e.type !== y.BranchingPoint)
|
|
406
|
-
throw new Error(
|
|
407
|
-
`Enode ${t} is not a branching point, it must be removed with its component.`
|
|
408
|
-
);
|
|
409
|
-
const i = {}, n = this.getWiresByNode(t);
|
|
410
|
-
if (n.length === 1 || n.length > 2) {
|
|
411
|
-
const s = [];
|
|
412
|
-
for (const o of n)
|
|
413
|
-
this.removeWire(o.id), s.push(o.id);
|
|
414
|
-
Object.assign(i, { deletedWires: s });
|
|
415
|
-
} else if (n.length === 2) {
|
|
416
|
-
const s = n[0], o = n[1], a = s.node1 === t ? s.node2 : s.node1, r = o.node1 === t ? o.node2 : o.node1, d = [];
|
|
417
|
-
a === s.node1 ? d.push(...s.intermediatePositions) : a === s.node2 && d.push(...[...s.intermediatePositions].reverse()), d.push(e.getPosition(this)), r === o.node1 ? d.push(...[...o.intermediatePositions].reverse()) : r === o.node2 && d.push(...o.intermediatePositions), this.removeWire(s.id), this.removeWire(o.id);
|
|
418
|
-
const g = this.addWire(a, r, d);
|
|
419
|
-
if (g instanceof Error)
|
|
420
|
-
throw new Error(`Failed to merge wires at branching point ${t}: ${g.message}`);
|
|
421
|
-
Object.assign(i, { mergedWires: [s.id, o.id] }), Object.assign(i, { newWire: g });
|
|
422
|
-
}
|
|
423
|
-
return this.enodes.delete(t), i;
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* Add a wire connecting two electrical nodes.
|
|
427
|
-
*
|
|
428
|
-
* Validates that both nodes exist, not a self-connection, and no duplicate.
|
|
429
|
-
* Updates bidirectional references (Wire ↔ ENodes).
|
|
430
|
-
*
|
|
431
|
-
* @param node1 - First ENode UUID
|
|
432
|
-
* @param node2 - Second ENode UUID
|
|
433
|
-
* @param intermediatePositions - Optional path waypoints for rendering
|
|
434
|
-
* @returns The created Wire, or Error if validation fails
|
|
435
|
-
*
|
|
436
|
-
* @example
|
|
437
|
-
* ```typescript
|
|
438
|
-
* const comp1 = circuit.addComponent(new Position(0, 0), new Rotation(0), 1);
|
|
439
|
-
* const comp2 = circuit.addComponent(new Position(10, 10), new Rotation(0), 1);
|
|
440
|
-
*
|
|
441
|
-
* const wire = circuit.addWire(comp1.pins[0], comp2.pins[0]);
|
|
442
|
-
* if (wire instanceof Error) {
|
|
443
|
-
* console.error('Failed:', wire.message);
|
|
444
|
-
* }
|
|
445
|
-
* ```
|
|
446
|
-
*/
|
|
447
|
-
addWire(t, e, i) {
|
|
448
|
-
if (t === e)
|
|
449
|
-
return new Error("Cannot create wire connecting node to itself");
|
|
450
|
-
const n = this.enodes.get(t), s = this.enodes.get(e);
|
|
451
|
-
if (!n || !s)
|
|
452
|
-
return new Error("Wire requires at least one existing ENode");
|
|
453
|
-
if (this.hasWireBetween(t, e))
|
|
454
|
-
return new Error("Duplicate wire between same nodes");
|
|
455
|
-
const o = new w(t, e, i || []);
|
|
456
|
-
return this.wires.set(o.id, o), n.wires.add(o.id), s.wires.add(o.id), o;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Remove a wire from the circuit.
|
|
460
|
-
*
|
|
461
|
-
* @param id - Wire UUID
|
|
462
|
-
* @throws {Error} If wire does not exist
|
|
463
|
-
*
|
|
464
|
-
* @example
|
|
465
|
-
* ```typescript
|
|
466
|
-
* circuit.removeWire(wireId);
|
|
467
|
-
* // Wire is removed
|
|
468
|
-
* ```
|
|
469
|
-
*/
|
|
470
|
-
removeWire(t) {
|
|
471
|
-
const e = this.wires.get(t);
|
|
472
|
-
if (!e)
|
|
473
|
-
throw new Error(`Wire ${t} does not exist`);
|
|
474
|
-
const i = this.enodes.get(e.node1), n = this.enodes.get(e.node2);
|
|
475
|
-
i && i.wires.delete(t), n && n.wires.delete(t), this.wires.delete(t);
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Split a wire in the circuit.
|
|
479
|
-
*
|
|
480
|
-
* It creates two new wires connected by either the target enode or a new branching point ENode at the specified position.
|
|
481
|
-
* Returns 2 UUIDS of the new wires.
|
|
482
|
-
*
|
|
483
|
-
* @param id - Wire UUID
|
|
484
|
-
* @param position
|
|
485
|
-
* @throws {Error} If wire does not exist
|
|
486
|
-
*
|
|
487
|
-
* @example
|
|
488
|
-
* ```typescript
|
|
489
|
-
* circuit.splitWire(wireId);
|
|
490
|
-
* // Wire and any orphaned branching points are removed
|
|
491
|
-
* ```
|
|
492
|
-
*/
|
|
493
|
-
/**
|
|
494
|
-
* Split an existing wire at a position, creating a branching point.
|
|
495
|
-
* The original wire is removed and replaced with two new wires
|
|
496
|
-
* connecting through the new branching point.
|
|
497
|
-
* NB : in the special case where targetEnode belongs to a component where the wire is already connected
|
|
498
|
-
* only one new wire will be created as this method don't allow a wire directly connecting two pins of the same component.
|
|
499
|
-
*
|
|
500
|
-
* @param wireId - Wire to split
|
|
501
|
-
* @param position - Position for the new branching point : no effect if targetEnodeId provided
|
|
502
|
-
* @param targetEnodeId - if provided, the existing enode to split the wire at
|
|
503
|
-
* @returns Object containing the new branching point and an array of the two new wires
|
|
504
|
-
* @throws Error if wireId not found
|
|
505
|
-
*/
|
|
506
|
-
splitWire(t, e, i = null) {
|
|
507
|
-
const n = this.wires.get(t);
|
|
508
|
-
if (!n)
|
|
509
|
-
throw new Error(`Wire ${t} does not exist`);
|
|
510
|
-
const s = this.enodes.get(n.node1), o = this.enodes.get(n.node2);
|
|
511
|
-
if (!s || !o)
|
|
512
|
-
throw new Error(`Wire ${t} is connected to non-existent ENodes`);
|
|
513
|
-
const a = [
|
|
514
|
-
s.getPosition(this),
|
|
515
|
-
...n.intermediatePositions,
|
|
516
|
-
o.getPosition(this)
|
|
517
|
-
], r = G(a, e), d = a.slice(1, r), g = a.slice(r, a.length - 1);
|
|
518
|
-
this.wires.delete(t), s.wires.delete(t), o.wires.delete(t);
|
|
519
|
-
let l;
|
|
520
|
-
if (i)
|
|
521
|
-
if (this.enodes.get(i))
|
|
522
|
-
l = this.enodes.get(i);
|
|
523
|
-
else
|
|
524
|
-
throw new Error(`Target ENode ${i} does not exist`);
|
|
525
|
-
else
|
|
526
|
-
l = this.addBranchingPoint(e);
|
|
527
|
-
const m = [];
|
|
528
|
-
if ((!l.component || s.component !== l.component) && !this.hasWireBetween(s.id, l.id)) {
|
|
529
|
-
const u = this.addWire(s.id, l.id, d);
|
|
530
|
-
u instanceof w ? (this.simplifyWireIntermediatePositions(u.id), m.push(u)) : console.warn(`Failure to create wire at split : ${u.message}`);
|
|
531
|
-
}
|
|
532
|
-
if ((!l.component || o.component !== l.component) && !this.hasWireBetween(o.id, l.id)) {
|
|
533
|
-
const u = this.addWire(l.id, o.id, g);
|
|
534
|
-
u instanceof w ? (this.simplifyWireIntermediatePositions(u.id), m.push(u)) : console.warn(`Failure to create wire at split : ${u.message}`);
|
|
535
|
-
}
|
|
536
|
-
return {
|
|
537
|
-
branchingPoint: l,
|
|
538
|
-
wires: m
|
|
539
|
-
};
|
|
540
|
-
}
|
|
541
|
-
getWireBetweenNodes(t, e) {
|
|
542
|
-
const i = this.enodes.get(t);
|
|
543
|
-
if (i)
|
|
544
|
-
for (const n of i.wires) {
|
|
545
|
-
const s = this.wires.get(n);
|
|
546
|
-
if (s && (s.node2 === e || s.node1 === e))
|
|
547
|
-
return s;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Get a wire by ID.
|
|
552
|
-
*
|
|
553
|
-
* @param id - Wire UUID
|
|
554
|
-
* @returns The Wire or undefined if not found
|
|
555
|
-
*/
|
|
556
|
-
getWire(t) {
|
|
557
|
-
return this.wires.get(t);
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* Get all wires in the circuit.
|
|
561
|
-
*
|
|
562
|
-
* Returns a new array on each call (defensive copy).
|
|
563
|
-
*
|
|
564
|
-
* @returns Array of all Wires
|
|
565
|
-
*/
|
|
566
|
-
getAllWires() {
|
|
567
|
-
return Array.from(this.wires.values());
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Get all wires connected to a specific ENode.
|
|
571
|
-
*
|
|
572
|
-
* @param nodeId - ENode UUID
|
|
573
|
-
* @returns Array of connected Wires, or empty array if node not found
|
|
574
|
-
*/
|
|
575
|
-
getWiresByNode(t) {
|
|
576
|
-
const e = this.enodes.get(t);
|
|
577
|
-
if (!e)
|
|
578
|
-
return [];
|
|
579
|
-
const i = [];
|
|
580
|
-
for (const n of e.wires) {
|
|
581
|
-
const s = this.wires.get(n);
|
|
582
|
-
s && i.push(s);
|
|
583
|
-
}
|
|
584
|
-
return i;
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* Get all wires connected to a component, e.g to any pin enode of the component.
|
|
588
|
-
*
|
|
589
|
-
* @param componentId - Component UUID
|
|
590
|
-
* @returns Array of connected Wires, or empty array if component not found
|
|
591
|
-
*/
|
|
592
|
-
getWiresByComponent(t) {
|
|
593
|
-
const e = this.components.get(t);
|
|
594
|
-
if (!e)
|
|
595
|
-
return [];
|
|
596
|
-
const i = [];
|
|
597
|
-
for (const n of e.pins)
|
|
598
|
-
i.push(...this.getWiresByNode(n));
|
|
599
|
-
return i;
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* Get both ENodes connected by a wire.
|
|
603
|
-
*
|
|
604
|
-
* @param wireId - Wire UUID
|
|
605
|
-
* @returns Tuple [node1, node2] or undefined if wire not found
|
|
606
|
-
*/
|
|
607
|
-
getNodesByWire(t) {
|
|
608
|
-
const e = this.wires.get(t);
|
|
609
|
-
if (!e)
|
|
610
|
-
return;
|
|
611
|
-
const i = this.enodes.get(e.node1), n = this.enodes.get(e.node2);
|
|
612
|
-
if (!(!i || !n))
|
|
613
|
-
return [i, n];
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Check if a wire already exists between two nodes.
|
|
617
|
-
*
|
|
618
|
-
* Order-independent: returns true for (A, B) or (B, A).
|
|
619
|
-
*
|
|
620
|
-
* @param node1 - First ENode UUID
|
|
621
|
-
* @param node2 - Second ENode UUID
|
|
622
|
-
* @returns true if wire exists, false otherwise
|
|
623
|
-
*/
|
|
624
|
-
hasWireBetween(t, e) {
|
|
625
|
-
const i = this.enodes.get(t);
|
|
626
|
-
if (!i)
|
|
627
|
-
return !1;
|
|
628
|
-
for (const n of i.wires) {
|
|
629
|
-
const s = this.wires.get(n);
|
|
630
|
-
if (s && (s.node2 === e || s.node1 === e))
|
|
631
|
-
return !0;
|
|
632
|
-
}
|
|
633
|
-
return !1;
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Find all components with pins among the provided enode IDs set.
|
|
637
|
-
*
|
|
638
|
-
* @param pinIds - Set of pins UUIDs
|
|
639
|
-
* @returns Set of components UUIDs
|
|
640
|
-
*/
|
|
641
|
-
getComponentsOfPins(t) {
|
|
642
|
-
const e = /* @__PURE__ */ new Set();
|
|
643
|
-
for (const i of t) {
|
|
644
|
-
const n = this.enodes.get(i);
|
|
645
|
-
n?.component && e.add(n.component);
|
|
646
|
-
}
|
|
647
|
-
return e;
|
|
648
|
-
}
|
|
649
|
-
/**
|
|
650
|
-
* Get a component's pin ENode by its label.
|
|
651
|
-
* @param component
|
|
652
|
-
* @param pinLabel
|
|
653
|
-
*/
|
|
654
|
-
getComponentPinByLabel(t, e) {
|
|
655
|
-
let i = 0;
|
|
656
|
-
const n = V[t.type], s = Array.from(n.pins.keys());
|
|
657
|
-
for (const o of t.pins) {
|
|
658
|
-
const a = this.enodes.get(o), r = s[i];
|
|
659
|
-
if (r) {
|
|
660
|
-
if (a && r === e)
|
|
661
|
-
return a;
|
|
662
|
-
i++;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Update the intermediate positions of a wire.
|
|
668
|
-
* Update the wire in place.
|
|
669
|
-
*
|
|
670
|
-
* @param wireId - Wire to update
|
|
671
|
-
* @param intermediatePositions - New intermediate positions
|
|
672
|
-
* @param simplify - Whether to simplify positions by removing collinear points : useful when finalizing wire routing
|
|
673
|
-
* @returns The updated Wire
|
|
674
|
-
* @throws Error if wireId not found
|
|
675
|
-
*/
|
|
676
|
-
updateWireIntermediatePositions(t, e, i = !1) {
|
|
677
|
-
const n = this.wires.get(t);
|
|
678
|
-
if (!n)
|
|
679
|
-
throw new Error(`Wire ${t} does not exist`);
|
|
680
|
-
if (i) {
|
|
681
|
-
const s = [
|
|
682
|
-
this.enodes.get(n.node1).getPosition(this),
|
|
683
|
-
...e,
|
|
684
|
-
this.enodes.get(n.node2).getPosition(this)
|
|
685
|
-
], o = C(s, 10);
|
|
686
|
-
n.intermediatePositions = o.slice(
|
|
687
|
-
1,
|
|
688
|
-
o.length - 1
|
|
689
|
-
);
|
|
690
|
-
} else
|
|
691
|
-
n.intermediatePositions = e;
|
|
692
|
-
return n;
|
|
693
|
-
}
|
|
694
|
-
/**
|
|
695
|
-
* Simplify intermediate positions of a wire.
|
|
696
|
-
* Update the wire in place.
|
|
697
|
-
* @param wireId - Wire to simplify
|
|
698
|
-
* @returns The updated Wire
|
|
699
|
-
* @throws Error if wireId not found
|
|
700
|
-
*/
|
|
701
|
-
simplifyWireIntermediatePositions(t) {
|
|
702
|
-
const e = this.wires.get(t);
|
|
703
|
-
if (!e)
|
|
704
|
-
throw new Error(`Wire ${t} does not exist`);
|
|
705
|
-
const i = [
|
|
706
|
-
this.enodes.get(e.node1).getPosition(this),
|
|
707
|
-
...e.intermediatePositions,
|
|
708
|
-
this.enodes.get(e.node2).getPosition(this)
|
|
709
|
-
], n = C(i, 5);
|
|
710
|
-
return e.intermediatePositions = n.slice(
|
|
711
|
-
1,
|
|
712
|
-
n.length - 1
|
|
713
|
-
), e.intermediatePositions = C(e.intermediatePositions), e;
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* Update the source type of an ENode (branching point or component pin).
|
|
717
|
-
* @param enodeId - ENode to update
|
|
718
|
-
* @param sourceType - New source type (null to clear)
|
|
719
|
-
* @throws Error if enodeId not found
|
|
720
|
-
*/
|
|
721
|
-
updateENodeSourceType(t, e) {
|
|
722
|
-
const i = this.enodes.get(t);
|
|
723
|
-
if (!i)
|
|
724
|
-
throw new Error(`ENode ${t} does not exist`);
|
|
725
|
-
i.source = e || void 0;
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* iterate through all components, enodes and wires positions to get the size that allows to enclose all elements.
|
|
729
|
-
* @param margin - optional margin to add to the size
|
|
730
|
-
* @returns size that allows to enclose all elements plus margin
|
|
731
|
-
* @todo if calls to this method at each build operation ends causes slowness see to optimize by restricting checked elements
|
|
732
|
-
*/
|
|
733
|
-
getEnclosingSize(t = 0) {
|
|
734
|
-
let e = 0;
|
|
735
|
-
for (const i of this.components.values())
|
|
736
|
-
e = Math.max(e, Math.abs(i.position.x), Math.abs(i.position.y));
|
|
737
|
-
for (const i of this.enodes.values()) {
|
|
738
|
-
if (i.type === y.Pin) continue;
|
|
739
|
-
const n = i.position;
|
|
740
|
-
n && (e = Math.max(e, Math.abs(n.x), Math.abs(n.y)));
|
|
741
|
-
}
|
|
742
|
-
for (const i of this.wires.values())
|
|
743
|
-
for (const n of i.intermediatePositions)
|
|
744
|
-
e = Math.max(e, Math.abs(n.x), Math.abs(n.y));
|
|
745
|
-
return Math.ceil(e * 2 + Math.max(t, 0));
|
|
746
|
-
}
|
|
747
|
-
/**
|
|
748
|
-
* Serialize circuit to JSON.
|
|
749
|
-
*
|
|
750
|
-
* @returns JSON-serializable object containing all components, enodes, and wires
|
|
751
|
-
*
|
|
752
|
-
* @example
|
|
753
|
-
* ```typescript
|
|
754
|
-
* const json = circuit.toJSON();
|
|
755
|
-
* localStorage.setItem('my-circuit', JSON.stringify(json));
|
|
756
|
-
* ```
|
|
757
|
-
*/
|
|
758
|
-
toJSON() {
|
|
759
|
-
return {
|
|
760
|
-
metadata: this.metadata.toJSON(),
|
|
761
|
-
components: this.getAllComponents().map((t) => t.toJSON()),
|
|
762
|
-
enodes: this.getAllENodes().map((t) => t.toJSON()),
|
|
763
|
-
wires: this.getAllWires().map((t) => t.toJSON())
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Deserialize circuit from JSON.
|
|
768
|
-
*
|
|
769
|
-
* @param json - Circuit data
|
|
770
|
-
* @returns Circuit instance
|
|
771
|
-
* @throws {Error} If JSON is invalid or violates invariants
|
|
772
|
-
*
|
|
773
|
-
* @example
|
|
774
|
-
* ```typescript
|
|
775
|
-
* const jsonStr = localStorage.getItem('my-circuit');
|
|
776
|
-
* const json = JSON.parse(jsonStr);
|
|
777
|
-
* const circuit = Circuit.fromJSON(json);
|
|
778
|
-
* ```
|
|
779
|
-
*/
|
|
780
|
-
static fromJSON(t) {
|
|
781
|
-
const e = new _();
|
|
782
|
-
e.metadata = v.fromJSON(t.metadata);
|
|
783
|
-
for (const i of t.components) {
|
|
784
|
-
const n = P.fromJSON(
|
|
785
|
-
i
|
|
786
|
-
);
|
|
787
|
-
e.components.set(n.id, n);
|
|
788
|
-
}
|
|
789
|
-
for (const i of t.enodes) {
|
|
790
|
-
const n = S.fromJSON(
|
|
791
|
-
i
|
|
792
|
-
);
|
|
793
|
-
e.enodes.set(n.id, n);
|
|
794
|
-
}
|
|
795
|
-
if (t.wires)
|
|
796
|
-
for (const i of t.wires) {
|
|
797
|
-
const n = w.fromJSON(
|
|
798
|
-
i
|
|
799
|
-
);
|
|
800
|
-
e.wires.set(n.id, n);
|
|
801
|
-
const s = e.enodes.get(n.node1), o = e.enodes.get(n.node2);
|
|
802
|
-
s && s.wires.add(n.id), o && o.wires.add(n.id);
|
|
803
|
-
}
|
|
804
|
-
return e;
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
class ge {
|
|
808
|
-
behaviors;
|
|
809
|
-
/**
|
|
810
|
-
* Create a new empty behavior registry.
|
|
811
|
-
*/
|
|
812
|
-
constructor() {
|
|
813
|
-
this.behaviors = /* @__PURE__ */ new Map();
|
|
814
|
-
}
|
|
815
|
-
/**
|
|
816
|
-
* Register a behavior for a component type.
|
|
817
|
-
* Overwrites any existing behavior for the same type.
|
|
818
|
-
*
|
|
819
|
-
* @param behavior - The component behavior to register
|
|
820
|
-
* @throws TypeError if behavior is null/undefined or componentType is empty
|
|
821
|
-
* @returns The registry instance for chaining
|
|
822
|
-
*/
|
|
823
|
-
register(t) {
|
|
824
|
-
if (!t)
|
|
825
|
-
throw new TypeError("Behavior cannot be null or undefined");
|
|
826
|
-
if (!t.componentType || t.componentType.trim() === "")
|
|
827
|
-
throw new TypeError("Behavior componentType cannot be empty");
|
|
828
|
-
return this.behaviors.set(t.componentType, t), this;
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* Register multiple behaviors at once.
|
|
832
|
-
* Convenience method for bulk registration.
|
|
833
|
-
*
|
|
834
|
-
* @param behaviors - Array of behaviors to register
|
|
835
|
-
*/
|
|
836
|
-
registerAll(t) {
|
|
837
|
-
t.forEach((e) => this.register(e));
|
|
838
|
-
}
|
|
839
|
-
/**
|
|
840
|
-
* Get the behavior for a component type.
|
|
841
|
-
*
|
|
842
|
-
* @param componentType - Type identifier (e.g., "battery", "led")
|
|
843
|
-
* @returns The registered behavior, or undefined if not found
|
|
844
|
-
*/
|
|
845
|
-
get(t) {
|
|
846
|
-
return this.behaviors.get(t);
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Check if a behavior is registered for a component type.
|
|
850
|
-
*
|
|
851
|
-
* @param componentType - Type identifier to check
|
|
852
|
-
* @returns True if behavior is registered
|
|
853
|
-
*/
|
|
854
|
-
has(t) {
|
|
855
|
-
return this.behaviors.has(t);
|
|
856
|
-
}
|
|
857
|
-
/**
|
|
858
|
-
* Unregister a behavior for a component type.
|
|
859
|
-
*
|
|
860
|
-
* @param componentType - Type identifier to unregister
|
|
861
|
-
* @returns True if behavior was found and removed
|
|
862
|
-
*/
|
|
863
|
-
unregister(t) {
|
|
864
|
-
return this.behaviors.delete(t);
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* Clear all registered behaviors.
|
|
868
|
-
*/
|
|
869
|
-
clear() {
|
|
870
|
-
this.behaviors.clear();
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
* Get all registered component types.
|
|
874
|
-
*
|
|
875
|
-
* @returns Array of component type identifiers
|
|
876
|
-
*/
|
|
877
|
-
getRegisteredTypes() {
|
|
878
|
-
return Array.from(this.behaviors.keys());
|
|
879
|
-
}
|
|
880
|
-
/**
|
|
881
|
-
* Get count of registered behaviors.
|
|
882
|
-
*
|
|
883
|
-
* @returns Number of registered behaviors
|
|
884
|
-
*/
|
|
885
|
-
size() {
|
|
886
|
-
return this.behaviors.size;
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
class p {
|
|
890
|
-
/**
|
|
891
|
-
* Component UUID this state belongs to.
|
|
892
|
-
* @readonly
|
|
893
|
-
*/
|
|
894
|
-
componentId;
|
|
895
|
-
/**
|
|
896
|
-
* Current operational state (varies by component type).
|
|
897
|
-
* Examples: "on", "off", "open", "closed", "activating", "active"
|
|
898
|
-
*/
|
|
899
|
-
state;
|
|
900
|
-
/**
|
|
901
|
-
* Tick when this state started.
|
|
902
|
-
*/
|
|
903
|
-
startTick;
|
|
904
|
-
/**
|
|
905
|
-
* Create a new component state.
|
|
906
|
-
*
|
|
907
|
-
* @param componentId - UUID of the component
|
|
908
|
-
* @param initialState - Initial operational state
|
|
909
|
-
*/
|
|
910
|
-
constructor(t, e) {
|
|
911
|
-
this.componentId = t, this.state = e, this.startTick = 0;
|
|
912
|
-
}
|
|
913
|
-
hasSameComponent(t) {
|
|
914
|
-
return this.componentId === t.componentId;
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
class x extends p {
|
|
918
|
-
/**
|
|
919
|
-
* Create a new battery state.
|
|
920
|
-
*
|
|
921
|
-
* @param componentId - UUID of the battery component
|
|
922
|
-
*/
|
|
923
|
-
constructor(t) {
|
|
924
|
-
super(t, "on");
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
class W {
|
|
928
|
-
componentType = h.Battery;
|
|
929
|
-
/**
|
|
930
|
-
* Create initial state for a battery.
|
|
931
|
-
*
|
|
932
|
-
* @param component - The Battery component
|
|
933
|
-
* @returns Battery Initial state (always active and delivering voltage)
|
|
934
|
-
*/
|
|
935
|
-
createInitialState(t) {
|
|
936
|
-
if (t.type !== h.Battery)
|
|
937
|
-
throw new Error(`Invalid component type for BatteryBehavior: ${t.type}`);
|
|
938
|
-
return new x(t.id);
|
|
939
|
-
}
|
|
940
|
-
allowConductivity(t, e, i, n, s) {
|
|
941
|
-
return !1;
|
|
942
|
-
}
|
|
943
|
-
/**
|
|
944
|
-
* Batteries are always on, and their pins are locked so this is more of a decorative function
|
|
945
|
-
* @param component
|
|
946
|
-
* @param componentState
|
|
947
|
-
* @param nodeStates
|
|
948
|
-
* @param _targetTick
|
|
949
|
-
*/
|
|
950
|
-
onPinsChange(t, e, i, n) {
|
|
951
|
-
const s = /* @__PURE__ */ new Map();
|
|
952
|
-
for (const o in t.pins)
|
|
953
|
-
s.set(t.getPinLabel(o), i.get(o));
|
|
954
|
-
return {
|
|
955
|
-
componentState: e,
|
|
956
|
-
hasChanged: !1,
|
|
957
|
-
scheduledEvents: []
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
onUserCommand(t, e, i) {
|
|
961
|
-
return {
|
|
962
|
-
componentState: e,
|
|
963
|
-
hasChanged: !1,
|
|
964
|
-
scheduledEvents: []
|
|
965
|
-
};
|
|
966
|
-
}
|
|
967
|
-
onEventFiring(t, e, i) {
|
|
968
|
-
return {
|
|
969
|
-
componentState: e,
|
|
970
|
-
hasChanged: !1,
|
|
971
|
-
scheduledEvents: []
|
|
972
|
-
};
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
class $ extends p {
|
|
976
|
-
/**
|
|
977
|
-
* Create a new Lightbulb state.
|
|
978
|
-
*
|
|
979
|
-
* @param componentId - UUID of the Lightbulb component
|
|
980
|
-
* @param initialState - Initial operational state (default: "off")
|
|
981
|
-
*/
|
|
982
|
-
constructor(t, e = "off") {
|
|
983
|
-
super(t, e);
|
|
984
|
-
}
|
|
985
|
-
/**
|
|
986
|
-
* Check if Lightbulb is in lit state (on or going_on)
|
|
987
|
-
*/
|
|
988
|
-
get isLit() {
|
|
989
|
-
return this.state === "on" || this.state === "goingOn";
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
class M {
|
|
993
|
-
componentType = h.Lightbulb;
|
|
994
|
-
/**
|
|
995
|
-
* Create initial state for a lightbulb.
|
|
996
|
-
*
|
|
997
|
-
* @param component - The lightbulb component
|
|
998
|
-
* @returns lightbulbInitial state (always active and delivering voltage)
|
|
999
|
-
*/
|
|
1000
|
-
createInitialState(t) {
|
|
1001
|
-
if (t.type !== h.Lightbulb)
|
|
1002
|
-
throw new Error(`Invalid component type for lightbulbBehavior: ${t.type}`);
|
|
1003
|
-
return new $(t.id);
|
|
1004
|
-
}
|
|
1005
|
-
allowConductivity(t, e, i, n, s) {
|
|
1006
|
-
return !0;
|
|
1007
|
-
}
|
|
1008
|
-
/**
|
|
1009
|
-
* @param component
|
|
1010
|
-
* @param state
|
|
1011
|
-
* @param nodeStates
|
|
1012
|
-
* @param targetTick
|
|
1013
|
-
*/
|
|
1014
|
-
onPinsChange(t, e, i, n) {
|
|
1015
|
-
const s = /* @__PURE__ */ new Map();
|
|
1016
|
-
for (const d of t.pins)
|
|
1017
|
-
s.set(t.getPinLabel(d), i.get(d));
|
|
1018
|
-
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;
|
|
1019
|
-
const r = [];
|
|
1020
|
-
return o ? (e.state === "off" || e.state === "goingOff") && (a = !0, e.state = "goingOn", e.startTick = n, r.push({
|
|
1021
|
-
targetId: t.id,
|
|
1022
|
-
scheduledAtTick: n,
|
|
1023
|
-
readyAtTick: n + 1,
|
|
1024
|
-
// TODO handle component config later
|
|
1025
|
-
type: "GoingOnEnd",
|
|
1026
|
-
parameters: void 0
|
|
1027
|
-
}), e.state = "goingOn") : (e.state === "on" || e.state === "goingOn") && (a = !0, e.state = "goingOff", e.startTick = n, r.push({
|
|
1028
|
-
targetId: t.id,
|
|
1029
|
-
scheduledAtTick: n,
|
|
1030
|
-
readyAtTick: n + 1,
|
|
1031
|
-
// TODO handle component config later
|
|
1032
|
-
type: "GoingOffEnd",
|
|
1033
|
-
parameters: void 0
|
|
1034
|
-
}), e.state = "goingOff"), {
|
|
1035
|
-
componentState: e,
|
|
1036
|
-
hasChanged: a,
|
|
1037
|
-
scheduledEvents: r
|
|
1038
|
-
};
|
|
1039
|
-
}
|
|
1040
|
-
onUserCommand(t, e, i) {
|
|
1041
|
-
return {
|
|
1042
|
-
componentState: e,
|
|
1043
|
-
hasChanged: !1,
|
|
1044
|
-
scheduledEvents: []
|
|
1045
|
-
};
|
|
1046
|
-
}
|
|
1047
|
-
onEventFiring(t, e, i) {
|
|
1048
|
-
let n = !1;
|
|
1049
|
-
return i.type === "GoingOffEnd" ? e.state !== "off" && (n = !0, e.startTick = i.readyAtTick, e.state = "off") : i.type === "GoingOnEnd" && e.state !== "on" && (n = !0, e.startTick = i.readyAtTick, e.state = "on"), {
|
|
1050
|
-
componentState: e,
|
|
1051
|
-
hasChanged: n,
|
|
1052
|
-
scheduledEvents: []
|
|
1053
|
-
};
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
class L extends p {
|
|
1057
|
-
/**
|
|
1058
|
-
* Create a new SmallLED state.
|
|
1059
|
-
*
|
|
1060
|
-
* @param componentId - UUID of the LED component
|
|
1061
|
-
* @param initialState - Initial operational state (default: "off")
|
|
1062
|
-
*/
|
|
1063
|
-
constructor(t, e = "off") {
|
|
1064
|
-
super(t, e);
|
|
1065
|
-
}
|
|
1066
|
-
/**
|
|
1067
|
-
* Check if LED is in lit state (on or going_on)
|
|
1068
|
-
*/
|
|
1069
|
-
get isLit() {
|
|
1070
|
-
return this.state === "on" || this.state === "goingOn";
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
class N {
|
|
1074
|
-
componentType = h.SmallLED;
|
|
1075
|
-
/**
|
|
1076
|
-
* Create initial state for a smallLED.
|
|
1077
|
-
*
|
|
1078
|
-
* @param component - The smallLED component
|
|
1079
|
-
* @returns LED Initial state (always active and delivering voltage)
|
|
1080
|
-
*/
|
|
1081
|
-
createInitialState(t) {
|
|
1082
|
-
if (t.type !== h.SmallLED)
|
|
1083
|
-
throw new Error(`Invalid component type for SmallLEDBehavior: ${t.type}`);
|
|
1084
|
-
return new L(t.id);
|
|
1085
|
-
}
|
|
1086
|
-
allowConductivity(t, e, i, n, s) {
|
|
1087
|
-
return !0;
|
|
1088
|
-
}
|
|
1089
|
-
/**
|
|
1090
|
-
* only symmetrical behavior of LEDS is handled for now
|
|
1091
|
-
* @param component
|
|
1092
|
-
* @param state
|
|
1093
|
-
* @param nodeStates
|
|
1094
|
-
* @param targetTick
|
|
1095
|
-
*/
|
|
1096
|
-
onPinsChange(t, e, i, n) {
|
|
1097
|
-
const s = /* @__PURE__ */ new Map();
|
|
1098
|
-
for (const d of t.pins)
|
|
1099
|
-
s.set(t.getPinLabel(d), i.get(d));
|
|
1100
|
-
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;
|
|
1101
|
-
const r = [];
|
|
1102
|
-
return o ? (e.state === "off" || e.state === "goingOff") && (a = !0, e.state = "goingOn", e.startTick = n, r.push({
|
|
1103
|
-
targetId: t.id,
|
|
1104
|
-
scheduledAtTick: n,
|
|
1105
|
-
readyAtTick: n + 1,
|
|
1106
|
-
// TODO handle component config later
|
|
1107
|
-
type: "GoingOnEnd",
|
|
1108
|
-
parameters: void 0
|
|
1109
|
-
})) : (e.state === "on" || e.state === "goingOn") && (a = !0, e.state = "goingOff", e.startTick = n, r.push({
|
|
1110
|
-
targetId: t.id,
|
|
1111
|
-
scheduledAtTick: n,
|
|
1112
|
-
readyAtTick: n + 1,
|
|
1113
|
-
// TODO handle component config later
|
|
1114
|
-
type: "GoingOffEnd",
|
|
1115
|
-
parameters: void 0
|
|
1116
|
-
})), {
|
|
1117
|
-
componentState: e,
|
|
1118
|
-
hasChanged: a,
|
|
1119
|
-
scheduledEvents: r
|
|
1120
|
-
};
|
|
1121
|
-
}
|
|
1122
|
-
onUserCommand(t, e, i) {
|
|
1123
|
-
return {
|
|
1124
|
-
componentState: e,
|
|
1125
|
-
hasChanged: !1,
|
|
1126
|
-
scheduledEvents: []
|
|
1127
|
-
};
|
|
1128
|
-
}
|
|
1129
|
-
onEventFiring(t, e, i) {
|
|
1130
|
-
let n = !1;
|
|
1131
|
-
return i.type === "GoingOffEnd" ? e.state !== "off" && (n = !0, e.startTick = i.readyAtTick, e.state = "off") : i.type === "GoingOnEnd" && e.state !== "on" && (n = !0, e.startTick = i.readyAtTick, e.state = "on"), {
|
|
1132
|
-
componentState: e,
|
|
1133
|
-
hasChanged: n,
|
|
1134
|
-
scheduledEvents: []
|
|
1135
|
-
};
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
class R extends L {
|
|
1139
|
-
}
|
|
1140
|
-
class F extends N {
|
|
1141
|
-
componentType = h.RectangleLED;
|
|
1142
|
-
/**
|
|
1143
|
-
* Create initial state for a RectangleLED.
|
|
1144
|
-
*
|
|
1145
|
-
* @param component - The smallLED component
|
|
1146
|
-
* @returns LED Initial state (always active and delivering voltage)
|
|
1147
|
-
*/
|
|
1148
|
-
createInitialState(t) {
|
|
1149
|
-
if (t.type !== h.RectangleLED)
|
|
1150
|
-
throw new Error(`Invalid component type for RectangleLEDBehavior: ${t.type}`);
|
|
1151
|
-
return new R(t.id);
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
class D extends p {
|
|
1155
|
-
/**
|
|
1156
|
-
* Create a new Relay state.
|
|
1157
|
-
*
|
|
1158
|
-
* @param componentId - UUID of the Relay component
|
|
1159
|
-
* @param initialState - Initial operational state (default: "open")
|
|
1160
|
-
*/
|
|
1161
|
-
constructor(t, e = "open") {
|
|
1162
|
-
super(t, e);
|
|
1163
|
-
}
|
|
1164
|
-
/**
|
|
1165
|
-
* Check if relay is in opening or closing state
|
|
1166
|
-
*/
|
|
1167
|
-
get isInTransition() {
|
|
1168
|
-
return this.state === "closing" || this.state === "opening";
|
|
1169
|
-
}
|
|
1170
|
-
/**
|
|
1171
|
-
* Check if relay is in closed or closing state
|
|
1172
|
-
*/
|
|
1173
|
-
get isClosed() {
|
|
1174
|
-
return this.state === "closed" || this.state === "closing";
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
function J(c) {
|
|
1178
|
-
const t = parseInt(c.get("transitionSpan") || "", 10);
|
|
1179
|
-
return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
|
|
1180
|
-
}
|
|
1181
|
-
class U {
|
|
1182
|
-
componentType = h.Relay;
|
|
1183
|
-
/**
|
|
1184
|
-
* Create initial state for a relay.
|
|
1185
|
-
*
|
|
1186
|
-
* @param component - The Relay component
|
|
1187
|
-
* @returns Relay Initial state (open by default)
|
|
1188
|
-
*/
|
|
1189
|
-
createInitialState(t) {
|
|
1190
|
-
if (t.type !== h.Relay)
|
|
1191
|
-
throw new Error(`Invalid component type for RelayBehavior: ${t.type}`);
|
|
1192
|
-
const e = t.config.get("activationLogic") === "negative" ? "closed" : "open";
|
|
1193
|
-
return new D(t.id, e);
|
|
1194
|
-
}
|
|
1195
|
-
allowConductivity(t, e, i, n, s) {
|
|
1196
|
-
if (n === s) return !0;
|
|
1197
|
-
const o = t.getPinLabel(n), a = t.getPinLabel(s);
|
|
1198
|
-
if (!o || !a) return !1;
|
|
1199
|
-
const r = [o, a];
|
|
1200
|
-
return r.includes("cmd_in") && r.includes("cmd_out") ? !0 : r.includes("power_in") && r.includes("power_out") ? e.state === "closed" || e.state === "opening" : !1;
|
|
1201
|
-
}
|
|
1202
|
-
/**
|
|
1203
|
-
* Relay cmd pins need to have voltage and current so that relay contactor stays closed
|
|
1204
|
-
* @param component
|
|
1205
|
-
* @param state
|
|
1206
|
-
* @param nodeStates
|
|
1207
|
-
* @param targetTick
|
|
1208
|
-
*/
|
|
1209
|
-
onPinsChange(t, e, i, n) {
|
|
1210
|
-
const s = /* @__PURE__ */ new Map();
|
|
1211
|
-
for (const l of t.pins)
|
|
1212
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1213
|
-
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 = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1214
|
-
let r = !1;
|
|
1215
|
-
const d = [], g = J(t.config);
|
|
1216
|
-
return a ? (e.state === "open" || e.state === "opening") && (r = !0, e.state = "closing", e.startTick = n, d.push({
|
|
1217
|
-
targetId: t.id,
|
|
1218
|
-
scheduledAtTick: n,
|
|
1219
|
-
readyAtTick: n + g,
|
|
1220
|
-
type: "ClosingEnd",
|
|
1221
|
-
parameters: void 0
|
|
1222
|
-
})) : (e.state === "closed" || e.state === "closing") && (r = !0, e.state = "opening", e.startTick = n, d.push({
|
|
1223
|
-
targetId: t.id,
|
|
1224
|
-
scheduledAtTick: n,
|
|
1225
|
-
readyAtTick: n + g,
|
|
1226
|
-
type: "OpeningEnd",
|
|
1227
|
-
parameters: void 0
|
|
1228
|
-
})), {
|
|
1229
|
-
componentState: e,
|
|
1230
|
-
hasChanged: r,
|
|
1231
|
-
scheduledEvents: d
|
|
1232
|
-
};
|
|
1233
|
-
}
|
|
1234
|
-
onUserCommand(t, e, i) {
|
|
1235
|
-
return {
|
|
1236
|
-
componentState: e,
|
|
1237
|
-
hasChanged: !1,
|
|
1238
|
-
scheduledEvents: []
|
|
1239
|
-
};
|
|
1240
|
-
}
|
|
1241
|
-
onEventFiring(t, e, i) {
|
|
1242
|
-
let n = !1;
|
|
1243
|
-
return i.type === "ClosingEnd" ? e.state !== "closed" && (n = !0, e.startTick = i.readyAtTick, e.state = "closed") : i.type === "OpeningEnd" && e.state !== "open" && (n = !0, e.startTick = i.readyAtTick, e.state = "open"), {
|
|
1244
|
-
componentState: e,
|
|
1245
|
-
hasChanged: n,
|
|
1246
|
-
scheduledEvents: []
|
|
1247
|
-
};
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
class H extends p {
|
|
1251
|
-
/**
|
|
1252
|
-
* Create a new Switch state.
|
|
1253
|
-
*
|
|
1254
|
-
* @param componentId - UUID of the Switch component
|
|
1255
|
-
* @param initialState - Initial operational state (default: "open")
|
|
1256
|
-
*/
|
|
1257
|
-
constructor(t, e = "open") {
|
|
1258
|
-
super(t, e);
|
|
1259
|
-
}
|
|
1260
|
-
/**
|
|
1261
|
-
* Check if switch is in opening or closing state
|
|
1262
|
-
*/
|
|
1263
|
-
get isInTransition() {
|
|
1264
|
-
return this.state === "closing" || this.state === "opening";
|
|
1265
|
-
}
|
|
1266
|
-
/**
|
|
1267
|
-
* Check if switch is in closed or closing state
|
|
1268
|
-
*/
|
|
1269
|
-
get isClosed() {
|
|
1270
|
-
return this.state === "closed" || this.state === "closing";
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
class z extends p {
|
|
1274
|
-
/**
|
|
1275
|
-
* Create a new Transistor state.
|
|
1276
|
-
*
|
|
1277
|
-
* @param componentId - UUID of the Transistor component
|
|
1278
|
-
* @param initialState - Initial operational state (default: "open")
|
|
1279
|
-
*/
|
|
1280
|
-
constructor(t, e = "open") {
|
|
1281
|
-
super(t, e);
|
|
1282
|
-
}
|
|
1283
|
-
/**
|
|
1284
|
-
* Check if transistor is in opening or closing state
|
|
1285
|
-
*/
|
|
1286
|
-
get isInTransition() {
|
|
1287
|
-
return this.state === "closing" || this.state === "opening";
|
|
1288
|
-
}
|
|
1289
|
-
/**
|
|
1290
|
-
* Check if transistor is in closed or closing state
|
|
1291
|
-
*/
|
|
1292
|
-
get isClosed() {
|
|
1293
|
-
return this.state === "closed" || this.state === "closing";
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
class K extends p {
|
|
1297
|
-
/**
|
|
1298
|
-
* Create a new Buffer state.
|
|
1299
|
-
*
|
|
1300
|
-
* @param componentId - UUID of the Buffer component
|
|
1301
|
-
* @param initialState - Initial operational state (default: "low")
|
|
1302
|
-
*/
|
|
1303
|
-
constructor(t, e = "low") {
|
|
1304
|
-
super(t, e);
|
|
1305
|
-
}
|
|
1306
|
-
/**
|
|
1307
|
-
* Check if output is in a rising or falling transition
|
|
1308
|
-
*/
|
|
1309
|
-
get isInTransition() {
|
|
1310
|
-
return this.state === "rising" || this.state === "falling";
|
|
1311
|
-
}
|
|
1312
|
-
/**
|
|
1313
|
-
* Check if output is high
|
|
1314
|
-
*/
|
|
1315
|
-
get isHigh() {
|
|
1316
|
-
return this.state === "high";
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
class T extends p {
|
|
1320
|
-
/**
|
|
1321
|
-
* Create a new AND Gate state.
|
|
1322
|
-
*
|
|
1323
|
-
* @param componentId - UUID of the AND Gate component
|
|
1324
|
-
* @param initialState - Initial operational state (default: "low")
|
|
1325
|
-
*/
|
|
1326
|
-
constructor(t, e = "low") {
|
|
1327
|
-
super(t, e);
|
|
1328
|
-
}
|
|
1329
|
-
/**
|
|
1330
|
-
* Check if output is in a rising or falling transition
|
|
1331
|
-
*/
|
|
1332
|
-
get isInTransition() {
|
|
1333
|
-
return this.state === "rising" || this.state === "falling";
|
|
1334
|
-
}
|
|
1335
|
-
/**
|
|
1336
|
-
* Check if output is high
|
|
1337
|
-
*/
|
|
1338
|
-
get isHigh() {
|
|
1339
|
-
return this.state === "high";
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
|
-
class X extends T {
|
|
1343
|
-
constructor(t, e = "low") {
|
|
1344
|
-
super(t, e);
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
|
-
class q extends T {
|
|
1348
|
-
constructor(t, e = "low") {
|
|
1349
|
-
super(t, e);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
class E extends p {
|
|
1353
|
-
constructor(t, e = "low") {
|
|
1354
|
-
super(t, e);
|
|
1355
|
-
}
|
|
1356
|
-
get isInTransition() {
|
|
1357
|
-
return this.state === "rising" || this.state === "falling";
|
|
1358
|
-
}
|
|
1359
|
-
get isHigh() {
|
|
1360
|
-
return this.state === "high";
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
class Q extends E {
|
|
1364
|
-
constructor(t, e = "low") {
|
|
1365
|
-
super(t, e);
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
class Y extends E {
|
|
1369
|
-
constructor(t, e = "low") {
|
|
1370
|
-
super(t, e);
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
class Z extends p {
|
|
1374
|
-
constructor(t, e = "low") {
|
|
1375
|
-
super(t, e);
|
|
1376
|
-
}
|
|
1377
|
-
get isInTransition() {
|
|
1378
|
-
return this.state === "rising" || this.state === "falling";
|
|
1379
|
-
}
|
|
1380
|
-
get isHigh() {
|
|
1381
|
-
return this.state === "high";
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
function j(c) {
|
|
1385
|
-
if (!c)
|
|
1386
|
-
return f.TRANSITION_SPAN_TICKS;
|
|
1387
|
-
const t = parseInt(c.get("tickCount") || "", 10);
|
|
1388
|
-
return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
|
|
1389
|
-
}
|
|
1390
|
-
class ee {
|
|
1391
|
-
componentType = h.Switch;
|
|
1392
|
-
/**
|
|
1393
|
-
* Create initial state for a switch.
|
|
1394
|
-
*
|
|
1395
|
-
* @param component - The Switch component
|
|
1396
|
-
* @returns Switch Initial state (open by default)
|
|
1397
|
-
*/
|
|
1398
|
-
createInitialState(t) {
|
|
1399
|
-
if (t.type !== h.Switch)
|
|
1400
|
-
throw new Error(`Invalid component type for SwitchBehavior: ${t.type}`);
|
|
1401
|
-
const e = t.config.get("initialState") || "open";
|
|
1402
|
-
return new H(t.id, e);
|
|
1403
|
-
}
|
|
1404
|
-
allowConductivity(t, e, i, n, s) {
|
|
1405
|
-
return e.state === "closed" || e.state === "opening";
|
|
1406
|
-
}
|
|
1407
|
-
/**
|
|
1408
|
-
* Switches states depend on user interaction, not their pins so this is more of a decorative function
|
|
1409
|
-
* @param _component
|
|
1410
|
-
* @param componentState
|
|
1411
|
-
* @param _nodeStates
|
|
1412
|
-
* @param _targetTick
|
|
1413
|
-
*/
|
|
1414
|
-
onPinsChange(t, e, i, n) {
|
|
1415
|
-
return {
|
|
1416
|
-
componentState: e,
|
|
1417
|
-
hasChanged: !1,
|
|
1418
|
-
scheduledEvents: []
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
onUserCommand(t, e, i) {
|
|
1422
|
-
let n = !1;
|
|
1423
|
-
const s = [];
|
|
1424
|
-
if (i.type === "toggle_switch" && ["open", "closed"].includes(e.state)) {
|
|
1425
|
-
e.state = e.state === "open" ? "closing" : "opening", e.startTick = i.scheduledAtTick + 1, n = !0;
|
|
1426
|
-
const o = j(i.parameters);
|
|
1427
|
-
s.push({
|
|
1428
|
-
targetId: t.id,
|
|
1429
|
-
scheduledAtTick: e.startTick,
|
|
1430
|
-
readyAtTick: e.startTick + o,
|
|
1431
|
-
type: e.state === "closing" ? "ClosingEnd" : "OpeningEnd",
|
|
1432
|
-
parameters: void 0
|
|
1433
|
-
});
|
|
1434
|
-
}
|
|
1435
|
-
return {
|
|
1436
|
-
componentState: e,
|
|
1437
|
-
hasChanged: n,
|
|
1438
|
-
scheduledEvents: s
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
onEventFiring(t, e, i) {
|
|
1442
|
-
let n = !1;
|
|
1443
|
-
return i.type === "ClosingEnd" ? e.state !== "closed" && (n = !0, e.startTick = i.readyAtTick, e.state = "closed") : i.type === "OpeningEnd" && e.state !== "open" && (n = !0, e.startTick = i.readyAtTick, e.state = "open"), {
|
|
1444
|
-
componentState: e,
|
|
1445
|
-
hasChanged: n,
|
|
1446
|
-
scheduledEvents: []
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
function te(c) {
|
|
1451
|
-
const t = parseInt(c.get("transitionSpan") || "", 10);
|
|
1452
|
-
return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
|
|
1453
|
-
}
|
|
1454
|
-
class ne {
|
|
1455
|
-
componentType = h.Transistor;
|
|
1456
|
-
/**
|
|
1457
|
-
* Create initial state for a transistor.
|
|
1458
|
-
*
|
|
1459
|
-
* @param component - The Transistor component
|
|
1460
|
-
* @returns Transistor Initial state (open by default)
|
|
1461
|
-
*/
|
|
1462
|
-
createInitialState(t) {
|
|
1463
|
-
if (t.type !== h.Transistor)
|
|
1464
|
-
throw new Error(`Invalid component type for TransistorBehavior: ${t.type}`);
|
|
1465
|
-
const e = t.config.get("activationLogic") === "negative" ? "closed" : "open";
|
|
1466
|
-
return new z(t.id, e);
|
|
1467
|
-
}
|
|
1468
|
-
allowConductivity(t, e, i, n, s) {
|
|
1469
|
-
if (n === s) return !0;
|
|
1470
|
-
const o = t.getPinLabel(n), a = t.getPinLabel(s);
|
|
1471
|
-
if (!o || !a) return !1;
|
|
1472
|
-
const r = [o, a];
|
|
1473
|
-
return r.includes("collector") && r.includes("emitter") ? e.state === "closed" || e.state === "opening" : !1;
|
|
1474
|
-
}
|
|
1475
|
-
/**
|
|
1476
|
-
* Transistor Base need to have only voltage so that transistor contactor stays closed
|
|
1477
|
-
* @param component
|
|
1478
|
-
* @param state
|
|
1479
|
-
* @param nodeStates
|
|
1480
|
-
* @param targetTick
|
|
1481
|
-
*/
|
|
1482
|
-
onPinsChange(t, e, i, n) {
|
|
1483
|
-
const s = /* @__PURE__ */ new Map();
|
|
1484
|
-
for (const l of t.pins)
|
|
1485
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1486
|
-
const o = s.get("base").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1487
|
-
let r = !1;
|
|
1488
|
-
const d = [], g = te(t.config);
|
|
1489
|
-
return a ? (e.state === "open" || e.state === "opening") && (r = !0, e.state = "closing", e.startTick = n, d.push({
|
|
1490
|
-
targetId: t.id,
|
|
1491
|
-
scheduledAtTick: n,
|
|
1492
|
-
readyAtTick: n + g,
|
|
1493
|
-
type: "ClosingEnd",
|
|
1494
|
-
parameters: void 0
|
|
1495
|
-
})) : (e.state === "closed" || e.state === "closing") && (r = !0, e.state = "opening", e.startTick = n, d.push({
|
|
1496
|
-
targetId: t.id,
|
|
1497
|
-
scheduledAtTick: n,
|
|
1498
|
-
readyAtTick: n + g,
|
|
1499
|
-
type: "OpeningEnd",
|
|
1500
|
-
parameters: void 0
|
|
1501
|
-
})), {
|
|
1502
|
-
componentState: e,
|
|
1503
|
-
hasChanged: r,
|
|
1504
|
-
scheduledEvents: d
|
|
1505
|
-
};
|
|
1506
|
-
}
|
|
1507
|
-
onUserCommand(t, e, i) {
|
|
1508
|
-
return {
|
|
1509
|
-
componentState: e,
|
|
1510
|
-
hasChanged: !1,
|
|
1511
|
-
scheduledEvents: []
|
|
1512
|
-
};
|
|
1513
|
-
}
|
|
1514
|
-
onEventFiring(t, e, i) {
|
|
1515
|
-
let n = !1;
|
|
1516
|
-
return i.type === "ClosingEnd" ? e.state !== "closed" && (n = !0, e.startTick = i.readyAtTick, e.state = "closed") : i.type === "OpeningEnd" && e.state !== "open" && (n = !0, e.startTick = i.readyAtTick, e.state = "open"), {
|
|
1517
|
-
componentState: e,
|
|
1518
|
-
hasChanged: n,
|
|
1519
|
-
scheduledEvents: []
|
|
1520
|
-
};
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
function ie(c) {
|
|
1524
|
-
const t = parseInt(c.get("transitionSpan") || "", 10);
|
|
1525
|
-
return isNaN(t) || t < 1 ? f.TRANSITION_SPAN_TICKS : t;
|
|
1526
|
-
}
|
|
1527
|
-
class se {
|
|
1528
|
-
componentType = h.Buffer;
|
|
1529
|
-
/**
|
|
1530
|
-
* Create initial state for a Buffer.
|
|
1531
|
-
*
|
|
1532
|
-
* @param component - The Buffer component
|
|
1533
|
-
* @returns Buffer Initial state (low by default, high for negative activation logic)
|
|
1534
|
-
*/
|
|
1535
|
-
createInitialState(t) {
|
|
1536
|
-
if (t.type !== h.Buffer)
|
|
1537
|
-
throw new Error(`Invalid component type for BufferBehavior: ${t.type}`);
|
|
1538
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1539
|
-
return new K(t.id, e);
|
|
1540
|
-
}
|
|
1541
|
-
allowConductivity(t, e, i, n, s) {
|
|
1542
|
-
if (n === s) return !0;
|
|
1543
|
-
const o = t.getPinLabel(n), a = t.getPinLabel(s);
|
|
1544
|
-
if (!o || !a) return !1;
|
|
1545
|
-
const r = [o, a];
|
|
1546
|
-
return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
|
|
1547
|
-
}
|
|
1548
|
-
/**
|
|
1549
|
-
* Relayer needs voltage on input to drive the output high, and on the contrary Inverter needs no voltage on input
|
|
1550
|
-
* @param component
|
|
1551
|
-
* @param state
|
|
1552
|
-
* @param nodeStates
|
|
1553
|
-
* @param targetTick
|
|
1554
|
-
*/
|
|
1555
|
-
onPinsChange(t, e, i, n) {
|
|
1556
|
-
const s = /* @__PURE__ */ new Map();
|
|
1557
|
-
for (const l of t.pins)
|
|
1558
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1559
|
-
const o = s.get("input").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1560
|
-
let r = !1;
|
|
1561
|
-
const d = [], g = ie(t.config);
|
|
1562
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1563
|
-
targetId: t.id,
|
|
1564
|
-
scheduledAtTick: n,
|
|
1565
|
-
readyAtTick: n + g,
|
|
1566
|
-
type: "RisingComplete",
|
|
1567
|
-
parameters: void 0
|
|
1568
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1569
|
-
targetId: t.id,
|
|
1570
|
-
scheduledAtTick: n,
|
|
1571
|
-
readyAtTick: n + g,
|
|
1572
|
-
type: "FallingComplete",
|
|
1573
|
-
parameters: void 0
|
|
1574
|
-
})), {
|
|
1575
|
-
componentState: e,
|
|
1576
|
-
hasChanged: r,
|
|
1577
|
-
scheduledEvents: d
|
|
1578
|
-
};
|
|
1579
|
-
}
|
|
1580
|
-
onUserCommand(t, e, i) {
|
|
1581
|
-
return {
|
|
1582
|
-
componentState: e,
|
|
1583
|
-
hasChanged: !1,
|
|
1584
|
-
scheduledEvents: []
|
|
1585
|
-
};
|
|
1586
|
-
}
|
|
1587
|
-
onEventFiring(t, e, i) {
|
|
1588
|
-
let n = !1;
|
|
1589
|
-
return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
|
|
1590
|
-
componentState: e,
|
|
1591
|
-
hasChanged: n,
|
|
1592
|
-
scheduledEvents: []
|
|
1593
|
-
};
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
class I {
|
|
1597
|
-
componentType = h.AndGate;
|
|
1598
|
-
/**
|
|
1599
|
-
* Create initial state for an AND Gate.
|
|
1600
|
-
*
|
|
1601
|
-
* @param component - The AND Gate component
|
|
1602
|
-
* @returns Initial state (low by default, high for negative activation logic)
|
|
1603
|
-
*/
|
|
1604
|
-
createInitialState(t) {
|
|
1605
|
-
if (t.type !== h.AndGate)
|
|
1606
|
-
throw new Error(`Invalid component type for AndGateBehavior: ${t.type}`);
|
|
1607
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1608
|
-
return new T(t.id, e);
|
|
1609
|
-
}
|
|
1610
|
-
allowConductivity(t, e, i, n, s) {
|
|
1611
|
-
if (n === s) return !0;
|
|
1612
|
-
const o = t.getPinLabel(n), a = t.getPinLabel(s);
|
|
1613
|
-
if (!o || !a) return !1;
|
|
1614
|
-
const r = [o, a];
|
|
1615
|
-
return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
|
|
1616
|
-
}
|
|
1617
|
-
/**
|
|
1618
|
-
* Get the transition span from component config.
|
|
1619
|
-
* @param config - Component config map
|
|
1620
|
-
* @returns Number of ticks for transition (minimum 1)
|
|
1621
|
-
*/
|
|
1622
|
-
getTransitionSpan(t) {
|
|
1623
|
-
const e = parseInt(t.get("transitionSpan") || "", 10);
|
|
1624
|
-
return isNaN(e) || e < 1 ? f.TRANSITION_SPAN_TICKS : e;
|
|
1625
|
-
}
|
|
1626
|
-
/**
|
|
1627
|
-
* AND gate output goes high when ALL inputs have voltage.
|
|
1628
|
-
* With negative activationLogic (NAND), output goes high when ANY input lacks voltage.
|
|
1629
|
-
*/
|
|
1630
|
-
onPinsChange(t, e, i, n) {
|
|
1631
|
-
const s = /* @__PURE__ */ new Map();
|
|
1632
|
-
for (const l of t.pins)
|
|
1633
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1634
|
-
const o = s.get("input1").hasVoltage && s.get("input2").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1635
|
-
let r = !1;
|
|
1636
|
-
const d = [], g = this.getTransitionSpan(t.config);
|
|
1637
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1638
|
-
targetId: t.id,
|
|
1639
|
-
scheduledAtTick: n,
|
|
1640
|
-
readyAtTick: n + g,
|
|
1641
|
-
type: "RisingComplete",
|
|
1642
|
-
parameters: void 0
|
|
1643
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1644
|
-
targetId: t.id,
|
|
1645
|
-
scheduledAtTick: n,
|
|
1646
|
-
readyAtTick: n + g,
|
|
1647
|
-
type: "FallingComplete",
|
|
1648
|
-
parameters: void 0
|
|
1649
|
-
})), {
|
|
1650
|
-
componentState: e,
|
|
1651
|
-
hasChanged: r,
|
|
1652
|
-
scheduledEvents: d
|
|
1653
|
-
};
|
|
1654
|
-
}
|
|
1655
|
-
onUserCommand(t, e, i) {
|
|
1656
|
-
return {
|
|
1657
|
-
componentState: e,
|
|
1658
|
-
hasChanged: !1,
|
|
1659
|
-
scheduledEvents: []
|
|
1660
|
-
};
|
|
1661
|
-
}
|
|
1662
|
-
onEventFiring(t, e, i) {
|
|
1663
|
-
let n = !1;
|
|
1664
|
-
return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
|
|
1665
|
-
componentState: e,
|
|
1666
|
-
hasChanged: n,
|
|
1667
|
-
scheduledEvents: []
|
|
1668
|
-
};
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
class oe extends I {
|
|
1672
|
-
componentType = h.And4Gate;
|
|
1673
|
-
createInitialState(t) {
|
|
1674
|
-
if (t.type !== h.And4Gate)
|
|
1675
|
-
throw new Error(`Invalid component type for And4GateBehavior: ${t.type}`);
|
|
1676
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1677
|
-
return new X(t.id, e);
|
|
1678
|
-
}
|
|
1679
|
-
onPinsChange(t, e, i, n) {
|
|
1680
|
-
const s = /* @__PURE__ */ new Map();
|
|
1681
|
-
for (const l of t.pins)
|
|
1682
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1683
|
-
const o = s.get("input1").hasVoltage && s.get("input2").hasVoltage && s.get("input3").hasVoltage && s.get("input4").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1684
|
-
let r = !1;
|
|
1685
|
-
const d = [], g = this.getTransitionSpan(t.config);
|
|
1686
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1687
|
-
targetId: t.id,
|
|
1688
|
-
scheduledAtTick: n,
|
|
1689
|
-
readyAtTick: n + g,
|
|
1690
|
-
type: "RisingComplete",
|
|
1691
|
-
parameters: void 0
|
|
1692
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1693
|
-
targetId: t.id,
|
|
1694
|
-
scheduledAtTick: n,
|
|
1695
|
-
readyAtTick: n + g,
|
|
1696
|
-
type: "FallingComplete",
|
|
1697
|
-
parameters: void 0
|
|
1698
|
-
})), {
|
|
1699
|
-
componentState: e,
|
|
1700
|
-
hasChanged: r,
|
|
1701
|
-
scheduledEvents: d
|
|
1702
|
-
};
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
class re extends I {
|
|
1706
|
-
componentType = h.And8Gate;
|
|
1707
|
-
createInitialState(t) {
|
|
1708
|
-
if (t.type !== h.And8Gate)
|
|
1709
|
-
throw new Error(`Invalid component type for And8GateBehavior: ${t.type}`);
|
|
1710
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1711
|
-
return new q(t.id, e);
|
|
1712
|
-
}
|
|
1713
|
-
onPinsChange(t, e, i, n) {
|
|
1714
|
-
const s = /* @__PURE__ */ new Map();
|
|
1715
|
-
for (const l of t.pins)
|
|
1716
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1717
|
-
const o = s.get("input1").hasVoltage && s.get("input2").hasVoltage && s.get("input3").hasVoltage && s.get("input4").hasVoltage && s.get("input5").hasVoltage && s.get("input6").hasVoltage && s.get("input7").hasVoltage && s.get("input8").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1718
|
-
let r = !1;
|
|
1719
|
-
const d = [], g = this.getTransitionSpan(t.config);
|
|
1720
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1721
|
-
targetId: t.id,
|
|
1722
|
-
scheduledAtTick: n,
|
|
1723
|
-
readyAtTick: n + g,
|
|
1724
|
-
type: "RisingComplete",
|
|
1725
|
-
parameters: void 0
|
|
1726
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1727
|
-
targetId: t.id,
|
|
1728
|
-
scheduledAtTick: n,
|
|
1729
|
-
readyAtTick: n + g,
|
|
1730
|
-
type: "FallingComplete",
|
|
1731
|
-
parameters: void 0
|
|
1732
|
-
})), {
|
|
1733
|
-
componentState: e,
|
|
1734
|
-
hasChanged: r,
|
|
1735
|
-
scheduledEvents: d
|
|
1736
|
-
};
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
class A {
|
|
1740
|
-
componentType = h.OrGate;
|
|
1741
|
-
createInitialState(t) {
|
|
1742
|
-
if (t.type !== h.OrGate)
|
|
1743
|
-
throw new Error(`Invalid component type for OrGateBehavior: ${t.type}`);
|
|
1744
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1745
|
-
return new E(t.id, e);
|
|
1746
|
-
}
|
|
1747
|
-
allowConductivity(t, e, i, n, s) {
|
|
1748
|
-
if (n === s) return !0;
|
|
1749
|
-
const o = t.getPinLabel(n), a = t.getPinLabel(s);
|
|
1750
|
-
if (!o || !a) return !1;
|
|
1751
|
-
const r = [o, a];
|
|
1752
|
-
return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
|
|
1753
|
-
}
|
|
1754
|
-
getTransitionSpan(t) {
|
|
1755
|
-
const e = parseInt(t.get("transitionSpan") || "", 10);
|
|
1756
|
-
return isNaN(e) || e < 1 ? f.TRANSITION_SPAN_TICKS : e;
|
|
1757
|
-
}
|
|
1758
|
-
/**
|
|
1759
|
-
* OR gate output goes high when ANY input has voltage.
|
|
1760
|
-
* With negative activationLogic (NOR), output goes high when ALL inputs lack voltage.
|
|
1761
|
-
*/
|
|
1762
|
-
onPinsChange(t, e, i, n) {
|
|
1763
|
-
const s = /* @__PURE__ */ new Map();
|
|
1764
|
-
for (const l of t.pins)
|
|
1765
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1766
|
-
const o = s.get("input1").hasVoltage || s.get("input2").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1767
|
-
let r = !1;
|
|
1768
|
-
const d = [], g = this.getTransitionSpan(t.config);
|
|
1769
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1770
|
-
targetId: t.id,
|
|
1771
|
-
scheduledAtTick: n,
|
|
1772
|
-
readyAtTick: n + g,
|
|
1773
|
-
type: "RisingComplete",
|
|
1774
|
-
parameters: void 0
|
|
1775
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1776
|
-
targetId: t.id,
|
|
1777
|
-
scheduledAtTick: n,
|
|
1778
|
-
readyAtTick: n + g,
|
|
1779
|
-
type: "FallingComplete",
|
|
1780
|
-
parameters: void 0
|
|
1781
|
-
})), {
|
|
1782
|
-
componentState: e,
|
|
1783
|
-
hasChanged: r,
|
|
1784
|
-
scheduledEvents: d
|
|
1785
|
-
};
|
|
1786
|
-
}
|
|
1787
|
-
onUserCommand(t, e, i) {
|
|
1788
|
-
return {
|
|
1789
|
-
componentState: e,
|
|
1790
|
-
hasChanged: !1,
|
|
1791
|
-
scheduledEvents: []
|
|
1792
|
-
};
|
|
1793
|
-
}
|
|
1794
|
-
onEventFiring(t, e, i) {
|
|
1795
|
-
let n = !1;
|
|
1796
|
-
return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
|
|
1797
|
-
componentState: e,
|
|
1798
|
-
hasChanged: n,
|
|
1799
|
-
scheduledEvents: []
|
|
1800
|
-
};
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
class ae extends A {
|
|
1804
|
-
componentType = h.Or4Gate;
|
|
1805
|
-
createInitialState(t) {
|
|
1806
|
-
if (t.type !== h.Or4Gate)
|
|
1807
|
-
throw new Error(`Invalid component type for Or4GateBehavior: ${t.type}`);
|
|
1808
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1809
|
-
return new Q(t.id, e);
|
|
1810
|
-
}
|
|
1811
|
-
onPinsChange(t, e, i, n) {
|
|
1812
|
-
const s = /* @__PURE__ */ new Map();
|
|
1813
|
-
for (const l of t.pins)
|
|
1814
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1815
|
-
const o = s.get("input1").hasVoltage || s.get("input2").hasVoltage || s.get("input3").hasVoltage || s.get("input4").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1816
|
-
let r = !1;
|
|
1817
|
-
const d = [], g = this.getTransitionSpan(t.config);
|
|
1818
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1819
|
-
targetId: t.id,
|
|
1820
|
-
scheduledAtTick: n,
|
|
1821
|
-
readyAtTick: n + g,
|
|
1822
|
-
type: "RisingComplete",
|
|
1823
|
-
parameters: void 0
|
|
1824
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1825
|
-
targetId: t.id,
|
|
1826
|
-
scheduledAtTick: n,
|
|
1827
|
-
readyAtTick: n + g,
|
|
1828
|
-
type: "FallingComplete",
|
|
1829
|
-
parameters: void 0
|
|
1830
|
-
})), {
|
|
1831
|
-
componentState: e,
|
|
1832
|
-
hasChanged: r,
|
|
1833
|
-
scheduledEvents: d
|
|
1834
|
-
};
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
class de extends A {
|
|
1838
|
-
componentType = h.Or8Gate;
|
|
1839
|
-
createInitialState(t) {
|
|
1840
|
-
if (t.type !== h.Or8Gate)
|
|
1841
|
-
throw new Error(`Invalid component type for Or8GateBehavior: ${t.type}`);
|
|
1842
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1843
|
-
return new Y(t.id, e);
|
|
1844
|
-
}
|
|
1845
|
-
onPinsChange(t, e, i, n) {
|
|
1846
|
-
const s = /* @__PURE__ */ new Map();
|
|
1847
|
-
for (const l of t.pins)
|
|
1848
|
-
s.set(t.getPinLabel(l), i.get(l));
|
|
1849
|
-
const o = s.get("input1").hasVoltage || s.get("input2").hasVoltage || s.get("input3").hasVoltage || s.get("input4").hasVoltage || s.get("input5").hasVoltage || s.get("input6").hasVoltage || s.get("input7").hasVoltage || s.get("input8").hasVoltage, a = t.config.get("activationLogic") === "negative" ? !o : o;
|
|
1850
|
-
let r = !1;
|
|
1851
|
-
const d = [], g = this.getTransitionSpan(t.config);
|
|
1852
|
-
return a ? (e.state === "low" || e.state === "falling") && (r = !0, e.state = "rising", e.startTick = n, d.push({
|
|
1853
|
-
targetId: t.id,
|
|
1854
|
-
scheduledAtTick: n,
|
|
1855
|
-
readyAtTick: n + g,
|
|
1856
|
-
type: "RisingComplete",
|
|
1857
|
-
parameters: void 0
|
|
1858
|
-
})) : (e.state === "high" || e.state === "rising") && (r = !0, e.state = "falling", e.startTick = n, d.push({
|
|
1859
|
-
targetId: t.id,
|
|
1860
|
-
scheduledAtTick: n,
|
|
1861
|
-
readyAtTick: n + g,
|
|
1862
|
-
type: "FallingComplete",
|
|
1863
|
-
parameters: void 0
|
|
1864
|
-
})), {
|
|
1865
|
-
componentState: e,
|
|
1866
|
-
hasChanged: r,
|
|
1867
|
-
scheduledEvents: d
|
|
1868
|
-
};
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
class ce {
|
|
1872
|
-
componentType = h.XorGate;
|
|
1873
|
-
createInitialState(t) {
|
|
1874
|
-
if (t.type !== h.XorGate)
|
|
1875
|
-
throw new Error(`Invalid component type for XorGateBehavior: ${t.type}`);
|
|
1876
|
-
const e = t.config.get("activationLogic") === "negative" ? "high" : "low";
|
|
1877
|
-
return new Z(t.id, e);
|
|
1878
|
-
}
|
|
1879
|
-
allowConductivity(t, e, i, n, s) {
|
|
1880
|
-
if (n === s) return !0;
|
|
1881
|
-
const o = t.getPinLabel(n), a = t.getPinLabel(s);
|
|
1882
|
-
if (!o || !a) return !1;
|
|
1883
|
-
const r = [o, a];
|
|
1884
|
-
return r.includes("vcc") && r.includes("output") ? e.state === "high" || e.state === "falling" : !1;
|
|
1885
|
-
}
|
|
1886
|
-
getTransitionSpan(t) {
|
|
1887
|
-
const e = parseInt(t.get("transitionSpan") || "", 10);
|
|
1888
|
-
return isNaN(e) || e < 1 ? f.TRANSITION_SPAN_TICKS : e;
|
|
1889
|
-
}
|
|
1890
|
-
/**
|
|
1891
|
-
* XOR gate output goes high when inputs differ (one high, one low).
|
|
1892
|
-
* With negative activationLogic (XNOR), output goes high when inputs are equal.
|
|
1893
|
-
*/
|
|
1894
|
-
onPinsChange(t, e, i, n) {
|
|
1895
|
-
const s = /* @__PURE__ */ new Map();
|
|
1896
|
-
for (const u of t.pins)
|
|
1897
|
-
s.set(t.getPinLabel(u), i.get(u));
|
|
1898
|
-
const o = s.get("input1").hasVoltage, a = s.get("input2").hasVoltage, r = o !== a, d = t.config.get("activationLogic") === "negative" ? !r : r;
|
|
1899
|
-
let g = !1;
|
|
1900
|
-
const l = [], m = this.getTransitionSpan(t.config);
|
|
1901
|
-
return d ? (e.state === "low" || e.state === "falling") && (g = !0, e.state = "rising", e.startTick = n, l.push({
|
|
1902
|
-
targetId: t.id,
|
|
1903
|
-
scheduledAtTick: n,
|
|
1904
|
-
readyAtTick: n + m,
|
|
1905
|
-
type: "RisingComplete",
|
|
1906
|
-
parameters: void 0
|
|
1907
|
-
})) : (e.state === "high" || e.state === "rising") && (g = !0, e.state = "falling", e.startTick = n, l.push({
|
|
1908
|
-
targetId: t.id,
|
|
1909
|
-
scheduledAtTick: n,
|
|
1910
|
-
readyAtTick: n + m,
|
|
1911
|
-
type: "FallingComplete",
|
|
1912
|
-
parameters: void 0
|
|
1913
|
-
})), {
|
|
1914
|
-
componentState: e,
|
|
1915
|
-
hasChanged: g,
|
|
1916
|
-
scheduledEvents: l
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
onUserCommand(t, e, i) {
|
|
1920
|
-
return {
|
|
1921
|
-
componentState: e,
|
|
1922
|
-
hasChanged: !1,
|
|
1923
|
-
scheduledEvents: []
|
|
1924
|
-
};
|
|
1925
|
-
}
|
|
1926
|
-
onEventFiring(t, e, i) {
|
|
1927
|
-
let n = !1;
|
|
1928
|
-
return i.type === "RisingComplete" ? e.state !== "high" && (n = !0, e.startTick = i.readyAtTick, e.state = "high") : i.type === "FallingComplete" && e.state !== "low" && (n = !0, e.startTick = i.readyAtTick, e.state = "low"), {
|
|
1929
|
-
componentState: e,
|
|
1930
|
-
hasChanged: n,
|
|
1931
|
-
scheduledEvents: []
|
|
1932
|
-
};
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
function he(c) {
|
|
1936
|
-
return c.register(new W()).register(new M()).register(new F()).register(new U()).register(new N()).register(new ee()).register(new ne()).register(new se()), c;
|
|
1937
|
-
}
|
|
1938
|
-
function ue(c) {
|
|
1939
|
-
return c.register(new I()).register(new oe()).register(new re()).register(new A()).register(new ae()).register(new de()).register(new ce()), c;
|
|
1940
|
-
}
|
|
1
|
+
import { $ as t, A as e, B as s, C as o, D as i, E as r, F as n, G as S, H as h, I as v, J as B, K as G, L as c, M as l, N, O as E, P as p, Q as T, R as m, S as u, T as C, U as I, V as L, W as D, X as d, Y as y, Z as g, _, _t as A, a as R, at as M, b as O, bt as b, c as P, ct as w, d as U, dt as X, et as f, f as F, ft as k, g as x, gt as z, h as Y, ht as Q, i as V, it as W, j, k as q, l as H, lt as J, m as K, mt as Z, n as $, nt as aa, o as ta, ot as ea, p as sa, pt as oa, q as ia, r as ra, rt as na, s as Sa, st as ha, t as va, tt as Ba, u as Ga, ut as ca, v as la, vt as Na, w as Ea, x as pa, y as Ta, yt as ma, z as ua } from "../core-Bjta9Y7_.js";
|
|
1941
2
|
export {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
U as
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
3
|
+
M as ALL_LOGIC_FAMILIES,
|
|
4
|
+
Ea as BatteryBehavior,
|
|
5
|
+
D as BatteryState,
|
|
6
|
+
r as BehaviorRegistry,
|
|
7
|
+
ea as CIRCUIT_FILE_VERSION,
|
|
8
|
+
ha as COMPONENT_TYPE_METADATA,
|
|
9
|
+
A as CameraOptions,
|
|
10
|
+
d as Circuit,
|
|
11
|
+
f as CircuitMetadata,
|
|
12
|
+
Ba as CircuitOptions,
|
|
13
|
+
ra as CircuitRunner,
|
|
14
|
+
_ as ClockBehavior,
|
|
15
|
+
c as ClockState,
|
|
16
|
+
aa as Component,
|
|
17
|
+
S as ComponentState,
|
|
18
|
+
w as ComponentType,
|
|
19
|
+
J as DEFAULT_LOGIC_FAMILY,
|
|
20
|
+
R as DirtyTracker,
|
|
21
|
+
la as DoubleThrowSwitchBehavior,
|
|
22
|
+
m as DoubleThrowSwitchState,
|
|
23
|
+
W as ENode,
|
|
24
|
+
ca as ENodeSourceType,
|
|
25
|
+
X as ENodeType,
|
|
26
|
+
ta as EventQueue,
|
|
27
|
+
x as InverterBehavior,
|
|
28
|
+
v as InverterState,
|
|
29
|
+
o as LightbulbBehavior,
|
|
30
|
+
I as LightbulbState,
|
|
31
|
+
ma as Memoize,
|
|
32
|
+
b as MemoizeExpiring,
|
|
33
|
+
K as Nand4GateBehavior,
|
|
34
|
+
p as Nand4GateState,
|
|
35
|
+
sa as Nand8GateBehavior,
|
|
36
|
+
N as Nand8GateState,
|
|
37
|
+
Y as NandGateBehavior,
|
|
38
|
+
n as NandGateState,
|
|
39
|
+
U as Nor4GateBehavior,
|
|
40
|
+
j as Nor4GateState,
|
|
41
|
+
Ga as Nor8GateBehavior,
|
|
42
|
+
e as Nor8GateState,
|
|
43
|
+
F as NorGateBehavior,
|
|
44
|
+
l as NorGateState,
|
|
45
|
+
Z as Position,
|
|
46
|
+
Na as Position3D,
|
|
47
|
+
u as RectangleLEDBehavior,
|
|
48
|
+
L as RectangleLEDState,
|
|
49
|
+
pa as RelayBehavior,
|
|
50
|
+
s as RelayState,
|
|
51
|
+
oa as Rotation,
|
|
52
|
+
B as SIMULATION_SPEED,
|
|
53
|
+
G as SimulationState,
|
|
54
|
+
O as SmallLEDBehavior,
|
|
55
|
+
h as SmallLEDState,
|
|
56
|
+
V as StateManager,
|
|
57
|
+
Ta as SwitchBehavior,
|
|
58
|
+
ua as SwitchState,
|
|
59
|
+
y as TRANSITION_DEFAULTS,
|
|
60
|
+
na as Wire,
|
|
61
|
+
P as Xor4GateBehavior,
|
|
62
|
+
E as Xor4GateState,
|
|
63
|
+
Sa as Xor8GateBehavior,
|
|
64
|
+
i as Xor8GateState,
|
|
65
|
+
H as XorGateBehavior,
|
|
66
|
+
q as XorGateState,
|
|
67
|
+
g as classifyGate,
|
|
68
|
+
T as computeGateDelay,
|
|
69
|
+
t as computeTransitionSpan,
|
|
70
|
+
Q as findPositionBestIndex,
|
|
71
|
+
k as generateUUID,
|
|
72
|
+
C as getTransitionSpan,
|
|
73
|
+
va as registerBasicComponentsBehaviors,
|
|
74
|
+
$ as registerGatesComponentsBehaviors,
|
|
75
|
+
z as simplifyPositions,
|
|
76
|
+
ia as unionElectricalStates
|
|
2001
77
|
};
|
|
2002
|
-
//# sourceMappingURL=index.js.map
|