aboutsummaryrefslogtreecommitdiff
path: root/src/model/event.rs
blob: 6cc16a2836c5f102d1dffd938012acb3c97bc57d (plain)
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
use chrono::{NaiveDate, NaiveTime};
use std::collections::HashMap;
use uuid::Uuid;

use crate::model::repetition::Repetition;
use crate::model::time;
use crate::validation;

pub static DATE_FORMAT: &str = "%d/%m/%Y";

#[derive(Debug, Clone)]
pub struct Event {
    pub id: Uuid,
    pub date: NaiveDate,
    pub start: Option<NaiveTime>,
    pub end: Option<NaiveTime>,
    pub name: String,
    pub repetition: Option<Repetition>,
    pub category: Option<Uuid>,
}

impl Event {
    pub fn pprint(&self) -> String {
        let start = self.start.map(time::pprint).unwrap_or_default();
        let end = self
            .end
            .map(|t| format!("-{}", time::pprint(t)))
            .unwrap_or_default();
        let space = if self.start.is_some() || self.end.is_some() {
            " "
        } else {
            ""
        };
        format!("{}{}{}{}", start, end, space, self.name)
    }
}

/// Recurring events in an date range (inclusive)
pub fn repetitions_between(
    events: &[Event],
    start: NaiveDate,
    end: NaiveDate,
) -> HashMap<NaiveDate, Vec<Event>> {
    let mut res: HashMap<NaiveDate, Vec<Event>> = HashMap::new();

    for event in events {
        if let Some(repetition) = &event.repetition {
            for date in repetition.between(event.date, start, end) {
                res.entry(date).or_insert_with(Vec::new).push(event.clone())
            }
        }
    }

    res
}

// Validation

pub fn validate(
    id: Uuid,
    date: String,
    name: String,
    start: String,
    end: String,
    repetition: Option<Repetition>,
    category: Option<Uuid>,
) -> Option<Event> {
    let start = validation::time(start)?;
    let end = validation::time(end)?;

    match (start, end) {
        (Some(s), Some(e)) if s > e => None?,
        _ => (),
    }

    Some(Event {
        id,
        date: NaiveDate::parse_from_str(&date, DATE_FORMAT).ok()?,
        name: validation::non_empty(name)?,
        start,
        end,
        repetition,
        category,
    })
}