// Define the possible states
enum State {
IDLE = "IDLE",
LOADING = "LOADING",
SUCCESS = "SUCCESS",
ERROR = "ERROR"
}
// Define the possible events/inputs
enum Event {
START = "START",
COMPLETE = "COMPLETE",
FAIL = "FAIL",
RESET = "RESET"
}
// Define the state transitions
type StateTransitions = {
[key in State]: Partial<Record<Event, State>>;
};
// Define valid transitions between states
const transitions: StateTransitions = {
[State.IDLE]: {
[Event.START]: State.LOADING
},
[State.LOADING]: {
[Event.COMPLETE]: State.SUCCESS,
[Event.FAIL]: State.ERROR
},
[State.SUCCESS]: {
[Event.RESET]: State.IDLE
},
[State.ERROR]: {
[Event.RESET]: State.IDLE,
[Event.START]: State.LOADING
}
};
// FSA class
class FiniteStateAutomaton {
private currentState: State;
constructor(initialState: State = State.IDLE) {
this.currentState = initialState;
}
// Get current state
getCurrentState(): State {
return this.currentState;
}
// Process an event and transition to new state if valid
processEvent(event: Event): boolean {
const possibleTransitions = transitions[this.currentState];
const nextState = possibleTransitions?.[event];
if (nextState) {
console.log(`Transitioning from ${this.currentState} to ${nextState} on event ${event}`);
this.currentState = nextState;
return true;
} else {
console.log(`Invalid transition: ${event} from state ${this.currentState}`);
return false;
}
}
// Check if a transition is valid without executing it
canTransition(event: Event): boolean {
return transitions[this.currentState]?.[event] !== undefined;
}
// Reset to initial state
reset(): void {
this.currentState = State.IDLE;
console.log("FSA reset to IDLE state");
}
}
// Example usage
const fsa = new FiniteStateAutomaton();
console.log("Initial state:", fsa.getCurrentState()); // IDLE
// Valid transitions
fsa.processEvent(Event.START); // IDLE -> LOADING
fsa.processEvent(Event.COMPLETE); // LOADING -> SUCCESS
fsa.processEvent(Event.RESET); // SUCCESS -> IDLE
// Invalid transition example
fsa.processEvent(Event.COMPLETE); // Invalid: can't go from IDLE to SUCCESS directly
// Another sequence
fsa.processEvent(Event.START); // IDLE -> LOADING
fsa.processEvent(Event.FAIL); // LOADING -> ERROR
fsa.processEvent(Event.START); // ERROR -> LOADING
fsa.processEvent(Event.COMPLETE); // LOADING -> SUCCESS