Skip to content

Commit c94ebe9

Browse files
committed
Separate model technical specifications from model reporting mechanisms by expanding/splitting traits
1 parent 2706961 commit c94ebe9

17 files changed

Lines changed: 196 additions & 130 deletions

sim/src/models/batcher.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::f64::INFINITY;
22

33
use serde::{Deserialize, Serialize};
44

5-
use super::model_trait::{AsModel, SerializableModel};
5+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
66
use super::ModelMessage;
77
use crate::simulator::Services;
88
use crate::utils::errors::SimulationError;
@@ -125,15 +125,7 @@ impl Batcher {
125125
}
126126
}
127127

128-
impl AsModel for Batcher {
129-
fn status(&self) -> String {
130-
match self.state.phase {
131-
Phase::Passive => String::from("Passive"),
132-
Phase::Batching => String::from("Creating batch"),
133-
Phase::Release => String::from("Releasing batch"),
134-
}
135-
}
136-
128+
impl DevsModel for Batcher {
137129
fn events_ext(
138130
&mut self,
139131
incoming_message: &ModelMessage,
@@ -168,3 +160,15 @@ impl AsModel for Batcher {
168160
self.state.until_next_event
169161
}
170162
}
163+
164+
impl Reportable for Batcher {
165+
fn status(&self) -> String {
166+
match self.state.phase {
167+
Phase::Passive => String::from("Passive"),
168+
Phase::Batching => String::from("Creating batch"),
169+
Phase::Release => String::from("Releasing batch"),
170+
}
171+
}
172+
}
173+
174+
impl ReportableModel for Batcher {}

sim/src/models/exclusive_gateway.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::f64::INFINITY;
22

33
use serde::{Deserialize, Serialize};
44

5-
use super::model_trait::{AsModel, SerializableModel};
5+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
66
use super::ModelMessage;
77
use crate::input_modeling::IndexRandomVariable;
88
use crate::simulator::Services;
@@ -182,15 +182,7 @@ impl ExclusiveGateway {
182182
}
183183
}
184184

185-
impl AsModel for ExclusiveGateway {
186-
fn status(&self) -> String {
187-
match self.state.phase {
188-
Phase::Passive => String::from("Passive"),
189-
Phase::Pass => format!["Passing {}", self.state.jobs[0].content],
190-
Phase::Respond => String::from("Fetching records"),
191-
}
192-
}
193-
185+
impl DevsModel for ExclusiveGateway {
194186
fn events_ext(
195187
&mut self,
196188
incoming_message: &ModelMessage,
@@ -228,3 +220,15 @@ impl AsModel for ExclusiveGateway {
228220
self.state.until_next_event
229221
}
230222
}
223+
224+
impl Reportable for ExclusiveGateway {
225+
fn status(&self) -> String {
226+
match self.state.phase {
227+
Phase::Passive => String::from("Passive"),
228+
Phase::Pass => format!["Passing {}", self.state.jobs[0].content],
229+
Phase::Respond => String::from("Fetching records"),
230+
}
231+
}
232+
}
233+
234+
impl ReportableModel for ExclusiveGateway {}

sim/src/models/gate.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::f64::INFINITY;
22

33
use serde::{Deserialize, Serialize};
44

5-
use super::model_trait::{AsModel, SerializableModel};
5+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
66
use super::ModelMessage;
77
use crate::simulator::Services;
88
use crate::utils::default_records_port_name;
@@ -232,16 +232,7 @@ impl Gate {
232232
}
233233
}
234234

235-
impl AsModel for Gate {
236-
fn status(&self) -> String {
237-
match self.state.phase {
238-
Phase::Open => String::from("Open"),
239-
Phase::Closed => String::from("Closed"),
240-
Phase::Pass => format!["Passing {}", self.state.jobs[0].content],
241-
Phase::RespondWhileOpen | Phase::RespondWhileClosed => String::from("Fetching records"),
242-
}
243-
}
244-
235+
impl DevsModel for Gate {
245236
fn events_ext(
246237
&mut self,
247238
incoming_message: &ModelMessage,
@@ -282,3 +273,16 @@ impl AsModel for Gate {
282273
self.state.until_next_event
283274
}
284275
}
276+
277+
impl Reportable for Gate {
278+
fn status(&self) -> String {
279+
match self.state.phase {
280+
Phase::Open => String::from("Open"),
281+
Phase::Closed => String::from("Closed"),
282+
Phase::Pass => format!["Passing {}", self.state.jobs[0].content],
283+
Phase::RespondWhileOpen | Phase::RespondWhileClosed => String::from("Fetching records"),
284+
}
285+
}
286+
}
287+
288+
impl ReportableModel for Gate {}

sim/src/models/generator.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use serde::{Deserialize, Serialize};
22

3-
use super::model_trait::{AsModel, SerializableModel};
3+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
44
use super::ModelMessage;
55
use crate::input_modeling::ContinuousRandomVariable;
66
use crate::input_modeling::Thinning;
@@ -185,11 +185,7 @@ impl Generator {
185185
}
186186
}
187187

188-
impl AsModel for Generator {
189-
fn status(&self) -> String {
190-
format!["Generating {}s", self.ports_out.job]
191-
}
192-
188+
impl DevsModel for Generator {
193189
fn events_ext(
194190
&mut self,
195191
incoming_message: &ModelMessage,
@@ -222,3 +218,11 @@ impl AsModel for Generator {
222218
self.state.until_next_event
223219
}
224220
}
221+
222+
impl Reportable for Generator {
223+
fn status(&self) -> String {
224+
format!["Generating {}s", self.ports_out.job]
225+
}
226+
}
227+
228+
impl ReportableModel for Generator {}

sim/src/models/load_balancer.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::f64::INFINITY;
22

33
use serde::{Deserialize, Serialize};
44

5-
use super::model_trait::{AsModel, SerializableModel};
5+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
66
use super::ModelMessage;
77
use crate::simulator::Services;
88
use crate::utils::default_records_port_name;
@@ -187,11 +187,7 @@ impl LoadBalancer {
187187
}
188188
}
189189

190-
impl AsModel for LoadBalancer {
191-
fn status(&self) -> String {
192-
format!["Listening for {}s", self.ports_in.job]
193-
}
194-
190+
impl DevsModel for LoadBalancer {
195191
fn events_ext(
196192
&mut self,
197193
incoming_message: &ModelMessage,
@@ -228,3 +224,11 @@ impl AsModel for LoadBalancer {
228224
self.state.until_next_event
229225
}
230226
}
227+
228+
impl Reportable for LoadBalancer {
229+
fn status(&self) -> String {
230+
format!["Listening for {}s", self.ports_in.job]
231+
}
232+
}
233+
234+
impl ReportableModel for LoadBalancer {}

sim/src/models/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
//! specifies the requirements of any additional custom models, via the
44
//! `Model` trait.
55
6+
use serde::{Deserialize, Serialize};
7+
68
pub mod batcher;
79
pub mod exclusive_gateway;
810
pub mod gate;
@@ -25,7 +27,7 @@ pub use self::gate::Gate;
2527
pub use self::generator::Generator;
2628
pub use self::load_balancer::LoadBalancer;
2729
pub use self::model::Model;
28-
pub use self::model_trait::AsModel;
30+
pub use self::model_trait::{DevsModel, Reportable, ReportableModel};
2931
pub use self::parallel_gateway::ParallelGateway;
3032
pub use self::processor::Processor;
3133
pub use self::stochastic_gate::StochasticGate;
@@ -39,3 +41,10 @@ pub struct ModelMessage {
3941
pub port_name: String,
4042
pub content: String,
4143
}
44+
45+
#[derive(Debug, Clone, Serialize, Deserialize)]
46+
pub struct ModelRecord {
47+
pub time: f64,
48+
pub action: String,
49+
pub subject: String,
50+
}

sim/src/models/model.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use serde::ser::SerializeMap;
22
use serde::{Deserialize, Deserializer, Serialize, Serializer};
33

4-
use super::model_trait::{AsModel, SerializableModel};
4+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
55
use super::ModelMessage;
66
use crate::simulator::Services;
77
use crate::utils::errors::SimulationError;
@@ -12,11 +12,11 @@ use crate::utils::errors::SimulationError;
1212
#[derive(Clone)]
1313
pub struct Model {
1414
id: String,
15-
inner: Box<dyn AsModel>,
15+
inner: Box<dyn ReportableModel>,
1616
}
1717

1818
impl Model {
19-
pub fn new(id: String, inner: Box<dyn AsModel>) -> Self {
19+
pub fn new(id: String, inner: Box<dyn ReportableModel>) -> Self {
2020
Self { id, inner }
2121
}
2222

@@ -51,11 +51,7 @@ impl<'de> Deserialize<'de> for Model {
5151

5252
impl SerializableModel for Model {}
5353

54-
impl AsModel for Model {
55-
fn status(&self) -> String {
56-
self.inner.status()
57-
}
58-
54+
impl DevsModel for Model {
5955
fn events_ext(
6056
&mut self,
6157
incoming_message: &ModelMessage,
@@ -79,3 +75,11 @@ impl AsModel for Model {
7975
self.inner.until_next_event()
8076
}
8177
}
78+
79+
impl Reportable for Model {
80+
fn status(&self) -> String {
81+
self.inner.status()
82+
}
83+
}
84+
85+
impl ReportableModel for Model {}

sim/src/models/model_factory.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::model_trait::AsModel;
1+
use super::model_trait::ReportableModel;
22
use serde::de;
33
use serde::Deserializer;
44
use std::collections::HashMap;
@@ -7,7 +7,7 @@ use lazy_static::lazy_static;
77

88
use std::sync::Mutex;
99

10-
pub type ModelConstructor = fn(serde_yaml::Value) -> Option<Box<dyn AsModel>>;
10+
pub type ModelConstructor = fn(serde_yaml::Value) -> Option<Box<dyn ReportableModel>>;
1111
lazy_static! {
1212
static ref CONSTRUCTORS: Mutex<HashMap<&'static str, ModelConstructor>> = {
1313
let mut m = HashMap::new();
@@ -65,7 +65,7 @@ pub fn register(model_type: &'static str, model_constructor: ModelConstructor) {
6565
pub fn create<'de, D: Deserializer<'de>>(
6666
model_type: &str,
6767
extra_fields: serde_yaml::Value,
68-
) -> Result<Box<dyn AsModel>, D::Error> {
68+
) -> Result<Box<dyn ReportableModel>, D::Error> {
6969
let model = match CONSTRUCTORS.lock().unwrap().get(model_type) {
7070
Some(constructor) => constructor(extra_fields),
7171
None => None,

sim/src/models/model_trait.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ use crate::simulator::Services;
33
use crate::utils::errors::SimulationError;
44

55
pub trait ModelClone {
6-
fn clone_box(&self) -> Box<dyn AsModel>;
6+
fn clone_box(&self) -> Box<dyn ReportableModel>;
77
}
88

99
impl<T> ModelClone for T
1010
where
11-
T: 'static + AsModel + Clone,
11+
T: 'static + ReportableModel + Clone,
1212
{
13-
fn clone_box(&self) -> Box<dyn AsModel> {
13+
fn clone_box(&self) -> Box<dyn ReportableModel> {
1414
Box::new(self.clone())
1515
}
1616
}
1717

18-
impl Clone for Box<dyn AsModel> {
19-
fn clone(&self) -> Box<dyn AsModel> {
18+
impl Clone for Box<dyn ReportableModel> {
19+
fn clone(&self) -> Box<dyn ReportableModel> {
2020
self.clone_box()
2121
}
2222
}
@@ -30,14 +30,11 @@ pub trait SerializableModel {
3030
}
3131
}
3232

33-
/// The `AsModel` trait defines everything required for a model to operate
33+
/// The `DevsModel` trait defines everything required for a model to operate
3434
/// within the discrete event simulation. The simulator formalism (Discrete
3535
/// Event System Specification) requires `events_ext`, `events_int`,
36-
/// `time_advance`, and `until_next_event`. The additional `status` is for
37-
/// facilitation of simulation reasoning, reporting, and debugging.
38-
// #[enum_dispatch]
39-
pub trait AsModel: ModelClone + SerializableModel {
40-
fn status(&self) -> String;
36+
/// `time_advance`, and `until_next_event`.
37+
pub trait DevsModel: ModelClone + SerializableModel {
4138
fn events_ext(
4239
&mut self,
4340
incoming_message: &ModelMessage,
@@ -48,3 +45,15 @@ pub trait AsModel: ModelClone + SerializableModel {
4845
fn time_advance(&mut self, time_delta: f64);
4946
fn until_next_event(&self) -> f64;
5047
}
48+
49+
/// The additional status and record-keeping methods of `Reportable` provide
50+
/// improved simulation reasoning, reporting, and debugging, but do not
51+
/// impact simulation execution or results.
52+
pub trait Reportable {
53+
fn status(&self) -> String;
54+
}
55+
56+
/// A `ReportableModel` has the required Discrete Event System Specification
57+
/// methods of trait `DevsModel` and the status reporting and record keeping
58+
/// mechanisms of trait `Reportable`.
59+
pub trait ReportableModel: DevsModel + Reportable {}

sim/src/models/parallel_gateway.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::f64::INFINITY;
33

44
use serde::{Deserialize, Serialize};
55

6-
use super::model_trait::{AsModel, SerializableModel};
6+
use super::model_trait::{DevsModel, Reportable, ReportableModel, SerializableModel};
77
use super::ModelMessage;
88
use crate::simulator::Services;
99
use crate::utils::default_records_port_name;
@@ -216,11 +216,7 @@ impl ParallelGateway {
216216
}
217217
}
218218

219-
impl AsModel for ParallelGateway {
220-
fn status(&self) -> String {
221-
String::from("Active")
222-
}
223-
219+
impl DevsModel for ParallelGateway {
224220
fn events_ext(
225221
&mut self,
226222
incoming_message: &ModelMessage,
@@ -261,3 +257,11 @@ impl AsModel for ParallelGateway {
261257
self.state.until_next_event
262258
}
263259
}
260+
261+
impl Reportable for ParallelGateway {
262+
fn status(&self) -> String {
263+
String::from("Active")
264+
}
265+
}
266+
267+
impl ReportableModel for ParallelGateway {}

0 commit comments

Comments
 (0)