1
0
Fork 0

Refactor codes for recurring tasks

This commit is contained in:
Malte Brandy 2018-06-10 18:10:22 +02:00
parent 69b8993d4d
commit 3c643f1abc
No known key found for this signature in database
GPG key ID: 226A2D41EF5378C9
6 changed files with 204 additions and 127 deletions

View file

@ -274,7 +274,7 @@ where
T::Item: Into<Task>; T::Item: Into<Task>;
} }
fn gen_match(a: &Task, b: &Task) -> bool { pub fn gen_match(a: &Task, b: &Task) -> bool {
a.gen_name() == b.gen_name() && a.gen_id() == b.gen_id() a.gen_name() == b.gen_name() && a.gen_id() == b.gen_id()
} }
impl TaskGenerator for TaskCache { impl TaskGenerator for TaskCache {

View file

@ -100,7 +100,7 @@ enum MPD {
} }
#[derive(Copy, Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[derive(Copy, Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
struct State { pub struct State {
mode: Mode, mode: Mode,
location: Location, location: Location,
connectivity: Connectivity, connectivity: Connectivity,

View file

@ -3,7 +3,6 @@ extern crate uuid;
extern crate task_hookrs; extern crate task_hookrs;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate kairos;
extern crate chrono; extern crate chrono;
#[macro_use] #[macro_use]
extern crate error_chain; extern crate error_chain;
@ -17,6 +16,7 @@ pub mod refresh;
pub mod update; pub mod update;
pub mod kassandra; pub mod kassandra;
pub mod tasktree; pub mod tasktree;
pub mod well_known;
pub mod error { pub mod error {
use task_hookrs::error as terror; use task_hookrs::error as terror;

View file

@ -1,9 +1,5 @@
use chrono::offset::{Local, TimeZone}; use chrono::offset::{Local, TimeZone};
use chrono::Duration; use chrono::{NaiveDate, Duration, NaiveTime, Datelike, NaiveDateTime};
use kairos::timetype::TimeType as TT;
use kairos::iter::Iter;
use kairos::error::Result as KairosResult;
use task_hookrs::status::TaskStatus as TS; use task_hookrs::status::TaskStatus as TS;
use task_hookrs::task::Task; use task_hookrs::task::Task;
@ -14,9 +10,47 @@ use task_hookrs::date::Date;
use generate::TaskGenerator; use generate::TaskGenerator;
use tasktree::TaskNode; use tasktree::TaskNode;
#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum Timer { pub enum Timer {
DeadTime(Duration), DeadTime(Duration),
Repetition(Iter), Repetition(CalendarRepeater),
}
#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub enum Interval {
Year(i32),
Month(u32),
Day(i32),
}
#[derive(Copy, Debug, Clone, Eq, PartialEq)]
pub struct CalendarRepeater {
pub time: NaiveTime,
pub date: NaiveDate,
pub repeat: Interval,
}
impl Iterator for CalendarRepeater {
type Item = NaiveDateTime;
fn next(&mut self) -> Option<NaiveDateTime> {
let ret = Some(self.date.clone().and_time(self.time));
self.date = match self.repeat {
Interval::Year(year) => {
NaiveDate::from_ymd(self.date.year() + year, self.date.month(), self.date.day())
}
Interval::Month(month) => {
NaiveDate::from_ymd(
self.date.year() + ((self.date.month() + month - 1) / 12) as i32,
1 + ((self.date.month() + month - 1) % 12),
self.date.day(),
)
}
Interval::Day(day) => NaiveDate::from_num_days_from_ce(
self.date.num_days_from_ce() + day,
),
};
ret
}
} }
pub trait TaskRefresher { pub trait TaskRefresher {
@ -34,12 +68,10 @@ impl TaskRefresher for TaskCache {
recurrence: Timer, recurrence: Timer,
) -> Result<()> { ) -> Result<()> {
let now = Local::now(); let now = Local::now();
let now_moment = TT::Moment(Local::now().naive_local());
let recent = match recurrence { let recent = match recurrence {
Timer::DeadTime(time) => TT::Moment((now - time).naive_local()), Timer::DeadTime(time) => (now - time).naive_local(),
Timer::Repetition(iter) => { Timer::Repetition(iter) => {
iter.filter_map(KairosResult::ok) iter.take_while(|t| *t <= now.naive_local())
.take_while(|t| *t <= now_moment)
.last() .last()
.ok_or("Repetition starts in the future")? .ok_or("Repetition starts in the future")?
.clone() .clone()
@ -50,13 +82,11 @@ impl TaskRefresher for TaskCache {
.into_iter() .into_iter()
.filter(|task| if let Some(old) = self.get_by_gen(&task) { .filter(|task| if let Some(old) = self.get_by_gen(&task) {
if old.obsolete() && if old.obsolete() &&
TT::Moment(
Local Local
.from_utc_datetime( .from_utc_datetime(
&**old.end().expect("Ended tasks have to have an end date"), &**old.end().expect("Ended tasks have to have an end date"),
) )
.naive_local(), .naive_local() < recent
) < recent
{ {
uuids.push(old.uuid().clone()); uuids.push(old.uuid().clone());
} }

View file

@ -1,107 +1,17 @@
use task_hookrs::{ use task_hookrs::error::Result;
error::Result, use task_hookrs::cache::TaskCache;
cache::TaskCache,
task::{Task, TaskBuilder} use refresh::TaskRefresher;
};
use generate::GeneratedTask;
use refresh::{TaskRefresher, Timer};
use tasktree::TreeCache; use tasktree::TreeCache;
use chrono::{NaiveDate,Duration}; use well_known::{SIMPLE, WellKnown};
use kairos::{
timetype::TimeType as TT,
iter::extensions::{Weekly, Monthly, Daily}
};
fn simple_task(name: &str) -> Task {
let mut task = TaskBuilder::default().description(name).build().expect(
"TaskBuilding failed inspite of set description",
);
task.set_gen_name(Some(name));
task.set_gen_id(Some(name));
task
}
fn simple_tasks<'a>(names: impl IntoIterator<Item = &'a str>) -> impl Iterator<Item = Task> {
names.into_iter().map(simple_task)
}
pub fn update_tasks(cache: &mut TaskCache) -> Result<()> { pub fn update_tasks(cache: &mut TaskCache) -> Result<()> {
let daily = || { for simple_task in SIMPLE.iter() {
Timer::Repetition(
TT::moment(NaiveDate::from_ymd(2018, 5, 8).and_hms(20, 0, 0))
.daily(1)
.unwrap(),
)
};
let weekly = || {
Timer::Repetition(
TT::moment(NaiveDate::from_ymd(2018, 5, 8).and_hms(20, 0, 0))
.weekly(1)
.unwrap(),
)
};
let monthly = || {
Timer::Repetition(
TT::moment(NaiveDate::from_ymd(2018, 5, 3).and_hms(20, 0, 0))
.monthly(1)
.unwrap(),
)
};
cache.reactivate( cache.reactivate(
simple_tasks(vec![ Some(simple_task.definition().clone()),
"Staubsaugen", simple_task.refresh(),
"Putze Waschbecken",
"Wäsche sortieren und entscheiden, welche Waschgänge notwendig sind",
]),
Timer::DeadTime(Duration::weeks(2)),
)?;
cache.reactivate(
simple_tasks(
vec!["Reinige Toilette", "Zehennägel schneiden"],
),
Timer::DeadTime(Duration::weeks(4)),
)?;
cache.reactivate(
simple_tasks(vec!["Friseurtermin machen"]),
Timer::DeadTime(Duration::weeks(6)),
)?;
cache.reactivate(
simple_tasks(vec![
"Aktualisiere Buchhaltung",
"Leere Inbox",
"Sortiere Tasktree",
"Sortiere Inbox",
"Sortiere Inbox Auslandskoordination",
"Sortiere Inbox Kiva",
"Klavier üben",
"Tasks der Woche kontrollieren"
]),
daily(),
)?;
cache.reactivate(
simple_tasks(vec!["Kontrolliere +optional","Verbuche Kontoauszüge"]),
monthly(),
)?;
cache.reactivate(
simple_tasks(vec![
"Kontrolliere Spam",
"Korrigiere Portemonnaiezählstand",
"Sortiere Archiv",
"Sortiere Archiv Kiva",
"Sortiere Archiv Auslandskoordination",
"Kontrolliere +later",
"Kontrolliere +await",
"Block leeren und wegsortieren",
"Leere Kiva Fächer",
"Inbox zu Hause wegsortieren",
"Cryptpads sichern",
"Update nixos apollo",
"Update home hephaistos",
"Tasks des Monats kontrollieren"
]),
weekly(),
)?; )?;
}
cache.refresh_tree(); cache.refresh_tree();
Ok(()) Ok(())
} }

View file

@ -1,8 +1,145 @@
use task_hookrs::task::{Task, TaskBuilder};
use task_hookrs::cache::TaskCache;
pub Trait { use error::Result;
fn definition() -> Task use kassandra::State;
fn is_task(&Task) -> bool use generate::{gen_match, GeneratedTask};
fn action_necessary(&TaskCache, State) -> Result<bool> use refresh::{Timer, CalendarRepeater, Interval};
fn process(&mut TaskCache) -> Result<()>
fn refresh() -> refresh::Timer use chrono::{NaiveDate, NaiveTime, Duration};
pub trait WellKnown {
fn definition(&self) -> &Task;
fn is_this(&self, task: &Task) -> bool {
gen_match(task, self.definition())
}
fn action_necessary(&self, &TaskCache, State) -> Result<bool> {
Ok(true)
}
fn process(&self, &mut TaskCache, State) -> Result<()> {
Ok(())
}
fn refresh(&self) -> Timer;
}
pub struct SimpleTask {
definition: Task,
timer: Timer,
}
impl SimpleTask {
fn new(
description: impl Into<String>,
gen_name: impl Into<String>,
gen_id: impl Into<String>,
timer: Timer,
) -> Self {
let mut task = TaskBuilder::default()
.description(description.into())
.build()
.expect("TaskBuilding failed inspite of set description");
task.set_gen_name(Some(gen_name.into()));
task.set_gen_id(Some(gen_id.into()));
SimpleTask {
definition: task,
timer: timer,
}
}
}
impl WellKnown for SimpleTask {
fn definition(&self) -> &Task {
&self.definition
}
fn refresh(&self) -> Timer {
self.timer.clone()
}
}
fn simple_task(name: &str, timer: Timer) -> SimpleTask {
SimpleTask::new(name, name, name, timer)
}
fn simple_tasks<'a>(
names: impl IntoIterator<Item = impl Into<String>>,
timer: Timer,
) -> impl Iterator<Item = SimpleTask> {
names.into_iter().map(move |x| {
simple_task(&x.into(), timer.clone())
})
}
fn make_simple() -> Vec<SimpleTask> {
let daily = Timer::Repetition(CalendarRepeater {
date: NaiveDate::from_ymd(2018, 5, 8),
time: NaiveTime::from_hms(20, 0, 0),
repeat: Interval::Day(1),
});
let weekly = Timer::Repetition(CalendarRepeater {
date: NaiveDate::from_ymd(2018, 5, 8),
time: NaiveTime::from_hms(20, 0, 0),
repeat: Interval::Day(7),
});
let monthly = Timer::Repetition(CalendarRepeater {
date: NaiveDate::from_ymd(2018, 5, 3),
time: NaiveTime::from_hms(20, 0, 0),
repeat: Interval::Month(1),
});
simple_tasks(
vec![
"Staubsaugen",
"Putze Waschbecken",
"Wäsche sortieren und entscheiden, welche Waschgänge notwendig sind",
],
Timer::DeadTime(Duration::weeks(2)),
).chain(simple_tasks(
vec!["Reinige Toilette", "Zehennägel schneiden"],
Timer::DeadTime(Duration::weeks(4)),
))
.chain(simple_tasks(
vec!["Friseurtermin machen"],
Timer::DeadTime(Duration::weeks(6)),
))
.chain(simple_tasks(
vec![
"Aktualisiere Buchhaltung",
"Leere Inbox",
"Sortiere Tasktree",
"Sortiere Inbox",
"Sortiere Inbox Auslandskoordination",
"Sortiere Inbox Kiva",
"Klavier üben",
"Tasks der Woche kontrollieren",
],
daily,
))
.chain(simple_tasks(
vec!["Kontrolliere +optional", "Verbuche Kontoauszüge"],
monthly,
))
.chain(simple_tasks(
vec![
"Kontrolliere Spam",
"Korrigiere Portemonnaiezählstand",
"Sortiere Archiv",
"Sortiere Archiv Kiva",
"Sortiere Archiv Auslandskoordination",
"Kontrolliere +later",
"Kontrolliere +await",
"Block leeren und wegsortieren",
"Leere Kiva Fächer",
"Inbox zu Hause wegsortieren",
"Cryptpads sichern",
"Update nixos apollo",
"Update home hephaistos",
"Tasks des Monats kontrollieren",
],
weekly,
))
.collect::<Vec<_>>()
}
lazy_static! {
pub static ref SIMPLE: Vec<SimpleTask> = make_simple();
} }