Refactor codes for recurring tasks
This commit is contained in:
parent
69b8993d4d
commit
3c643f1abc
6 changed files with 204 additions and 127 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue