From d029abee25e0e8f472e3491858dce3be96ced505 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sun, 9 Feb 2020 22:35:59 +0530 Subject: init --- src/main.rs | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 src/main.rs (limited to 'src') 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 @@ +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(unused_must_use)] + +use chrono::prelude::*; +use chrono::{Local, NaiveDate}; +use serde::Serialize; + +use cursive::direction::{Direction, Orientation}; +use cursive::event::{Event, EventResult, Key}; +use cursive::theme::Color::*; +use cursive::theme::PaletteColor::*; +use cursive::theme::{BaseColor, BorderStyle, Palette, Theme}; +use cursive::view::View; +use cursive::views::{Dialog, DummyView, LinearLayout, TextView}; +use cursive::{Cursive, Printer, Vec2}; + +use std::fs::File; +use std::io::prelude::*; + +use std::collections::HashMap; + +#[derive(Debug)] +struct Habit { + name: String, + stats: HashMap, +} + +impl Habit +where + T: Copy, +{ + fn new(name: &str) -> Habit { + return Habit { + name: name.to_owned(), + stats: HashMap::new(), + }; + } + + fn get_by_date(&self, date: NaiveDate) -> Option<&T> { + self.stats.get(&date) + } + + fn insert_entry(&mut self, date: NaiveDate, val: T) { + *self.stats.entry(date).or_insert(val) = val; + } +} + +impl Habit { + fn toggle(&mut self, date: NaiveDate) { + if let Some(v) = self.stats.get_mut(&date) { + *v ^= true + } else { + self.insert_entry(date, true); + } + } +} + +impl Habit { + fn increment(&mut self, date: NaiveDate) { + if let Some(v) = self.stats.get_mut(&date) { + *v += 1 + } + } + fn decrement(&mut self, date: NaiveDate) { + if let Some(v) = self.stats.get_mut(&date) { + if *v >= 1 { + *v -= 1; + } else { + *v = 0; + }; + } + } + fn set(&mut self, date: NaiveDate, val: u32) { + *self.stats.entry(date).or_insert(val) = val; + } +} + +enum ViewMode { + Daily, + Monthly, +} + +struct BitView { + habit: Habit, + true_chr: char, + false_chr: char, + future_chr: char, + + view_width: u32, + view_height: u32, + // color config +} + +impl BitView { + fn new(habit: Habit) -> Self { + return BitView { + habit, + true_chr: 'x', + false_chr: 'o', + future_chr: '.', + view_width: 21, + view_height: 9, + }; + } + fn get_title(&self) -> String { + return self.habit.name.to_owned(); + // return format!( + // "{:^width$.max$}", + // self.habit.name, + // width = self.view_width as usize, + // max = self.view_width as usize - 3 + // ); + } +} + +impl View for BitView { + fn draw(&self, printer: &Printer) { + let now = Local::now(); + let year = now.year(); + let month = now.month(); + + for i in 1..=31 { + let day = NaiveDate::from_ymd_opt(year, month, i); + let d = day.unwrap(); + let day_stat = self.habit.get_by_date(d).unwrap_or(&false); + let coords = ((i % 7) * 3, i / 7 + 2); + + if d < now.naive_utc().date() { + printer.print(coords, &format!("{:^3}", self.false_chr)) + } else if d > now.naive_utc().date() { + printer.print(coords, &format!("{:^3}", self.future_chr)) + } else { + printer.print(coords, &format!("{:^3}", self.future_chr)) + } + // if let Some(d) = day { + // let day_status = self.habit.get_by_date(d).unwrap_or(&false); + // let coords = ((i % 7) * 3, i / 7 + 2); + + // if d <= now.naive_utc().date() { + // if *day_status { + // printer.print(coords, &format!("{:^3}", self.true_chr)) + // } else { + // printer.print(coords, &format!("{:^3}", self.false_chr)) + // } + // } else { + // printer.print(coords, &format!("{:^3}", self.future_chr)) + // } + // } + } + } + + fn required_size(&mut self, _: Vec2) -> Vec2 { + (20, 9).into() + } + + fn take_focus(&mut self, _: Direction) -> bool { + true + } + + fn on_event(&mut self, e: Event) -> EventResult { + match e { + Event::Key(Key::Enter) => { + self.habit.toggle(Local::now().naive_utc().date()); + return EventResult::Consumed(None); + } + _ => return EventResult::Ignored, + } + } +} + +fn pallete_gen() -> Palette { + let mut p = Palette::default(); + p[Background] = Dark(BaseColor::Black); + p[Shadow] = Light(BaseColor::Black); + p[View] = Dark(BaseColor::Black); + p[Primary] = Dark(BaseColor::White); + p[Secondary] = Light(BaseColor::Black); + p[Tertiary] = Dark(BaseColor::Green); + p[TitlePrimary] = Light(BaseColor::White); + p[Highlight] = Dark(BaseColor::Red); + p[HighlightInactive] = Dark(BaseColor::Black); + + return p; +} + +fn theme_gen() -> Theme { + let mut t = Theme::default(); + t.shadow = false; + t.borders = BorderStyle::Simple; + t.palette = pallete_gen(); + return t; +} + +fn main() { + let mut work_out: Habit = Habit::new("gymming"); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 4), true); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 2), true); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 3), true); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 1), true); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 5), false); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 8), false); + work_out.insert_entry(NaiveDate::from_ymd(2020, 2, 11), false); + + let mut again: Habit = Habit::new("reading"); + again.insert_entry(NaiveDate::from_ymd(2020, 2, 4), true); + again.insert_entry(NaiveDate::from_ymd(2020, 2, 2), true); + + let mut s = Cursive::default(); + + let gym_view = BitView::new(work_out); + let gym_title = gym_view.get_title(); + + let reading_view = BitView::new(again); + let reading_title = reading_view.get_title(); + + s.add_global_callback('q', |a| a.quit()); + s.add_layer( + LinearLayout::horizontal() + .child(Dialog::around(gym_view).title(gym_title)) + .child(Dialog::around(reading_view).title(reading_title)), + ); + + s.set_theme(theme_gen()); + s.run(); +} -- cgit v1.2.3