feat(sim): P4 slice 2 — burnt parts go open + LED joins the charred visual
- The live solver now excludes runtime-destroyed components from the netlist, so a burnt part actually goes OPEN: its current stops and anything it fed loses power (cascading failure), the way real hardware behaves once a part burns out. Filter is in CircuitSimulationService.runSolve (no-op when nothing is burnt). - The LED's burnout now also marks it in the shared burntComponents set, so a burnt LED gets the same charred + smoke-badge visual (and is opened in the solve) as a resistor / capacitor, on top of going dark.
This commit is contained in:
parent
cbcf6ba81e
commit
e4aae82ca5
|
|
@ -1,5 +1,6 @@
|
||||||
import { PartSimulationRegistry } from './PartSimulationRegistry';
|
import { PartSimulationRegistry } from './PartSimulationRegistry';
|
||||||
import { useElectricalStore } from '../../store/useElectricalStore';
|
import { useElectricalStore } from '../../store/useElectricalStore';
|
||||||
|
import { useSimulatorStore } from '../../store/useSimulatorStore';
|
||||||
import { emitPropertyChange } from './partUtils';
|
import { emitPropertyChange } from './partUtils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -171,6 +172,14 @@ const LED_BURNOUT_A = 0.1;
|
||||||
/** Surface a circuit fault for an LED — console + a UI event the toolbar shows. */
|
/** Surface a circuit fault for an LED — console + a UI event the toolbar shows. */
|
||||||
function reportLedFault(componentId: string, kind: string, message: string): void {
|
function reportLedFault(componentId: string, kind: string, message: string): void {
|
||||||
console.warn(`[led] ${componentId}: ${message}`);
|
console.warn(`[led] ${componentId}: ${message}`);
|
||||||
|
// Mark it destroyed in the shared burnt set (P4): the canvas renders it
|
||||||
|
// charred + a smoke badge, and the solver opens it — same treatment as a
|
||||||
|
// burnt resistor/capacitor. (The LED also goes dark via its own update.)
|
||||||
|
try {
|
||||||
|
useSimulatorStore.getState().markComponentBurnt?.(componentId);
|
||||||
|
} catch {
|
||||||
|
/* store unavailable (test env) — ignore */
|
||||||
|
}
|
||||||
if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function') {
|
if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function') {
|
||||||
try {
|
try {
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,9 @@ export interface SimulatorStorePort {
|
||||||
end: { componentId: string; pinName: string };
|
end: { componentId: string; pinName: string };
|
||||||
}>;
|
}>;
|
||||||
boards: Array<{ id: string; boardKind: string; pinStates?: Record<string, unknown> }>;
|
boards: Array<{ id: string; boardKind: string; pinStates?: Record<string, unknown> }>;
|
||||||
|
/** Components destroyed at runtime (P4) — excluded from the netlist so a
|
||||||
|
* burnt part actually goes open. Optional for non-store ports. */
|
||||||
|
burntComponents?: Set<string>;
|
||||||
};
|
};
|
||||||
subscribe(listener: (state: unknown, prev: unknown) => void): () => void;
|
subscribe(listener: (state: unknown, prev: unknown) => void): () => void;
|
||||||
}
|
}
|
||||||
|
|
@ -279,8 +282,14 @@ export class CircuitSimulationService {
|
||||||
|
|
||||||
private async runSolve(): Promise<void> {
|
private async runSolve(): Promise<void> {
|
||||||
const state = this.simStore.getState();
|
const state = this.simStore.getState();
|
||||||
|
// P4: a runtime-destroyed part is excluded from the netlist so it actually
|
||||||
|
// goes open — its current stops and anything it fed loses power (cascading
|
||||||
|
// failure), the way real hardware behaves once a component burns out.
|
||||||
|
const burnt = state.burntComponents;
|
||||||
|
const liveComponents =
|
||||||
|
burnt && burnt.size > 0 ? state.components.filter((c) => !burnt.has(c.id)) : state.components;
|
||||||
const snap = {
|
const snap = {
|
||||||
components: state.components,
|
components: liveComponents,
|
||||||
wires: state.wires,
|
wires: state.wires,
|
||||||
boards: state.boards.map((b) => ({
|
boards: state.boards.map((b) => ({
|
||||||
id: b.id,
|
id: b.id,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue