2 个版本
0.1.1 | 2021 年 4 月 11 日 |
---|---|
0.1.0 | 2021 年 4 月 11 日 |
#123 在 模拟
33KB
628 行
sim-by-fired-event
这个库是一个离散时间模拟库,具有事件调度和按时间触发事件的功能。
如何使用
使用示例 时间线。
创建模型结构
首先,创建模型结构。此时间线模拟使用模型,以懒加载方式读取时间线项目。
以下定义
#[derive(Debug, Eq, PartialEq, Ord, Clone)]
struct TimelineItem {
account: String,
message: String,
created_at: Duration,
}
#[derive(Debug, Clone)]
struct Timeline {
// meta
start: SystemTime,
follow: HashMap<String, Vec<String>>,
use_flush: bool,
// items
items: Vec<TimelineItem>,
before_flush: Vec<TimelineItem>,
}
然后在模型初始化器中创建以下账户和账户的消息。
fn new() -> Self {
Timeline {
start: SystemTime::now(),
follow: HashMap::from_iter(
vec![
(
"Azio".to_string(),
vec![
"こんにちは".to_string(),
"你好".to_string(),
"안녕하세요".to_string(),
"Xin chào".to_string(),
"नमस्ते".to_string(),
],
),
(
"Mezoriento".to_string(),
vec![
"Mezoriento".to_string(),
"Merhaba".to_string(),
"გამარჯობა".to_string(),
"سلام علیکم".to_string(),
"ԲարեՎ".to_string(),
],
),
(
"Eŭropo".to_string(),
vec![
"Bonjour".to_string(),
"Guten tag".to_string(),
"Buon giorno".to_string(),
"Buon giorno".to_string(),
"Olá".to_string(),
],
),
]
.into_iter(),
),
use_flush: false,
items: vec![],
before_flush: vec![],
}
创建事件结构
其次,创建事件结构。
如果不使用事件,可以跳过此步骤,等等。请参阅计数器模拟的详细信息。以下是在使用事件时的模拟。
我想使用账户请求获取所需项目的事件,以及账户请求创建时间线项目的事件。
以下定义
#[derive(Debug, Clone)]
enum TimelineEvent {
Flush,
// pair of account and message
Spawn(String, String),
}
impl Event for TimelineEvent {}
在模型和 impl 步骤中使事件可用
第三,使事件在模型中可用。
我们之前创建了模型和事件,但现在需要实现模型处理事件的方式。
以下实现:(以下是根据时间线用户请求每 10 帧刷新。)
impl Model<Recorder> for Timeline {
type ModelEvent = TimelineEvent;
fn initialize<R: Rng + ?Sized>(
&mut self,
rng: &mut R,
_recorder: &mut Recorder,
scheduler: &mut EventScheduler<Self::ModelEvent>,
) {
// schedule pull-to-refresh event every 10 frame as the lowest priority
scheduler
.every_interval(
rng,
EventTimer::Time(10),
Priority::MIN,
TimelineEvent::Flush,
)
.unwrap();
// create random post for each account
let accounts: Vec<String> = self.follow.keys().map(|s| s.to_string()).collect();
for account in accounts.iter() {
self.schedule(rng, scheduler, account);
}
}
fn start_frame(&mut self, _recorder: &mut Recorder) {
// wait time for apply every 0.25sec. (not need)
sleep(Duration::from_millis(250));
}
fn finish_frame(&mut self, recorder: &mut Recorder) {
if self.use_flush {
self.flush(recorder);
}
}
}
这个记录器在扩展实现中是一个记录日志和摘要等的结构。
initialize 方法是在初始化模拟时的动作。start_frame(finish_frame) 是帧开始(结束)时的动作。
以下实现并不是实现模型处理事件的方式。因为处理器的定义有很多种,实现是在扩展 trait 中定义的。以下是对每个事件的实现。如果您想一起处理所有已触发的事件,请使用 BulkEvents trait。
// and impl step
impl StepEachEvent<Recorder, TimelineEvent> for Timeline {
fn step_each_event<R: Rng + ?Sized>(
&mut self,
rng: &mut R,
_recorder: &mut Recorder,
scheduler: &mut EventScheduler<Self::ModelEvent>,
_priority: Priority,
fired_event: Self::ModelEvent,
) {
match fired_event {
TimelineEvent::Flush => self.use_flush = true,
TimelineEvent::Spawn(account, message) => {
self.schedule(rng, scheduler, account.as_str());
self.spawn_item(account, message);
}
}
}
}
运行模拟
最后,运行模拟。
初始化模拟。
let mut rng = thread_rng();
let model = Timeline::new();
let mut simulator = Simulator::create_from(&mut rng, model, Recorder {});
运行模拟 COUNT 帧。
simulator.run_n_each_event(&mut rng, COUNT);
如果您使用其他方式模拟(例如,运行一帧,运行模拟直到 ..,带有检查和更新模型状态的运行),您可以使用其他 run_XXX 方法。
依赖关系
~305KB