use crate::net::{Arc, Net, Place, Transition};
use crate::sim::{Marking, Simulation, Step, Tokens};
use crate::NodeId;
use std::marker::PhantomData;
use std::rc::Rc;
#[allow(unused_variables)]
pub trait SimulationTracer {
type Place: Place;
type Transition: Transition;
type Arc: Arc;
type Net: Net<Place = Self::Place, Transition = Self::Transition, Arc = Self::Arc>;
type Tokens: Tokens;
type Marking: Marking<Tokens = Self::Tokens>;
type Simulation: Simulation<
Place = Self::Place,
Transition = Self::Transition,
Arc = Self::Arc,
Tokens = Self::Tokens,
Marking = Self::Marking,
>;
fn started(&self, sim: &Self::Simulation) {}
fn step_started(&self, step: Step, sim: &Self::Simulation) {}
fn place_updated(&self, place: NodeId, sim: &Self::Simulation) {}
fn transition_started(&self, transition: NodeId, sim: &Self::Simulation) {}
fn transition_ended(&self, transition: NodeId, sim: &Self::Simulation) {}
fn step_ended(&self, step: Step, sim: &Self::Simulation) {}
fn ended(&self, sim: &Self::Simulation) {}
}
pub trait TraceableSimulation: Simulation {
fn add_tracer<T>(&mut self, tracer: Rc<T>)
where
T: SimulationTracer<
Place = Self::Place,
Transition = Self::Transition,
Arc = Self::Arc,
Net = Self::Net,
Tokens = Self::Tokens,
Marking = Self::Marking,
Simulation = Self,
> + 'static;
fn remove_tracer(&mut self);
}
#[derive(Debug)]
pub struct MatrixTracer<P, T, A, N, C, M, S>
where
P: Place,
T: Transition,
A: Arc,
N: Net<Place = P, Transition = T, Arc = A>,
C: Tokens,
M: Marking<Tokens = C>,
S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
{
net: PhantomData<N>,
sim: PhantomData<S>,
show_empty: bool,
}
const FORMAT_FIELD_WIDTH: usize = 6;
const TRANSITION_ENABLED: &str = "Y";
const TRANSITION_DISABLED: &str = "";
impl<P, T, A, N, C, M, S> Default for MatrixTracer<P, T, A, N, C, M, S>
where
P: Place,
T: Transition,
A: Arc,
N: Net<Place = P, Transition = T, Arc = A>,
C: Tokens,
M: Marking<Tokens = C>,
S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
{
fn default() -> Self {
Self::new(false)
}
}
impl<P, T, A, N, C, M, S> SimulationTracer for MatrixTracer<P, T, A, N, C, M, S>
where
P: Place,
T: Transition,
A: Arc,
N: Net<Place = P, Transition = T, Arc = A>,
C: Tokens,
M: Marking<Tokens = C>,
S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
{
type Place = P;
type Transition = T;
type Arc = A;
type Net = N;
type Tokens = C;
type Marking = M;
type Simulation = S;
fn started(&self, sim: &Self::Simulation) {
let (places, transitions) = self.columns(&sim.net());
println!(
"| {:>FORMAT_FIELD_WIDTH$} | {} |",
"#",
places
.iter()
.map(|id| format!("{:^FORMAT_FIELD_WIDTH$}", id.as_ref()))
.chain(
transitions
.iter()
.map(|id| format!("{:^FORMAT_FIELD_WIDTH$}", id.as_ref()))
)
.collect::<Vec<String>>()
.join(" | ")
);
let fields = places.len() + transitions.len();
let width = FORMAT_FIELD_WIDTH + 2; println!(
"|{}|",
(0..=fields)
.map(|_| format!("{:-<width$}", ""))
.collect::<Vec<String>>()
.join("+")
);
}
fn step_ended(&self, step: Step, sim: &Self::Simulation) {
let (places, transitions) = self.columns(&sim.net());
let marking = sim.current_marking();
let enabled = sim.enabled();
println!(
"| {:>FORMAT_FIELD_WIDTH$} | {} |",
step.as_ref(),
places
.iter()
.map(|id| if self.show_empty {
format!("{:#^FORMAT_FIELD_WIDTH$}", marking.marking(id).to_string())
} else {
format!("{:^FORMAT_FIELD_WIDTH$}", marking.marking(id).to_string())
})
.chain(transitions.iter().map(|id| format!(
"{:^FORMAT_FIELD_WIDTH$}",
if enabled.contains(id) {
TRANSITION_ENABLED
} else {
TRANSITION_DISABLED
}
)))
.collect::<Vec<String>>()
.join(" | ")
);
}
}
impl<P, T, A, N, C, M, S> MatrixTracer<P, T, A, N, C, M, S>
where
P: Place,
T: Transition,
A: Arc,
N: Net<Place = P, Transition = T, Arc = A>,
C: Tokens,
M: Marking<Tokens = C>,
S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
{
pub fn new(show_empty: bool) -> Self {
Self {
net: Default::default(),
sim: Default::default(),
show_empty,
}
}
#[inline(always)]
fn columns(&self, net: &<S as Simulation>::Net) -> (Vec<NodeId>, Vec<NodeId>) {
let mut places: Vec<NodeId> = net.places().iter().map(|place| place.id()).collect();
places.sort();
let mut transitions: Vec<NodeId> = net
.transitions()
.iter()
.map(|transition| transition.id())
.collect();
transitions.sort();
(places, transitions)
}
}