kobo_db_tools/model/session/
reading_session.rs

1use chrono::{DateTime, Duration, Utc};
2use uuid::Uuid;
3
4#[derive(Debug, Clone, Copy)]
5pub enum ReadingMetric {
6    SecondsRead,
7    PagesTurned,
8    ButtonPressCount,
9    Progress,
10}
11
12#[derive(Debug)]
13pub enum ReadingSessionError {
14    InvalidEndTime,
15    InvalidProgressValue,
16}
17
18#[derive(Debug, Default)]
19pub struct ReadingSession {
20    pub id: Uuid,
21    pub open_content_id: String,
22    pub leave_content_id: Option<String>,
23    pub time_start: DateTime<Utc>,
24    pub time_end: Option<DateTime<Utc>>,
25    pub volume_id: Option<String>,
26    pub start_progress: u8,
27    pub end_progress: Option<u8>,
28    pub book_title: Option<String>,
29    pub button_press_count: Option<u64>,
30    pub seconds_read: Option<u64>,
31    pub pages_turned: Option<u64>,
32}
33
34impl ReadingSession {
35    pub fn new(
36        ts: DateTime<Utc>,
37        start_progress: u8,
38        book_title: Option<String>,
39        volume_id: Option<String>,
40        open_content_id: String,
41    ) -> Self {
42        Self {
43            id: Uuid::new_v4(),
44            time_start: ts,
45            time_end: None,
46            open_content_id,
47            leave_content_id: None,
48            volume_id,
49            start_progress,
50            end_progress: None,
51            book_title,
52            button_press_count: None,
53            seconds_read: None,
54            pages_turned: None,
55        }
56    }
57
58    pub fn complete_session(
59        &mut self,
60        time_end: DateTime<Utc>,
61        end_progress: u8,
62        button_press_count: u64,
63        seconds_read: u64,
64        pages_turned: u64,
65        leave_content_id: String,
66    ) -> Result<&mut Self, ReadingSessionError> {
67        if self.time_start > time_end {
68            return Err(ReadingSessionError::InvalidEndTime);
69        }
70
71        if end_progress > 100 || self.start_progress > 100 || end_progress < self.start_progress {
72            return Err(ReadingSessionError::InvalidProgressValue);
73        }
74
75        self.time_end = Some(time_end);
76        self.end_progress = Some(end_progress);
77        self.button_press_count = Some(button_press_count);
78        self.seconds_read = Some(seconds_read);
79        self.pages_turned = Some(pages_turned);
80        self.leave_content_id = Some(leave_content_id);
81        Ok(self)
82    }
83
84    pub fn is_complete(&self) -> bool {
85        self.end_progress.is_some()
86    }
87
88    pub fn duration(&self) -> Option<Duration> {
89        self.time_end.map(|end| end - self.time_start)
90    }
91}