#![allow(clippy::print_stdout, clippy::enum_glob_use)]
use ready_active_safe::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
enum Mode {
Ready,
Active,
Safe,
}
impl core::fmt::Display for Mode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{self:?}")
}
}
#[derive(Debug, Clone)]
enum Event {
PowerOn,
SensorReady,
BeginMeasurement,
DataCollected,
AnomalyDetected,
OperatorReset,
}
#[derive(Debug, Clone, PartialEq)]
enum Command {
InitializeSensors,
StartDataAcquisition,
StoreReading,
TriggerAlarm,
ClearAlarm,
RecalibrateSensors,
}
struct LabInstrument;
impl Machine for LabInstrument {
type Mode = Mode;
type Event = Event;
type Command = Command;
fn initial_mode(&self) -> Mode {
Mode::Ready
}
fn on_event(
&self,
mode: &Self::Mode,
event: &Self::Event,
) -> Decision<Self::Mode, Self::Command> {
use Command::*;
use Event::*;
use Mode::*;
match (mode, event) {
(Ready, PowerOn) => stay().emit(InitializeSensors),
(Ready, BeginMeasurement) => transition(Active).emit(StartDataAcquisition),
(Active, DataCollected) => stay().emit(StoreReading),
(Active, AnomalyDetected) => transition(Safe).emit(TriggerAlarm),
(Safe, OperatorReset) => transition(Ready).emit_all([ClearAlarm, RecalibrateSensors]),
_ => ignore(),
}
}
}
fn main() {
let instrument = LabInstrument;
let mut runner = Runner::new(&instrument);
let events = [
Event::PowerOn,
Event::SensorReady,
Event::BeginMeasurement,
Event::DataCollected,
Event::DataCollected,
Event::AnomalyDetected,
Event::OperatorReset,
Event::BeginMeasurement,
];
let mut journal: InMemoryJournal<Mode, Event, Command> = InMemoryJournal::new();
println!("--- Recording transitions ---\n");
for event in events {
let from = runner.mode().clone();
let commands = runner.feed(&event);
let to = runner.mode().clone();
println!(" {from:?} + {event:?} => {to:?}");
if !commands.is_empty() {
println!(" commands: {commands:?}");
}
journal.record_step(&from, &to, &event, &commands);
}
println!("\n--- Journal: {} records ---\n", journal.len());
for record in journal.records() {
println!(
" step {}: {:?} => {:?} (via {:?})",
record.step, record.from, record.to, record.event,
);
}
println!("\n--- Replaying ---\n");
match journal.replay(&instrument, instrument.initial_mode()) {
Ok(final_mode) => {
println!(" replay verified: final mode = {final_mode:?}");
assert_eq!(final_mode, runner.mode().clone());
}
Err(err) => {
println!(" {err}");
}
}
}