simple-circuit-engine 0.0.11 → 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 +10 -7
- package/CLAUDE.md +4 -6
- package/README.md +5 -2
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +74 -2114
- 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 -6306
- package/dist/index.js +117 -110
- package/dist/scene/CircuitEngine.d.ts +270 -0
- package/dist/scene/index.d.ts +0 -1
- package/dist/scene/index.js +43 -39
- 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-BQQlhwjD.js +0 -1981
- package/dist/CircuitRunner-BQQlhwjD.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-CIq_kgaw.js +0 -10230
- package/dist/setup-CIq_kgaw.js.map +0 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BehaviorRegistry } from './simulation';
|
|
2
|
+
/**
|
|
3
|
+
* Register all basic component behaviors in the given registry
|
|
4
|
+
* Basic components are : Battery, Lightbulb, RectangleLED, Relay, SmallLED, Switch, double switch
|
|
5
|
+
* @public
|
|
6
|
+
* @param registry
|
|
7
|
+
* @return the input behavior registry for chaining
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerBasicComponentsBehaviors(registry: BehaviorRegistry): BehaviorRegistry;
|
|
10
|
+
/**
|
|
11
|
+
* Register all gates component behaviors in the given registry
|
|
12
|
+
* Gates components are : Inverter, NandGate (2,4,8), NorGate (2,4,8), XorGate (2,4,8)
|
|
13
|
+
* @public
|
|
14
|
+
* @param registry
|
|
15
|
+
* @return the input behavior registry for chaining
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerGatesComponentsBehaviors(registry: BehaviorRegistry): BehaviorRegistry;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Circuit } from '../topology/Circuit';
|
|
2
|
+
import { ComponentState } from './states/ComponentState.js';
|
|
3
|
+
import { SimulationState } from './states/SimulationState';
|
|
4
|
+
import { StateManager } from './StateManager.js';
|
|
5
|
+
import { EventQueue } from './EventQueue.js';
|
|
6
|
+
import { DirtyTracker } from './DirtyTracker.js';
|
|
7
|
+
import { BehaviorRegistry } from './behaviors';
|
|
8
|
+
import { INodeElectricalState } from './states';
|
|
9
|
+
import { IUserCommand, IRunnerOptions, IRunnerResult } from './types';
|
|
10
|
+
import { UUID } from '../utils/types';
|
|
11
|
+
/**
|
|
12
|
+
* Main circuit simulation controller.
|
|
13
|
+
* Manages discrete-time simulation with event-driven state propagation.
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Boolean electrical state (voltage/current present or not)
|
|
17
|
+
* - Event-driven delayed transitions
|
|
18
|
+
* - Dirty tracking for optimization
|
|
19
|
+
* - Configurable history storage
|
|
20
|
+
* - Registry-based component behaviors
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export declare class CircuitRunner {
|
|
25
|
+
readonly circuit: Circuit;
|
|
26
|
+
readonly stateManager: StateManager;
|
|
27
|
+
readonly eventQueue: EventQueue;
|
|
28
|
+
readonly commands: Map<UUID, IUserCommand>;
|
|
29
|
+
readonly dirtyTracker: DirtyTracker;
|
|
30
|
+
readonly behaviorRegistry: BehaviorRegistry;
|
|
31
|
+
/**
|
|
32
|
+
* Create a new circuit simulation runner.
|
|
33
|
+
*
|
|
34
|
+
* @param circuit - The circuit topology to simulate
|
|
35
|
+
* @param behaviorRegistry - Registry of component behaviors
|
|
36
|
+
* @param options - Simulation options (history settings)
|
|
37
|
+
*/
|
|
38
|
+
constructor(circuit: Circuit, behaviorRegistry: BehaviorRegistry, options?: IRunnerOptions);
|
|
39
|
+
/**
|
|
40
|
+
* Execute one simulation tick.
|
|
41
|
+
* Process scheduled events, update state (electrical propagation), process user commands and advance tick.
|
|
42
|
+
*
|
|
43
|
+
* @returns the result of the tick execution
|
|
44
|
+
*/
|
|
45
|
+
tick(): IRunnerResult;
|
|
46
|
+
/**
|
|
47
|
+
* Execute multiple simulation ticks.
|
|
48
|
+
*
|
|
49
|
+
* @param count - Number of ticks to execute
|
|
50
|
+
* @returns an array of IRunnerResult for each tick executed
|
|
51
|
+
*/
|
|
52
|
+
tickN(count: number): IRunnerResult[];
|
|
53
|
+
/**
|
|
54
|
+
* Reset simulation to tick 0.
|
|
55
|
+
* Clears all state, history, and scheduled events.
|
|
56
|
+
*/
|
|
57
|
+
reset(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get current simulation tick number.
|
|
60
|
+
*
|
|
61
|
+
* @returns Current tick
|
|
62
|
+
*/
|
|
63
|
+
getCurrentTick(): number;
|
|
64
|
+
/**
|
|
65
|
+
* Get current simulation state snapshot.
|
|
66
|
+
*
|
|
67
|
+
* @returns Current state (readonly)
|
|
68
|
+
*/
|
|
69
|
+
getCurrentState(): SimulationState;
|
|
70
|
+
/**
|
|
71
|
+
* Get electrical state of a specific ENode.
|
|
72
|
+
*
|
|
73
|
+
* @param enodeId - UUID of the ENode
|
|
74
|
+
* @returns Electrical state, or undefined if not found
|
|
75
|
+
*/
|
|
76
|
+
getEnodeState(enodeId: UUID): INodeElectricalState | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Get electrical state of a specific Wire.
|
|
79
|
+
*
|
|
80
|
+
* @param wireId - UUID of the Wire
|
|
81
|
+
* @returns Electrical state, or undefined if not found
|
|
82
|
+
*/
|
|
83
|
+
getWireState(wireId: UUID): INodeElectricalState | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Get component state for a specific component.
|
|
86
|
+
*
|
|
87
|
+
* @param componentId - UUID of the component
|
|
88
|
+
* @returns Component state, or undefined if not found
|
|
89
|
+
*/
|
|
90
|
+
getComponentState(componentId: UUID): ComponentState | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Get historical state at a specific tick.
|
|
93
|
+
* Only works if history is enabled.
|
|
94
|
+
*
|
|
95
|
+
* @param tick - Tick number to retrieve
|
|
96
|
+
* @returns Historical state, or undefined if not available
|
|
97
|
+
*/
|
|
98
|
+
getStateAtTick(tick: number): SimulationState | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Check if a component is registered in behavior registry.
|
|
101
|
+
*
|
|
102
|
+
* @param componentType - Component type to check
|
|
103
|
+
* @returns True if behavior is registered
|
|
104
|
+
*/
|
|
105
|
+
hasBehavior(componentType: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Submit a user command to execute at the next tick.
|
|
108
|
+
* only one command per component per tick is allowed.
|
|
109
|
+
* Subsequent commands for the same component at this tick will be discarded.
|
|
110
|
+
*
|
|
111
|
+
* @param command - User command to submit
|
|
112
|
+
*/
|
|
113
|
+
submitCommand(command: IUserCommand): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Process all scheduled user commands.
|
|
116
|
+
* Mark changed components as Dirty and enqueue consequent scheduled events
|
|
117
|
+
* Finally clears command queue after processing.
|
|
118
|
+
*
|
|
119
|
+
* @returns Array of IBehaviorResult for each processed command
|
|
120
|
+
*/
|
|
121
|
+
private processCommands;
|
|
122
|
+
/**
|
|
123
|
+
* Helper function to extract initializationOrder from component config.
|
|
124
|
+
* Returns numeric order value, with empty string or null defaulting to 0.
|
|
125
|
+
*
|
|
126
|
+
* @param config - Component configuration map
|
|
127
|
+
* @returns Order value (lower = processed first)
|
|
128
|
+
*/
|
|
129
|
+
private getInitializationOrder;
|
|
130
|
+
/**
|
|
131
|
+
* Initialize simulation state for all components.
|
|
132
|
+
* Called on construction and reset.
|
|
133
|
+
*
|
|
134
|
+
* Uses order-based initialization to resolve feedback loops:
|
|
135
|
+
* 1. Components are grouped by initializationOrder (higher = processed LAST)
|
|
136
|
+
* 2. Within each group, components are sorted by UUID (ascending) for determinism
|
|
137
|
+
* 3. Conductivity is propagated after each component
|
|
138
|
+
*
|
|
139
|
+
* In feedback circuits, the component processed LAST "wins" because earlier
|
|
140
|
+
* components react to the initial symmetric state and open, while later
|
|
141
|
+
* components see the updated (asymmetric) state and stay closed.
|
|
142
|
+
*/
|
|
143
|
+
private initializeState;
|
|
144
|
+
/**
|
|
145
|
+
* Core method that orchestrates nodes, wires and components state updates
|
|
146
|
+
* enqueue resulting events and update dirty tracker accordingly
|
|
147
|
+
* @param targetTick - Tick at which to perform the update
|
|
148
|
+
*/
|
|
149
|
+
private updateState;
|
|
150
|
+
/**
|
|
151
|
+
* runs BFS (Breadth First Search) on voltage and current conductivity
|
|
152
|
+
* to propagate voltage/current conductivity
|
|
153
|
+
* and update enodes/wires electrical states throughout the circuit
|
|
154
|
+
* update is performed in place and updated nodes and wires returned
|
|
155
|
+
*/
|
|
156
|
+
private propagateConductivity;
|
|
157
|
+
/**
|
|
158
|
+
* given a conductivity conductivityType and a set of seed nodes, compute all reachable nodes and wires
|
|
159
|
+
* depends on componentStates to determine if conductivity is allowed through components
|
|
160
|
+
* this method doesn't mutate any state, it's a pure function
|
|
161
|
+
* @param conductivityType
|
|
162
|
+
* @param seeds
|
|
163
|
+
* @param componentStates
|
|
164
|
+
*/
|
|
165
|
+
private computeReachability;
|
|
166
|
+
/**
|
|
167
|
+
* Fire ready events and update current state accordingly
|
|
168
|
+
* eventual subsequent events are enqueued
|
|
169
|
+
*
|
|
170
|
+
* @param targetTick - Tick at which to process events
|
|
171
|
+
* @param events - Events to apply
|
|
172
|
+
* @param state - Current simulation state
|
|
173
|
+
* @param targetTick - Target tick for event processing
|
|
174
|
+
*/
|
|
175
|
+
private applyReadyEvents;
|
|
176
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { IDirtyElements } from './types';
|
|
2
|
+
import { UUID } from '../utils/types';
|
|
3
|
+
/**
|
|
4
|
+
* Tracks per-element changes for optimized state propagation.
|
|
5
|
+
* Provides granular dirty tracking at component/wire/enode level.
|
|
6
|
+
*
|
|
7
|
+
* Used to avoid re-processing unchanged elements during simulation ticks.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export declare class DirtyTracker {
|
|
12
|
+
private dirtyComponents;
|
|
13
|
+
private dirtyWires;
|
|
14
|
+
private dirtyEnodes;
|
|
15
|
+
/**
|
|
16
|
+
* Create a new dirty tracker with no marked elements.
|
|
17
|
+
*/
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Mark a component as having changed state this tick.
|
|
21
|
+
*
|
|
22
|
+
* @param componentId - UUID of the component
|
|
23
|
+
*/
|
|
24
|
+
markComponentDirty(componentId: UUID): void;
|
|
25
|
+
/**
|
|
26
|
+
* Mark a wire as having changed electrical state this tick.
|
|
27
|
+
*
|
|
28
|
+
* @param wireId - UUID of the wire
|
|
29
|
+
*/
|
|
30
|
+
markWireDirty(wireId: UUID): void;
|
|
31
|
+
/**
|
|
32
|
+
* Mark an ENode as having changed electrical state this tick.
|
|
33
|
+
*
|
|
34
|
+
* @param enodeId - UUID of the ENode
|
|
35
|
+
*/
|
|
36
|
+
markEnodeDirty(enodeId: UUID): void;
|
|
37
|
+
/**
|
|
38
|
+
* Set the entire set of dirty components. Should be only used at CircuitRunner initialization.
|
|
39
|
+
* @param componentIds
|
|
40
|
+
*/
|
|
41
|
+
setDirtyComponents(componentIds: Set<UUID>): void;
|
|
42
|
+
/**
|
|
43
|
+
* Set the entire set of dirty components. Should be only used at CircuitRunner initialization.
|
|
44
|
+
* @param enodeIds
|
|
45
|
+
*/
|
|
46
|
+
setDirtyEnodes(enodeIds: Set<UUID>): void;
|
|
47
|
+
/**
|
|
48
|
+
* Set the entire set of dirty components. Should be only used at CircuitRunner initialization.
|
|
49
|
+
* @param wireIds
|
|
50
|
+
*/
|
|
51
|
+
setDirtyWires(wireIds: Set<UUID>): void;
|
|
52
|
+
/**
|
|
53
|
+
* Get all dirty elements and clear the tracker.
|
|
54
|
+
* This is typically called at the end of a tick to collect changes.
|
|
55
|
+
*
|
|
56
|
+
* @returns Object containing sets of dirty component/wire/enode UUIDs
|
|
57
|
+
*/
|
|
58
|
+
getDirtyElements(): IDirtyElements;
|
|
59
|
+
/**
|
|
60
|
+
* Check if any elements are marked dirty.
|
|
61
|
+
*
|
|
62
|
+
* @returns True if at least one element is dirty
|
|
63
|
+
*/
|
|
64
|
+
hasDirtyElements(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Clear all dirty markers without returning them.
|
|
67
|
+
*/
|
|
68
|
+
clear(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Get current count of dirty components (for debugging/metrics).
|
|
71
|
+
*
|
|
72
|
+
* @returns Number of dirty components
|
|
73
|
+
*/
|
|
74
|
+
getDirtyComponentCount(): number;
|
|
75
|
+
/**
|
|
76
|
+
* Get current count of dirty wires (for debugging/metrics).
|
|
77
|
+
*
|
|
78
|
+
* @returns Number of dirty wires
|
|
79
|
+
*/
|
|
80
|
+
getDirtyWireCount(): number;
|
|
81
|
+
/**
|
|
82
|
+
* Get current count of dirty enodes (for debugging/metrics).
|
|
83
|
+
*
|
|
84
|
+
* @returns Number of dirty enodes
|
|
85
|
+
*/
|
|
86
|
+
getDirtyEnodeCount(): number;
|
|
87
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { IScheduledEvent } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Min-heap priority queue for scheduling future component transitions.
|
|
4
|
+
* Events are ordered by readyAtTick (earliest first).
|
|
5
|
+
* Events with same readyAtTick are returned in FIFO order (by scheduledAtTick).
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export declare class EventQueue {
|
|
10
|
+
private heap;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new empty event queue.
|
|
13
|
+
*/
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Schedule a future event.
|
|
17
|
+
* Inserted with O(log N) complexity using heap operations.
|
|
18
|
+
*
|
|
19
|
+
* @param event - Event to schedule
|
|
20
|
+
*/
|
|
21
|
+
schedule(event: IScheduledEvent): void;
|
|
22
|
+
/**
|
|
23
|
+
* Get all events ready to fire at or before current tick.
|
|
24
|
+
* Returns events in FIFO order for same readyAtTick.
|
|
25
|
+
* Removes returned events from the queue.
|
|
26
|
+
*
|
|
27
|
+
* @param currentTick - Current simulation tick
|
|
28
|
+
* @returns Array of ready events (removed from queue)
|
|
29
|
+
*/
|
|
30
|
+
getReadyEvents(currentTick: number): IScheduledEvent[];
|
|
31
|
+
/**
|
|
32
|
+
* Check if any events are pending.
|
|
33
|
+
*
|
|
34
|
+
* @returns True if queue contains events
|
|
35
|
+
*/
|
|
36
|
+
hasEvents(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Clear all pending events.
|
|
39
|
+
*/
|
|
40
|
+
clear(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Schedule multiple events at once, optionally cancelling pending events for specific targets.
|
|
43
|
+
* More efficient than individual schedule() + removeEventsForTarget() calls:
|
|
44
|
+
* single filter pass for all cancellations, batch push, single heap rebuild.
|
|
45
|
+
*
|
|
46
|
+
* @param events - Events to schedule
|
|
47
|
+
* @param cancelTargets - Target IDs whose pending events should be removed before inserting
|
|
48
|
+
*/
|
|
49
|
+
scheduleMany(events: ReadonlyArray<IScheduledEvent>, cancelTargets?: ReadonlySet<string>): void;
|
|
50
|
+
/**
|
|
51
|
+
* Remove all pending events targeting a specific component.
|
|
52
|
+
* Used when a behavior signals shouldCancelPending (e.g., Vcc loss, input change during transition).
|
|
53
|
+
*
|
|
54
|
+
* @param targetId - UUID of the component whose events should be removed
|
|
55
|
+
* @returns Number of events removed
|
|
56
|
+
*/
|
|
57
|
+
removeEventsForTarget(targetId: string): number;
|
|
58
|
+
/**
|
|
59
|
+
* Get number of pending events.
|
|
60
|
+
*
|
|
61
|
+
* @returns Event count
|
|
62
|
+
*/
|
|
63
|
+
size(): number;
|
|
64
|
+
private rebuildHeap;
|
|
65
|
+
private bubbleUp;
|
|
66
|
+
private bubbleDown;
|
|
67
|
+
private extractMin;
|
|
68
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { SimulationState } from './states/SimulationState';
|
|
2
|
+
/**
|
|
3
|
+
* Manages current simulation state and historical state storage.
|
|
4
|
+
* Uses a circular buffer for efficient memory-bounded history.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export declare class StateManager {
|
|
9
|
+
private currentState;
|
|
10
|
+
private history;
|
|
11
|
+
private readonly historyEnabled;
|
|
12
|
+
private readonly historyLimit;
|
|
13
|
+
private historyWriteIndex;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new state controllerType.
|
|
16
|
+
*
|
|
17
|
+
* @param enableHistory - Whether to store state history (default: false)
|
|
18
|
+
* @param historyLimit - Maximum number of historical states to keep (default: 1000)
|
|
19
|
+
*/
|
|
20
|
+
constructor(enableHistory?: boolean, historyLimit?: number);
|
|
21
|
+
/**
|
|
22
|
+
* Get the current simulation state.
|
|
23
|
+
*
|
|
24
|
+
* @returns Current state (mutable for simulation controller use)
|
|
25
|
+
*/
|
|
26
|
+
getCurrentState(): SimulationState;
|
|
27
|
+
/**
|
|
28
|
+
* Get current tick number.
|
|
29
|
+
*
|
|
30
|
+
* @returns Current simulation tick
|
|
31
|
+
*/
|
|
32
|
+
getCurrentTick(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Advance to next tick, optionally saving current state to history.
|
|
35
|
+
* Creates a new SimulationState for the next tick.
|
|
36
|
+
*
|
|
37
|
+
* @returns New current state for the next tick
|
|
38
|
+
*/
|
|
39
|
+
advanceToNextTick(): SimulationState;
|
|
40
|
+
/**
|
|
41
|
+
* Get a historical state by tick number.
|
|
42
|
+
* Only works if history is enabled.
|
|
43
|
+
*
|
|
44
|
+
* @param tick - Tick number to retrieve
|
|
45
|
+
* @returns State at that tick, or undefined if not available
|
|
46
|
+
*/
|
|
47
|
+
getStateAtTick(tick: number): SimulationState | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Get all available historical states.
|
|
50
|
+
* Returns empty array if history is disabled.
|
|
51
|
+
*
|
|
52
|
+
* @returns Array of historical states, sorted by tick (oldest first)
|
|
53
|
+
*/
|
|
54
|
+
getHistory(): ReadonlyArray<SimulationState>;
|
|
55
|
+
/**
|
|
56
|
+
* Get the oldest tick number available in history.
|
|
57
|
+
*
|
|
58
|
+
* @returns Oldest tick number, or undefined if no history
|
|
59
|
+
*/
|
|
60
|
+
getOldestTick(): number | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Get the newest tick number in history (not including current tick).
|
|
63
|
+
*
|
|
64
|
+
* @returns Newest historical tick, or undefined if no history
|
|
65
|
+
*/
|
|
66
|
+
getNewestHistoricalTick(): number | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Clear all history.
|
|
69
|
+
*/
|
|
70
|
+
clearHistory(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Reset to tick 0, clearing current state and all history.
|
|
73
|
+
*/
|
|
74
|
+
reset(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Check if history tracking is enabled.
|
|
77
|
+
*
|
|
78
|
+
* @returns True if history is enabled
|
|
79
|
+
*/
|
|
80
|
+
isHistoryEnabled(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Get the configured history limit.
|
|
83
|
+
*
|
|
84
|
+
* @returns Maximum number of historical states
|
|
85
|
+
*/
|
|
86
|
+
getHistoryLimit(): number;
|
|
87
|
+
/**
|
|
88
|
+
* Get current history size.
|
|
89
|
+
*
|
|
90
|
+
* @returns Number of states in history
|
|
91
|
+
*/
|
|
92
|
+
getHistorySize(): number;
|
|
93
|
+
/**
|
|
94
|
+
* Save a state to history using circular buffer.
|
|
95
|
+
* Private helper for advanceToNextTick.
|
|
96
|
+
*
|
|
97
|
+
* @param state - State to save
|
|
98
|
+
*/
|
|
99
|
+
private saveToHistory;
|
|
100
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { IComponentBehavior } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Registry for component behavior implementations.
|
|
4
|
+
* Maps component types to their behavior handlers.
|
|
5
|
+
*
|
|
6
|
+
* This allows the simulation controller to be extended with new component types
|
|
7
|
+
* without modifying core simulation logic.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export declare class BehaviorRegistry {
|
|
12
|
+
private behaviors;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new empty behavior registry.
|
|
15
|
+
*/
|
|
16
|
+
constructor();
|
|
17
|
+
/**
|
|
18
|
+
* Register a behavior for a component type.
|
|
19
|
+
* Overwrites any existing behavior for the same type.
|
|
20
|
+
*
|
|
21
|
+
* @param behavior - The component behavior to register
|
|
22
|
+
* @throws TypeError if behavior is null/undefined or componentType is empty
|
|
23
|
+
* @returns The registry instance for chaining
|
|
24
|
+
*/
|
|
25
|
+
register(behavior: IComponentBehavior): BehaviorRegistry;
|
|
26
|
+
/**
|
|
27
|
+
* Register multiple behaviors at once.
|
|
28
|
+
* Convenience method for bulk registration.
|
|
29
|
+
*
|
|
30
|
+
* @param behaviors - Array of behaviors to register
|
|
31
|
+
*/
|
|
32
|
+
registerAll(behaviors: IComponentBehavior[]): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get the behavior for a component type.
|
|
35
|
+
*
|
|
36
|
+
* @param componentType - Type identifier (e.g., "battery", "led")
|
|
37
|
+
* @returns The registered behavior, or undefined if not found
|
|
38
|
+
*/
|
|
39
|
+
get(componentType: string): IComponentBehavior | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Check if a behavior is registered for a component type.
|
|
42
|
+
*
|
|
43
|
+
* @param componentType - Type identifier to check
|
|
44
|
+
* @returns True if behavior is registered
|
|
45
|
+
*/
|
|
46
|
+
has(componentType: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Unregister a behavior for a component type.
|
|
49
|
+
*
|
|
50
|
+
* @param componentType - Type identifier to unregister
|
|
51
|
+
* @returns True if behavior was found and removed
|
|
52
|
+
*/
|
|
53
|
+
unregister(componentType: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Clear all registered behaviors.
|
|
56
|
+
*/
|
|
57
|
+
clear(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get all registered component types.
|
|
60
|
+
*
|
|
61
|
+
* @returns Array of component type identifiers
|
|
62
|
+
*/
|
|
63
|
+
getRegisteredTypes(): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Get count of registered behaviors.
|
|
66
|
+
*
|
|
67
|
+
* @returns Number of registered behaviors
|
|
68
|
+
*/
|
|
69
|
+
size(): number;
|
|
70
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Component } from '../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../states/ComponentState.js';
|
|
3
|
+
import { IScheduledEvent, IUserCommand } from '../types';
|
|
4
|
+
import { IBehaviorResult } from './types';
|
|
5
|
+
import { INodeElectricalState } from '../states/types';
|
|
6
|
+
import { UUID } from '../../utils/types';
|
|
7
|
+
import { ComponentType, ENodeSourceType, IComponentTypeMetadata } from '../../topology/types';
|
|
8
|
+
/**
|
|
9
|
+
* to factorize default implementations in component behaviors
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class ComponentBehaviorMixin {
|
|
12
|
+
/**
|
|
13
|
+
* Component type this behavior handles (e.g., "battery", "led", "switch").
|
|
14
|
+
* Used as the key in BehaviorRegistry.
|
|
15
|
+
*/
|
|
16
|
+
protected readonly _componentType: ComponentType;
|
|
17
|
+
constructor(componentType: ComponentType);
|
|
18
|
+
get componentType(): ComponentType;
|
|
19
|
+
protected get typeMetadata(): IComponentTypeMetadata;
|
|
20
|
+
protected getPinStates(component: Component, nodeStates: ReadonlyMap<UUID, INodeElectricalState>): Map<string, INodeElectricalState>;
|
|
21
|
+
protected getChangedPins(newPinStates: Map<string, INodeElectricalState>, prevPinStates: Map<string, INodeElectricalState>): Set<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Default: no custom onStart behavior
|
|
24
|
+
* @param _component
|
|
25
|
+
* @param _componentState
|
|
26
|
+
*/
|
|
27
|
+
onStart(_component: Component, _componentState: ComponentState): IBehaviorResult | null;
|
|
28
|
+
/**
|
|
29
|
+
* Default: nothing happens
|
|
30
|
+
* @param _component
|
|
31
|
+
* @param componentState
|
|
32
|
+
* @param _nodeStates
|
|
33
|
+
* @param _targetTick
|
|
34
|
+
*/
|
|
35
|
+
onPinsChange(_component: Component, componentState: ComponentState, _nodeStates: ReadonlyMap<UUID, INodeElectricalState>, _targetTick: number): IBehaviorResult;
|
|
36
|
+
/**
|
|
37
|
+
* Default: no conductivity between pins
|
|
38
|
+
* @param _component
|
|
39
|
+
* @param _state
|
|
40
|
+
* @param _conductivityType
|
|
41
|
+
* @param _pinId
|
|
42
|
+
* @param _otherPinId
|
|
43
|
+
*/
|
|
44
|
+
allowConductivity(_component: Component, _state: ComponentState, _conductivityType: ENodeSourceType, _pinId: string, _otherPinId: string): boolean;
|
|
45
|
+
onUserCommand(_component: Component, state: ComponentState, _command: IUserCommand): IBehaviorResult;
|
|
46
|
+
onEventFiring(_component: Component, state: ComponentState, _event: IScheduledEvent): IBehaviorResult;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the transition span from component config.
|
|
50
|
+
* @param config - Component config map
|
|
51
|
+
* @returns Number of ticks for transition (minimum 1)
|
|
52
|
+
*/
|
|
53
|
+
export declare function getTransitionSpan(config: Map<string, string>): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentBehaviorMixin } from '../ComponentBehavior';
|
|
3
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
4
|
+
import { IComponentBehavior } from '../types';
|
|
5
|
+
export declare class BatteryBehavior extends ComponentBehaviorMixin implements IComponentBehavior {
|
|
6
|
+
constructor();
|
|
7
|
+
/**
|
|
8
|
+
* Create initial state for a battery.
|
|
9
|
+
*
|
|
10
|
+
* @param component - The Battery component
|
|
11
|
+
* @returns Battery Initial state (always active and delivering voltage)
|
|
12
|
+
*/
|
|
13
|
+
createInitialState(component: Component): ComponentState;
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentBehaviorMixin } from '../ComponentBehavior';
|
|
3
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
4
|
+
import { IComponentBehavior, IBehaviorResult } from '../types';
|
|
5
|
+
import { ENodeSourceType } from '../../../topology/types';
|
|
6
|
+
import { IScheduledEvent } from '../../types';
|
|
7
|
+
export declare class ClockBehavior extends ComponentBehaviorMixin implements IComponentBehavior {
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Create initial state for a Clock.
|
|
11
|
+
*
|
|
12
|
+
* @param component - The Clock component
|
|
13
|
+
* @returns Clock Initial state (needle rotation)
|
|
14
|
+
*/
|
|
15
|
+
createInitialState(component: Component): ComponentState;
|
|
16
|
+
allowConductivity(component: Component, state: ComponentState, _conductivityType: ENodeSourceType, pinId: string, otherPinId: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Clock onStart allows to bootstrap cycling
|
|
19
|
+
* @param component
|
|
20
|
+
* @param state
|
|
21
|
+
*/
|
|
22
|
+
onStart(component: Component, state: ComponentState): IBehaviorResult | null;
|
|
23
|
+
onEventFiring(component: Component, state: ComponentState, event: IScheduledEvent): IBehaviorResult;
|
|
24
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState, INodeElectricalState } from '../../states';
|
|
3
|
+
import { IScheduledEvent, IUserCommand } from '../../types';
|
|
4
|
+
import { ComponentBehaviorMixin } from '../ComponentBehavior';
|
|
5
|
+
import { IBehaviorResult, IComponentBehavior } from '../types';
|
|
6
|
+
import { ENodeSourceType } from '../../../topology/types';
|
|
7
|
+
import { UUID } from '../../../utils';
|
|
8
|
+
/**
|
|
9
|
+
* Behavior implementation for switches components.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export declare class DoubleThrowSwitchBehavior extends ComponentBehaviorMixin implements IComponentBehavior {
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Create initial state for a double throw switch (SPDT).
|
|
17
|
+
*
|
|
18
|
+
* @param component - The double Switch component
|
|
19
|
+
* @returns double Switch Initial state (input1 by default)
|
|
20
|
+
*/
|
|
21
|
+
createInitialState(component: Component): ComponentState;
|
|
22
|
+
allowConductivity(component: Component, state: ComponentState, _conductivityType: ENodeSourceType, pinId: string, otherPinId: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* used for contactor color change
|
|
25
|
+
* @param component
|
|
26
|
+
* @param state
|
|
27
|
+
* @param nodeStates
|
|
28
|
+
* @param _targetTick
|
|
29
|
+
*/
|
|
30
|
+
onPinsChange(component: Component, state: ComponentState, nodeStates: ReadonlyMap<UUID, INodeElectricalState>, _targetTick: number): IBehaviorResult;
|
|
31
|
+
onUserCommand(component: Component, state: ComponentState, command: IUserCommand): IBehaviorResult;
|
|
32
|
+
onEventFiring(_component: Component, state: ComponentState, event: IScheduledEvent): IBehaviorResult;
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
3
|
+
import { BipolarLightEmitterBehaviorMixin } from './index';
|
|
4
|
+
import { IBehaviorResult, IComponentBehavior } from '../types';
|
|
5
|
+
import { INodeElectricalState } from '../../states';
|
|
6
|
+
import { UUID } from '../../../utils/types';
|
|
7
|
+
export declare class LightbulbBehavior extends BipolarLightEmitterBehaviorMixin implements IComponentBehavior {
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Create initial state for a lightbulb.
|
|
11
|
+
*
|
|
12
|
+
* @param component - The lightbulb component
|
|
13
|
+
* @returns lightbulbInitial state (always active and delivering voltage)
|
|
14
|
+
*/
|
|
15
|
+
createInitialState(component: Component): ComponentState;
|
|
16
|
+
/**
|
|
17
|
+
* @param component
|
|
18
|
+
* @param state
|
|
19
|
+
* @param nodeStates
|
|
20
|
+
* @param targetTick
|
|
21
|
+
*/
|
|
22
|
+
onPinsChange(component: Component, state: ComponentState, nodeStates: ReadonlyMap<UUID, INodeElectricalState>, targetTick: number): IBehaviorResult;
|
|
23
|
+
}
|