#事件 #离散 #简单 #科学

sim-by-fired-event

这个库是一个离散时间模拟库,具有事件调度和按时间触发事件的功能

2 个版本

0.1.1 2021 年 4 月 11 日
0.1.0 2021 年 4 月 11 日

#123模拟

MIT 许可证

33KB
628

sim-by-fired-event

这个库是一个离散时间模拟库,具有事件调度和按时间触发事件的功能。

如何使用

使用示例 时间线

  1. 创建模型结构
  2. 创建事件结构
  3. 在模型和 impl 步骤中使事件可用
  4. 运行模拟

创建模型结构

首先,创建模型结构。此时间线模拟使用模型,以懒加载方式读取时间线项目。

以下定义

#[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