aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-02-09 17:05:59 +0000
committerAkshay <[email protected]>2020-02-09 17:05:59 +0000
commitd029abee25e0e8f472e3491858dce3be96ced505 (patch)
tree5536971cc33ed8345540023e52531abbe52402b6
parent7662bc2dfb29d115583f87859366df50638fac52 (diff)
init
-rw-r--r--src/main.rs226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..0afd0b1
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,226 @@
1#![allow(dead_code)]
2#![allow(unused_imports)]
3#![allow(unused_must_use)]
4
5use chrono::prelude::*;
6use chrono::{Local, NaiveDate};
7use serde::Serialize;
8
9use cursive::direction::{Direction, Orientation};
10use cursive::event::{Event, EventResult, Key};
11use cursive::theme::Color::*;
12use cursive::theme::PaletteColor::*;
13use cursive::theme::{BaseColor, BorderStyle, Palette, Theme};
14use cursive::view::View;
15use cursive::views::{Dialog, DummyView, LinearLayout, TextView};
16use cursive::{Cursive, Printer, Vec2};
17
18use std::fs::File;
19use std::io::prelude::*;
20
21use std::collections::HashMap;
22
23#[derive(Debug)]
24struct Habit<T> {
25 name: String,
26 stats: HashMap<NaiveDate, T>,
27}
28
29impl<T> Habit<T>
30where
31 T: Copy,
32{
33 fn new(name: &str) -> Habit<T> {
34 return Habit {
35 name: name.to_owned(),
36 stats: HashMap::new(),
37 };
38 }
39
40 fn get_by_date(&self, date: NaiveDate) -> Option<&T> {
41 self.stats.get(&date)
42 }
43
44 fn insert_entry(&mut self, date: NaiveDate, val: T) {
45 *self.stats.entry(date).or_insert(val) = val;
46 }
47}
48
49impl Habit<bool> {
50 fn toggle(&mut self, date: NaiveDate) {
51 if let Some(v) = self.stats.get_mut(&date) {
52 *v ^= true
53 } else {
54 self.insert_entry(date, true);
55 }
56 }
57}
58
59impl Habit<u32> {
60 fn increment(&mut self, date: NaiveDate) {
61 if let Some(v) = self.stats.get_mut(&date) {
62 *v += 1
63 }
64 }
65 fn decrement(&mut self, date: NaiveDate) {
66 if let Some(v) = self.stats.get_mut(&date) {
67 if *v >= 1 {
68 *v -= 1;
69 } else {
70 *v = 0;
71 };
72 }
73 }
74 fn set(&mut self, date: NaiveDate, val: u32) {
75 *self.stats.entry(date).or_insert(val) = val;
76 }
77}
78
79enum ViewMode {
80 Daily,
81 Monthly,
82}
83
84struct BitView {
85 habit: Habit<bool>,
86 true_chr: char,
87 false_chr: char,
88 future_chr: char,
89
90 view_width: u32,
91 view_height: u32,
92 // color config
93}
94
95impl BitView {
96 fn new(habit: Habit<bool>) -> Self {
97 return BitView {
98 habit,
99 true_chr: 'x',
100 false_chr: 'o',
101 future_chr: '.',
102 view_width: 21,
103 view_height: 9,
104 };
105 }
106 fn get_title(&self) -> String {
107 return self.habit.name.to_owned();
108 // return format!(
109 // "{:^width$.max$}",
110 // self.habit.name,
111 // width = self.view_width as usize,
112 // max = self.view_width as usize - 3
113 // );
114 }
115}
116
117impl View for BitView {
118 fn draw(&self, printer: &Printer) {
119 let now = Local::now();
120 let year = now.year();
121 let month = now.month();
122
123 for i in 1..=31 {
124 let day = NaiveDate::from_ymd_opt(year, month, i);
125 let d = day.unwrap();
126 let day_stat = self.habit.get_by_date(d).unwrap_or(&false);
127 let coords = ((i % 7) * 3, i / 7 + 2);
128
129 if d < now.naive_utc().date() {
130 printer.print(coords, &format!("{:^3}", self.false_chr))
131 } else if d > now.naive_utc().date() {
132 printer.print(coords, &format!("{:^3}", self.future_chr))
133 } else {
134 printer.print(coords, &format!("{:^3}", self.future_chr))
135 }
136 // if let Some(d) = day {
137 // let day_status = self.habit.get_by_date(d).unwrap_or(&false);
138 // let coords = ((i % 7) * 3, i / 7 + 2);
139
140 // if d <= now.naive_utc().date() {
141 // if *day_status {
142 // printer.print(coords, &format!("{:^3}", self.true_chr))
143 // } else {
144 // printer.print(coords, &format!("{:^3}", self.false_chr))
145 // }
146 // } else {
147 // printer.print(coords, &format!("{:^3}", self.future_chr))
148 // }
149 // }
150 }
151 }
152
153 fn required_size(&mut self, _: Vec2) -> Vec2 {
154 (20, 9).into()
155 }
156
157 fn take_focus(&mut self, _: Direction) -> bool {
158 true
159 }
160
161 fn on_event(&mut self, e: Event) -> EventResult {
162 match e {
163 Event::Key(Key::Enter) => {
164 self.habit.toggle(Local::now().naive_utc().date());
165 return EventResult::Consumed(None);
166 }
167 _ => return EventResult::Ignored,
168 }
169 }
170}
171
172fn pallete_gen() -> Palette {
173 let mut p = Palette::default();
174 p[Background] = Dark(BaseColor::Black);
175 p[Shadow] = Light(BaseColor::Black);
176 p[View] = Dark(BaseColor::Black);
177 p[Primary] = Dark(BaseColor::White);
178 p[Secondary] = Light(BaseColor::Black);
179 p[Tertiary] = Dark(BaseColor::Green);
180 p[TitlePrimary] = Light(BaseColor::White);
181 p[Highlight] = Dark(BaseColor::Red);
182 p[HighlightInactive] = Dark(BaseColor::Black);
183
184 return p;
185}
186
187fn theme_gen() -> Theme {
188 let mut t = Theme::default();
189 t.shadow = false;
190 t.borders = BorderStyle::Simple;
191 t.palette = pallete_gen();
192 return t;
193}
194
195fn main() {
196 let mut work_out: Habit<bool> = Habit::new("gymming");
197 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 4), true);
198 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 2), true);
199 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 3), true);
200 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 1), true);
201 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 5), false);
202 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 8), false);
203 work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 11), false);
204
205 let mut again: Habit<bool> = Habit::new("reading");
206 again.insert_entry(NaiveDate::from_ymd(2020, 2, 4), true);
207 again.insert_entry(NaiveDate::from_ymd(2020, 2, 2), true);
208
209 let mut s = Cursive::default();
210
211 let gym_view = BitView::new(work_out);
212 let gym_title = gym_view.get_title();
213
214 let reading_view = BitView::new(again);
215 let reading_title = reading_view.get_title();
216
217 s.add_global_callback('q', |a| a.quit());
218 s.add_layer(
219 LinearLayout::horizontal()
220 .child(Dialog::around(gym_view).title(gym_title))
221 .child(Dialog::around(reading_view).title(reading_title)),
222 );
223
224 s.set_theme(theme_gen());
225 s.run();
226}