///|
pub(all) struct InteractiveRunner {
engine : @simulator.SimulationEngine
} derive(Debug)
///|
pub fn InteractiveRunner::new(
engine : @simulator.SimulationEngine,
) -> InteractiveRunner {
{ engine, }
}
///|
pub fn InteractiveRunner::execute_command(
self : InteractiveRunner,
cmd : String,
) -> String {
let parts = cmd.split(" ").collect()
if parts.length() == 0 {
return "Empty command"
}
let op = parts[0].to_owned()
match op {
"status" => render_station_dashboard(self.engine)
"request" =>
if parts.length() < 2 {
"Usage: request "
} else {
let r_id_int = match parse_int_custom(parts[1].to_owned()) {
Some(v) => v
None => return "Invalid route_id"
}
let r_id = @interlocking.RouteId::new(r_id_int)
let ev = @simulator.SimulationEvent::{
event_id: 1,
event_type: EventRequestRoute,
route_id: Some(r_id),
track_id: None,
turnout_id: None,
target_position: None,
train_id: "CLI_TRAIN",
timestamp_ms: 0,
}
let _ = self.engine.push_event(ev)
let report = self.engine.step_cycle()
"Requested route #" +
r_id_int.to_string() +
". Cycle report: Events=" +
report.events_processed.to_string() +
" ActiveRoutes=" +
report.routes_active.to_string()
}
"cancel" =>
if parts.length() < 2 {
"Usage: cancel "
} else {
let r_id_int = match parse_int_custom(parts[1].to_owned()) {
Some(v) => v
None => return "Invalid route_id"
}
let r_id = @interlocking.RouteId::new(r_id_int)
let ev = @simulator.SimulationEvent::{
event_id: 2,
event_type: EventCancelRoute,
route_id: Some(r_id),
track_id: None,
turnout_id: None,
target_position: None,
train_id: "",
timestamp_ms: 0,
}
let _ = self.engine.push_event(ev)
let _ = self.engine.step_cycle()
"Cancelled route #" + r_id_int.to_string()
}
"step" => {
let count = if parts.length() >= 2 {
match parse_int_custom(parts[1].to_owned()) {
Some(v) => v
None => return "Invalid step count"
}
} else {
1
}
for i = 0; i < count; i = i + 1 {
let _ = self.engine.step_cycle()
}
"Executed " + count.to_string() + " simulation 10ms cycles."
}
"audit" => {
let report = self.engine.audit()
"safety fatal=" +
report.fatal_count.to_string() +
" warning=" +
report.warning_count.to_string() +
" violations=" +
report.violations().length().to_string() +
" can_clear_signal=" +
report.can_clear_signal.to_string()
}
"scenario" =>
if parts.length() < 2 {
"Usage: scenario "
} else {
match parts[1] {
"standard" =>
@scenarios.run_scenario(@scenarios.StandardRoute).render()
"hostile" => @scenarios.run_scenario(@scenarios.HostileRoute).render()
"fault" => @scenarios.run_scenario(@scenarios.FaultRecovery).render()
"topology" =>
@scenarios.run_scenario(@scenarios.InvalidTopology).render()
_ => "Usage: scenario "
}
}
"benchmark" => @benchmarks.run_fixed_benchmark().render()
_ =>
"Unknown command: " +
op +
". Available: status, request, cancel, step, audit, scenario, benchmark"
}
}
///|
fn parse_int_custom(s : String) -> Int? {
let mut acc = 0
for ch in s {
if ch >= '0' && ch <= '9' {
acc = acc * 10 + (ch.to_int() - '0'.to_int())
} else {
return None
}
}
Some(acc)
}