kobo_db_tools/model/session/
reading_session.rs1use 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}