use std::collections::BTreeMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::io::Write;
use std::time::Duration;
use crate::{DiscoveryClassification, Model, Path};
pub struct ReportData {
pub total_states: usize,
pub unique_states: usize,
pub max_depth: usize,
pub duration: Duration,
pub done: bool,
}
pub struct ReportDiscovery<M>
where
M: Model,
{
pub path: Path<M::State, M::Action>,
pub classification: DiscoveryClassification,
}
pub trait Reporter<M: Model> {
fn report_checking(&mut self, data: ReportData);
fn report_discoveries(
&mut self,
model: &M,
discoveries: BTreeMap<&'static str, ReportDiscovery<M>>,
) where
M::Action: Debug + PartialEq,
M::State: Debug + Hash + PartialEq;
fn delay(&self) -> std::time::Duration {
std::time::Duration::from_millis(1_000)
}
}
pub struct WriteReporter<'a, W> {
writer: &'a mut W,
}
impl<'a, W> WriteReporter<'a, W> {
pub fn new(writer: &'a mut W) -> Self {
Self { writer }
}
}
impl<M, W> Reporter<M> for WriteReporter<'_, W>
where
M: Model,
W: Write,
{
fn report_checking(&mut self, data: ReportData) {
if data.done {
let _ = writeln!(
self.writer,
"Done. states={}, unique={}, depth={}, sec={}",
data.total_states,
data.unique_states,
data.max_depth,
data.duration.as_secs(),
);
} else {
let _ = writeln!(
self.writer,
"Checking. states={}, unique={}, depth={}",
data.total_states, data.unique_states, data.max_depth
);
}
}
fn report_discoveries(
&mut self,
model: &M,
discoveries: BTreeMap<&'static str, ReportDiscovery<M>>,
) where
M::Action: Debug + PartialEq,
M::State: Debug + Hash + PartialEq,
{
for (name, discovery) in discoveries {
let _ = write!(
self.writer,
"Discovered \"{}\" {} {}",
name, discovery.classification, discovery.path,
);
let _ = writeln!(
self.writer,
"Action index path: {}",
discovery.path.encode(model)
);
}
}
}