#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TimelineEntry {
pub period: String,
pub events: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TimelineSection {
pub name: Option<String>,
pub entries: Vec<TimelineEntry>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Timeline {
pub title: Option<String>,
pub sections: Vec<TimelineSection>,
}
impl Timeline {
pub fn total_entries(&self) -> usize {
self.sections.iter().map(|s| s.entries.len()).sum()
}
pub fn total_events(&self) -> usize {
self.sections
.iter()
.flat_map(|s| s.entries.iter())
.map(|e| e.events.len())
.sum()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn total_entries_across_sections() {
let diag = Timeline {
title: Some("Test".to_string()),
sections: vec![
TimelineSection {
name: Some("Early".to_string()),
entries: vec![
TimelineEntry {
period: "2002".to_string(),
events: vec!["LinkedIn".to_string()],
},
TimelineEntry {
period: "2003".to_string(),
events: vec!["MySpace".to_string()],
},
],
},
TimelineSection {
name: Some("Later".to_string()),
entries: vec![TimelineEntry {
period: "2005".to_string(),
events: vec!["YouTube".to_string()],
}],
},
],
};
assert_eq!(diag.total_entries(), 3);
}
#[test]
fn total_events_counts_all_events_across_multi_event_entries() {
let diag = Timeline {
title: None,
sections: vec![TimelineSection {
name: None,
entries: vec![
TimelineEntry {
period: "2004".to_string(),
events: vec!["Facebook".to_string(), "Google IPO".to_string()],
},
TimelineEntry {
period: "2005".to_string(),
events: vec!["YouTube".to_string()],
},
],
}],
};
assert_eq!(diag.total_entries(), 2);
assert_eq!(diag.total_events(), 3);
}
#[test]
fn total_entries_empty_diagram() {
assert_eq!(Timeline::default().total_entries(), 0);
assert_eq!(Timeline::default().total_events(), 0);
}
}