diff options
author | Akshay <[email protected]> | 2020-02-15 12:50:36 +0000 |
---|---|---|
committer | Akshay <[email protected]> | 2020-02-15 12:50:36 +0000 |
commit | 13af935178655b3ea3a8b631931a4bd68934d4af (patch) | |
tree | 12310b44828324a4dbe4ffa7db4dc683d20dd9dd | |
parent | 036357bc3c6227ac747c89cc82c29ef6a940ccbe (diff) |
rework habit structures
-rw-r--r-- | src/habit.rs | 132 |
1 files changed, 84 insertions, 48 deletions
diff --git a/src/habit.rs b/src/habit.rs index 6445545..cd1703e 100644 --- a/src/habit.rs +++ b/src/habit.rs | |||
@@ -3,73 +3,109 @@ use std::collections::HashMap; | |||
3 | use chrono::NaiveDate; | 3 | use chrono::NaiveDate; |
4 | use serde::Serialize; | 4 | use serde::Serialize; |
5 | 5 | ||
6 | #[derive(Serialize, Debug, Clone, Copy)] | ||
7 | pub enum HabitType { | ||
8 | Bit(bool), | ||
9 | Count(u32), | ||
10 | } | ||
11 | |||
12 | impl HabitType { | ||
13 | fn inner_bit(&self) -> bool { | ||
14 | if let HabitType::Bit(v) = self { | ||
15 | *v | ||
16 | } else { | ||
17 | panic!("why"); | ||
18 | } | ||
19 | } | ||
20 | fn inner_count(&self) -> u32 { | ||
21 | if let HabitType::Count(v) = self { | ||
22 | *v | ||
23 | } else { | ||
24 | panic!("why"); | ||
25 | } | ||
26 | } | ||
27 | } | ||
28 | |||
29 | pub trait HabitTrait { | ||
30 | fn set_name(&mut self, name: impl AsRef<str>); | ||
31 | fn set_goal(&mut self, goal: HabitType); | ||
32 | fn get_name(&self) -> String; | ||
33 | fn get_by_date(&self, date: NaiveDate) -> Option<&HabitType>; | ||
34 | fn insert_entry(&mut self, date: NaiveDate, val: HabitType); | ||
35 | fn reached_goal(&self, date: NaiveDate) -> bool; | ||
36 | } | ||
37 | |||
6 | #[derive(Serialize, Debug)] | 38 | #[derive(Serialize, Debug)] |
7 | pub struct Habit<T> { | 39 | pub struct Habit { |
8 | name: String, | 40 | name: String, |
9 | stats: HashMap<NaiveDate, T>, | 41 | stats: HashMap<NaiveDate, HabitType>, |
10 | goal: T, | 42 | goal: HabitType, |
43 | } | ||
44 | |||
45 | pub enum TrackEvent { | ||
46 | Increment, | ||
47 | Decrement, | ||
11 | } | 48 | } |
12 | 49 | ||
13 | impl<T> Habit<T> | 50 | impl Habit { |
14 | where | 51 | pub fn new(name: impl AsRef<str>, goal: HabitType) -> Self { |
15 | T: Copy, | ||
16 | { | ||
17 | pub fn new(name: &str, goal: T) -> Habit<T> { | ||
18 | return Habit { | 52 | return Habit { |
19 | name: name.to_owned(), | 53 | name: name.as_ref().to_owned(), |
20 | stats: HashMap::new(), | 54 | stats: HashMap::new(), |
21 | goal, | 55 | goal, |
22 | }; | 56 | }; |
23 | } | 57 | } |
24 | pub fn get_name(&self) -> String { | ||
25 | return self.name.to_owned(); | ||
26 | } | ||
27 | pub fn get_by_date(&self, date: NaiveDate) -> Option<&T> { | ||
28 | self.stats.get(&date) | ||
29 | } | ||
30 | pub fn insert_entry(&mut self, date: NaiveDate, val: T) { | ||
31 | *self.stats.entry(date).or_insert(val) = val; | ||
32 | } | ||
33 | } | ||
34 | 58 | ||
35 | impl Habit<bool> { | 59 | pub fn modify(&mut self, date: NaiveDate, event: TrackEvent) { |
36 | pub fn toggle(&mut self, date: NaiveDate) { | 60 | if let Some(val) = self.stats.get_mut(&date) { |
37 | if let Some(v) = self.stats.get_mut(&date) { | 61 | match val { |
38 | *v ^= true | 62 | HabitType::Bit(b) => *b ^= true, |
63 | HabitType::Count(c) => match event { | ||
64 | TrackEvent::Increment => *c += 1, | ||
65 | TrackEvent::Decrement => { | ||
66 | if *c > 0 { | ||
67 | *c -= 1; | ||
68 | } else { | ||
69 | *c = 0; | ||
70 | } | ||
71 | } | ||
72 | }, | ||
73 | } | ||
39 | } else { | 74 | } else { |
40 | self.insert_entry(date, true); | 75 | match self.goal { |
76 | HabitType::Bit(_) => self.insert_entry(date, HabitType::Bit(false)), | ||
77 | HabitType::Count(_) => self.insert_entry(date, HabitType::Count(0)), | ||
78 | } | ||
41 | } | 79 | } |
42 | } | 80 | } |
43 | pub fn reached_goal(&self, date: NaiveDate) -> bool { | ||
44 | *self.get_by_date(date).unwrap_or(&false) | ||
45 | } | ||
46 | } | 81 | } |
47 | 82 | ||
48 | impl Habit<u32> { | 83 | impl HabitTrait for Habit { |
49 | pub fn increment(&mut self, date: NaiveDate) { | 84 | fn get_name(&self) -> String { |
50 | if let Some(v) = self.stats.get_mut(&date) { | 85 | return self.name.to_owned(); |
51 | *v += 1; | ||
52 | } else { | ||
53 | self.insert_entry(date, 1); | ||
54 | } | ||
55 | } | 86 | } |
56 | pub fn decrement(&mut self, date: NaiveDate) { | 87 | fn set_name(&mut self, n: impl AsRef<str>) { |
57 | if let Some(v) = self.stats.get_mut(&date) { | 88 | self.name = n.as_ref().to_owned(); |
58 | if *v > 0 { | 89 | } |
59 | *v -= 1; | 90 | fn set_goal(&mut self, g: HabitType) { |
60 | } else { | 91 | self.goal = g; |
61 | *v = 0; | ||
62 | }; | ||
63 | } | ||
64 | } | 92 | } |
65 | pub fn set(&mut self, date: NaiveDate, val: u32) { | 93 | fn get_by_date(&self, date: NaiveDate) -> Option<&HabitType> { |
94 | self.stats.get(&date) | ||
95 | } | ||
96 | fn insert_entry(&mut self, date: NaiveDate, val: HabitType) { | ||
66 | *self.stats.entry(date).or_insert(val) = val; | 97 | *self.stats.entry(date).or_insert(val) = val; |
67 | } | 98 | } |
68 | pub fn reached_goal(&self, date: NaiveDate) -> bool { | 99 | fn reached_goal(&self, date: NaiveDate) -> bool { |
69 | if let Some(v) = self.get_by_date(date) { | 100 | if let Some(val) = self.stats.get(&date) { |
70 | if *v >= self.goal { | 101 | match val { |
71 | return true; | 102 | HabitType::Bit(b) => return *b, |
72 | } | 103 | HabitType::Count(c) => { |
104 | if *c >= self.goal.inner_count() { | ||
105 | return true; | ||
106 | } | ||
107 | } | ||
108 | }; | ||
73 | } | 109 | } |
74 | return false; | 110 | return false; |
75 | } | 111 | } |