simple-circuit-engine 0.0.12 → 0.0.14
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 +9 -6
- package/CLAUDE.md +2 -0
- package/README.md +8 -8
- package/dist/core/index.js +109 -74
- package/dist/core/setup.d.ts +18 -0
- package/dist/core/simulation/behaviors/arithmetic/AdderBehavior.d.ts +28 -0
- package/dist/core/simulation/behaviors/arithmetic/ArithmeticBehaviorMixin.d.ts +63 -0
- package/dist/core/simulation/behaviors/arithmetic/EightBitAdderBehavior.d.ts +51 -0
- package/dist/core/simulation/behaviors/arithmetic/EightBitOnesComplementBehavior.d.ts +29 -0
- package/dist/core/simulation/behaviors/arithmetic/HalfAdderBehavior.d.ts +22 -0
- package/dist/core/simulation/behaviors/arithmetic/index.d.ts +7 -0
- package/dist/core/simulation/behaviors/index.d.ts +14 -0
- package/dist/core/simulation/behaviors/interface/EightInputBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/EightLightBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/FourInputBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/FourLightBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/InputBehaviorMixin.d.ts +37 -0
- package/dist/core/simulation/behaviors/interface/LightBehaviorMixin.d.ts +60 -0
- package/dist/core/simulation/behaviors/interface/OneInputBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/OneLightBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/TwoInputBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/TwoLightBehavior.d.ts +9 -0
- package/dist/core/simulation/behaviors/interface/index.d.ts +0 -0
- package/dist/core/simulation/states/arithmetic/AdderState.d.ts +16 -0
- package/dist/core/simulation/states/arithmetic/ArithmeticState.d.ts +53 -0
- package/dist/core/simulation/states/arithmetic/EightBitAdderState.d.ts +25 -0
- package/dist/core/simulation/states/arithmetic/EightBitOnesComplementState.d.ts +18 -0
- package/dist/core/simulation/states/arithmetic/HalfAdderState.d.ts +16 -0
- package/dist/core/simulation/states/arithmetic/index.d.ts +7 -0
- package/dist/core/simulation/states/index.d.ts +15 -0
- package/dist/core/simulation/states/interface/EightInputState.d.ts +6 -0
- package/dist/core/simulation/states/interface/EightLightState.d.ts +6 -0
- package/dist/core/simulation/states/interface/FourInputState.d.ts +6 -0
- package/dist/core/simulation/states/interface/FourLightState.d.ts +6 -0
- package/dist/core/simulation/states/interface/InputState.d.ts +45 -0
- package/dist/core/simulation/states/interface/LightState.d.ts +54 -0
- package/dist/core/simulation/states/interface/OneInputState.d.ts +6 -0
- package/dist/core/simulation/states/interface/OneLightState.d.ts +6 -0
- package/dist/core/simulation/states/interface/TwoInputState.d.ts +6 -0
- package/dist/core/simulation/states/interface/TwoLightState.d.ts +6 -0
- package/dist/core/simulation/types.d.ts +10 -2
- package/dist/core/topology/Component.d.ts +6 -1
- package/dist/core/topology/ENode.d.ts +7 -2
- package/dist/core/topology/index.d.ts +2 -0
- package/dist/core/topology/networkTraversal.d.ts +50 -0
- package/dist/core/topology/types.d.ts +31 -6
- package/dist/core-HH6iRWtB.js +4671 -0
- package/dist/core-HH6iRWtB.js.map +1 -0
- package/dist/i18n/index.d.ts +1158 -0
- package/dist/i18n/locales/en.json.d.ts +366 -0
- package/dist/i18n/locales/fr.json.d.ts +366 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +172 -118
- package/dist/scene/CircuitEngine.d.ts +49 -4
- package/dist/scene/index.d.ts +6 -2
- package/dist/scene/index.js +62 -45
- package/dist/scene/setup.d.ts +18 -0
- package/dist/scene/shared/AbstractCircuitController.d.ts +11 -3
- package/dist/scene/shared/HoverManager.d.ts +15 -0
- package/dist/scene/shared/components/arithmetic/AdderVisualFactory.d.ts +54 -0
- package/dist/scene/shared/components/arithmetic/EightBitAdderVisualFactory.d.ts +45 -0
- package/dist/scene/shared/components/arithmetic/EightBitOnesComplementVisualFactory.d.ts +63 -0
- package/dist/scene/shared/components/arithmetic/HalfAdderVisualFactory.d.ts +55 -0
- package/dist/scene/shared/components/arithmetic/index.d.ts +4 -0
- package/dist/scene/shared/components/index.d.ts +14 -0
- package/dist/scene/shared/components/interface/EightInputVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/EightLightVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/FourInputVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/FourLightVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/InputVisualFactoryBase.d.ts +50 -0
- package/dist/scene/shared/components/interface/LightVisualFactoryBase.d.ts +46 -0
- package/dist/scene/shared/components/interface/OneInputVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/OneLightVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/TwoInputVisualFactory.d.ts +15 -0
- package/dist/scene/shared/components/interface/TwoLightVisualFactory.d.ts +15 -0
- package/dist/scene/shared/types.d.ts +34 -4
- package/dist/scene/shared/utils/ControlsUtils.d.ts +1 -1
- package/dist/scene/shared/utils/GeometryUtils.d.ts +111 -0
- package/dist/scene/static/CircuitController.d.ts +13 -1
- package/dist/scene/static/tools/BuildTool.d.ts +81 -0
- package/dist/scene/static/tools/ComponentPickerWidget.d.ts +7 -0
- package/dist/scene/static/tools/ConfigPanelWidget.d.ts +14 -0
- package/dist/scene/static/tools/MultiWiringPlacement.d.ts +40 -0
- package/dist/scene/widgets/HelpWidget.d.ts +13 -0
- package/dist/scene/widgets/ModeWidget.d.ts +16 -0
- package/dist/scene/widgets/MultiWiringWidget.d.ts +21 -0
- package/dist/scene/{static → widgets}/PinTooltipWidget.d.ts +7 -1
- package/dist/scene/widgets/SimulationPlayerWidget.d.ts +62 -0
- package/dist/scene/widgets/ToolsWidget.d.ts +18 -0
- package/dist/scene/widgets/WidgetsManager.d.ts +65 -0
- package/dist/scene/widgets/assets/icons.d.ts +20 -0
- package/dist/scene/widgets/index.d.ts +9 -0
- package/dist/scene/widgets/styles.d.ts +33 -0
- package/dist/{scene-CVsDdySt.js → scene-C1xhdw_B.js} +3993 -772
- package/dist/scene-C1xhdw_B.js.map +1 -0
- package/package.json +14 -9
- package/dist/core-Bjta9Y7_.js +0 -2707
- package/dist/core-Bjta9Y7_.js.map +0 -1
- package/dist/scene-CVsDdySt.js.map +0 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
3
|
+
import { INodeElectricalState } from '../../states/types';
|
|
4
|
+
import { UUID } from '../../../utils/types';
|
|
5
|
+
import { ENodeSourceType } from '../../../topology/types';
|
|
6
|
+
import { IScheduledEvent } from '../../types';
|
|
7
|
+
import { IBehaviorResult } from '../types';
|
|
8
|
+
import { ComponentBehaviorMixin } from '../ComponentBehavior';
|
|
9
|
+
import { LightState } from '../../states/interface/LightState';
|
|
10
|
+
/**
|
|
11
|
+
* Factorises the plumbing shared by `OneLight`, `TwoLight`, `FourLight` and
|
|
12
|
+
* `EightLight` behaviors.
|
|
13
|
+
*
|
|
14
|
+
* These components mirror their `input-i` pins onto matching `output-i` pins
|
|
15
|
+
* with a per-light `transitionSpan` delay. The state encodes the current
|
|
16
|
+
* outputs as a hex value (e.g. `'5'` = `0101` for FourLight); while at least
|
|
17
|
+
* one light is moving the state literal is `'moving'` and a parameter map
|
|
18
|
+
* tracks each pending light (`${index}` → `${target}-${startTick}-${endTick}`)
|
|
19
|
+
* plus the actual driving value in `prevState`.
|
|
20
|
+
*
|
|
21
|
+
* Guards (run first in `onPinsChange`):
|
|
22
|
+
* - Vcc loss collapses the state to `allLowState` and clears all pending.
|
|
23
|
+
* - Any ill-defined logic input switches the state to `'indeterminate'`.
|
|
24
|
+
*
|
|
25
|
+
* Concurrency model (per-light, independent transitions):
|
|
26
|
+
* - When an input changes, the target output bit is recomputed; if it differs
|
|
27
|
+
* from the currently-driving (or already-pending) target a `lightChanged`
|
|
28
|
+
* event is scheduled with a per-light span.
|
|
29
|
+
* - If the same input toggles while its light is still moving, the symmetric
|
|
30
|
+
* transition pattern shortens the new span to `Math.max(prevEnd - prevStart, 1)`
|
|
31
|
+
* and the in-flight event becomes a no-op (its readyAtTick no longer matches
|
|
32
|
+
* the pending entry).
|
|
33
|
+
* - `shouldCancelPending: false` outside guards — other lights' transitions
|
|
34
|
+
* keep their schedule.
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export declare abstract class LightBehaviorMixin extends ComponentBehaviorMixin {
|
|
39
|
+
onPinsChange(component: Component, state: ComponentState, nodeStates: ReadonlyMap<UUID, INodeElectricalState>, targetTick: number): IBehaviorResult;
|
|
40
|
+
onEventFiring(_component: Component, state: ComponentState, event: IScheduledEvent): IBehaviorResult;
|
|
41
|
+
allowConductivity(component: Component, state: ComponentState, _conductivityType: ENodeSourceType, pinId: string, otherPinId: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* On vcc loss: drop all outputs low immediately and clear any pending
|
|
44
|
+
* transitions. Returns `null` when vcc is present so callers can proceed.
|
|
45
|
+
*/
|
|
46
|
+
protected vccGuardBehavior(state: LightState, pinStates: Map<string, INodeElectricalState>, targetTick: number): IBehaviorResult | null;
|
|
47
|
+
/**
|
|
48
|
+
* Scan all logic inputs; if any is ill-defined (both voltage and ground, or
|
|
49
|
+
* neither), switch to `'indeterminate'` immediately and clear any pending
|
|
50
|
+
* transitions. Otherwise returns `null` so the caller can proceed.
|
|
51
|
+
*/
|
|
52
|
+
protected nonLogicInputGuardBehavior(state: LightState, pinStates: Map<string, INodeElectricalState>, targetTick: number): IBehaviorResult | null;
|
|
53
|
+
/**
|
|
54
|
+
* For each logic input, compute the desired output bit and schedule a
|
|
55
|
+
* per-light `lightChanged` event whenever that bit differs from the current
|
|
56
|
+
* effective (or already-pending) target.
|
|
57
|
+
*/
|
|
58
|
+
protected scheduleInputTransitions(component: Component, state: LightState, pinStates: Map<string, INodeElectricalState>, targetTick: number): IBehaviorResult;
|
|
59
|
+
protected noChange(state: ComponentState): IBehaviorResult;
|
|
60
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
3
|
+
import { IComponentBehavior } from '../types';
|
|
4
|
+
import { InputBehaviorMixin } from './InputBehaviorMixin';
|
|
5
|
+
/** Single-switch user input. See {@link InputBehaviorMixin}. */
|
|
6
|
+
export declare class OneInputBehavior extends InputBehaviorMixin implements IComponentBehavior {
|
|
7
|
+
constructor();
|
|
8
|
+
createInitialState(component: Component): ComponentState;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
3
|
+
import { IComponentBehavior } from '../types';
|
|
4
|
+
import { LightBehaviorMixin } from './LightBehaviorMixin';
|
|
5
|
+
/** Single-light input mirror. See {@link LightBehaviorMixin}. */
|
|
6
|
+
export declare class OneLightBehavior extends LightBehaviorMixin implements IComponentBehavior {
|
|
7
|
+
constructor();
|
|
8
|
+
createInitialState(component: Component): ComponentState;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
3
|
+
import { IComponentBehavior } from '../types';
|
|
4
|
+
import { InputBehaviorMixin } from './InputBehaviorMixin';
|
|
5
|
+
/** Two-switch user input. See {@link InputBehaviorMixin}. */
|
|
6
|
+
export declare class TwoInputBehavior extends InputBehaviorMixin implements IComponentBehavior {
|
|
7
|
+
constructor();
|
|
8
|
+
createInitialState(component: Component): ComponentState;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Component } from '../../../topology/Component';
|
|
2
|
+
import { ComponentState } from '../../states/ComponentState';
|
|
3
|
+
import { IComponentBehavior } from '../types';
|
|
4
|
+
import { LightBehaviorMixin } from './LightBehaviorMixin';
|
|
5
|
+
/** Two-light input mirror. See {@link LightBehaviorMixin}. */
|
|
6
|
+
export declare class TwoLightBehavior extends LightBehaviorMixin implements IComponentBehavior {
|
|
7
|
+
constructor();
|
|
8
|
+
createInitialState(component: Component): ComponentState;
|
|
9
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ArithmeticState } from './ArithmeticState';
|
|
3
|
+
/**
|
|
4
|
+
* Simulation state for Full Adder components.
|
|
5
|
+
*
|
|
6
|
+
* Hex-encoded stable states: `'0'` (both low), `'1'` (sum high),
|
|
7
|
+
* `'2'` (carry high), `'3'` (both high). All four are reachable;
|
|
8
|
+
* in particular `A = B = carryIn = 1` yields `'3'`.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export declare class AdderState extends ArithmeticState {
|
|
13
|
+
constructor(componentId: UUID, initialState?: string);
|
|
14
|
+
get sumHigh(): boolean;
|
|
15
|
+
get carryOutHigh(): boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ComponentState } from '../ComponentState';
|
|
3
|
+
/**
|
|
4
|
+
* Base simulation state for arithmetic components (half adder, full adder and
|
|
5
|
+
* future multi-bit adders, multiplexers, ...).
|
|
6
|
+
*
|
|
7
|
+
* Stable states are encoded as a zero-padded hexadecimal string where each
|
|
8
|
+
* bit position maps to one logic output. Simple components use one bit per
|
|
9
|
+
* output in declaration order (bit 0 = first logicOutput). For example a
|
|
10
|
+
* half-adder with sum (bit 0) and carry (bit 1) uses `'0'`..`'3'`.
|
|
11
|
+
*
|
|
12
|
+
* Components with internal carry chains (e.g. 8-bit ripple adder) use an
|
|
13
|
+
* **interleaved** encoding `CiSi` where sum occupies even bits (`2*i`) and
|
|
14
|
+
* carry occupies odd bits (`2*i + 1`). This stores intermediate carries for
|
|
15
|
+
* ripple animation, giving `outputCount = 2 * stageCount` (e.g. 16 bits /
|
|
16
|
+
* 4 hex digits for 8 stages, states `'0000'`..`'ffff'`).
|
|
17
|
+
*
|
|
18
|
+
* Transient (in-flight) states follow the `to${nextState}` convention so
|
|
19
|
+
* animations can be driven generically from `state`/`nextState`. The
|
|
20
|
+
* previously-held stable state is preserved in `parameters.prevState` so the
|
|
21
|
+
* behavior's `allowConductivity` keeps the old outputs energized until the
|
|
22
|
+
* transition fires.
|
|
23
|
+
*
|
|
24
|
+
* A special `'indeterminate'` state is used when any logic input is ill-defined.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare abstract class ArithmeticState extends ComponentState {
|
|
29
|
+
/**
|
|
30
|
+
* Number of logic outputs for this state
|
|
31
|
+
* (e.g. 2 for half/full adder, 9 for an 8-bit adder: 8 sum bits + carry out).
|
|
32
|
+
*/
|
|
33
|
+
readonly outputCount: number;
|
|
34
|
+
/** Number of hex digits needed to encode all outputs. */
|
|
35
|
+
readonly hexDigitCount: number;
|
|
36
|
+
/** All-outputs-low state string (e.g. `'0'` for 2 outputs, `'000'` for 9). */
|
|
37
|
+
readonly allLowState: string;
|
|
38
|
+
protected constructor(componentId: UUID, outputCount: number, initialState: string);
|
|
39
|
+
/** True when the current state is a transient `to${stable}` transition. */
|
|
40
|
+
get isInTransition(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Stable state that effectively drives the outputs right now:
|
|
43
|
+
* - stable state → returns that state
|
|
44
|
+
* - transient `to<hex>` → returns the previous stable kept in parameters
|
|
45
|
+
* - `'indeterminate'` → returns `'indeterminate'`
|
|
46
|
+
*/
|
|
47
|
+
get effectiveState(): string;
|
|
48
|
+
/**
|
|
49
|
+
* Whether the `index`-th output is high in the current effective state.
|
|
50
|
+
* Returns `false` when effective state is `'indeterminate'`.
|
|
51
|
+
*/
|
|
52
|
+
isOutputHigh(index: number): boolean;
|
|
53
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ArithmeticState } from './ArithmeticState';
|
|
3
|
+
/**
|
|
4
|
+
* Simulation state for the 8-bit ripple carry adder.
|
|
5
|
+
*
|
|
6
|
+
* Uses an interleaved 16-bit encoding `C7S7 C6S6 … C1S1 C0S0` where each
|
|
7
|
+
* stage occupies two bits: sum at even position (`2*i`) and carry at odd
|
|
8
|
+
* position (`2*i + 1`). This stores intermediate carries so the ripple
|
|
9
|
+
* animation can show carry propagation stage by stage.
|
|
10
|
+
*
|
|
11
|
+
* Stable states range from `'0000'` (all low) to `'ffff'` (all high).
|
|
12
|
+
* The external outputs are `sum-0`..`sum-7` (bits 0,2,4,…,14) and
|
|
13
|
+
* `carryOut` (bit 15 = C7).
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export declare class EightBitAdderState extends ArithmeticState {
|
|
18
|
+
constructor(componentId: UUID, initialState?: string);
|
|
19
|
+
/** Whether stage `i`'s sum output is high in the current effective state. */
|
|
20
|
+
isSumHigh(stageIndex: number): boolean;
|
|
21
|
+
/** Whether stage `i`'s internal carry is high in the current effective state. */
|
|
22
|
+
isStageCarryHigh(stageIndex: number): boolean;
|
|
23
|
+
/** Whether the final carry out (C7) is high — drives the `carryOut` pin. */
|
|
24
|
+
isCarryOutHigh(): boolean;
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ArithmeticState } from './ArithmeticState';
|
|
3
|
+
/**
|
|
4
|
+
* Simulation state for the 8-bit one's complement (8 parallel XOR gates).
|
|
5
|
+
*
|
|
6
|
+
* Uses a 9-bit encoding stored as a 3-digit hex string (`'000'`..`'1ff'`):
|
|
7
|
+
* - Bits 0–7: output values (`output-i = input-i XOR invert`)
|
|
8
|
+
* - Bit 8: current invert input value (stored for animation)
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export declare class EightBitOnesComplementState extends ArithmeticState {
|
|
13
|
+
constructor(componentId: UUID, initialState?: string);
|
|
14
|
+
/** Whether output bit `index` (0–7) is high in the current effective state. */
|
|
15
|
+
isOutputBitHigh(index: number): boolean;
|
|
16
|
+
/** Whether the invert flag (bit 8) is high in the current effective state. */
|
|
17
|
+
isInvertHigh(): boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ArithmeticState } from './ArithmeticState';
|
|
3
|
+
/**
|
|
4
|
+
* Simulation state for Half Adder components.
|
|
5
|
+
*
|
|
6
|
+
* Hex-encoded stable states: `'0'` (both low), `'1'` (sum high),
|
|
7
|
+
* `'2'` (carry high). `'3'` is unreachable because `sum = A XOR B`
|
|
8
|
+
* and `carry = A AND B` can never both be true.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export declare class HalfAdderState extends ArithmeticState {
|
|
13
|
+
constructor(componentId: UUID, initialState?: string);
|
|
14
|
+
get sumHigh(): boolean;
|
|
15
|
+
get carryHigh(): boolean;
|
|
16
|
+
}
|
|
@@ -24,3 +24,18 @@ export { Nor8GateState } from './gates/Nor8GateState';
|
|
|
24
24
|
export { XorGateState } from './gates/XorGateState';
|
|
25
25
|
export { Xor4GateState } from './gates/Xor4GateState';
|
|
26
26
|
export { Xor8GateState } from './gates/Xor8GateState';
|
|
27
|
+
export { ArithmeticState } from './arithmetic/ArithmeticState';
|
|
28
|
+
export { HalfAdderState } from './arithmetic/HalfAdderState';
|
|
29
|
+
export { AdderState } from './arithmetic/AdderState';
|
|
30
|
+
export { EightBitAdderState } from './arithmetic/EightBitAdderState';
|
|
31
|
+
export { EightBitOnesComplementState } from './arithmetic/EightBitOnesComplementState';
|
|
32
|
+
export { InputState } from './interface/InputState';
|
|
33
|
+
export { OneInputState } from './interface/OneInputState';
|
|
34
|
+
export { TwoInputState } from './interface/TwoInputState';
|
|
35
|
+
export { FourInputState } from './interface/FourInputState';
|
|
36
|
+
export { EightInputState } from './interface/EightInputState';
|
|
37
|
+
export { LightState } from './interface/LightState';
|
|
38
|
+
export { OneLightState } from './interface/OneLightState';
|
|
39
|
+
export { TwoLightState } from './interface/TwoLightState';
|
|
40
|
+
export { FourLightState } from './interface/FourLightState';
|
|
41
|
+
export { EightLightState } from './interface/EightLightState';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { InputState } from './InputState';
|
|
3
|
+
/** Eight-switch user input. Stable states `'00'`..`'ff'`. */
|
|
4
|
+
export declare class EightInputState extends InputState {
|
|
5
|
+
constructor(componentId: UUID, initialState?: string);
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { LightState } from './LightState';
|
|
3
|
+
/** Eight-light input mirror. Stable states `'00'`–`'ff'`. */
|
|
4
|
+
export declare class EightLightState extends LightState {
|
|
5
|
+
constructor(componentId: UUID, initialState?: string);
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { InputState } from './InputState';
|
|
3
|
+
/** Four-switch user input. Stable states `'0'`..`'f'`. */
|
|
4
|
+
export declare class FourInputState extends InputState {
|
|
5
|
+
constructor(componentId: UUID, initialState?: string);
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { LightState } from './LightState';
|
|
3
|
+
/** Four-light input mirror. Stable states `'0'`–`'f'`. */
|
|
4
|
+
export declare class FourLightState extends LightState {
|
|
5
|
+
constructor(componentId: UUID, initialState?: string);
|
|
6
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ComponentState } from '../ComponentState';
|
|
3
|
+
/**
|
|
4
|
+
* Base simulation state for user-controlled input components (OneInput,
|
|
5
|
+
* TwoInput, FourInput, EightInput).
|
|
6
|
+
*
|
|
7
|
+
* Stable states are encoded as a zero-padded hexadecimal string where each
|
|
8
|
+
* bit position maps to one logic output (bit `i` ↔ `output-i`).
|
|
9
|
+
*
|
|
10
|
+
* While at least one switch is moving, the state value is the literal
|
|
11
|
+
* `'moving'` and the `parameters` map carries:
|
|
12
|
+
* - `prevState`: the stable hex value the outputs are still energizing
|
|
13
|
+
* - one entry per pending switch keyed by its index, encoded as
|
|
14
|
+
* `${target}-${startTick}-${endTick}` (target ∈ {0,1}).
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export declare abstract class InputState extends ComponentState {
|
|
19
|
+
/** Number of logic outputs (1, 2, 4 or 8). */
|
|
20
|
+
readonly outputCount: number;
|
|
21
|
+
/** Number of hex digits needed to encode all outputs. */
|
|
22
|
+
readonly hexDigitCount: number;
|
|
23
|
+
/** All-outputs-low state string (e.g. `'0'` for 1–4 outputs, `'00'` for 8). */
|
|
24
|
+
readonly allLowState: string;
|
|
25
|
+
protected constructor(componentId: UUID, outputCount: number, initialState: string);
|
|
26
|
+
/** True while at least one switch is mid-transition. */
|
|
27
|
+
get isInTransition(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Stable state that effectively drives the outputs right now:
|
|
30
|
+
* - stable state → returns that state
|
|
31
|
+
* - `'moving'` → returns the previous stable kept in `parameters.prevState`
|
|
32
|
+
*/
|
|
33
|
+
get effectiveState(): string;
|
|
34
|
+
/** Whether output `index` is high in the current effective state. */
|
|
35
|
+
isOutputHigh(index: number): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Pending move descriptor for switch `index`, parsed from the parameter map,
|
|
38
|
+
* or `null` when no transition is in flight for that switch.
|
|
39
|
+
*/
|
|
40
|
+
getPendingMove(index: number): {
|
|
41
|
+
target: 0 | 1;
|
|
42
|
+
startTick: number;
|
|
43
|
+
endTick: number;
|
|
44
|
+
} | null;
|
|
45
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { ComponentState } from '../ComponentState';
|
|
3
|
+
/**
|
|
4
|
+
* Base simulation state for input-driven multi-light components (OneLight,
|
|
5
|
+
* TwoLight, FourLight, EightLight).
|
|
6
|
+
*
|
|
7
|
+
* Stable states are encoded as a zero-padded hexadecimal string where each
|
|
8
|
+
* bit position maps to one logic output (bit `i` ↔ `output-i`). Outputs
|
|
9
|
+
* mirror their corresponding `input-i` after `transitionSpan` ticks so the
|
|
10
|
+
* component can be cascaded.
|
|
11
|
+
*
|
|
12
|
+
* While at least one light is moving, the state value is the literal
|
|
13
|
+
* `'moving'` and the `parameters` map carries:
|
|
14
|
+
* - `prevState`: the stable hex value the outputs are still energizing
|
|
15
|
+
* - one entry per pending light keyed by its index, encoded as
|
|
16
|
+
* `${target}-${startTick}-${endTick}` (target ∈ {0,1}).
|
|
17
|
+
*
|
|
18
|
+
* A special `'indeterminate'` state is used when any logic input is
|
|
19
|
+
* ill-defined (set immediately by the non-logic-input guard).
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export declare abstract class LightState extends ComponentState {
|
|
24
|
+
/** Number of lights / logic outputs (1, 2, 4 or 8). */
|
|
25
|
+
readonly lightCount: number;
|
|
26
|
+
/** Number of hex digits needed to encode all outputs. */
|
|
27
|
+
readonly hexDigitCount: number;
|
|
28
|
+
/** All-outputs-low state string (e.g. `'0'` for 1–4 lights, `'00'` for 8). */
|
|
29
|
+
readonly allLowState: string;
|
|
30
|
+
protected constructor(componentId: UUID, lightCount: number, initialState: string);
|
|
31
|
+
/** True while at least one light is mid-transition. */
|
|
32
|
+
get isInTransition(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Stable state that effectively drives the outputs right now:
|
|
35
|
+
* - stable hex state → returns that state
|
|
36
|
+
* - `'moving'` → returns the previous stable kept in `parameters.prevState`
|
|
37
|
+
* - `'indeterminate'` → returns `'indeterminate'`
|
|
38
|
+
*/
|
|
39
|
+
get effectiveState(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Whether output `index` is high in the current effective state.
|
|
42
|
+
* Returns `false` when effective state is `'indeterminate'`.
|
|
43
|
+
*/
|
|
44
|
+
isOutputHigh(index: number): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Pending move descriptor for light `index`, parsed from the parameter map,
|
|
47
|
+
* or `null` when no transition is in flight for that light.
|
|
48
|
+
*/
|
|
49
|
+
getPendingMove(index: number): {
|
|
50
|
+
target: 0 | 1;
|
|
51
|
+
startTick: number;
|
|
52
|
+
endTick: number;
|
|
53
|
+
} | null;
|
|
54
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { InputState } from './InputState';
|
|
3
|
+
/** Single-switch user input. Stable states `'0'` and `'1'`. */
|
|
4
|
+
export declare class OneInputState extends InputState {
|
|
5
|
+
constructor(componentId: UUID, initialState?: string);
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UUID } from '../../../utils/types';
|
|
2
|
+
import { LightState } from './LightState';
|
|
3
|
+
/** Single-light input mirror. Stable states `'0'` and `'1'`. */
|
|
4
|
+
export declare class OneLightState extends LightState {
|
|
5
|
+
constructor(componentId: UUID, initialState?: string);
|
|
6
|
+
}
|
|
@@ -11,7 +11,7 @@ export declare const SIMULATION_SPEED: {
|
|
|
11
11
|
/**
|
|
12
12
|
* Maximum simulation speed in ticks per second
|
|
13
13
|
*/
|
|
14
|
-
readonly MAX_TPS:
|
|
14
|
+
readonly MAX_TPS: 100;
|
|
15
15
|
/**
|
|
16
16
|
* Default simulation speed in ticks per second
|
|
17
17
|
*/
|
|
@@ -44,8 +44,13 @@ export declare const TRANSITION_DEFAULTS: {
|
|
|
44
44
|
export interface IUserCommand {
|
|
45
45
|
/**
|
|
46
46
|
* Type of command.
|
|
47
|
+
*
|
|
48
|
+
* - `toggle_switch`: flip a (double-throw) switch component.
|
|
49
|
+
* - `toggle_input`: flip one switch of a multi-switch input component
|
|
50
|
+
* (OneInput, TwoInput, FourInput, EightInput); `parameters` MUST carry
|
|
51
|
+
* `index` identifying which switch was toggled.
|
|
47
52
|
*/
|
|
48
|
-
readonly type: 'toggle_switch';
|
|
53
|
+
readonly type: 'toggle_switch' | 'toggle_input';
|
|
49
54
|
/**
|
|
50
55
|
* UUID of target component.
|
|
51
56
|
*/
|
|
@@ -61,6 +66,9 @@ export interface IUserCommand {
|
|
|
61
66
|
* - `tickCount`: Number of ticks for the switch transition. Computed at toggle time
|
|
62
67
|
* using the formula: `ceil(transitionUserSpan × simulationSpeed / 1000)` with minimum of 1.
|
|
63
68
|
* If not provided, behavior uses default transition timing.
|
|
69
|
+
*
|
|
70
|
+
* For `toggle_input` commands:
|
|
71
|
+
* - `index`: index of the toggled switch within the multi-switch component.
|
|
64
72
|
*/
|
|
65
73
|
readonly parameters?: Map<string, string> | null;
|
|
66
74
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UUID, Position, Rotation } from '../utils';
|
|
2
|
-
import { ComponentType, IComponent } from './types';
|
|
2
|
+
import { ComponentType, IComponent, IPinMetadata } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Electrical component placed on the circuit grid.
|
|
5
5
|
*
|
|
@@ -96,6 +96,11 @@ export declare class Component {
|
|
|
96
96
|
*/
|
|
97
97
|
constructor(type: ComponentType, position: Position, rotation: Rotation, pins: ReadonlyArray<UUID>, editable?: boolean);
|
|
98
98
|
getPinLabel(pinId: UUID): string | undefined;
|
|
99
|
+
getPinMetadata(pinId: UUID): IPinMetadata | undefined;
|
|
100
|
+
/** Resolve the ENode UUID of the logic pin at `index` within `interfaceName`, or undefined. */
|
|
101
|
+
getPinIdByInterface(interfaceName: string, index: number): UUID | undefined;
|
|
102
|
+
/** Largest index found across pins of the given logic interface, or -1 if none. */
|
|
103
|
+
getInterfaceMaxIndex(interfaceName: string): number;
|
|
99
104
|
setAllParameters(config: Map<string, string>): void;
|
|
100
105
|
setParameter(key: string, value: string): void;
|
|
101
106
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UUID, Position } from '../utils';
|
|
2
|
-
import { ENodeSourceType, ENodeType, IENode } from './types';
|
|
2
|
+
import { ENodeSourceType, ENodeType, IENode, ILogicPinMetadata } from './types';
|
|
3
3
|
import { Circuit } from './Circuit';
|
|
4
4
|
/**
|
|
5
5
|
* Electrical connection point (component pin or wire branching point).
|
|
@@ -76,6 +76,10 @@ export declare class ENode {
|
|
|
76
76
|
* @readonly
|
|
77
77
|
*/
|
|
78
78
|
readonly subtype: string;
|
|
79
|
+
/**
|
|
80
|
+
* logic pin metadata for logicInput / logicOutput pins
|
|
81
|
+
*/
|
|
82
|
+
readonly logicMetadata: ILogicPinMetadata | undefined;
|
|
79
83
|
/**
|
|
80
84
|
* Create a new electrical node.
|
|
81
85
|
*
|
|
@@ -89,6 +93,7 @@ export declare class ENode {
|
|
|
89
93
|
* @param source - Source type (Voltage/Current) or undefined
|
|
90
94
|
*
|
|
91
95
|
* @param subtype
|
|
96
|
+
* @param logicMetadata
|
|
92
97
|
* @example
|
|
93
98
|
* ```typescript
|
|
94
99
|
* // Pin node (internal to Circuit)
|
|
@@ -110,7 +115,7 @@ export declare class ENode {
|
|
|
110
115
|
* );
|
|
111
116
|
* ```
|
|
112
117
|
*/
|
|
113
|
-
constructor(type: ENodeType, component: UUID | undefined, pinLabel: string | undefined, position: Position | undefined, source
|
|
118
|
+
constructor(type: ENodeType, component: UUID | undefined, pinLabel: string | undefined, position: Position | undefined, source: ENodeSourceType | undefined, subtype: string | undefined, logicMetadata: ILogicPinMetadata | undefined);
|
|
114
119
|
/**
|
|
115
120
|
* Get the position of this electrical node.
|
|
116
121
|
*
|
|
@@ -12,3 +12,5 @@ export { CircuitOptions } from './CircuitOptions.js';
|
|
|
12
12
|
export { CircuitMetadata } from './CircuitMetadata.js';
|
|
13
13
|
export { Circuit } from './Circuit.js';
|
|
14
14
|
export { computeTransitionSpan, classifyGate, computeGateDelay } from './delays.js';
|
|
15
|
+
export { findPinsReachableFromBp, findBpsAtLogicDistance, findPinsReachableFromBpWithPath, findBpsAtLogicDistanceWithPath, } from './networkTraversal.js';
|
|
16
|
+
export type { IPinReach, IBpAtDistance } from './networkTraversal.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Circuit } from './Circuit';
|
|
2
|
+
import { UUID } from '../utils';
|
|
3
|
+
/** Reach record returned by `findPinsReachableFromBpWithPath`. */
|
|
4
|
+
export interface IPinReach {
|
|
5
|
+
/** Logic distance — number of wire edges from the start BP to this pin. */
|
|
6
|
+
Dl: number;
|
|
7
|
+
/** ENode immediately preceding the pin on the shortest BFS path back to the
|
|
8
|
+
* start BP. For Dl=1 this is the start BP itself. */
|
|
9
|
+
predecessor: UUID;
|
|
10
|
+
}
|
|
11
|
+
/** Sibling record returned by `findBpsAtLogicDistanceWithPath`. */
|
|
12
|
+
export interface IBpAtDistance {
|
|
13
|
+
/** Branching-point UUID at exactly the requested logic distance. */
|
|
14
|
+
id: UUID;
|
|
15
|
+
/** ENode immediately preceding this BP on the shortest BFS path back to
|
|
16
|
+
* the start pin. For Dl=1 this is the start pin itself. */
|
|
17
|
+
predecessor: UUID;
|
|
18
|
+
}
|
|
19
|
+
/** BFS the BP-only sub-graph from a start branching point and report every
|
|
20
|
+
* pin reached as a terminal endpoint, with its logic distance Dl.
|
|
21
|
+
*
|
|
22
|
+
* Pins are NEVER traversed through. If two paths reach the same pin, the
|
|
23
|
+
* smallest Dl wins.
|
|
24
|
+
*
|
|
25
|
+
* @returns A map of `pinId → Dl`. Empty if no pin is reachable.
|
|
26
|
+
*/
|
|
27
|
+
export declare function findPinsReachableFromBp(circuit: Circuit, startBpId: UUID): Map<UUID, number>;
|
|
28
|
+
/** Same as `findPinsReachableFromBp` but each entry also carries the BFS
|
|
29
|
+
* predecessor (the ENode one step closer to the start BP on the shortest
|
|
30
|
+
* path). Used by rule 4 to identify which of newBP's two wires leads back
|
|
31
|
+
* to the anchor pin.
|
|
32
|
+
*
|
|
33
|
+
* Map insertion order matches BFS visit order, so iterating it yields ties
|
|
34
|
+
* in BFS-first order.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findPinsReachableFromBpWithPath(circuit: Circuit, startBpId: UUID): Map<UUID, IPinReach>;
|
|
37
|
+
/** BFS the BP-only sub-graph from a start pin and return every BP reached at
|
|
38
|
+
* exactly logic distance `Dl` (i.e. path-edge count = `Dl`).
|
|
39
|
+
*
|
|
40
|
+
* Branches that hit any pin before reaching the target depth are cut. The
|
|
41
|
+
* start pin itself is never returned.
|
|
42
|
+
*
|
|
43
|
+
* @returns Array of branching-point UUIDs at logic distance Dl from the pin.
|
|
44
|
+
*/
|
|
45
|
+
export declare function findBpsAtLogicDistance(circuit: Circuit, startPinId: UUID, Dl: number): UUID[];
|
|
46
|
+
/** Same as `findBpsAtLogicDistance` but each entry carries the BFS
|
|
47
|
+
* predecessor (one step closer to the start pin). Used by rule 4 to identify
|
|
48
|
+
* which wire of each sibling to split.
|
|
49
|
+
*/
|
|
50
|
+
export declare function findBpsAtLogicDistanceWithPath(circuit: Circuit, startPinId: UUID, Dl: number): IBpAtDistance[];
|