aboutsummaryrefslogtreecommitdiff
path: root/src/habit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/habit.rs')
-rw-r--r--src/habit.rs271
1 files changed, 0 insertions, 271 deletions
diff --git a/src/habit.rs b/src/habit.rs
deleted file mode 100644
index 48dd363..0000000
--- a/src/habit.rs
+++ /dev/null
@@ -1,271 +0,0 @@
1use std::collections::HashMap;
2
3use chrono::NaiveDate;
4use serde::{Deserialize, Serialize};
5
6use cursive::direction::Direction;
7use cursive::event::{Event, EventResult};
8use cursive::{Printer, Vec2};
9
10use crate::views::ShadowView;
11use crate::CONFIGURATION;
12
13pub enum TrackEvent {
14 Increment,
15 Decrement,
16}
17
18#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
19pub struct CustomBool(bool);
20
21use std::fmt;
22impl fmt::Display for CustomBool {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 write!(
25 f,
26 "{:^3}",
27 if self.0 {
28 CONFIGURATION.true_chr
29 } else {
30 CONFIGURATION.false_chr
31 }
32 )
33 }
34}
35
36impl From<bool> for CustomBool {
37 fn from(b: bool) -> Self {
38 CustomBool(b)
39 }
40}
41
42pub trait Habit {
43 type HabitType;
44
45 fn set_name(&mut self, name: impl AsRef<str>);
46 fn set_goal(&mut self, goal: Self::HabitType);
47 fn name(&self) -> String;
48 fn get_by_date(&self, date: NaiveDate) -> Option<&Self::HabitType>;
49 fn insert_entry(&mut self, date: NaiveDate, val: Self::HabitType);
50 fn reached_goal(&self, date: NaiveDate) -> bool;
51 fn remaining(&self, date: NaiveDate) -> u32;
52 fn total(&self) -> u32;
53 fn modify(&mut self, date: NaiveDate, event: TrackEvent);
54 fn set_view_month_offset(&mut self, offset: u32);
55 fn view_month_offset(&self) -> u32;
56}
57
58#[typetag::serde(tag = "type")]
59pub trait HabitWrapper: erased_serde::Serialize {
60 fn remaining(&self, date: NaiveDate) -> u32;
61 fn total(&self) -> u32;
62 fn modify(&mut self, date: NaiveDate, event: TrackEvent);
63 fn draw(&self, printer: &Printer);
64 fn on_event(&mut self, event: Event) -> EventResult;
65 fn required_size(&mut self, _: Vec2) -> Vec2;
66 fn take_focus(&mut self, _: Direction) -> bool;
67 fn set_view_month_offset(&mut self, offset: u32);
68 fn view_month_offset(&self) -> u32;
69 fn get_name(&self) -> String;
70}
71
72macro_rules! auto_habit_impl {
73 ($struct_name:ident) => {
74 #[typetag::serde]
75 impl HabitWrapper for $struct_name {
76 fn remaining(&self, date: NaiveDate) -> u32 {
77 Habit::remaining(self, date)
78 }
79 fn total(&self) -> u32 {
80 Habit::total(self)
81 }
82 fn modify(&mut self, date: NaiveDate, event: TrackEvent) {
83 Habit::modify(self, date, event);
84 }
85 fn draw(&self, printer: &Printer) {
86 ShadowView::draw(self, printer)
87 }
88 fn on_event(&mut self, event: Event) -> EventResult {
89 ShadowView::on_event(self, event)
90 }
91 fn required_size(&mut self, x: Vec2) -> Vec2 {
92 ShadowView::required_size(self, x)
93 }
94 fn take_focus(&mut self, d: Direction) -> bool {
95 ShadowView::take_focus(self, d)
96 }
97 fn set_view_month_offset(&mut self, offset: u32) {
98 Habit::set_view_month_offset(self, offset)
99 }
100 fn view_month_offset(&self) -> u32 {
101 Habit::view_month_offset(self)
102 }
103 fn get_name(&self) -> String {
104 Habit::name(self)
105 }
106 }
107 };
108}
109
110auto_habit_impl!(Count);
111auto_habit_impl!(Bit);
112
113#[derive(Debug, Serialize, Deserialize)]
114pub struct Count {
115 name: String,
116 stats: HashMap<NaiveDate, u32>,
117 goal: u32,
118
119 #[serde(skip)]
120 view_month_offset: u32,
121}
122
123impl Count {
124 pub fn new(name: impl AsRef<str>, goal: u32) -> Self {
125 return Count {
126 name: name.as_ref().to_owned(),
127 stats: HashMap::new(),
128 goal,
129 view_month_offset: 0,
130 };
131 }
132}
133
134impl Habit for Count {
135 type HabitType = u32;
136
137 fn name(&self) -> String {
138 return self.name.clone();
139 }
140 fn set_name(&mut self, n: impl AsRef<str>) {
141 self.name = n.as_ref().to_owned();
142 }
143 fn set_goal(&mut self, g: Self::HabitType) {
144 self.goal = g;
145 }
146 fn get_by_date(&self, date: NaiveDate) -> Option<&Self::HabitType> {
147 self.stats.get(&date)
148 }
149 fn insert_entry(&mut self, date: NaiveDate, val: Self::HabitType) {
150 *self.stats.entry(date).or_insert(val) = val;
151 }
152 fn reached_goal(&self, date: NaiveDate) -> bool {
153 if let Some(val) = self.stats.get(&date) {
154 if val >= &self.goal {
155 return true;
156 }
157 }
158 return false;
159 }
160 fn remaining(&self, date: NaiveDate) -> u32 {
161 if self.reached_goal(date) {
162 return 0;
163 } else {
164 if let Some(val) = self.stats.get(&date) {
165 return self.goal - val;
166 } else {
167 return self.goal;
168 }
169 }
170 }
171 fn total(&self) -> u32 {
172 return self.goal;
173 }
174 fn modify(&mut self, date: NaiveDate, event: TrackEvent) {
175 if let Some(val) = self.stats.get_mut(&date) {
176 match event {
177 TrackEvent::Increment => *val += 1,
178 TrackEvent::Decrement => {
179 if *val > 0 {
180 *val -= 1
181 } else {
182 *val = 0
183 };
184 }
185 }
186 } else {
187 self.insert_entry(date, 1);
188 }
189 }
190 fn set_view_month_offset(&mut self, offset: u32) {
191 self.view_month_offset = offset;
192 }
193 fn view_month_offset(&self) -> u32 {
194 self.view_month_offset
195 }
196}
197
198#[derive(Debug, Serialize, Deserialize)]
199pub struct Bit {
200 name: String,
201 stats: HashMap<NaiveDate, CustomBool>,
202 goal: CustomBool,
203
204 #[serde(skip)]
205 view_month_offset: u32,
206}
207
208impl Bit {
209 pub fn new(name: impl AsRef<str>) -> Self {
210 return Bit {
211 name: name.as_ref().to_owned(),
212 stats: HashMap::new(),
213 goal: CustomBool(true),
214 view_month_offset: 0,
215 };
216 }
217}
218
219impl Habit for Bit {
220 type HabitType = CustomBool;
221 fn name(&self) -> String {
222 return self.name.clone();
223 }
224 fn set_name(&mut self, n: impl AsRef<str>) {
225 self.name = n.as_ref().to_owned();
226 }
227 fn set_goal(&mut self, g: Self::HabitType) {
228 self.goal = g;
229 }
230 fn get_by_date(&self, date: NaiveDate) -> Option<&Self::HabitType> {
231 self.stats.get(&date)
232 }
233 fn insert_entry(&mut self, date: NaiveDate, val: Self::HabitType) {
234 *self.stats.entry(date).or_insert(val) = val;
235 }
236 fn reached_goal(&self, date: NaiveDate) -> bool {
237 if let Some(val) = self.stats.get(&date) {
238 if val.0 >= self.goal.0 {
239 return true;
240 }
241 }
242 return false;
243 }
244 fn remaining(&self, date: NaiveDate) -> u32 {
245 if let Some(val) = self.stats.get(&date) {
246 if val.0 {
247 return 0;
248 } else {
249 return 1;
250 }
251 } else {
252 return 1;
253 }
254 }
255 fn total(&self) -> u32 {
256 return 1;
257 }
258 fn modify(&mut self, date: NaiveDate, _: TrackEvent) {
259 if let Some(val) = self.stats.get_mut(&date) {
260 *val = (val.0 ^ true).into();
261 } else {
262 self.insert_entry(date, CustomBool(true));
263 }
264 }
265 fn set_view_month_offset(&mut self, offset: u32) {
266 self.view_month_offset = offset;
267 }
268 fn view_month_offset(&self) -> u32 {
269 self.view_month_offset
270 }
271}