aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-02-15 12:50:36 +0000
committerAkshay <[email protected]>2020-02-15 12:50:36 +0000
commit13af935178655b3ea3a8b631931a4bd68934d4af (patch)
tree12310b44828324a4dbe4ffa7db4dc683d20dd9dd
parent036357bc3c6227ac747c89cc82c29ef6a940ccbe (diff)
rework habit structures
-rw-r--r--src/habit.rs132
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;
3use chrono::NaiveDate; 3use chrono::NaiveDate;
4use serde::Serialize; 4use serde::Serialize;
5 5
6#[derive(Serialize, Debug, Clone, Copy)]
7pub enum HabitType {
8 Bit(bool),
9 Count(u32),
10}
11
12impl 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
29pub 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)]
7pub struct Habit<T> { 39pub 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
45pub enum TrackEvent {
46 Increment,
47 Decrement,
11} 48}
12 49
13impl<T> Habit<T> 50impl Habit {
14where 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
35impl 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
48impl Habit<u32> { 83impl 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 }