1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! History of events.

use crate::battle::BattleRules;
use crate::error::{WeaselError, WeaselResult};
use crate::event::EventId;
use crate::event::EventWrapper;
use std::convert::TryInto;

/// History is the place where all events are kept, in a way such that they
/// construct a single, consistent timeline.
pub struct History<R: BattleRules> {
    events: Vec<EventWrapper<R>>,
}

impl<R: BattleRules> History<R> {
    /// Creates a new History.
    pub(crate) fn new() -> History<R> {
        History { events: Vec::new() }
    }

    /// Returns all events inside this timeline.
    pub fn events(&self) -> &[EventWrapper<R>] {
        &self.events
    }

    /// Stores a new event in the history logs.
    pub(crate) fn archive(&mut self, event: &EventWrapper<R>) {
        assert_eq!(event.id as usize, self.events.len());
        self.events.push(event.clone());
    }

    /// Verifies if an event has an id compatible with the current timeline.
    /// Timeline only accepts monotonically increasing ids with no gaps.
    pub(crate) fn verify_event(&self, event: &EventWrapper<R>) -> WeaselResult<(), R> {
        if event.id as usize != self.events.len() {
            return Err(WeaselError::NonContiguousEventId(
                event.id,
                self.events.len().try_into().unwrap(),
            ));
        }
        Ok(())
    }

    /// Returns the id for the next event.
    pub(crate) fn next_id(&self) -> EventId {
        self.events.len().try_into().unwrap()
    }

    /// Returns the number of events in this history.
    pub fn len(&self) -> EventId {
        self.events.len().try_into().unwrap()
    }

    /// Returns whether this history is empty.
    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::event::{DummyEvent, EventTrigger};
    use crate::{battle_rules, rules::empty::*};

    #[test]
    fn verify_id() {
        battle_rules! {}
        let mut history = History::<CustomRules>::new();
        let mut try_archive = |id| -> WeaselResult<(), _> {
            let event = EventWrapper {
                id,
                origin: None,
                event: DummyEvent::trigger(&mut ()).event(),
            };
            history.verify_event(&event)?;
            history.archive(&event);
            Ok(())
        };
        assert!(try_archive(3).is_err());
        assert!(try_archive(0).is_ok());
        assert!(try_archive(2).is_err());
        assert!(try_archive(1).is_ok());
        assert!(try_archive(1).is_err());
        assert!(try_archive(0).is_err());
    }
}