1use crate::net::{Arc, Net, Place, Transition};
11use crate::sim::{Marking, Simulation, Step, Tokens};
12use crate::NodeId;
13use std::marker::PhantomData;
14use std::rc::Rc;
15
16#[allow(unused_variables)]
38pub trait SimulationTracer {
39 type Place: Place;
40 type Transition: Transition;
41 type Arc: Arc;
42 type Net: Net<Place = Self::Place, Transition = Self::Transition, Arc = Self::Arc>;
43 type Tokens: Tokens;
44 type Marking: Marking<Tokens = Self::Tokens>;
45 type Simulation: Simulation<
46 Place = Self::Place,
47 Transition = Self::Transition,
48 Arc = Self::Arc,
49 Tokens = Self::Tokens,
50 Marking = Self::Marking,
51 >;
52
53 fn started(&self, sim: &Self::Simulation) {}
58
59 fn step_started(&self, step: Step, sim: &Self::Simulation) {}
64
65 fn place_updated(&self, place: NodeId, sim: &Self::Simulation) {}
70
71 fn transition_started(&self, transition: NodeId, sim: &Self::Simulation) {}
76
77 fn transition_ended(&self, transition: NodeId, sim: &Self::Simulation) {}
82
83 fn step_ended(&self, step: Step, sim: &Self::Simulation) {}
88
89 fn ended(&self, sim: &Self::Simulation) {}
94}
95
96pub trait TraceableSimulation: Simulation {
103 fn add_tracer<T>(&mut self, tracer: Rc<T>)
107 where
108 T: SimulationTracer<
109 Place = Self::Place,
110 Transition = Self::Transition,
111 Arc = Self::Arc,
112 Net = Self::Net,
113 Tokens = Self::Tokens,
114 Marking = Self::Marking,
115 Simulation = Self,
116 > + 'static;
117
118 fn remove_tracer(&mut self);
123}
124
125#[derive(Debug)]
140pub struct MatrixTracer<P, T, A, N, C, M, S>
141where
142 P: Place,
143 T: Transition,
144 A: Arc,
145 N: Net<Place = P, Transition = T, Arc = A>,
146 C: Tokens,
147 M: Marking<Tokens = C>,
148 S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
149{
150 net: PhantomData<N>,
151 sim: PhantomData<S>,
152 show_empty: bool,
153}
154
155const FORMAT_FIELD_WIDTH: usize = 6;
160const TRANSITION_ENABLED: &str = "Y";
161const TRANSITION_DISABLED: &str = "";
162
163impl<P, T, A, N, C, M, S> Default for MatrixTracer<P, T, A, N, C, M, S>
164where
165 P: Place,
166 T: Transition,
167 A: Arc,
168 N: Net<Place = P, Transition = T, Arc = A>,
169 C: Tokens,
170 M: Marking<Tokens = C>,
171 S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
172{
173 fn default() -> Self {
174 Self::new(false)
175 }
176}
177
178impl<P, T, A, N, C, M, S> SimulationTracer for MatrixTracer<P, T, A, N, C, M, S>
179where
180 P: Place,
181 T: Transition,
182 A: Arc,
183 N: Net<Place = P, Transition = T, Arc = A>,
184 C: Tokens,
185 M: Marking<Tokens = C>,
186 S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
187{
188 type Place = P;
189 type Transition = T;
190 type Arc = A;
191 type Net = N;
192 type Tokens = C;
193 type Marking = M;
194 type Simulation = S;
195
196 fn started(&self, sim: &Self::Simulation) {
197 let (places, transitions) = self.columns(&sim.net());
198
199 println!(
200 "| {:>FORMAT_FIELD_WIDTH$} | {} |",
201 "#",
202 places
203 .iter()
204 .map(|id| format!("{:^FORMAT_FIELD_WIDTH$}", id.as_ref()))
205 .chain(
206 transitions
207 .iter()
208 .map(|id| format!("{:^FORMAT_FIELD_WIDTH$}", id.as_ref()))
209 )
210 .collect::<Vec<String>>()
211 .join(" | ")
212 );
213
214 let fields = places.len() + transitions.len();
215 let width = FORMAT_FIELD_WIDTH + 2; println!(
217 "|{}|",
218 (0..=fields)
219 .map(|_| format!("{:-<width$}", ""))
220 .collect::<Vec<String>>()
221 .join("+")
222 );
223 }
224
225 fn step_ended(&self, step: Step, sim: &Self::Simulation) {
226 let (places, transitions) = self.columns(&sim.net());
227
228 let marking = sim.current_marking();
229 let enabled = sim.enabled();
230
231 println!(
232 "| {:>FORMAT_FIELD_WIDTH$} | {} |",
233 step.as_ref(),
234 places
235 .iter()
236 .map(|id| if self.show_empty {
237 format!("{:#^FORMAT_FIELD_WIDTH$}", marking.marking(id).to_string())
238 } else {
239 format!("{:^FORMAT_FIELD_WIDTH$}", marking.marking(id).to_string())
240 })
241 .chain(transitions.iter().map(|id| format!(
242 "{:^FORMAT_FIELD_WIDTH$}",
243 if enabled.contains(id) {
244 TRANSITION_ENABLED
245 } else {
246 TRANSITION_DISABLED
247 }
248 )))
249 .collect::<Vec<String>>()
250 .join(" | ")
251 );
252 }
253}
254
255impl<P, T, A, N, C, M, S> MatrixTracer<P, T, A, N, C, M, S>
256where
257 P: Place,
258 T: Transition,
259 A: Arc,
260 N: Net<Place = P, Transition = T, Arc = A>,
261 C: Tokens,
262 M: Marking<Tokens = C>,
263 S: Simulation<Place = P, Transition = T, Arc = A, Tokens = C, Marking = M>,
264{
265 pub fn new(show_empty: bool) -> Self {
266 Self {
267 net: Default::default(),
268 sim: Default::default(),
269 show_empty,
270 }
271 }
272
273 #[inline(always)]
274 fn columns(&self, net: &<S as Simulation>::Net) -> (Vec<NodeId>, Vec<NodeId>) {
275 let mut places: Vec<NodeId> = net.places().iter().map(|place| place.id()).collect();
276 places.sort();
277 let mut transitions: Vec<NodeId> = net
278 .transitions()
279 .iter()
280 .map(|transition| transition.id())
281 .collect();
282 transitions.sort();
283 (places, transitions)
284 }
285}